[Restricted-changes] r163 - in dists/trunk: faac/debian hot-babe/debian lame/debian libdvdcss/debian xv/debian xv/debian/bug xv/debian/lintian xv/debian/patches xv/debian/pixmap xvidcore/debian

fabian-guest at alioth.debian.org fabian-guest at alioth.debian.org
Tue Jan 15 22:03:14 UTC 2008


Author: fabian-guest
Date: 2008-01-15 22:03:08 +0000 (Tue, 15 Jan 2008)
New Revision: 163

Added:
   dists/trunk/xv/debian/bug/
   dists/trunk/xv/debian/bug/xv
   dists/trunk/xv/debian/bug/xv-dbg
   dists/trunk/xv/debian/bug/xv-doc
   dists/trunk/xv/debian/changelog
   dists/trunk/xv/debian/compat
   dists/trunk/xv/debian/control
   dists/trunk/xv/debian/copyright
   dists/trunk/xv/debian/lintian/
   dists/trunk/xv/debian/lintian/xv
   dists/trunk/xv/debian/lintian/xv-dbg
   dists/trunk/xv/debian/lintian/xv-doc
   dists/trunk/xv/debian/patches/
   dists/trunk/xv/debian/patches/00list
   dists/trunk/xv/debian/patches/01-xv-3.10a-jumbo-fix-enh-patch-20070520.dpatch
   dists/trunk/xv/debian/patches/02-xv-3.10a-jumbo-files-20070520.dpatch
   dists/trunk/xv/debian/patches/03-no-docs.dpatch
   dists/trunk/xv/debian/patches/04-shared-libjasper.dpatch
   dists/trunk/xv/debian/patches/05-override-cflags.dpatch
   dists/trunk/xv/debian/pixmap/
   dists/trunk/xv/debian/pixmap/xv.xpm
   dists/trunk/xv/debian/rules
   dists/trunk/xv/debian/watch
   dists/trunk/xv/debian/xv-doc.doc-base
   dists/trunk/xv/debian/xv-doc.docs
   dists/trunk/xv/debian/xv.docs
   dists/trunk/xv/debian/xv.install
   dists/trunk/xv/debian/xv.menu
   dists/trunk/xv/debian/xv.mime
Removed:
   dists/trunk/faac/debian/libfaac0.links
   dists/trunk/lame/debian/libmp3lame0.links
   dists/trunk/libdvdcss/debian/libdvdcss2.links
   dists/trunk/xv/debian/bug/
   dists/trunk/xv/debian/changelog
   dists/trunk/xv/debian/compat
   dists/trunk/xv/debian/control
   dists/trunk/xv/debian/copyright
   dists/trunk/xv/debian/doc/
   dists/trunk/xv/debian/lintian/
   dists/trunk/xv/debian/patches/
   dists/trunk/xv/debian/pixmap/
   dists/trunk/xv/debian/rules
   dists/trunk/xv/debian/watch
   dists/trunk/xv/debian/xv-doc.dirs
   dists/trunk/xv/debian/xv-doc.doc-base
   dists/trunk/xv/debian/xv-doc.docs
   dists/trunk/xv/debian/xv.docs
   dists/trunk/xv/debian/xv.menu
   dists/trunk/xv/debian/xv.mime
Modified:
   dists/trunk/faac/debian/control
   dists/trunk/faac/debian/copyright
   dists/trunk/faac/debian/rules
   dists/trunk/hot-babe/debian/control
   dists/trunk/hot-babe/debian/copyright
   dists/trunk/hot-babe/debian/rules
   dists/trunk/lame/debian/control
   dists/trunk/lame/debian/copyright
   dists/trunk/lame/debian/rules
   dists/trunk/libdvdcss/debian/control
   dists/trunk/libdvdcss/debian/copyright
   dists/trunk/libdvdcss/debian/rules
   dists/trunk/xvidcore/debian/control
   dists/trunk/xvidcore/debian/copyright
   dists/trunk/xvidcore/debian/rules
Log:
all packages
------------
*/debian/control:
 + Bumped Standards-Vresion to 3.7.3.
  + Put Homepage line after Vcs-* lines (cosmetic).
  */debian/copyright:
   + Updated Debian packaging copyright to 2008.
   */debian/rules:
    + 's/common-install-arch/common-install-impl/g'
     + 's/DEB_DH_INSTALL_ARGS += --sourcedir=/DEB_DH_INSTALL_SOURCEDIR := /g'
     */debian/lib*.links:
      + Idiotic. Removed.

      xv additional
      -------------
      * Converted Debian packaging to CDBS + some smaller changes...
      * Added debian/patches/05-override-cflags.dpatch.
      * Removed documentation in PDF format.
      * Removed debian/patches/05-dlinux.dpatch.


Modified: dists/trunk/faac/debian/control
===================================================================
--- dists/trunk/faac/debian/control	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/faac/debian/control	2008-01-15 22:03:08 UTC (rev 163)
@@ -11,10 +11,10 @@
                debhelper (>= 5),
                dpatch,
                libtool
-Standards-Version: 3.7.2
-Homepage: http://www.audiocoding.com/
+Standards-Version: 3.7.3
 Vcs-Svn: svn://svn.debian.org/restricted/dists/trunk/faac/
 Vcs-Browser: http://svn.debian.org/wsvn/restricted/dists/trunk/faac/
+Homepage: http://www.audiocoding.com/
 
 Package: faac
 Section: restricted/sound

Modified: dists/trunk/faac/debian/copyright
===================================================================
--- dists/trunk/faac/debian/copyright	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/faac/debian/copyright	2008-01-15 22:03:08 UTC (rev 163)
@@ -578,5 +578,5 @@
 	     use the text of this Exhibit A rather than the text found in the
 	     Original Code Source Code for Your Modifications.]
 
-The Debian packaging is (C) 2005-2007, Fabian Greffrath <fabian at debian-unofficial.org> and
+The Debian packaging is (C) 2005-2008, Fabian Greffrath <fabian at debian-unofficial.org> and
 is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

Deleted: dists/trunk/faac/debian/libfaac0.links
===================================================================
--- dists/trunk/faac/debian/libfaac0.links	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/faac/debian/libfaac0.links	2008-01-15 22:03:08 UTC (rev 163)
@@ -1 +0,0 @@
-/usr/lib/libfaac.so.0.0.0 /usr/lib/libfaac.so.0.0

Modified: dists/trunk/faac/debian/rules
===================================================================
--- dists/trunk/faac/debian/rules	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/faac/debian/rules	2008-01-15 22:03:08 UTC (rev 163)
@@ -6,9 +6,9 @@
 
 DEB_CONFIGURE_EXTRA_FLAGS += --with-mp4v2
 
-DEB_DH_INSTALL_ARGS += --sourcedir=debian/tmp
+DEB_DH_INSTALL_SOURCEDIR := debian/tmp
 
-common-install-arch::
+common-install-impl::
 	# Installing bug control
 	for BUG in debian/bug/*; do \
 		install -D -m 0644 $$BUG debian/`basename $$BUG`/usr/share/bug/`basename $$BUG`/control || exit 1; \

Modified: dists/trunk/hot-babe/debian/control
===================================================================
--- dists/trunk/hot-babe/debian/control	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/hot-babe/debian/control	2008-01-15 22:03:08 UTC (rev 163)
@@ -10,10 +10,10 @@
                debhelper (>= 5),
                dpatch,
                libgtk2.0-dev
-Standards-Version: 3.7.2
-Homepage: http://www.dindinx.net/hotbabe/
+Standards-Version: 3.7.3
 Vcs-Svn: svn://svn.debian.org/restricted/dists/trunk/hot-babe/
 Vcs-Browser: http://svn.debian.org/wsvn/restricted/dists/trunk/hot-babe/
+Homepage: http://www.dindinx.net/hotbabe/
 
 Package: hot-babe
 Section: restricted/x11

Modified: dists/trunk/hot-babe/debian/copyright
===================================================================
--- dists/trunk/hot-babe/debian/copyright	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/hot-babe/debian/copyright	2008-01-15 22:03:08 UTC (rev 163)
@@ -20,5 +20,5 @@
 On Debian systems, the complete text of the Artistic License
 can be found in the `/usr/share/common-licenses/Artistic' file.
 
-The Debian packaging is (C) 2005-2007, Fabian Greffrath <fabian at debian-unofficial.org> and
+The Debian packaging is (C) 2005-2008, Fabian Greffrath <fabian at debian-unofficial.org> and
 is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

Modified: dists/trunk/hot-babe/debian/rules
===================================================================
--- dists/trunk/hot-babe/debian/rules	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/hot-babe/debian/rules	2008-01-15 22:03:08 UTC (rev 163)
@@ -7,7 +7,7 @@
 DEB_MAKE_BUILD_TARGET += PREFIX=/usr
 DEB_MAKE_INSTALL_TARGET += install PREFIX=/usr DESTDIR=$(CURDIR)/debian/hot-babe DOC="NEWS TODO CONTRIBUTORS"
 
-common-install-arch::
+common-install-impl::
 	# Installing bug control
 	for BUG in debian/bug/*; do \
 		install -D -m 0644 $$BUG debian/`basename $$BUG`/usr/share/bug/`basename $$BUG`/control || exit 1; \

Modified: dists/trunk/lame/debian/control
===================================================================
--- dists/trunk/lame/debian/control	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/lame/debian/control	2008-01-15 22:03:08 UTC (rev 163)
@@ -13,10 +13,10 @@
                libgtk1.2-dev,
                libncurses5-dev,
                nasm [i386]
-Standards-Version: 3.7.2
-Homepage: http://lame.sourceforge.net/
+Standards-Version: 3.7.3
 Vcs-Svn: svn://svn.debian.org/restricted/dists/trunk/lame/
 Vcs-Browser: http://svn.debian.org/wsvn/restricted/dists/trunk/lame/
+Homepage: http://lame.sourceforge.net/
 
 Package: lame
 Section: restricted/sound

Modified: dists/trunk/lame/debian/copyright
===================================================================
--- dists/trunk/lame/debian/copyright	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/lame/debian/copyright	2008-01-15 22:03:08 UTC (rev 163)
@@ -50,5 +50,5 @@
 On Debian systems, the complete text of the GNU General Public License
 can be found in /usr/share/common-licenses/GPL file.
 
-The Debian packaging is (C) 2007, Daniel Baumann <daniel at debian.org> and
+The Debian packaging is (C) 2007-2008, Daniel Baumann <daniel at debian.org> and
 is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

Deleted: dists/trunk/lame/debian/libmp3lame0.links
===================================================================
--- dists/trunk/lame/debian/libmp3lame0.links	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/lame/debian/libmp3lame0.links	2008-01-15 22:03:08 UTC (rev 163)
@@ -1 +0,0 @@
-/usr/lib/libmp3lame.so.0.0.0 /usr/lib/libmp3lame.so.0.0

Modified: dists/trunk/lame/debian/rules
===================================================================
--- dists/trunk/lame/debian/rules	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/lame/debian/rules	2008-01-15 22:03:08 UTC (rev 163)
@@ -14,14 +14,14 @@
 	--with-fileio=lame \
 	--with-pic
 
-DEB_DH_INSTALL_ARGS += --sourcedir=debian/tmp
+DEB_DH_INSTALL_SOURCEDIR := debian/tmp
 
 install/lame-utils::
 	mkdir -p debian/lame-utils/usr/share/lame
 	cp -r misc debian/lame-utils/usr/share/lame
 	rm -rf debian/lame-utils/usr/share/lame/misc/.deps
 
-common-install-arch::
+common-install-impl::
 	# Installing bug control
 	for BUG in debian/bug/*; do \
 		install -D -m 0644 $$BUG debian/`basename $$BUG`/usr/share/bug/`basename $$BUG`/control || exit 1; \

Modified: dists/trunk/libdvdcss/debian/control
===================================================================
--- dists/trunk/libdvdcss/debian/control	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/libdvdcss/debian/control	2008-01-15 22:03:08 UTC (rev 163)
@@ -10,10 +10,10 @@
                cdbs,
                debhelper (>= 5),
                dpatch
-Standards-Version: 3.7.2
-Homepage: http://developers.videolan.org/libdvdcss/
+Standards-Version: 3.7.3
 Vcs-Svn: svn://svn.debian.org/restricted/dists/trunk/libdvdcss/
 Vcs-Browser: http://svn.debian.org/wsvn/restricted/dists/trunk/libdvdcss/
+Homepage: http://developers.videolan.org/libdvdcss/
 
 Package: libdvdcss2
 Section: restricted/libs

Modified: dists/trunk/libdvdcss/debian/copyright
===================================================================
--- dists/trunk/libdvdcss/debian/copyright	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/libdvdcss/debian/copyright	2008-01-15 22:03:08 UTC (rev 163)
@@ -33,5 +33,5 @@
 	Copyright (C) 2001-2003 Sam Hocevar <sam at zoy.org>
 	This code is public domain.
 
-The Debian packaging is (C) 2007, Daniel Baumann <daniel at debian.org> and
+The Debian packaging is (C) 2007-2008, Daniel Baumann <daniel at debian.org> and
 is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

Deleted: dists/trunk/libdvdcss/debian/libdvdcss2.links
===================================================================
--- dists/trunk/libdvdcss/debian/libdvdcss2.links	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/libdvdcss/debian/libdvdcss2.links	2008-01-15 22:03:08 UTC (rev 163)
@@ -1 +0,0 @@
-/usr/lib/libdvdcss.so.2.0.8 /usr/lib/libdvdcss.so.2.0

Modified: dists/trunk/libdvdcss/debian/rules
===================================================================
--- dists/trunk/libdvdcss/debian/rules	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/libdvdcss/debian/rules	2008-01-15 22:03:08 UTC (rev 163)
@@ -4,9 +4,9 @@
 include /usr/share/cdbs/1/class/autotools.mk
 include /usr/share/cdbs/1/rules/dpatch.mk
 
-DEB_DH_INSTALL_ARGS += --sourcedir=debian/tmp
+DEB_DH_INSTALL_SOURCEDIR := debian/tmp
 
-common-install-arch::
+common-install-impl::
 	# Installing bug control
 	for BUG in debian/bug/*; do \
 		install -D -m 0644 $$BUG debian/`basename $$BUG`/usr/share/bug/`basename $$BUG`/control || exit 1; \

Added: dists/trunk/xv/debian/bug/xv
===================================================================
--- dists/trunk/xv/debian/bug/xv	                        (rev 0)
+++ dists/trunk/xv/debian/bug/xv	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+Send-To: Debian Restricted <restricted-devel at lists.alioth.debian.org>

Added: dists/trunk/xv/debian/bug/xv-dbg
===================================================================
--- dists/trunk/xv/debian/bug/xv-dbg	                        (rev 0)
+++ dists/trunk/xv/debian/bug/xv-dbg	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+Send-To: Debian Restricted <restricted-devel at lists.alioth.debian.org>

Added: dists/trunk/xv/debian/bug/xv-doc
===================================================================
--- dists/trunk/xv/debian/bug/xv-doc	                        (rev 0)
+++ dists/trunk/xv/debian/bug/xv-doc	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+Send-To: Debian Restricted <restricted-devel at lists.alioth.debian.org>

Deleted: dists/trunk/xv/debian/changelog
===================================================================
--- dists/trunk/xv/debian/changelog	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/changelog	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,15 +0,0 @@
-xv (1:3.10a-2) unstable; urgency=low
-
-  * Applied 'XV Jumbo Patches' of 20 May 2007.
-  * Added documentation in PDF format.
-  * Linked programs against shared libjasper.
-
- -- Fabian Greffrath <fabian at debian-unofficial.org>  Mon, 21 May 2007 00:00:00 +0100
-
-xv (1:3.10a-1) unstable; urgency=low
-
-  * Initial release.
-  * Applied 'XV Jumbo Patches' (fixes and enhancements) of 1 May 2005.
-  * Added pixmap for XV.
-
- -- Fabian Greffrath <fabian at debian-unofficial.org>  Wed,  1 Feb 2006 00:00:00 +0100

Added: dists/trunk/xv/debian/changelog
===================================================================
--- dists/trunk/xv/debian/changelog	                        (rev 0)
+++ dists/trunk/xv/debian/changelog	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,16 @@
+xv (1:3.10a-2) unstable; urgency=low
+
+  * Applied 'XV Jumbo Patches' of 20 May 2007.
+    - Removed documentation in PDF format.
+  * Converted Debian packaging to CDBS.
+  * Linked programs against shared libjasper.
+
+ -- Fabian Greffrath <fabian at debian-unofficial.org>  Mon, 21 May 2007 00:00:00 +0100
+
+xv (1:3.10a-1) unstable; urgency=low
+
+  * Initial release.
+  * Applied 'XV Jumbo Patches' (fixes and enhancements) of 1 May 2005.
+  * Added pixmap for XV.
+
+ -- Fabian Greffrath <fabian at debian-unofficial.org>  Wed,  1 Feb 2006 00:00:00 +0100

Deleted: dists/trunk/xv/debian/compat
===================================================================
--- dists/trunk/xv/debian/compat	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/compat	2008-01-15 22:03:08 UTC (rev 163)
@@ -1 +0,0 @@
-5

Added: dists/trunk/xv/debian/compat
===================================================================
--- dists/trunk/xv/debian/compat	                        (rev 0)
+++ dists/trunk/xv/debian/compat	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+5

Deleted: dists/trunk/xv/debian/control
===================================================================
--- dists/trunk/xv/debian/control	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/control	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,66 +0,0 @@
-Source: xv
-Section: restricted/graphics
-Priority: optional
-Maintainer: Debian Restricted <restricted-devel at lists.alioth.debian.org>
-Uploaders: Fabian Greffrath <fabian at debian-unofficial.org>,
-           Daniel Baumann <daniel at debian.org>
-Origin: debian-unofficial.org
-Bugs: mailto:restricted-devel at lists.alioth.debian.org
-Build-Depends: debhelper (>= 5),
-               dpatch,
-               libjasper-dev,
-               libjpeg62-dev,
-               libpng12-dev,
-               libtiff4-dev,
-               libx11-dev,
-               libxt-dev,
-               sharutils,
-               zlib1g-dev
-Standards-Version: 3.7.2
-Homepage: http://www.trilon.com/xv/
-Vcs-Svn: svn://svn.debian.org/restricted/dists/trunk/xv/
-Vcs-Browser: http://svn.debian.org/wsvn/restricted/dists/trunk/xv/
-
-Package: xv
-Section: restricted/graphics
-Architecture: any
-Depends: ${shlibs:Depends},
-         ${misc:Depends}
-Recommends: xv-doc
-Suggests: ghostscript-x
-Description: image viewer and manipulator
- XV is an interactive image manipulation program for the X Window System. It
- can operate on images in the GIF, JPEG, TIFF, PBM, PGM, PPM, XPM, X11 bitmap,
- Sun Rasterfile, Targa, RLE, RGB, BMP, PCX, FITS, and PM formats on all known
- types of X displays. It can generate PostScript files, and if you have
- ghostscript installed on your machine, it can also display them.
-
-Package: xv-dbg
-Section: restricted/devel
-Priority: extra
-Architecture: any
-Depends: xv (= ${binary:Version}),
-         ${misc:Depends}
-Description: image viewer and manipulator (debug)
- XV is an interactive image manipulation program for the X Window System. It
- can operate on images in the GIF, JPEG, TIFF, PBM, PGM, PPM, XPM, X11 bitmap,
- Sun Rasterfile, Targa, RLE, RGB, BMP, PCX, FITS, and PM formats on all known
- types of X displays. It can generate PostScript files, and if you have
- ghostscript installed on your machine, it can also display them.
- .
- This package contains the debug symbols.
-
-Package: xv-doc
-Section: restricted/doc
-Architecture: all
-Depends: ${misc:Depends}
-Recommends: xv
-Suggests: gv | postscript-viewer, xpdf | pdf-viewer
-Description: image viewer and manipulator (documentation)
- XV is an interactive image manipulation program for the X Window System. It
- can operate on images in the GIF, JPEG, TIFF, PBM, PGM, PPM, XPM, X11 bitmap,
- Sun Rasterfile, Targa, RLE, RGB, BMP, PCX, FITS, and PM formats on all known
- types of X displays. It can generate PostScript files, and if you have
- ghostscript installed on your machine, it can also display them.
- .
- This package contains the documentation.

Added: dists/trunk/xv/debian/control
===================================================================
--- dists/trunk/xv/debian/control	                        (rev 0)
+++ dists/trunk/xv/debian/control	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,66 @@
+Source: xv
+Section: restricted/graphics
+Priority: optional
+Maintainer: Debian Restricted <restricted-devel at lists.alioth.debian.org>
+Uploaders: Fabian Greffrath <fabian at debian-unofficial.org>,
+           Daniel Baumann <daniel at debian.org>
+Origin: debian-unofficial.org
+Bugs: mailto:restricted-devel at lists.alioth.debian.org
+Build-Depends: cdbs,
+               debhelper (>= 5),
+               dpatch,
+               libjasper-dev,
+               libjpeg62-dev,
+               libpng12-dev,
+               libtiff4-dev,
+               libx11-dev,
+               libxt-dev,
+               zlib1g-dev
+Standards-Version: 3.7.3
+Vcs-Svn: svn://svn.debian.org/restricted/dists/trunk/xv/
+Vcs-Browser: http://svn.debian.org/wsvn/restricted/dists/trunk/xv/
+Homepage: http://www.trilon.com/xv/
+
+Package: xv
+Section: restricted/graphics
+Architecture: any
+Depends: ${shlibs:Depends},
+         ${misc:Depends}
+Recommends: xv-doc
+Suggests: ghostscript | gs-esp | gs
+Description: image viewer and manipulator
+ XV is an interactive image manipulation program for the X Window System. It
+ can operate on images in the GIF, JPEG, TIFF, PBM, PGM, PPM, XPM, X11 bitmap,
+ Sun Rasterfile, Targa, RLE, RGB, BMP, PCX, FITS, and PM formats on all known
+ types of X displays. It can generate PostScript files, and if you have
+ ghostscript installed on your machine, it can also display them.
+
+Package: xv-dbg
+Section: restricted/devel
+Priority: extra
+Architecture: any
+Depends: xv (= ${binary:Version}),
+         ${misc:Depends}
+Description: image viewer and manipulator (debug)
+ XV is an interactive image manipulation program for the X Window System. It
+ can operate on images in the GIF, JPEG, TIFF, PBM, PGM, PPM, XPM, X11 bitmap,
+ Sun Rasterfile, Targa, RLE, RGB, BMP, PCX, FITS, and PM formats on all known
+ types of X displays. It can generate PostScript files, and if you have
+ ghostscript installed on your machine, it can also display them.
+ .
+ This package contains the debug symbols.
+
+Package: xv-doc
+Section: restricted/doc
+Architecture: all
+Depends: ${misc:Depends}
+Recommends: xv
+Suggests: gv | postscript-viewer
+Description: image viewer and manipulator (documentation)
+ XV is an interactive image manipulation program for the X Window System. It
+ can operate on images in the GIF, JPEG, TIFF, PBM, PGM, PPM, XPM, X11 bitmap,
+ Sun Rasterfile, Targa, RLE, RGB, BMP, PCX, FITS, and PM formats on all known
+ types of X displays. It can generate PostScript files, and if you have
+ ghostscript installed on your machine, it can also display them.
+ .
+ This package contains the documentation.

Deleted: dists/trunk/xv/debian/copyright
===================================================================
--- dists/trunk/xv/debian/copyright	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/copyright	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,134 +0,0 @@
-This package was debianized by Fabian Greffrath <fabian at debian-unofficial.org> on
-Wed,  1 Feb 2006 00:00:00 +0100.
-
-It was downloaded from <http://www.trilon.com/xv/>.
-
-Upstream Author:
-
-	John Bradley <bradley at trilon.com>
-
-License:
-
-	Copyright (C) 1989-1994 John Bradley
-	All rights reserved.
-
-	Permission to copy and distribute XV in its entirety, for non-commercial
-	purposes, is hereby granted without fee, provided that this license
-	information and copyright notice appear unmodified in all copies.
-
-	Note that distributing XV 'bundled' in with any product is considered to
-	be a 'commercial purpose'.
-
-	Also note that any copies of XV that are distributed must be built
-	and/or configured to be in their 'unregistered copy' mode, so that it is
-	made obvious to the user that XV is shareware, and that they should
-	consider donating, or at least reading this License Info.
-
-	The software may be modified for your own purposes, but modified
-	versions may not be distributed without prior consent of the author.
-
-	This software is provided 'as-is', without any express or implied
-	warranty. In no event will the author be held liable for any damages
-	arising from the use of this software.
-
-	If you would like to do something with XV that this copyright prohibits
-	(such as distributing it with a commercial product, using portions of
-	the source in some other program, etc.), please contact the author
-	(preferably via email). Arrangements can probably be worked out.
-
-	XV is shareware for PERSONAL USE only. You may use XV for your own
-	amusement, and if you find it nifty, useful, generally cool, or of some
-	value to you, your non-deductable donation would be greatly appreciated.
-	$25 is the suggested donation, though, of course, larger donations are
-	quite welcome. Folks who donate $25 or more can receive a Real Nice
-	bound copy of the XV manual for no extra charge.
-
-	Commercial, government, and institutional users must register their
-	copies of XV, for the price of $25 per workstation/X terminal or per XV
-	user, whichever is less. Note that it does NOT say 'simultaneous user',
-	but rather, the total number of people who use XV on any sort of
-	recurring basis. Site licenses are available (and recommended) for those
-	who wish to run XV on a large (>10) number of machines. Contact the
-	author for more details.
-
-	The author may be contacted via:
-
-		Email:		bradley at cis.upenn.edu (preferred!)
-
-		FAX:		(610) 520-2042
-
-		US Mail:	John Bradley
-				1053 Floyd Terrace
-
-	The author may not be contacted by (voice) phone. Please don't try.
-
-License (XV Jumbo Patches):
-
-	Portions Copyright (C) 2000-2007 Greg Roelofs and contributors:
-
-	Andrey A. Chernov [ache]
-	  (http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-ab)
-	Andreas Dilger (adilger clusterfs.com)
-	Alexander Lehmann (lehmann usa.net)
-	Alexey Spiridonov (http://www-math.mit.edu/~lesha/)
-	Anthony Thyssen (http://www.cit.gu.edu.au/~anthony/)
-	Bruno Rohee (http://bruno.rohee.com/)
-	David A. Clunie (http://www.dclunie.com/xv-pcd.html)
-	Erling A. Jacobsen (linuxcub email.dk)
-	Egmont Koblinger (egmont users.sourceforge.net)
-	Fabian Greffrath (fabian debian-unofficial.org)
-	Greg Roelofs (http://pobox.com/~newt/greg_contact.html)
-	Guido Vollbeding (http://sylvana.net/guido/)
-	IKEMOTO Masahiro (ikeyan airlab.cs.ritsumei.ac.jp)
-	John Cooper (john.cooper third-harmonic.com)
-	John C. Elliott (http://www.seasip.demon.co.uk/ZX/zxdload.html)
-	John D. Baker (http://mylinuxisp.com/~jdbaker/)
-	Jörgen Grahn (jgrahn algonet.se)
-	John H. Bradley, of course (http://www.trilon.com/xv/)
-	Jean-Pierre Demailly (http://www-fourier.ujf-grenoble.fr/~demailly/)
-	John Rochester (http://www.freebsd.org/cgi/query-pr.cgi?pr=2920)
-	  (also http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-af, -ag)
-	James Roberts Kirkpatrick (uwyo.edu)
-	Joe Zbiciak (http://spatula-city.org/~im14u2c/)
-	Kyoichiro Suda (http://www.coara.or.jp/~sudakyo/XV_jp.html)
-	Landon Curt "chongo" Noll (http://www.isthe.com/chongo/)
-	Larry Jones (lawrence.jones ugs.com)
-	Peter Jordan (http://www.ibiblio.org/pub/Linux/apps/graphics/viewers/X/)
-	Pawel S. Veselov (http://manticore.2y.net/wbmp.html)
-	Ross Combs (rocombs cs.nmsu.edu)
-	Robin Humble (http://www.cita.utoronto.ca/~rjh/)
-	Sean Borman (http://www.nd.edu/~sborman/software/xvwheelmouse.html)
-	TenThumbs (tenthumbs cybernex.net)
-	Scott B. Marovich (formerly marovich hpl.hp.com)
-	Tim Adye (http://hepwww.rl.ac.uk/Adye/xv-psnewstyle.html)
-	Tim Ramsey (tar pobox.com)
-	Tetsuya INOUE (tin329 chino.it.okayama-u.ac.jp)
-	Tavis Ormandy (taviso gentoo.org)
-	Werner Fink (http://www.suse.de/~werner/)
-
-	Other credits are as listed on the XV Downloads page or in the respective
-	patches (e.g., the jp-extension patches or within the PNG patch).
-
-License (Redistribution):
-
-	From: Daniel Kirchheimer <kirchh at trilon.com>
-	To: fabian at ep1.rub.de
-	Subject: RE: Again: Request for the permission to release xv, PLEASE ANSWER
-	Date: Mon, 5 Dec 2005 18:44:25 -0500
-
-	Greetings. Mr. Bradley has moved to South America and become a warrior-god
-	to some hitherto-unknown Amazon river tribe. However, he advises that he
-	grants you permission to distribute the modified version of XV as long as
-	all license agreements and other terms are distributed with the code as per
-	the terms of the license.
-
-	Actually, he just doesn't like talking to people -- that's what he has me
-	for!
-
-	Best regards --
-	--Daniel
-
-All license agreements and other terms can be found in `/usr/share/doc/xv/README.gz'.
-
-The Debian packaging is (C) 2005-2007, Fabian Greffrath <fabian at debian-unofficial.org> and
-is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

Added: dists/trunk/xv/debian/copyright
===================================================================
--- dists/trunk/xv/debian/copyright	                        (rev 0)
+++ dists/trunk/xv/debian/copyright	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,134 @@
+This package was debianized by Fabian Greffrath <fabian at debian-unofficial.org> on
+Wed,  1 Feb 2006 00:00:00 +0100.
+
+It was downloaded from <http://www.trilon.com/xv/>.
+
+Upstream Author:
+
+	John Bradley <bradley at trilon.com>
+
+License:
+
+	Copyright (C) 1989-1994 John Bradley
+	All rights reserved.
+
+	Permission to copy and distribute XV in its entirety, for non-commercial
+	purposes, is hereby granted without fee, provided that this license
+	information and copyright notice appear unmodified in all copies.
+
+	Note that distributing XV 'bundled' in with any product is considered to
+	be a 'commercial purpose'.
+
+	Also note that any copies of XV that are distributed must be built
+	and/or configured to be in their 'unregistered copy' mode, so that it is
+	made obvious to the user that XV is shareware, and that they should
+	consider donating, or at least reading this License Info.
+
+	The software may be modified for your own purposes, but modified
+	versions may not be distributed without prior consent of the author.
+
+	This software is provided 'as-is', without any express or implied
+	warranty. In no event will the author be held liable for any damages
+	arising from the use of this software.
+
+	If you would like to do something with XV that this copyright prohibits
+	(such as distributing it with a commercial product, using portions of
+	the source in some other program, etc.), please contact the author
+	(preferably via email). Arrangements can probably be worked out.
+
+	XV is shareware for PERSONAL USE only. You may use XV for your own
+	amusement, and if you find it nifty, useful, generally cool, or of some
+	value to you, your non-deductable donation would be greatly appreciated.
+	$25 is the suggested donation, though, of course, larger donations are
+	quite welcome. Folks who donate $25 or more can receive a Real Nice
+	bound copy of the XV manual for no extra charge.
+
+	Commercial, government, and institutional users must register their
+	copies of XV, for the price of $25 per workstation/X terminal or per XV
+	user, whichever is less. Note that it does NOT say 'simultaneous user',
+	but rather, the total number of people who use XV on any sort of
+	recurring basis. Site licenses are available (and recommended) for those
+	who wish to run XV on a large (>10) number of machines. Contact the
+	author for more details.
+
+	The author may be contacted via:
+
+		Email:		bradley at cis.upenn.edu (preferred!)
+
+		FAX:		(610) 520-2042
+
+		US Mail:	John Bradley
+				1053 Floyd Terrace
+
+	The author may not be contacted by (voice) phone. Please don't try.
+
+License (XV Jumbo Patches):
+
+	Portions Copyright (C) 2000-2007 Greg Roelofs and contributors:
+
+	Andrey A. Chernov [ache]
+	  (http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-ab)
+	Andreas Dilger (adilger clusterfs.com)
+	Alexander Lehmann (lehmann usa.net)
+	Alexey Spiridonov (http://www-math.mit.edu/~lesha/)
+	Anthony Thyssen (http://www.cit.gu.edu.au/~anthony/)
+	Bruno Rohee (http://bruno.rohee.com/)
+	David A. Clunie (http://www.dclunie.com/xv-pcd.html)
+	Erling A. Jacobsen (linuxcub email.dk)
+	Egmont Koblinger (egmont users.sourceforge.net)
+	Fabian Greffrath (fabian debian-unofficial.org)
+	Greg Roelofs (http://pobox.com/~newt/greg_contact.html)
+	Guido Vollbeding (http://sylvana.net/guido/)
+	IKEMOTO Masahiro (ikeyan airlab.cs.ritsumei.ac.jp)
+	John Cooper (john.cooper third-harmonic.com)
+	John C. Elliott (http://www.seasip.demon.co.uk/ZX/zxdload.html)
+	John D. Baker (http://mylinuxisp.com/~jdbaker/)
+	Jörgen Grahn (jgrahn algonet.se)
+	John H. Bradley, of course (http://www.trilon.com/xv/)
+	Jean-Pierre Demailly (http://www-fourier.ujf-grenoble.fr/~demailly/)
+	John Rochester (http://www.freebsd.org/cgi/query-pr.cgi?pr=2920)
+	  (also http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-af, -ag)
+	James Roberts Kirkpatrick (uwyo.edu)
+	Joe Zbiciak (http://spatula-city.org/~im14u2c/)
+	Kyoichiro Suda (http://www.coara.or.jp/~sudakyo/XV_jp.html)
+	Landon Curt "chongo" Noll (http://www.isthe.com/chongo/)
+	Larry Jones (lawrence.jones ugs.com)
+	Peter Jordan (http://www.ibiblio.org/pub/Linux/apps/graphics/viewers/X/)
+	Pawel S. Veselov (http://manticore.2y.net/wbmp.html)
+	Ross Combs (rocombs cs.nmsu.edu)
+	Robin Humble (http://www.cita.utoronto.ca/~rjh/)
+	Sean Borman (http://www.nd.edu/~sborman/software/xvwheelmouse.html)
+	TenThumbs (tenthumbs cybernex.net)
+	Scott B. Marovich (formerly marovich hpl.hp.com)
+	Tim Adye (http://hepwww.rl.ac.uk/Adye/xv-psnewstyle.html)
+	Tim Ramsey (tar pobox.com)
+	Tetsuya INOUE (tin329 chino.it.okayama-u.ac.jp)
+	Tavis Ormandy (taviso gentoo.org)
+	Werner Fink (http://www.suse.de/~werner/)
+
+	Other credits are as listed on the XV Downloads page or in the respective
+	patches (e.g., the jp-extension patches or within the PNG patch).
+
+License (Redistribution):
+
+	From: Daniel Kirchheimer <kirchh at trilon.com>
+	To: fabian at ep1.rub.de
+	Subject: RE: Again: Request for the permission to release xv, PLEASE ANSWER
+	Date: Mon, 5 Dec 2005 18:44:25 -0500
+
+	Greetings. Mr. Bradley has moved to South America and become a warrior-god
+	to some hitherto-unknown Amazon river tribe. However, he advises that he
+	grants you permission to distribute the modified version of XV as long as
+	all license agreements and other terms are distributed with the code as per
+	the terms of the license.
+
+	Actually, he just doesn't like talking to people -- that's what he has me
+	for!
+
+	Best regards --
+	--Daniel
+
+All license agreements and other terms can be found in `/usr/share/doc/xv/README.gz'.
+
+The Debian packaging is (C) 2005-2008, Fabian Greffrath <fabian at debian-unofficial.org> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

Added: dists/trunk/xv/debian/lintian/xv
===================================================================
--- dists/trunk/xv/debian/lintian/xv	                        (rev 0)
+++ dists/trunk/xv/debian/lintian/xv	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+xv: unknown-section restricted/graphics

Added: dists/trunk/xv/debian/lintian/xv-dbg
===================================================================
--- dists/trunk/xv/debian/lintian/xv-dbg	                        (rev 0)
+++ dists/trunk/xv/debian/lintian/xv-dbg	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+xv-dbg: unknown-section restricted/devel

Added: dists/trunk/xv/debian/lintian/xv-doc
===================================================================
--- dists/trunk/xv/debian/lintian/xv-doc	                        (rev 0)
+++ dists/trunk/xv/debian/lintian/xv-doc	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+xv-doc: unknown-section restricted/doc

Added: dists/trunk/xv/debian/patches/00list
===================================================================
--- dists/trunk/xv/debian/patches/00list	                        (rev 0)
+++ dists/trunk/xv/debian/patches/00list	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,5 @@
+01-xv-3.10a-jumbo-fix-enh-patch-20070520
+02-xv-3.10a-jumbo-files-20070520
+03-no-docs
+04-shared-libjasper
+05-override-cflags

Added: dists/trunk/xv/debian/patches/01-xv-3.10a-jumbo-fix-enh-patch-20070520.dpatch
===================================================================
--- dists/trunk/xv/debian/patches/01-xv-3.10a-jumbo-fix-enh-patch-20070520.dpatch	                        (rev 0)
+++ dists/trunk/xv/debian/patches/01-xv-3.10a-jumbo-fix-enh-patch-20070520.dpatch	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,42409 @@
+#!/bin/sh /usr/share/dpatch/dpatch-run
+## xv-3.10a-jumbo-fix-enh-patch-20070520.txt by Greg Roelofs <newt at pobox.com>
+## It was downloaded from <http://www.sonic.net/~roelofs/greg_xv.html>.
+##
+## DP: XV Jumbo Patches (fixes and enhancements).
+
+ at DPATCH@
+
+diff :  xv-3.10a-jumbo-fix-enh-patch-20070520.txt
+
+This is a unified diff.  It should be applied (using Larry Wall's "patch"
+program) to the stock XV 3.10a sources.  See the "How to build" section of
+README.jumbo, which, along with roughly 40 other new files and 3 new sub-
+directories, should have been unpacked along with this jumbo patch:
+
+	README.jumbo
+	README.pcd
+	bits/br_bzip2
+	bits/br_jp2
+	bits/br_jpc
+	bits/br_mag
+	bits/br_maki
+	bits/br_mgcsfx
+	bits/br_pcd
+	bits/br_pi
+	bits/br_pic
+	bits/br_pic2
+	bits/br_png
+	bits/br_zx
+	contrib/
+	contrib/fnkey-scripts/
+	contrib/fnkey-scripts/README
+	contrib/fnkey-scripts/jpegcrop.sh
+	contrib/fnkey-scripts/jpegeditcom.sh
+	contrib/fnkey-scripts/jpeglogrot.sh
+	contrib/fnkey-scripts/jpegrot.sh
+	contrib/fnkey-scripts/jpegundocrop.sh
+	contrib/fedora/
+	contrib/fedora/README
+	contrib/fedora/Build-FC5
+	docs/xvdocs.pdf
+	tiff/RANLIB.sh
+	xv_mgcsfx.sample
+	xvhips.c
+	xvhips.h
+	xvjp2k.c
+	xvmag.c
+	xvmaki.c
+	xvmgcsfx.c
+	xvml.c
+	xvml.h
+	xvpcd.c
+	xvpi.c
+	xvpic.c
+	xvpic2.c
+	xvpng.c
+	xvvd.c
+	xvwbmp.c
+	xvzx.c
+
+
+diffs below:
+
+	Imakefile
+	Makefile
+	Makefile.std
+	bggen.c
+	bits/br_targa
+	bits/icon
+	cleandir
+	config.h
+	copyright.h
+	docs/bggen.man
+	docs/xcmap.man
+	docs/xv.man
+	docs/xvp2p.man
+	tiff/Makefile
+	tiff/Makefile.std
+	vdcomp.c
+	xcmap.c
+	xv.c
+	xv.h
+	xv24to8.c
+	xvalg.c
+	xvbmp.c
+	xvbrowse.c
+	xvbutt.c
+	xvcolor.c
+	xvctrl.c
+	xvcut.c
+	xvdflt.c
+	xvdflt.h
+	xvdial.c
+	xvdir.c
+	xvevent.c
+	xvfits.c
+	xvgam.c
+	xvgif.c
+	xvgifwr.c
+	xvgrab.c
+	xvgraf.c
+	xviff.c
+	xvimage.c
+	xvinfo.c
+	xviris.c
+	xvjpeg.c
+	xvmisc.c
+	xvpbm.c
+	xvpcx.c
+	xvpds.c
+	xvpictoppm.c
+	xvpm.c
+	xvpopup.c
+	xvps.c
+	xvrle.c
+	xvroot.c
+	xvscrl.c
+	xvsmooth.c
+	xvsunras.c
+	xvtarga.c
+	xvtext.c
+	xvtiff.c
+	xvtiffwr.c
+	xvxbm.c
+	xvxpm.c
+	xvxwd.c
+
+
+diff -ru xv-3.10a/Imakefile xv-3.10a-enhancements/Imakefile
+--- xv-3.10a/Imakefile	1995-01-13 12:24:01.000000000 -0800
++++ xv-3.10a-enhancements/Imakefile	2005-04-17 14:04:22.000000000 -0700
+@@ -104,6 +104,11 @@
+ SGI = -Dsgi
+ #endif
+ 
++/* install directory of xv_mgcsfx.sample. */
++MGCSFXDIR = $(LIBDIR)
++/* Directory of default configuration file. */
++MGCSFX = -DMGCSFXDIR=\"$(MGCSFXDIR)\"
++
+ 
+ 
+ 
+@@ -137,6 +142,8 @@
+ #if defined(SCOArchitecture)
+ SCO= -Dsco -DPOSIX -DNO_RANDOM 
+ SYS_LIBRARIES=        -lm -lc -lx 
++#elif defined(HPArchitecture)
++SYS_LIBRARIES=        -lm -lV3
+ #else
+ SYS_LIBRARIES=        -lm
+ #endif
+@@ -147,7 +154,7 @@
+ 
+ DEFINES= $(SCO) $(UNIX) $(NODIRENT) $(VPRINTF) $(TIMERS) \
+ 	$(HPUX7) $(JPEG) $(TIFF) $(PDS) $(DXWM) $(RAND) \
+-	$(BACKING_STORE) $(BSDTYPES) $(SGI)
++	$(BACKING_STORE) $(BSDTYPES) $(SGI) $(MGCSFX)
+ 
+ INCLUDES = $(JPEGINCLUDE) $(TIFFINCLUDE)
+ 
+@@ -157,7 +164,9 @@
+ 	xvdial.c xvgraf.c xvsunras.c xvjpeg.c xvps.c xvpopup.c xvdflt.c \
+ 	xvtiff.c xvtiffwr.c xvpds.c xvrle.c xviris.c xvgrab.c vprintf.c \
+ 	xvbrowse.c xvtext.c xvpcx.c xviff.c xvtarga.c xvxpm.c xvcut.c \
+-	xvxwd.c xvfits.c
++	xvxwd.c xvfits.c xvpng.c xvzx.c xvwbmp.c xvpcd.c \
++	xvmag.c xvpic.c xvmaki.c xvpi.c xvpic2.c xvvd.c xvmgcsfx.c \
++	xvml.c
+ 
+ OBJS1 =	xv.o xvevent.o xvroot.o xvmisc.o xvimage.o xvcolor.o xvsmooth.o \
+ 	xv24to8.o xvgif.o xvpm.o xvinfo.o xvctrl.o xvscrl.o xvalg.o \
+@@ -165,7 +174,9 @@
+ 	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
+ 	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
+ 	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
+-	xvxwd.o xvfits.o
++	xvxwd.o xvfits.o xvpng.o xvzx.o xvwbmp.o xvpcd.o \
++	xvmag.o xvpic.o xvmaki.o xvpi.o xvpic2.o xvvd.o xvmgcsfx.o \
++	xvml.o
+ 
+ SRCS2=	bggen.c
+ OBJS2=	bggen.o
+@@ -266,6 +277,8 @@
+ InstallManPageLong(docs/xvp2p,$(MANDIR),xvpictoppm)
+ InstallManPageLong(docs/vdcomp,$(MANDIR),vdcomp)
+ 
++InstallNonExecFile(xv_mgcsfx.sample,$(MGCSFXDIR))
++
+ tar:
+ 	tar cf xv.tar Makefile* Imakefile *.c *.h bits docs \
+ 		 docs unsupt vms $(JPEGDIR) $(TIFFDIR) $(MISC)
+diff -ru xv-3.10a/Makefile xv-3.10a-enhancements/Makefile
+--- xv-3.10a/Makefile	1995-01-23 12:20:54.000000000 -0800
++++ xv-3.10a-enhancements/Makefile	2007-05-20 21:17:35.000000000 -0700
+@@ -2,7 +2,11 @@
+ 
+ # your C compiler (and options) of choice
+ CC = cc
+-# CC = gcc -ansi
++#CC = gcc -ansi
++# note that -ansi kills __USE_MISC (gcc 2.95.3), which, at least on Linux,
++# determines whether stdlib.h includes prototypes for mktemp(), random(), etc.
++# (i.e., if you use it, you will get unnecessary compiler warnings)
++#CC = gcc
+ 
+ # use this if you're using 'cc' on a DEC Alpha (OSF/1) or MIPS (Ultrix) system:
+ # CC = cc -std1 -Olimit 750
+@@ -14,8 +18,20 @@
+ #       -Wuninitialized -Wparentheses
+ 
+ 
+-CCOPTS = -O 
+-
++CCOPTS = -O
++#
++# these are the usual optimization and warning options for gcc; all such
++# warnings but one (mktemp() use) have been eliminated (at least on Linux):
++#CCOPTS = -O3 -Wall
++#
++# slightly more warnings... older code often made non-const pointers to
++# static strings (nothing should blow up unless something tries to write
++# to them):
++#CCOPTS = -O3 -Wall -Wpointer-arith -Wcast-align -Wwrite-strings -Wnested-externs
++#
++# for the next step up in gcc noise, try adding -W (but note that it adds a
++# huge number of unused-parameter and signed/unsigned comparison warnings):
++#CCOPTS = -O3 -Wall -W
+ 
+ ### NOTE: Sun running OpenWindows:
+ ### if you're using a SUN running OPENWINDOWS, you need to add these two
+@@ -27,50 +43,155 @@
+ ### '-I' options on the CCOPTS line to tell the compiler where said files are.
+ 
+ 
++# older Unixen don't support the -p option, but its lack may mean installation
++# will fail (if more than one directory level is missing)
++MKDIR = mkdir -p
++
++
++# BeOS _may_ need to use a different version (below), but probably not
++CLEANDIR = cleandir
++
++
+ ### Installation locations
+-BINDIR = /usr/local/bin
+-MANDIR = /usr/local/man/man1
++### NOTE: Users of old K&R compilers (i.e., any version not supporting C89
++### string concatenation, such as "fub" "ar" => "fubar") should update
++### xvtext.c:1831 (or thereabouts) if either PREFIX or DOCDIR changes:
++PREFIX = /usr/local
++BINDIR = $(PREFIX)/bin
++MANDIR = $(PREFIX)/share/man/man1
+ MANSUF = 1
+-LIBDIR = /usr/local/lib
++DOCDIR = $(PREFIX)/share/doc/xv
++LIBDIR = $(PREFIX)/lib/xv
++SYSCONFDIR = /etc
++DESTDIR =
+ 
+ 
+ buildit: all
+ 
+ 
+ ########################### CONFIGURATION OPTIONS ############################
+-### NOTE: be sure to check 'config.h', for a few other configuration options 
++### NOTE: be sure to check 'config.h', for a few other configuration options
+ ##############################################################################
+ 
+ ###
++### if, for whatever reason, you're unable to get the TIFF library to compile
++### on your machine, *COMMENT OUT* the following lines
++###
++### GRR 20050319:  USE_TILED_TIFF_BOTLEFT_FIX enables an experimental fix for
++###   tiled TIFFs with ORIENTATION_BOTLEFT.  It may break other tiled TIFFs,
++###   or it may be required for certain other TIFF types (e.g., strips with
++###   ORIENTATION_BOTLEFT).  I don't have a sufficient variety of TIFF test
++###   images at hand.
++###
++#TIFF    = -DDOTIFF
++TIFF    = -DDOTIFF -DUSE_TILED_TIFF_BOTLEFT_FIX
++###
++#TIFFDIR = tiff
++TIFFDIR = /usr
++#TIFFDIR = /usr/local
++#TIFFDIR = ../../libtiff
++###
++TIFFINC = -I$(TIFFDIR)/include
++#TIFFINC = -I$(TIFFDIR)
++###
++### libtiff 3.5 and up may be compiled with zlib and libjpeg, but the
++### dependency is properly handled in LIBS line ~247 lines below
++###
++TIFFLIB = -L$(TIFFDIR)/lib -ltiff
++#TIFFLIB = $(TIFFDIR)/lib/libtiff.a
++#TIFFLIB = -L$(TIFFDIR) -ltiff
++#TIFFLIB = $(TIFFDIR)/libtiff.a
++###
++### this is intended to build the ancient version (3.3.016 beta) that's
++### included in the "tiff" subdir of XV, not an arbitrary copy of libtiff:
++###
++#$(TIFFLIB):
++#	( cd $(TIFFDIR) ; make CC='$(CC)' COPTS='$(CCOPTS) $(MCHN)' )
++
++
++###
+ ### if, for whatever reason, you're unable to get the JPEG library to compile
+ ### on your machine, *COMMENT OUT* the following lines
+ ###
++### NOTE: /usr/sfw can be used on Solaris with "Sun freeware" installed
++###
+ JPEG    = -DDOJPEG
+-JPEGDIR = jpeg
+-JPEGINC = -I$(JPEGDIR)
+-JPEGLIB = $(JPEGDIR)/libjpeg.a
+-$(JPEGDIR)/jconfig.h:
+-	cd $(JPEGDIR) ; ./configure CC='$(CC)'
+-$(JPEGLIB):  $(JPEGDIR)/jconfig.h
+-	cd $(JPEGDIR) ; make
++#JPEGDIR = jpeg
++JPEGDIR = /usr
++#JPEGDIR = /usr/local
++#JPEGDIR = ../../libjpeg
++#JPEGDIR = /usr/sfw
++###
++JPEGINC = -I$(JPEGDIR)/include
++#JPEGINC = -I$(JPEGDIR)
++###
++JPEGLIB = -L$(JPEGDIR)/lib -ljpeg
++#JPEGLIB = -L$(JPEGDIR) -ljpeg
++#JPEGLIB = $(JPEGDIR)/libjpeg.a
++###
++### this is intended to build the ancient version (5a) that's included in the
++### "jpeg" subdir of XV, not an arbitrary copy of libjpeg:
++###
++#$(JPEGDIR)/jconfig.h:
++#	cd $(JPEGDIR) ; ./configure CC='$(CC)'
++#$(JPEGLIB):  $(JPEGDIR)/jconfig.h
++#	cd $(JPEGDIR) ; make
+ 
+ 
+ ###
+-### if, for whatever reason, you're unable to get the TIFF library to compile
++### if, for whatever reason, you're unable to get the PNG library to compile
+ ### on your machine, *COMMENT OUT* the following lines
+ ###
+-TIFF    = -DDOTIFF
+-TIFFDIR = tiff
+-TIFFINC = -I$(TIFFDIR)
+-TIFFLIB = $(TIFFDIR)/libtiff.a
+-$(TIFFLIB):
+-	( cd $(TIFFDIR) ; make CC='$(CC)' )
++PNG    = -DDOPNG
++PNGDIR = /usr
++#PNGDIR = /usr/local
++#PNGDIR = ../../libpng
++###
++PNGINC = -I$(PNGDIR)/include
++#PNGINC = -I$(PNGDIR)
++###
++PNGLIB = -L$(PNGDIR)/lib -lpng
++#PNGLIB = -L$(PNGDIR) -lpng
++#PNGLIB = $(PNGDIR)/libpng.a
++
++
++###
++### if, for whatever reason, you're unable to get both the PNG library and
++### (newer versions of) the TIFF library to compile on your machine, *COMMENT
++### OUT* the following lines
++###
++ZLIBDIR = /usr
++#ZLIBDIR = /usr/local
++#ZLIBDIR = ../../zlib
++###
++ZLIBINC = -I$(ZLIBDIR)/include
++#ZLIBINC = -I$(ZLIBDIR)
++###
++ZLIBLIB = -L$(ZLIBDIR)/lib -lz
++#ZLIBLIB = -L$(ZLIBDIR) -lz
++#ZLIBLIB = $(ZLIBDIR)/libz.a
++
++
++###
++### if, for whatever reason, you're unable to get the JasPer JPEG-2000 library
++### to compile on your machine, *COMMENT OUT* the following lines
++###
++JP2K    = -DDOJP2K
++###
++#JP2KDIR = ../../jasper
++JP2KDIR = /usr/local/lib
++###
++#JP2KINC = -I$(JP2KDIR)
++JP2KINC = -I/usr/local/include
++###
++#JP2KLIB = -L$(JP2KDIR) -ljasper
++JP2KLIB = $(JP2KDIR)/libjasper.a
+ 
+ 
+ ###
+ ### if, for whatever reason, you're unable to get the PDS/VICAR support
+ ### to compile (xvpds.c, and vdcomp.c), *COMMENT OUT* the following line,
+-### and also remove 'vdcomp' from the 'all:' dependancy 
++### and also remove 'vdcomp' from the 'all:' dependency
+ ###
+ PDS = -DDOPDS
+ 
+@@ -78,46 +199,60 @@
+ #----------System V----------
+ 
+ # if you are running on a SysV-based machine, such as HP, Silicon Graphics,
+-# Solaris, etc., uncomment the following line to get mostly there.  
+-#UNIX = -DSVR4
++# Solaris, etc.; uncomment one of the following lines to get you *most* of
++# the way there.  SYSV means System V R3.
++# UNIX = -DSVR4
++# UNIX = -DSYSV
++
+ 
++#----------Machine-Specific Configurations----------
++
++### If you are using a BeOS system, uncomment the following line
++#MCHN = -DUSE_GETCWD -I/usr/X11/include -L/usr/X11/lib
++###
++### The stock version of cleandir now should work for BeOS, too, so try
++### leaving this commented out:
++#CLEANDIR = cleandir.BeOS
+ 
+-#----------Machine Specific Configurations----------
+ 
+ ### If you are using an SGI system, uncomment the following line
+ #MCHN = -Dsgi
+ 
+ 
+-### For HP-UX, uncomment the following line:
++### For HP-UX, uncomment the following line
+ #MCHN= -Dhpux -D_HPUX_SOURCE
+ # To use old HP compilers (HPUX 7.0 or so), you may need
+ #MCHN= -Dhpux -D_HPUX_SOURCE +Ns4000
+ #
+-# also, if you're using HP's compiler, add '-Aa' to whichever of those
++# Also, if you're using HP's compiler, add '-Aa' to whichever of those
+ # two lines you're using, to turn on ANSI C mode.  Or so I'm told.
+ #
+-# note:  You may need to add '-I/usr/include/X11R5' (or R6, or whatever)
++# Note:  You may need to add '-I/usr/include/X11R5' (or R6, or whatever)
+ # to whichever of those lines you used, as HP tends to store their X11
+ # include files in a non-standard place...
++#
++# And you probably have to add '-lV3' to the end of the LIBS def when
++# using XV's AUTO_EXPAND option.
+ 
+ 
+-### for LINUX, uncomment the following line
+-#MCHN = -DLINUX
++### for Linux, uncomment one of the following lines:
++#MCHN = -DLINUX -L/usr/X11R6/lib
++#MCHN = -DLINUX -L/usr/X11R6/lib64
+ 
+ 
+ # For SCO 1.1 (UNIX 3.2v2) machines, uncomment the following:
+ #MCHN = -Dsco -DPOSIX
+ #
+ # For ODT 2.0 (UNIX 3.2v4) machines, uncomment the following:
+-#MCHN= -Dsco -DPOSIX -DNO_RANDOM 
++#MCHN= -Dsco -DPOSIX -DNO_RANDOM
+ #
+ # Also, you should add '-lc -lx' to the end of the LIBS def below
+ # -lx must be after -lc so you get the right directory routines.
+ 
+ 
+ # for UMAX V by Encore Computers uncomment the following line for
+-# the portable c compiler, system specific definitions and
+-# location of local X11 library(if site specific, modify -L option)
++# the portable C compiler, system-specific definitions and
++# location of local X11 library (if site-specific, modify -L option)
+ # No other switches should be necessary, or so I'm told...
+ #
+ #MCHN = -q extensions=pcc_c -D__UMAXV__ -L/usr2/usr/lib/X11 -DSVR4
+@@ -147,8 +282,8 @@
+ #TIMERS = -DUSLEEP
+ 
+ 
+-# if XV locks up whenever you click on *any* of the buttons, the Timer() 
+-# function in xvmisc.c is going out to lunch.  A simple workaround is to 
++# if XV locks up whenever you click on *any* of the buttons, the Timer()
++# function in xvmisc.c is going out to lunch.  A simple workaround is to
+ # uncomment the following line:
+ #TIMERS = -DNOTIMER
+ 
+@@ -160,7 +295,7 @@
+ #DXWM = -DDXWM
+ 
+ 
+-# if, during compilation, your system complains about the types 
++# if, during compilation, your system complains about the types
+ # 'u_long', 'u_short', 'u_int', etc. as being undefined, uncomment the
+ # following line:
+ #BSDTYPES = -DBSDTYPES
+@@ -177,18 +312,38 @@
+ #VPRINTF = -DNEED_VPRINTF -DLONGINT -DNOSTDHDRS
+ 
+ 
++# if your machine puts the prototype for 'malloc()' in malloc.h rather than
++# stdlib.h, uncomment the following line:
++#
++#MALLOC = -DNEED_MALLOC_H
+ 
+ 
+-################ END OF CONFIGURATION OPTIONS #################
++# if your X Window System compiled with -DX_LOCALE, 
++# uncomment the following line:
++# TVL10N = -DX_LOCALE
++
++# Install directory of xv_mgcsfx.sample.
++MGCSFXDIR = $(LIBDIR)
++# Directory of default configuration file.
++MGCSFX = -DMGCSFXDIR=\"$(MGCSFXDIR)\"
++
+ 
+ 
+ 
++################ END OF CONFIGURATION OPTIONS #################
++
+ 
+-CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \
+-	$(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \
+-	$(DXWM) $(MCHN)
+ 
+-LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) -lm
++
++CFLAGS = $(CCOPTS) $(PNG) $(PNGINC) $(ZLIBINC) $(JPEG) $(JPEGINC) \
++	$(TIFF) $(TIFFINC) $(PDS) $(JP2K) $(JP2KINC) $(TVL10N) $(MGCSFX) \
++	$(UNIX) $(BSDTYPES) $(RAND) $(MALLOC) $(DXWM) $(MCHN) $(NODIRENT) \
++	$(VPRINTF) $(TIMERS) -DDOCDIR=\"$(DOCDIR)\" \
++	-DSYSCONFDIR=\"$(SYSCONFDIR)\" -DXVEXECPATH=\"$(LIBDIR)\"
++
++### remove -lm for BeOS:
++LIBS = $(TIFFLIB) $(JPEGLIB) $(PNGLIB) $(ZLIBLIB) $(JP2KLIB) -L/usr/X11R6/lib -lX11 -lm
++#LIBS = $(TIFFLIB) $(JPEGLIB) $(PNGLIB) $(ZLIBLIB) $(JP2KLIB) -lX11
+ 
+ OBJS = 	xv.o xvevent.o xvroot.o xvmisc.o xvimage.o xvcolor.o xvsmooth.o \
+ 	xv24to8.o xvgif.o xvpm.o xvinfo.o xvctrl.o xvscrl.o xvalg.o \
+@@ -196,7 +351,9 @@
+ 	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
+ 	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
+ 	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
+-	xvxwd.o xvfits.o
++	xvxwd.o xvfits.o xvpng.o xvzx.o xvwbmp.o xvpcd.o xvhips.o \
++	xvmag.o xvpic.o xvmaki.o xvpi.o xvpic2.o xvvd.o xvmgcsfx.o \
++	xvml.o xvjp2k.o
+ 
+ MISC = README INSTALL CHANGELOG IDEAS
+ 
+@@ -206,10 +363,12 @@
+ 
+ 
+ 
+-all: $(JPEGLIB) $(TIFFLIB) xv bggen vdcomp xcmap xvpictoppm
++#all: $(JPEGLIB) $(TIFFLIB) xv bggen vdcomp xcmap xvpictoppm
++all: xv bggen vdcomp xcmap xvpictoppm
+ 
+ 
+-xv: $(OBJS) $(JPEGLIB) $(TIFFLIB)
++#xv: $(OBJS) $(JPEGLIB) $(TIFFLIB)
++xv: $(OBJS)
+ 	$(CC) -o xv $(CFLAGS) $(OBJS) $(LIBS)
+ 
+ bggen: bggen.c
+@@ -231,23 +390,47 @@
+ 
+ clean:  xvclean
+ 	rm -f bggen vdcomp xcmap xvpictoppm
+-	./cleandir $(JPEGDIR)
+-	rm -f $(JPEGDIR)/jconfig.h $(JPEGDIR)/Makefile
+-	./cleandir $(TIFFDIR)
++#	clean only local jpeg and tiff dirs, not user's or system's copies:
++	./$(CLEANDIR) jpeg
++	rm -f jpeg/jconfig.h jpeg/Makefile
++	./$(CLEANDIR) tiff
+ 
+ 
++# could also do some shell trickery here to attempt mkdir only if dir is
++# missing (e.g., "test -d <dir> || $(MKDIR) <dir>")
+ install: all
+-	cp xv bggen vdcomp xcmap xvpictoppm $(BINDIR)
+-	cp docs/xv.man     $(MANDIR)/xv.$(MANSUF)
+-	cp docs/bggen.man  $(MANDIR)/bggen.$(MANSUF)
+-	cp docs/xcmap.man  $(MANDIR)/xcmap.$(MANSUF)
+-	cp docs/xvp2p.man  $(MANDIR)/xvpictoppm.$(MANSUF)
+-	cp docs/vdcomp.man $(MANDIR)/vdcomp.$(MANSUF)
+-	cp docs/xvdocs.ps* $(LIBDIR)
++	$(MKDIR) $(DESTDIR)$(BINDIR)
++	cp xv bggen vdcomp xcmap xvpictoppm $(DESTDIR)$(BINDIR)/.
++	chmod 755 $(DESTDIR)$(BINDIR)/xv $(DESTDIR)$(BINDIR)/bggen \
++	  $(DESTDIR)$(BINDIR)/vdcomp $(DESTDIR)$(BINDIR)/xcmap \
++	  $(DESTDIR)$(BINDIR)/xvpictoppm
++#
++	$(MKDIR) $(DESTDIR)$(MANDIR)
++	cp docs/xv.man     $(DESTDIR)$(MANDIR)/xv.$(MANSUF)
++	cp docs/bggen.man  $(DESTDIR)$(MANDIR)/bggen.$(MANSUF)
++	cp docs/xcmap.man  $(DESTDIR)$(MANDIR)/xcmap.$(MANSUF)
++	cp docs/xvp2p.man  $(DESTDIR)$(MANDIR)/xvpictoppm.$(MANSUF)
++	cp docs/vdcomp.man $(DESTDIR)$(MANDIR)/vdcomp.$(MANSUF)
++	chmod 644 $(DESTDIR)$(MANDIR)/xv.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/bggen.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/xcmap.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/xvpictoppm.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/vdcomp.$(MANSUF)
++#
++	$(MKDIR) $(DESTDIR)$(DOCDIR)		# or $(DESTDIR)$(LIBDIR)
++	cp README.jumbo docs/xvdocs.pdf docs/xvdocs.ps $(DESTDIR)$(DOCDIR)/.
++	chmod 644 $(DESTDIR)$(DOCDIR)/README.jumbo \
++	  $(DESTDIR)$(DOCDIR)/xvdocs.pdf $(DESTDIR)$(DOCDIR)/xvdocs.ps
++#
++	#$(MKDIR) $(DESTDIR)$(SYSCONFDIR)
++	#cp xv_mgcsfx.sample $(DESTDIR)$(SYSCONFDIR)/xv_mgcsfx
++	#chmod 644 $(DESTDIR)$(SYSCONFDIR)/xv_mgcsfx
++
+ 
+ tar:
++#	tar only local jpeg and tiff dirs, not user's or system's copies:
+ 	tar cvf xv.tar Makefile* Imakefile *.c *.h bits \
+-		docs unsupt vms $(JPEGDIR) $(TIFFDIR) $(MISC) 
++		docs unsupt vms jpeg tiff $(MISC)
+ 
+ xvtar:
+ 	tar cvf xv.tar Makefile* Imakefile *.c *.h bits
+@@ -257,26 +440,28 @@
+ 
+ ################# bitmap dependencies ####################
+ 
+-xv.o:      	bits/icon bits/iconmask bits/runicon bits/runiconm
+-xv.o:      	bits/cboard50 bits/gray25 
++xv.o:		bits/icon bits/iconmask bits/runicon bits/runiconm
++xv.o:		bits/cboard50 bits/gray25
+ 
+ xvbrowse.o:	bits/br_file bits/br_dir bits/br_exe bits/br_chr bits/br_blk
+-xvbrowse.o:	bits/br_sock bits/br_fifo bits/br_error bits/br_unknown
+-xvbrowse.o:	bits/br_cmpres bits/br_gif bits/br_pm bits/br_pbm
++xvbrowse.o:	bits/br_sock bits/br_fifo bits/br_error # bits/br_unknown
++xvbrowse.o:	bits/br_cmpres bits/br_bzip2 bits/br_gif bits/br_pm bits/br_pbm
+ xvbrowse.o:	bits/br_sunras bits/br_bmp bits/br_utah bits/br_iris
+-xvbrowse.o:	bits/br_pcx bits/br_jfif bits/br_tiff bits/br_pds 
+-xvbrowse.o:	bits/br_ps bits/br_iff bits/br_targa bits/br_xpm
++xvbrowse.o:	bits/br_pcx bits/br_jfif bits/br_tiff bits/br_pds bits/br_pcd
++xvbrowse.o:	bits/br_ps bits/br_iff bits/br_targa bits/br_xpm bits/br_xwd
++xvbrowse.o:	bits/br_fits bits/br_png bits/br_zx bits/br_mag bits/br_maki
++xvbrowse.o:	bits/br_pic bits/br_pi bits/br_pic2 bits/br_mgcsfx
++xvbrowse.o:	bits/br_jp2 bits/br_jpc
+ xvbrowse.o:	bits/br_trash bits/fcurs bits/fccurs bits/fdcurs bits/fcursm
+-xvbrowse.o:     bits/br_xwd
+ 
+ xvbutt.o:	bits/cboard50 bits/rb_frame bits/rb_frame1 bits/rb_top
+ xvbutt.o:	bits/rb_bot bits/rb_dtop bits/rb_dbot bits/rb_body
+ xvbutt.o:	bits/rb_dot bits/cb_check bits/mb_chk
+ 
+ xvctrl.o:	bits/gray25 bits/gray50 bits/i_fifo bits/i_chr bits/i_dir
+-xvctrl.o: 	bits/i_blk bits/i_lnk bits/i_sock bits/i_exe bits/i_reg
++xvctrl.o:	bits/i_blk bits/i_lnk bits/i_sock bits/i_exe bits/i_reg
+ xvctrl.o:	bits/h_rotl bits/h_rotr bits/fliph bits/flipv bits/p10
+-xvctrl.o:	bits/m10 bits/cut bits/copy bits/paste bits/clear 
++xvctrl.o:	bits/m10 bits/cut bits/copy bits/paste bits/clear
+ xvctrl.o:	bits/uicon bits/oicon1 bits/oicon2 bits/icon
+ xvctrl.o:	bits/padimg bits/annot
+ 
+@@ -285,13 +470,13 @@
+ xvdflt.o:	bits/logo_top bits/logo_bot bits/logo_out bits/xv_jhb
+ xvdflt.o:	bits/xv_cpyrt bits/xv_rev bits/xv_ver
+ xvdflt.o:	bits/xf_left bits/xf_right bits/font5x9.h
+-xvdflt.o:       xvdflt.h
++xvdflt.o:	xvdflt.h
+ 
+ xvdial.o:	bits/dial_cw1 bits/dial_ccw1 bits/dial_cw2 bits/dial_ccw2
+ 
+ xvdir.o:	bits/d_load bits/d_save
+ 
+-xvevent.o:	bits/dropper bits/dropperm bits/pen bits/penm 
++xvevent.o:	bits/dropper bits/dropperm bits/pen bits/penm
+ xvevent.o:	bits/blur bits/blurm
+ 
+ xvgam.o:	bits/h_rotl bits/h_rotr bits/h_flip bits/h_sinc bits/h_sdec
+diff -ru xv-3.10a/Makefile.std xv-3.10a-enhancements/Makefile.std
+--- xv-3.10a/Makefile.std	1995-01-23 17:06:26.000000000 -0800
++++ xv-3.10a-enhancements/Makefile.std	2007-05-20 21:17:35.000000000 -0700
+@@ -2,7 +2,11 @@
+ 
+ # your C compiler (and options) of choice
+ CC = cc
+-# CC = gcc -ansi
++#CC = gcc -ansi
++# note that -ansi kills __USE_MISC (gcc 2.95.3), which, at least on Linux,
++# determines whether stdlib.h includes prototypes for mktemp(), random(), etc.
++# (i.e., if you use it, you will get unnecessary compiler warnings)
++#CC = gcc
+ 
+ # use this if you're using 'cc' on a DEC Alpha (OSF/1) or MIPS (Ultrix) system:
+ # CC = cc -std1 -Olimit 750
+@@ -14,8 +18,20 @@
+ #       -Wuninitialized -Wparentheses
+ 
+ 
+-CCOPTS = -O 
+-
++CCOPTS = -O
++#
++# these are the usual optimization and warning options for gcc; all such
++# warnings but one (mktemp() use) have been eliminated (at least on Linux):
++#CCOPTS = -O3 -Wall
++#
++# slightly more warnings... older code often made non-const pointers to
++# static strings (nothing should blow up unless something tries to write
++# to them):
++#CCOPTS = -O3 -Wall -Wpointer-arith -Wcast-align -Wwrite-strings -Wnested-externs
++#
++# for the next step up in gcc noise, try adding -W (but note that it adds a
++# huge number of unused-parameter and signed/unsigned comparison warnings):
++#CCOPTS = -O3 -Wall -W
+ 
+ ### NOTE: Sun running OpenWindows:
+ ### if you're using a SUN running OPENWINDOWS, you need to add these two
+@@ -27,50 +43,155 @@
+ ### '-I' options on the CCOPTS line to tell the compiler where said files are.
+ 
+ 
++# older Unixen don't support the -p option, but its lack may mean installation
++# will fail (if more than one directory level is missing)
++MKDIR = mkdir -p
++
++
++# BeOS _may_ need to use a different version (below), but probably not
++CLEANDIR = cleandir
++
++
+ ### Installation locations
+-BINDIR = /usr/local/bin
+-MANDIR = /usr/local/man/man1
++### NOTE: Users of old K&R compilers (i.e., any version not supporting C89
++### string concatenation, such as "fub" "ar" => "fubar") should update
++### xvtext.c:1831 (or thereabouts) if either PREFIX or DOCDIR changes:
++PREFIX = /usr/local
++BINDIR = $(PREFIX)/bin
++MANDIR = $(PREFIX)/share/man/man1
+ MANSUF = 1
+-LIBDIR = /usr/local/lib
++DOCDIR = $(PREFIX)/share/doc/xv
++LIBDIR = $(PREFIX)/lib/xv
++SYSCONFDIR = /etc
++DESTDIR =
+ 
+ 
+ buildit: all
+ 
+ 
+ ########################### CONFIGURATION OPTIONS ############################
+-### NOTE: be sure to check 'config.h', for a few other configuration options 
++### NOTE: be sure to check 'config.h', for a few other configuration options
+ ##############################################################################
+ 
+ ###
++### if, for whatever reason, you're unable to get the TIFF library to compile
++### on your machine, *COMMENT OUT* the following lines
++###
++### GRR 20050319:  USE_TILED_TIFF_BOTLEFT_FIX enables an experimental fix for
++###   tiled TIFFs with ORIENTATION_BOTLEFT.  It may break other tiled TIFFs,
++###   or it may be required for certain other TIFF types (e.g., strips with
++###   ORIENTATION_BOTLEFT).  I don't have a sufficient variety of TIFF test
++###   images at hand.
++###
++#TIFF    = -DDOTIFF
++TIFF    = -DDOTIFF -DUSE_TILED_TIFF_BOTLEFT_FIX
++###
++#TIFFDIR = tiff
++TIFFDIR = /usr
++#TIFFDIR = /usr/local
++#TIFFDIR = ../../libtiff
++###
++TIFFINC = -I$(TIFFDIR)/include
++#TIFFINC = -I$(TIFFDIR)
++###
++### libtiff 3.5 and up may be compiled with zlib and libjpeg, but the
++### dependency is properly handled in LIBS line ~247 lines below
++###
++TIFFLIB = -L$(TIFFDIR)/lib -ltiff
++#TIFFLIB = $(TIFFDIR)/lib/libtiff.a
++#TIFFLIB = -L$(TIFFDIR) -ltiff
++#TIFFLIB = $(TIFFDIR)/libtiff.a
++###
++### this is intended to build the ancient version (3.3.016 beta) that's
++### included in the "tiff" subdir of XV, not an arbitrary copy of libtiff:
++###
++#$(TIFFLIB):
++#	( cd $(TIFFDIR) ; make CC='$(CC)' COPTS='$(CCOPTS) $(MCHN)' )
++
++
++###
+ ### if, for whatever reason, you're unable to get the JPEG library to compile
+ ### on your machine, *COMMENT OUT* the following lines
+ ###
++### NOTE: /usr/sfw can be used on Solaris with "Sun freeware" installed
++###
+ JPEG    = -DDOJPEG
+-JPEGDIR = jpeg
+-JPEGINC = -I$(JPEGDIR)
+-JPEGLIB = $(JPEGDIR)/libjpeg.a
+-$(JPEGDIR)/jconfig.h:
+-	cd $(JPEGDIR) ; ./configure CC='$(CC)'
+-$(JPEGLIB):  $(JPEGDIR)/jconfig.h
+-	cd $(JPEGDIR) ; make
++#JPEGDIR = jpeg
++JPEGDIR = /usr
++#JPEGDIR = /usr/local
++#JPEGDIR = ../../libjpeg
++#JPEGDIR = /usr/sfw
++###
++JPEGINC = -I$(JPEGDIR)/include
++#JPEGINC = -I$(JPEGDIR)
++###
++JPEGLIB = -L$(JPEGDIR)/lib -ljpeg
++#JPEGLIB = -L$(JPEGDIR) -ljpeg
++#JPEGLIB = $(JPEGDIR)/libjpeg.a
++###
++### this is intended to build the ancient version (5a) that's included in the
++### "jpeg" subdir of XV, not an arbitrary copy of libjpeg:
++###
++#$(JPEGDIR)/jconfig.h:
++#	cd $(JPEGDIR) ; ./configure CC='$(CC)'
++#$(JPEGLIB):  $(JPEGDIR)/jconfig.h
++#	cd $(JPEGDIR) ; make
+ 
+ 
+ ###
+-### if, for whatever reason, you're unable to get the TIFF library to compile
++### if, for whatever reason, you're unable to get the PNG library to compile
+ ### on your machine, *COMMENT OUT* the following lines
+ ###
+-TIFF    = -DDOTIFF
+-TIFFDIR = tiff
+-TIFFINC = -I$(TIFFDIR)
+-TIFFLIB = $(TIFFDIR)/libtiff.a
+-$(TIFFLIB):
+-	( cd $(TIFFDIR) ; make CC='$(CC)' )
++PNG    = -DDOPNG
++PNGDIR = /usr
++#PNGDIR = /usr/local
++#PNGDIR = ../../libpng
++###
++PNGINC = -I$(PNGDIR)/include
++#PNGINC = -I$(PNGDIR)
++###
++PNGLIB = -L$(PNGDIR)/lib -lpng
++#PNGLIB = -L$(PNGDIR) -lpng
++#PNGLIB = $(PNGDIR)/libpng.a
++
++
++###
++### if, for whatever reason, you're unable to get both the PNG library and
++### (newer versions of) the TIFF library to compile on your machine, *COMMENT
++### OUT* the following lines
++###
++ZLIBDIR = /usr
++#ZLIBDIR = /usr/local
++#ZLIBDIR = ../../zlib
++###
++ZLIBINC = -I$(ZLIBDIR)/include
++#ZLIBINC = -I$(ZLIBDIR)
++###
++ZLIBLIB = -L$(ZLIBDIR)/lib -lz
++#ZLIBLIB = -L$(ZLIBDIR) -lz
++#ZLIBLIB = $(ZLIBDIR)/libz.a
++
++
++###
++### if, for whatever reason, you're unable to get the JasPer JPEG-2000 library
++### to compile on your machine, *COMMENT OUT* the following lines
++###
++JP2K    = -DDOJP2K
++###
++#JP2KDIR = ../../jasper
++JP2KDIR = /usr/local/lib
++###
++#JP2KINC = -I$(JP2KDIR)
++JP2KINC = -I/usr/local/include
++###
++#JP2KLIB = -L$(JP2KDIR) -ljasper
++JP2KLIB = $(JP2KDIR)/libjasper.a
+ 
+ 
+ ###
+ ### if, for whatever reason, you're unable to get the PDS/VICAR support
+ ### to compile (xvpds.c, and vdcomp.c), *COMMENT OUT* the following line,
+-### and also remove 'vdcomp' from the 'all:' dependancy 
++### and also remove 'vdcomp' from the 'all:' dependency
+ ###
+ PDS = -DDOPDS
+ 
+@@ -78,46 +199,60 @@
+ #----------System V----------
+ 
+ # if you are running on a SysV-based machine, such as HP, Silicon Graphics,
+-# Solaris, etc., uncomment the following line to get mostly there.  
+-#UNIX = -DSVR4
++# Solaris, etc.; uncomment one of the following lines to get you *most* of
++# the way there.  SYSV means System V R3.
++# UNIX = -DSVR4
++# UNIX = -DSYSV
++
+ 
++#----------Machine-Specific Configurations----------
++
++### If you are using a BeOS system, uncomment the following line
++#MCHN = -DUSE_GETCWD -I/usr/X11/include -L/usr/X11/lib
++###
++### The stock version of cleandir now should work for BeOS, too, so try
++### leaving this commented out:
++#CLEANDIR = cleandir.BeOS
+ 
+-#----------Machine Specific Configurations----------
+ 
+ ### If you are using an SGI system, uncomment the following line
+ #MCHN = -Dsgi
+ 
+ 
+-### For HP-UX, uncomment the following line:
++### For HP-UX, uncomment the following line
+ #MCHN= -Dhpux -D_HPUX_SOURCE
+ # To use old HP compilers (HPUX 7.0 or so), you may need
+ #MCHN= -Dhpux -D_HPUX_SOURCE +Ns4000
+ #
+-# also, if you're using HP's compiler, add '-Aa' to whichever of those
++# Also, if you're using HP's compiler, add '-Aa' to whichever of those
+ # two lines you're using, to turn on ANSI C mode.  Or so I'm told.
+ #
+-# note:  You may need to add '-I/usr/include/X11R5' (or R6, or whatever)
++# Note:  You may need to add '-I/usr/include/X11R5' (or R6, or whatever)
+ # to whichever of those lines you used, as HP tends to store their X11
+ # include files in a non-standard place...
++#
++# And you probably have to add '-lV3' to the end of the LIBS def when
++# using XV's AUTO_EXPAND option.
+ 
+ 
+-### for LINUX, uncomment the following line
+-#MCHN = -DLINUX
++### for Linux, uncomment one of the following lines:
++#MCHN = -DLINUX -L/usr/X11R6/lib
++#MCHN = -DLINUX -L/usr/X11R6/lib64
+ 
+ 
+ # For SCO 1.1 (UNIX 3.2v2) machines, uncomment the following:
+ #MCHN = -Dsco -DPOSIX
+ #
+ # For ODT 2.0 (UNIX 3.2v4) machines, uncomment the following:
+-#MCHN= -Dsco -DPOSIX -DNO_RANDOM 
++#MCHN= -Dsco -DPOSIX -DNO_RANDOM
+ #
+ # Also, you should add '-lc -lx' to the end of the LIBS def below
+ # -lx must be after -lc so you get the right directory routines.
+ 
+ 
+ # for UMAX V by Encore Computers uncomment the following line for
+-# the portable c compiler, system specific definitions and
+-# location of local X11 library(if site specific, modify -L option)
++# the portable C compiler, system-specific definitions and
++# location of local X11 library (if site-specific, modify -L option)
+ # No other switches should be necessary, or so I'm told...
+ #
+ #MCHN = -q extensions=pcc_c -D__UMAXV__ -L/usr2/usr/lib/X11 -DSVR4
+@@ -147,8 +282,8 @@
+ #TIMERS = -DUSLEEP
+ 
+ 
+-# if XV locks up whenever you click on *any* of the buttons, the Timer() 
+-# function in xvmisc.c is going out to lunch.  A simple workaround is to 
++# if XV locks up whenever you click on *any* of the buttons, the Timer()
++# function in xvmisc.c is going out to lunch.  A simple workaround is to
+ # uncomment the following line:
+ #TIMERS = -DNOTIMER
+ 
+@@ -160,7 +295,7 @@
+ #DXWM = -DDXWM
+ 
+ 
+-# if, during compilation, your system complains about the types 
++# if, during compilation, your system complains about the types
+ # 'u_long', 'u_short', 'u_int', etc. as being undefined, uncomment the
+ # following line:
+ #BSDTYPES = -DBSDTYPES
+@@ -177,18 +312,38 @@
+ #VPRINTF = -DNEED_VPRINTF -DLONGINT -DNOSTDHDRS
+ 
+ 
++# if your machine puts the prototype for 'malloc()' in malloc.h rather than
++# stdlib.h, uncomment the following line:
++#
++#MALLOC = -DNEED_MALLOC_H
+ 
+ 
+-################ END OF CONFIGURATION OPTIONS #################
++# if your X Window System compiled with -DX_LOCALE, 
++# uncomment the following line:
++# TVL10N = -DX_LOCALE
++
++# Install directory of xv_mgcsfx.sample.
++MGCSFXDIR = $(LIBDIR)
++# Directory of default configuration file.
++MGCSFX = -DMGCSFXDIR=\"$(MGCSFXDIR)\"
++
+ 
+ 
+ 
++################ END OF CONFIGURATION OPTIONS #################
++
+ 
+-CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \
+-	$(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \
+-	$(DXWM) $(MCHN)
+ 
+-LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) -lm
++
++CFLAGS = $(CCOPTS) $(PNG) $(PNGINC) $(ZLIBINC) $(JPEG) $(JPEGINC) \
++	$(TIFF) $(TIFFINC) $(PDS) $(JP2K) $(JP2KINC) $(TVL10N) $(MGCSFX) \
++	$(UNIX) $(BSDTYPES) $(RAND) $(MALLOC) $(DXWM) $(MCHN) $(NODIRENT) \
++	$(VPRINTF) $(TIMERS) -DDOCDIR=\"$(DOCDIR)\" \
++	-DSYSCONFDIR=\"$(SYSCONFDIR)\" -DXVEXECPATH=\"$(LIBDIR)\"
++
++### remove -lm for BeOS:
++LIBS = $(TIFFLIB) $(JPEGLIB) $(PNGLIB) $(ZLIBLIB) $(JP2KLIB) -L/usr/X11R6/lib -lX11 -lm
++#LIBS = $(TIFFLIB) $(JPEGLIB) $(PNGLIB) $(ZLIBLIB) $(JP2KLIB) -lX11
+ 
+ OBJS = 	xv.o xvevent.o xvroot.o xvmisc.o xvimage.o xvcolor.o xvsmooth.o \
+ 	xv24to8.o xvgif.o xvpm.o xvinfo.o xvctrl.o xvscrl.o xvalg.o \
+@@ -196,7 +351,9 @@
+ 	xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \
+ 	xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \
+ 	xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \
+-	xvxwd.o xvfits.o
++	xvxwd.o xvfits.o xvpng.o xvzx.o xvwbmp.o xvpcd.o xvhips.o \
++	xvmag.o xvpic.o xvmaki.o xvpi.o xvpic2.o xvvd.o xvmgcsfx.o \
++	xvml.o xvjp2k.o
+ 
+ MISC = README INSTALL CHANGELOG IDEAS
+ 
+@@ -206,10 +363,12 @@
+ 
+ 
+ 
+-all: $(JPEGLIB) $(TIFFLIB) xv bggen vdcomp xcmap xvpictoppm
++#all: $(JPEGLIB) $(TIFFLIB) xv bggen vdcomp xcmap xvpictoppm
++all: xv bggen vdcomp xcmap xvpictoppm
+ 
+ 
+-xv: $(OBJS) $(JPEGLIB) $(TIFFLIB)
++#xv: $(OBJS) $(JPEGLIB) $(TIFFLIB)
++xv: $(OBJS)
+ 	$(CC) -o xv $(CFLAGS) $(OBJS) $(LIBS)
+ 
+ bggen: bggen.c
+@@ -231,23 +390,47 @@
+ 
+ clean:  xvclean
+ 	rm -f bggen vdcomp xcmap xvpictoppm
+-	./cleandir $(JPEGDIR)
+-	rm -f $(JPEGDIR)/jconfig.h $(JPEGDIR)/Makefile
+-	./cleandir $(TIFFDIR)
++#	clean only local jpeg and tiff dirs, not user's or system's copies:
++	./$(CLEANDIR) jpeg
++	rm -f jpeg/jconfig.h jpeg/Makefile
++	./$(CLEANDIR) tiff
+ 
+ 
++# could also do some shell trickery here to attempt mkdir only if dir is
++# missing (e.g., "test -d <dir> || $(MKDIR) <dir>")
+ install: all
+-	cp xv bggen vdcomp xcmap xvpictoppm $(BINDIR)
+-	cp docs/xv.man     $(MANDIR)/xv.$(MANSUF)
+-	cp docs/bggen.man  $(MANDIR)/bggen.$(MANSUF)
+-	cp docs/xcmap.man  $(MANDIR)/xcmap.$(MANSUF)
+-	cp docs/xvp2p.man  $(MANDIR)/xvpictoppm.$(MANSUF)
+-	cp docs/vdcomp.man $(MANDIR)/vdcomp.$(MANSUF)
+-	cp docs/xvdocs.ps* $(LIBDIR)
++	$(MKDIR) $(DESTDIR)$(BINDIR)
++	cp xv bggen vdcomp xcmap xvpictoppm $(DESTDIR)$(BINDIR)/.
++	chmod 755 $(DESTDIR)$(BINDIR)/xv $(DESTDIR)$(BINDIR)/bggen \
++	  $(DESTDIR)$(BINDIR)/vdcomp $(DESTDIR)$(BINDIR)/xcmap \
++	  $(DESTDIR)$(BINDIR)/xvpictoppm
++#
++	$(MKDIR) $(DESTDIR)$(MANDIR)
++	cp docs/xv.man     $(DESTDIR)$(MANDIR)/xv.$(MANSUF)
++	cp docs/bggen.man  $(DESTDIR)$(MANDIR)/bggen.$(MANSUF)
++	cp docs/xcmap.man  $(DESTDIR)$(MANDIR)/xcmap.$(MANSUF)
++	cp docs/xvp2p.man  $(DESTDIR)$(MANDIR)/xvpictoppm.$(MANSUF)
++	cp docs/vdcomp.man $(DESTDIR)$(MANDIR)/vdcomp.$(MANSUF)
++	chmod 644 $(DESTDIR)$(MANDIR)/xv.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/bggen.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/xcmap.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/xvpictoppm.$(MANSUF) \
++	  $(DESTDIR)$(MANDIR)/vdcomp.$(MANSUF)
++#
++	$(MKDIR) $(DESTDIR)$(DOCDIR)		# or $(DESTDIR)$(LIBDIR)
++	cp README.jumbo docs/xvdocs.pdf docs/xvdocs.ps $(DESTDIR)$(DOCDIR)/.
++	chmod 644 $(DESTDIR)$(DOCDIR)/README.jumbo \
++	  $(DESTDIR)$(DOCDIR)/xvdocs.pdf $(DESTDIR)$(DOCDIR)/xvdocs.ps
++#
++	#$(MKDIR) $(DESTDIR)$(SYSCONFDIR)
++	#cp xv_mgcsfx.sample $(DESTDIR)$(SYSCONFDIR)/xv_mgcsfx
++	#chmod 644 $(DESTDIR)$(SYSCONFDIR)/xv_mgcsfx
++
+ 
+ tar:
++#	tar only local jpeg and tiff dirs, not user's or system's copies:
+ 	tar cvf xv.tar Makefile* Imakefile *.c *.h bits \
+-		docs unsupt vms $(JPEGDIR) $(TIFFDIR) $(MISC) 
++		docs unsupt vms jpeg tiff $(MISC)
+ 
+ xvtar:
+ 	tar cvf xv.tar Makefile* Imakefile *.c *.h bits
+@@ -257,26 +440,28 @@
+ 
+ ################# bitmap dependencies ####################
+ 
+-xv.o:      	bits/icon bits/iconmask bits/runicon bits/runiconm
+-xv.o:      	bits/cboard50 bits/gray25 
++xv.o:		bits/icon bits/iconmask bits/runicon bits/runiconm
++xv.o:		bits/cboard50 bits/gray25
+ 
+ xvbrowse.o:	bits/br_file bits/br_dir bits/br_exe bits/br_chr bits/br_blk
+-xvbrowse.o:	bits/br_sock bits/br_fifo bits/br_error bits/br_unknown
+-xvbrowse.o:	bits/br_cmpres bits/br_gif bits/br_pm bits/br_pbm
++xvbrowse.o:	bits/br_sock bits/br_fifo bits/br_error # bits/br_unknown
++xvbrowse.o:	bits/br_cmpres bits/br_bzip2 bits/br_gif bits/br_pm bits/br_pbm
+ xvbrowse.o:	bits/br_sunras bits/br_bmp bits/br_utah bits/br_iris
+-xvbrowse.o:	bits/br_pcx bits/br_jfif bits/br_tiff bits/br_pds 
+-xvbrowse.o:	bits/br_ps bits/br_iff bits/br_targa bits/br_xpm
++xvbrowse.o:	bits/br_pcx bits/br_jfif bits/br_tiff bits/br_pds bits/br_pcd
++xvbrowse.o:	bits/br_ps bits/br_iff bits/br_targa bits/br_xpm bits/br_xwd
++xvbrowse.o:	bits/br_fits bits/br_png bits/br_zx bits/br_mag bits/br_maki
++xvbrowse.o:	bits/br_pic bits/br_pi bits/br_pic2 bits/br_mgcsfx
++xvbrowse.o:	bits/br_jp2 bits/br_jpc
+ xvbrowse.o:	bits/br_trash bits/fcurs bits/fccurs bits/fdcurs bits/fcursm
+-xvbrowse.o:     bits/br_xwd
+ 
+ xvbutt.o:	bits/cboard50 bits/rb_frame bits/rb_frame1 bits/rb_top
+ xvbutt.o:	bits/rb_bot bits/rb_dtop bits/rb_dbot bits/rb_body
+ xvbutt.o:	bits/rb_dot bits/cb_check bits/mb_chk
+ 
+ xvctrl.o:	bits/gray25 bits/gray50 bits/i_fifo bits/i_chr bits/i_dir
+-xvctrl.o: 	bits/i_blk bits/i_lnk bits/i_sock bits/i_exe bits/i_reg
++xvctrl.o:	bits/i_blk bits/i_lnk bits/i_sock bits/i_exe bits/i_reg
+ xvctrl.o:	bits/h_rotl bits/h_rotr bits/fliph bits/flipv bits/p10
+-xvctrl.o:	bits/m10 bits/cut bits/copy bits/paste bits/clear 
++xvctrl.o:	bits/m10 bits/cut bits/copy bits/paste bits/clear
+ xvctrl.o:	bits/uicon bits/oicon1 bits/oicon2 bits/icon
+ xvctrl.o:	bits/padimg bits/annot
+ 
+@@ -285,13 +470,13 @@
+ xvdflt.o:	bits/logo_top bits/logo_bot bits/logo_out bits/xv_jhb
+ xvdflt.o:	bits/xv_cpyrt bits/xv_rev bits/xv_ver
+ xvdflt.o:	bits/xf_left bits/xf_right bits/font5x9.h
+-xvdflt.o:       xvdflt.h
++xvdflt.o:	xvdflt.h
+ 
+ xvdial.o:	bits/dial_cw1 bits/dial_ccw1 bits/dial_cw2 bits/dial_ccw2
+ 
+ xvdir.o:	bits/d_load bits/d_save
+ 
+-xvevent.o:	bits/dropper bits/dropperm bits/pen bits/penm 
++xvevent.o:	bits/dropper bits/dropperm bits/pen bits/penm
+ xvevent.o:	bits/blur bits/blurm
+ 
+ xvgam.o:	bits/h_rotl bits/h_rotr bits/h_flip bits/h_sinc bits/h_sdec
+diff -ru xv-3.10a/bggen.c xv-3.10a-enhancements/bggen.c
+--- xv-3.10a/bggen.c	1994-12-22 14:34:41.000000000 -0800
++++ xv-3.10a-enhancements/bggen.c	2005-04-17 14:04:22.000000000 -0700
+@@ -18,6 +18,11 @@
+ #include <stdio.h>
+ #include <math.h>
+ 
++#ifdef __STDC__
++#  include <stdlib.h>	/* atoi() */
++#  include <ctype.h>	/* isdigit() */
++#endif
++
+ #ifndef M_PI
+ #  define M_PI       3.1415926535897932385
+ #endif
+@@ -29,7 +34,7 @@
+ #define MAXCOLS  128
+ 
+ /* some VMS thing... */
+-#ifdef vax11c
++#if defined(vax11c) || (defined(__sony_news) && (defined(bsd43) || defined(__bsd43) || defined(SYSTYPE_BSD) || defined(__SYSTYPE_BSD)))
+ #include <ctype.h>
+ #endif
+ 
+@@ -46,8 +51,8 @@
+ 
+ typedef unsigned char byte;
+ 
+-struct   color { int   r,g,b; 
+-		 int   y; 
++struct   color { int   r,g,b;
++		 int   y;
+ 	       } colors[MAXCOLS], *cur, *nex;
+ 
+ int      numcols;
+@@ -62,7 +67,7 @@
+ double computeDist PARM((int, int, int, int, int));
+ void   writePPM    PARM((byte *, int, int, int));
+ 
+-     
++
+ /*************************************/
+ int main(argc,argv)
+      int    argc;
+@@ -80,18 +85,18 @@
+   char *geom    = NULL;
+   char *rptgeom = NULL;
+ 
+-  
++
+ #ifdef VMS
+   getredirection(&argc, &argv);
+ #endif
+-  
++
+ 
+   for (i=1; i<argc; i++) {
+     if (!strncmp(argv[i],"-d",(size_t) 2)) {         /* -d disp */
+       i++;  if (i<argc) dname = argv[i];
+     }
+   }
+-    
++
+   if ((theDisp = XOpenDisplay(dname)) == NULL) {
+     fprintf(stderr,"bggen:  Warning - can't open display, screen %s",
+ 	    "size unknown, color names not accepted.\n");
+@@ -99,41 +104,41 @@
+ 
+ 
+   cnt = 0;  numcols = 0;
+-  
++
+   /* parse cmd-line args */
+   for (i=1; i<argc; i++) {
+     if (!strcmp(argv[i],"-h")) {                          /* -h high */
+       i++;  if (i<argc) high = atoi(argv[i]);
+       hset++;
+     }
+-    
++
+     else if (!strcmp(argv[i],"-w")) {                     /* -w wide */
+       i++;  if (i<argc) wide = atoi(argv[i]);
+       wset++;
+     }
+-    
++
+     else if (!strcmp(argv[i],"-b")) {                     /* -b bits */
+       i++;  if (i<argc) bits = atoi(argv[i]);
+     }
+-    
++
+     else if (!strncmp(argv[i],"-g",(size_t) 2)) {         /* -g geom */
+       i++;  if (i<argc) geom = argv[i];
+     }
+-    
++
+     else if (!strncmp(argv[i],"-d",(size_t) 2)) {         /* -d disp */
+       i++;  if (i<argc) dname = argv[i];
+     }
+-    
++
+     else if (!strcmp(argv[i],"-G")) {                      /* -G rptgeom */
+       i++;  if (i<argc) rptgeom = argv[i];
+     }
+-    
++
+     else if (!strncmp(argv[i],"-a",(size_t) 2)) doascii++;  /* -a */
+-    
++
+     else if (!strcmp(argv[i],"-r")) {                     /* -r rot */
+       i++;  if (i<argc) rot = atoi(argv[i]);
+     }
+-    
++
+     else if (argv[i][0]=='-') usage();    /* any other '-' option is unknown */
+ 
+     else if (isdigit(argv[i][0])) {
+@@ -143,7 +148,7 @@
+       case 2:  colors[numcols].b = atoi(argv[i]);  break;
+       }
+       cnt++;
+-      
++
+       if (cnt==3) {
+ 	if (numcols<MAXCOLS) numcols++;
+ 	cnt = 0;
+@@ -176,50 +181,50 @@
+       }
+     }
+   }
+-  
+-  
+-  
++
++
++
+   /* print error/usage message, if appropriate */
+   if (cnt || numcols==0 || high<1 || wide<1 || bits<1 || bits>8) usage();
+-  
+-  
++
++
+   if (geom) {
+     int x,y;  unsigned int w,h;
+     i = XParseGeometry(geom, &x, &y, &w, &h);
+     if (i&WidthValue)  { wset++;  wide = (int) w; }
+     if (i&HeightValue) { hset++;  high = (int) h; }
+   }
+-  
+-  
++
++
+   /* attempt to connect to X server and get screen dimensions */
+   if (theDisp) {
+     i = DefaultScreen(theDisp);
+     if (!wset) wide = DisplayWidth(theDisp, i);
+     if (!hset) high = DisplayHeight(theDisp, i);
+   }
+-  
+-  
++
++
+   /* normalize 'rot' */
+   while (rot<   0) rot += 360;
+   while (rot>=360) rot -= 360;
+-  
+-  
++
++
+   rptwide = wide;  rpthigh = high;
+   if (rptgeom) {
+     int x,y;  unsigned int w,h;
+     i = XParseGeometry(rptgeom, &x, &y, &w, &h);
+     if (i&WidthValue)  rptwide = (int) w;
+     if (i&HeightValue) rpthigh = (int) h;
+-    
++
+     RANGE(rptwide, 1, wide);
+     RANGE(rpthigh, 1, high);
+   }
+-  
+-  
+ 
+-  
++
++
++
+   rpic24 = (byte *) malloc(rptwide * rpthigh * 3 * sizeof(byte));
+-  if (rptwide != wide || rpthigh != high) 
++  if (rptwide != wide || rpthigh != high)
+     pic24  = (byte *) malloc(wide * high * 3 * sizeof(byte));
+   else pic24 = rpic24;
+ 
+@@ -229,7 +234,7 @@
+     exit(1);
+   }
+   for (i=0, pp=pic24; i<wide*high*3; i++) *pp++ = 0;
+-  
++
+ 
+ 
+   /*** generate image ***/
+@@ -244,34 +249,34 @@
+       }
+     }
+   }
+-  
+-  
++
++
+   else if (rot==0) {   /* un-rotated linear (vertical) gradient */
+     for (i=0; i<numcols; i++)
+       colors[i].y = ((rpthigh-1) * i) / (numcols-1);
+-    
++
+     cur = &colors[0];  nex = cur+1;
+-    
++
+     for (i=0; i<rpthigh; i++) {
+       pp = rpic24 + (i * rptwide * 3);
+ 
+       /* advance to next pair of colors if we're outside region */
+       while (nex->y < i) { cur++; nex++; }
+-      
++
+       r = cur->r + ((nex->r - cur->r) * (i - cur->y)) / (nex->y - cur->y);
+       g = cur->g + ((nex->g - cur->g) * (i - cur->y)) / (nex->y - cur->y);
+       b = cur->b + ((nex->b - cur->b) * (i - cur->y)) / (nex->y - cur->y);
+-      
++
+       r = r & bmask[bits-1];
+       g = g & bmask[bits-1];
+       b = b & bmask[bits-1];
+-      
++
+       for (j=0; j<rptwide; j++) {
+ 	*pp++ = (byte) r;  *pp++ = (byte) g;  *pp++ = (byte) b;
+       }
+     }
+   }
+-  
++
+   else dorot(rpic24, rptwide, rpthigh, rot);
+ 
+ 
+@@ -293,7 +298,7 @@
+ 	y = ((i-ay) % rpthigh);
+ 
+ 	sp = rpic24 + (y * rptwide + x) * 3;
+-	
++
+ 	pp[0] = *sp++;  pp[1] = *sp++;  pp[2] = *sp++;
+       }
+     }
+@@ -355,12 +360,12 @@
+     mind = computeDist(w-1,  0,    cx, cy, rot);
+     maxd = computeDist(0,    h-1,  cx, cy, rot);
+   }
+-  
++
+   del = maxd - mind;         /* maximum distance */
+-  
++
+   distdebug = 0;
+-  
+-  
++
++
+   for (y=0; y<h; y++) {
+     pp = pic + (y * w * 3);
+     for (x=0; x<w; x++) {
+@@ -368,11 +373,11 @@
+       rat = (d - mind) / del;
+       if (rat<0.0) rat = 0.0;
+       if (rat>1.0) rat = 1.0;
+-      
++
+       cval = rat * nc1;
+       bc   = floor(cval);
+       crat = cval - bc;
+-      
++
+       if (bc < nc1) {
+ 	r = colors[bc].r + crat * (colors[bc+1].r - colors[bc].r);
+ 	g = colors[bc].g + crat * (colors[bc+1].g - colors[bc].g);
+@@ -383,7 +388,7 @@
+ 	g = colors[nc1].g;
+ 	b = colors[nc1].b;
+       }
+-      
++
+       *pp++ = (byte) r;  *pp++ = (byte) g;  *pp++ = (byte) b;
+     }
+   }
+@@ -395,9 +400,9 @@
+      int x,y,cx,cy,rot;
+ {
+   /* rot has to be in range 0-359 */
+-  
+-  double x1, y1, x2, y2, x3, y3, d, d1, b, theta;
+-  
++
++  double x1, y1, x2, y2, x3, y3, d, d1, b;
++
+   if (rot == 0)   return (double) (y - cy);
+   if (rot == 180) return (double) (cy - y);
+ 
+@@ -407,7 +412,7 @@
+   /* x2,y2 = vertical projection onto a || line that runs through cx,cy */
+   x2 = x1;
+   y2 = cy - (cx-x2)*tant1;
+-  
++
+   d1 = y2 - y1;  /* vertical distance between lines */
+   b  = d1 * cost1;
+ 
+@@ -435,11 +440,11 @@
+      int   w,h,doascii;
+ {
+   /* dumps a pic24 in PPM format to stdout */
+-  
++
+   int x,y;
+-  
++
+   printf("P%s %d %d 255\n", (doascii) ? "3" : "6", w, h);
+-  
++
+   for (y=0; y<h; y++) {
+     if (doascii) {
+       for (x=0; x<w; x++, pic+=3)
+diff -ru xv-3.10a/bits/br_targa xv-3.10a-enhancements/bits/br_targa
+--- xv-3.10a/bits/br_targa	1994-12-22 14:35:30.000000000 -0800
++++ xv-3.10a-enhancements/bits/br_targa	2007-04-15 10:40:46.000000000 -0700
+@@ -1,6 +1,6 @@
+-#define br_targa_width 48
+-#define br_targa_height 48
+-static unsigned char br_targa_bits[] = {
++#define br_tga_width 48
++#define br_tga_height 48
++static unsigned char br_tga_bits[] = {
+    0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
+diff -ru xv-3.10a/bits/icon xv-3.10a-enhancements/bits/icon
+--- xv-3.10a/bits/icon	1994-12-22 14:35:28.000000000 -0800
++++ xv-3.10a-enhancements/bits/icon	2004-04-28 08:00:16.000000000 -0700
+@@ -1,5 +1,6 @@
+ #define icon_width 40
+ #define icon_height 32
++#ifndef OMIT_ICON_BITS
+ static unsigned char icon_bits[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+@@ -15,3 +16,4 @@
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00};
++#endif
+diff -ru xv-3.10a/cleandir xv-3.10a-enhancements/cleandir
+--- xv-3.10a/cleandir	1994-12-22 14:34:50.000000000 -0800
++++ xv-3.10a-enhancements/cleandir	2004-05-10 23:19:16.000000000 -0700
+@@ -1,9 +1,13 @@
+-#!/bin/csh -f
++#!/bin/sh -f
+ # cleandir: if called with an argument, cd's there and does a 'make clean'
+ #
+ 
+-if ( x$1 != x ) then
+-  echo "cleaning $1 subdirectory"
+-  cd $1
+-  make clean
+-endif
++if [ x"$1" != x ]; then
++  if [ -f "$1"/makefile -o -f "$1"/Makefile ]; then
++    echo "cleaning '$1' subdirectory"
++    cd "$1"
++    make clean
++# else
++#   echo "no makefile found; NOT cleaning '$1' subdirectory"
++  fi
++fi
+diff -ru xv-3.10a/config.h xv-3.10a-enhancements/config.h
+--- xv-3.10a/config.h	1995-01-05 10:49:21.000000000 -0800
++++ xv-3.10a-enhancements/config.h	2007-05-14 08:51:10.000000000 -0700
+@@ -6,25 +6,42 @@
+ /***************************************************************************
+  * GZIP'd file support
+  *
+- * if you have the gnu uncompression utility 'gunzip', XV can use it to
+- * automatically 'unzip' any gzip'd files.  To enable this feature,
+- * change 'undef' to 'define' in the following line.  Needless to say, if 
+- * your gunzip is installed elsewhere on your machine, change the 'GUNZIP'
+- * definition appropriately. (use 'which gunzip' to find if you have gunzip, 
+- * and where it lives)
++ * if you have the GNU uncompression utility 'gunzip' (or 'gzip' itself,
++ * which is just a link to gunzip), XV can use it to automatically 'unzip'
++ * any gzip'd files.  To enable this feature, change 'undef' to 'define' in
++ * the following line.  Needless to say, if your gunzip is installed elsewhere
++ * on your machine, change the 'GUNZIP' definition appropriately. (use
++ * 'which gunzip' to find if you have gunzip, and where it lives; ditto for
++ * gzip)
+  */
+-#undef USE_GUNZIP
++#define USE_GUNZIP
+ 
+ #ifdef USE_GUNZIP
+ #  ifdef VMS
+ #    define GUNZIP "UNCOMPRESS"
+ #  else
+-#    define GUNZIP "/usr/local/bin/gunzip -q"
++#    define GUNZIP "gzip -dq"
+ #  endif
+ #endif
+ 
+ 
+ /***************************************************************************
++ * BZIP2'd file support
++ *
++ * if you have the uncompression utility 'bunzip2' (or 'bzip2' itself, which
++ * is just a link to bunzip2), XV can use it to automatically 'unzip' any
++ * bzip2'd files.  To enable this feature, change 'undef' to 'define' in the
++ * following line (if not already done).  Use 'which bunzip2' or 'which bzip2'
++ * to find if you have bzip2/bunzip2, and where it lives.
++ */
++#define USE_BUNZIP2
++
++#ifdef USE_BUNZIP2
++#  define BUNZIP2 "bzip2 -d"  /* should this include the full path? */
++#endif
++
++
++/***************************************************************************
+  * compress'd file support
+  *
+  * if you have GUNZIP defined above, just ignore this, as 'gunzip' can
+@@ -37,9 +54,16 @@
+  */
+ #define UNCOMPRESS "/usr/ucb/uncompress"
+ 
+-#if defined(hpux) || defined(SVR4) || defined(__386BSD__)
++#if defined(hpux) || defined(SVR4) || \
++    defined(__386BSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
++    defined(__linux__)
++    /*
++     I want to use BSD macro for checking if this OS is *BSD or not,
++     but the macro is defined in <sys/parm.h>, which I don't know all
++     machine has or not.
++     */
+ #  undef  UNCOMPRESS
+-#  define UNCOMPRESS "/usr/bin/uncompress"
++#  define UNCOMPRESS "uncompress"
+ #endif
+ 
+ #if defined(sgi)
+@@ -70,18 +94,18 @@
+  * PostScript file input support:
+  *
+  * if you have the 'ghostscript' package installed (version 2.6 or later),
+- * XV can use it to read and display PostScript files.  To do so, 
++ * XV can use it to read and display PostScript files.  To do so,
+  * uncomment the '#define GS_PATH' line, below.  You probably will not
+  * need to modify the GS_LIB or GS_DEV lines, but if you do modify them,
+  * be sure to uncomment them, as well.
+  *
+- * the ghostscript package can be acquired via anonymous ftp on 
++ * the ghostscript package can be acquired via anonymous ftp on
+  * prep.ai.mit.edu, in the 'pub/gnu' directory
+  *
+- * GS_PATH specifies the complete path to your gs executable.  
++ * GS_PATH specifies the complete path to your gs executable.
+  *
+- * GS_LIB should be set if there's some other gs libs that should be 
+- * searched, but aren't by default.  (In which case you should probably 
++ * GS_LIB should be set if there's some other gs libs that should be
++ * searched, but aren't by default.  (In which case you should probably
+  * just fix your 'gs' so it looks in the right places without being told...)
+  *
+  * GS_DEV is the file format that ghostscript will convert PS into.  It
+@@ -89,6 +113,7 @@
+  */
+ 
+ /* #define GS_PATH "/usr/local/bin/gs" */
++#define GS_PATH "gs"
+ /* #define GS_LIB  "."                 */
+ /* #define GS_DEV  "ppmraw"            */
+ 
+@@ -97,10 +122,10 @@
+  * 'old-style' XV logo image:
+  *
+  * XV now has a nifty, new logo image.  The downside is that it increases
+- * the size of the 'xv' executable by 250K or so, and it's possible that 
+- * your compiler may choke while compiling 'xvdflt.c'.  If you're compiler
++ * the size of the 'xv' executable by 250K or so, and it's possible that
++ * your compiler may choke while compiling 'xvdflt.c'.  If your compiler
+  * can't handle it, or you're running Linux on a system with minimal memory,
+- * change 'undef' to 'define' in the following line
++ * change 'undef' to 'define' in the following line:
+  */
+ 
+ #undef USEOLDPIC
+@@ -108,8 +133,8 @@
+ 
+ /***************************************************************************
+  * Backing Store:
+- * 
+- * XV can request that 'Backing Store' may be turned on ('WhenMapped') for 
++ *
++ * XV can request that 'Backing Store' may be turned on ('WhenMapped') for
+  * several of its windows, which may help performance over a slow network
+  * connection.  However, it has been known to behave strangely (or crash)
+  * on some X servers, so it's left here as an option.  If you run into trouble
+@@ -119,3 +144,218 @@
+ 
+ #define BACKING_STORE
+ 
++
++/***************************************************************************
++ * TIFF YCbCr-to-RGB conversion:
++ *
++ * Newer versions of libtiff can be compiled with libjpeg for JPEG-in-TIFF
++ * support, and according to Scott Marovich, "the IJG JPEG Library...sometimes
++ * seems to produce slightly more accurate results" (one known example:  the
++ * 'quad-jpeg.tif' test image).  In addition, libtiff can be compiled with
++ * "old JPEG" support, although its configure script will not enable that by
++ * default.  Change 'define' and 'undef' in the following lines as you wish,
++ * but note that defining LIBTIFF_HAS_OLDJPEG_SUPPORT when such is _not_ the
++ * case will result in crashes when encountering old-JPEG TIFFs:
++ */
++
++#define USE_LIBJPEG_FOR_TIFF_YCbCr_RGB_CONVERSION
++#undef LIBTIFF_HAS_OLDJPEG_SUPPORT
++
++
++/***************************************************************************
++ * PhotoCD/MAG/PIC/MAKI/Pi/PIC2/HIPS format Support:
++ *
++ * if, for whatever reason--say, security concerns--you don't want to
++ * include support for one or more of the PhotoCD, MAG/MAKI/Pi/PIC/PIC2
++ * (Japanese), or HIPS (astronomical) image formats, change the relevant
++ * 'define' to 'undef' in the following lines.  Conversely, if you *do*
++ * want them, change 'undef' to 'define' as appropriate.
++ */
++
++#define HAVE_PCD	/* believed to be reasonably safe */
++
++#undef HAVE_MAG		/* probable security issues */
++#undef HAVE_MAKI	/* probable security issues */
++#undef HAVE_PI		/* probable security issues */
++#undef HAVE_PIC		/* probable security issues */
++#undef HAVE_PIC2	/* probable security issues */
++
++#undef HAVE_HIPS	/* probable security issues */
++
++
++/***************************************************************************
++ * MacBinary file support:
++ *
++ * if you want XV to be able to handle ``MacBinary'' files (which have
++ * 128 byte info file header at the head), change 'undef' to 'define'
++ * in the following line.
++ */
++
++#undef MACBINARY
++
++
++/***************************************************************************
++ * Auto Expand support:
++ *
++ * if you want to extract archived file automatically and regard it as
++ * a directory, change 'undef' to 'define' in the AUTO_EXPAND line.
++ *
++ * Virtual Thumbdir support:
++ *
++ * if you want Virtual directory based Thumbdir(It means that XV
++ * doesn't forget builded Icons still be quited even if the directory
++ * is read-only), change 'undef' to 'define' the VIRTUAL_TD line.
++ */
++
++#undef AUTO_EXPAND
++#undef VIRTUAL_TD
++
++#if defined(VIRTUAL_TD) && !defined(AUTO_EXPAND)
++#  undef VIRTUAL_TD
++#endif
++
++
++/***************************************************************************
++ * Adjust the aspect ratio of Icons:
++ *
++ * if you want to adjust the aspect ratio of the icons in Visual
++ * Schnauzer, change 'undef' to 'define' in the following line.
++ */
++
++#undef VS_ADJUST
++
++
++/***************************************************************************
++ * Restore original colormap:
++ *
++ * if you want to restore original colormap when icons in Visual
++ * Shunauzer is double-clicked, change 'undef' to 'define' in the
++ * following line.
++ */
++
++#undef VS_RESCMAP
++
++
++/***************************************************************************
++ * TextViewer l10n support:
++ *
++ * if you want XV to show the text in Japanese on TextViewer, change
++ * 'undef' to 'define' in the following line.
++ */
++
++#undef TV_L10N
++
++#ifdef TV_L10N
++/*
++ * if you want to change the default code-set used in case that XV
++ * fails to select correct code-set, uncomment the '#define
++ * LOCALE_DEFAULT' line and change the 'LOCALE_DEFAULT' definition
++ * appropriately.
++ * (0:ASCII, 1:EUC-j, 2:JIS, 3:MS Kanji) */
++
++/* #  define LOCALE_DEFAULT 0 */
++
++/*
++ * Uncomment and edit the following lines, if your X Window System was
++ * not compiled with -DX_LOCALE and you failed to display the Japanese
++ * text in TextViewer.  You don't have to write locale name of JIS code-set
++ * and Microsoft code-set, if your system doesn't support those code-sets.
++ */
++
++/*
++#  define LOCALE_NAME_EUC     "ja_JP.EUC"
++#  define LOCALE_NAME_JIS     "ja_JP.JIS"
++#  define LOCALE_NAME_MSCODE  "ja_JP.SJIS"
++*/
++
++/*
++ * if your system doesn't have the Japanese fonts in the sizes,
++ * Uncomment and edit the following font size entries.
++ */
++
++/* #  define TV_FONTSIZE 14,16,24 */
++
++/*
++ * If you need, uncomment and modify the following font name.
++ */
++
++/* #  define TV_FONTSET "-*-fixed-medium-r-normal--%d-*" */
++#endif /* TV_L10N */
++
++
++/***************************************************************************
++ * User definable filter support:
++ *
++ * Use the filters as input and output method for load and save unsupported
++ * image format file. The filter command is recognized by definition of
++ * magic number or suffix in "~/.xv_mgcsfx" .
++ * To enable this feature, change 'undef' to 'define' in the following line.
++ */
++#undef HAVE_MGCSFX
++
++#ifdef HAVE_MGCSFX
++/*
++ * Support symbol 'auto' as <input image type> in startup file. This type
++ * cannot use pipe as input; it writes to a temporary file and recognizes
++ * the actual filetype by XV processing.
++ */
++#  define HAVE_MGCSFX_AUTO
++
++/*
++ * The startup file of definition for MgcSfx. 'MGCSFX_SITE_RC' is read
++ * first and '~/MGCSFX_RC' is second. So same definitions in both files
++ * are overridden by '~/MGCSFX_RC'
++ * To define startup file, see the sample of startup file 'xv_mgcsfx.sample'.
++ */
++#  define MGCSFX_SITE_RC  "xv_mgcsfx"
++#  define MGCSFX_RC       ".xv_mgcsfx"
++
++/*
++ * If you want startup file to pass preprocessor in reading time, then
++ * change 'undef' to 'define' in the following line.
++ *
++ * WARNING : If you decide to use preprocessor, you must not write
++ *           '# <comment>' style comment in startup file. Because,
++ *           preprocessor can't recognize.  */
++#  undef USE_MGCSFX_PREPROCESSOR
++
++#  ifdef USE_MGCSFX_PREPROCESSOR
++/*
++ * This is used like "system("MGCSFX_PREPROCESSOR MGCSFX_RC > tmp_name");",
++ * and read tmp_name instead of MGCSFX_RC.
++ */
++#    define MGCSFX_PREPROCESSOR "/usr/lib/cpp"
++/* #    define MGCSFX_PREPROCESSOR "cc -E" */
++
++#  endif /* USE_MGCSFX_PREPROCESSOR */
++
++/*
++ * Default string of command. If input command is required for undefined file,
++ * dialog is popuped with 'MGCSFX_DEFAULT_INPUT_COMMAND'. And, if output
++ * command is required in save dialog of MgcSfx, dialog is popuped with
++ * 'MGCSFX_DEFAULT_OUTPUT_COMMAND'.
++ *
++ * WARNING : Now, supported only 'PNM' image format, when command input is
++ *           required. You should define filter which use 'PNM' image format
++ *           as input or output.
++ */
++#  define MGCSFX_DEFAULT_INPUT_COMMAND  "tifftopnm"
++#  define MGCSFX_DEFAULT_OUTPUT_COMMAND "pnmtotiff"
++
++#endif /* HAVE_MGCSFX */
++
++
++/***************************************************************************
++ * Multi-Lingual TextViewer
++ *
++ * if you want XV to show the text in multi-lingual on TextViewer, change
++ * 'undef' to 'define' in the following line.
++ */
++
++#undef TV_MULTILINGUAL
++
++#define TV_DEFAULT_CODESET TV_EUC_JAPAN
++
++#ifdef TV_MULTILINGUAL
++#  undef TV_L10N
++#endif
+diff -ru xv-3.10a/copyright.h xv-3.10a-enhancements/copyright.h
+--- xv-3.10a/copyright.h	1994-12-22 14:34:56.000000000 -0800
++++ xv-3.10a-enhancements/copyright.h	2007-05-20 21:35:34.000000000 -0700
+@@ -1,11 +1,11 @@
+ /* Copyright Notice
+  * ================
+  * Copyright 1989, 1994 by John Bradley
+- * 
+- * Permission to copy and distribute XV in its entirety, for non-commercial 
+- * purposes, is hereby granted without fee, provided that this license 
++ *
++ * Permission to copy and distribute XV in its entirety, for non-commercial
++ * purposes, is hereby granted without fee, provided that this license
+  * information and copyright notice appear unmodified in all copies.
+- * 
++ *
+  * Note that distributing XV 'bundled' in with any product is considered
+  * to be a 'commercial purpose'.
+  *
+@@ -13,16 +13,16 @@
+  * and/or configured to be in their 'unregistered copy' mode, so that it
+  * is made obvious to the user that XV is shareware, and that they should
+  * consider donating, or at least reading this License Info.
+- * 
++ *
+  * The software may be modified for your own purposes, but modified
+  * versions may not be distributed without prior consent of the author.
+- * 
++ *
+  * This software is provided 'as-is', without any express or implied
+  * warranty.  In no event will the author be held liable for any damages
+  * arising from the use of this software.
+- * 
++ *
+  * If you would like to do something with XV that this copyright
+- * prohibits (such as distributing it with a commercial product, 
++ * prohibits (such as distributing it with a commercial product,
+  * using portions of the source in some other program, etc.), please
+  * contact the author (preferably via email).  Arrangements can
+  * probably be worked out.
+@@ -34,13 +34,13 @@
+  * larger donations are quite welcome.  Folks who donate $25 or more
+  * can receive a Real Nice bound copy of the XV manual for no extra
+  * charge.
+- * 
++ *
+  * Commercial, government, and institutional users must register their
+  * copies of XV, for the price of $25 per workstation/X terminal or per
+  * XV user, whichever is less.  Note that it does NOT say 'simultaneous user',
+- * but rather, the total number of people who use XV on any sort of 
+- * recurring basis. Site licenses are available (and recommended) for those 
+- * who wish to run XV on a large (>10) number of machines.  
++ * but rather, the total number of people who use XV on any sort of
++ * recurring basis. Site licenses are available (and recommended) for those
++ * who wish to run XV on a large (>10) number of machines.
+  * Contact the author for more details.
+  *
+  * The author may be contacted via:
+@@ -56,3 +56,51 @@
+  * The author may not be contacted by (voice) phone.  Please don't try.
+  *
+  */
++
++/*
++ * Portions copyright 2000-2007 by Greg Roelofs and contributors:
++ *
++ *   Andrey A. Chernov [ache]
++ *     (http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-ab)
++ *   Andreas Dilger (adilger clusterfs.com)
++ *   Alexander Lehmann (lehmann usa.net)
++ *   Alexey Spiridonov (http://www-math.mit.edu/~lesha/)
++ *   Anthony Thyssen (http://www.cit.gu.edu.au/~anthony/)
++ *   Bruno Rohee (http://bruno.rohee.com/)
++ *   David A. Clunie (http://www.dclunie.com/xv-pcd.html)
++ *   Erling A. Jacobsen (linuxcub email.dk)
++ *   Egmont Koblinger (egmont users.sourceforge.net)
++ *   Fabian Greffrath (fabian debian-unofficial.org)
++ *   Greg Roelofs (http://pobox.com/~newt/greg_contact.html)
++ *   Guido Vollbeding (http://sylvana.net/guido/)
++ *   IKEMOTO Masahiro (ikeyan airlab.cs.ritsumei.ac.jp)
++ *   John Cooper (john.cooper third-harmonic.com)
++ *   John C. Elliott (http://www.seasip.demon.co.uk/ZX/zxdload.html)
++ *   John D. Baker (http://mylinuxisp.com/~jdbaker/)
++ *   Jörgen Grahn (jgrahn algonet.se)
++ *   John H. Bradley, of course (http://www.trilon.com/xv/)
++ *   Jean-Pierre Demailly (http://www-fourier.ujf-grenoble.fr/~demailly/)
++ *   John Rochester (http://www.freebsd.org/cgi/query-pr.cgi?pr=2920)
++ *   (also http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-af, -ag)
++ *   James Roberts Kirkpatrick (uwyo.edu)
++ *   Joe Zbiciak (http://spatula-city.org/~im14u2c/)
++ *   Kyoichiro Suda (http://www.coara.or.jp/~sudakyo/XV_jp.html)
++ *   Landon Curt "chongo" Noll (http://www.isthe.com/chongo/)
++ *   Larry Jones (lawrence.jones ugs.com)
++ *   Peter Jordan (http://www.ibiblio.org/pub/Linux/apps/graphics/viewers/X/)
++ *   Pawel S. Veselov (http://manticore.2y.net/wbmp.html)
++ *   Ross Combs (rocombs cs.nmsu.edu)
++ *   Robin Humble (http://www.cita.utoronto.ca/~rjh/)
++ *   Sean Borman (http://www.nd.edu/~sborman/software/xvwheelmouse.html)
++ *   TenThumbs (tenthumbs cybernex.net)
++ *   Scott B. Marovich (formerly marovich hpl.hp.com)
++ *   Tim Adye (http://hepwww.rl.ac.uk/Adye/xv-psnewstyle.html)
++ *   Tim Ramsey (tar pobox.com)
++ *   Tetsuya INOUE (tin329 chino.it.okayama-u.ac.jp)
++ *   Tavis Ormandy (taviso gentoo.org)
++ *   Werner Fink (http://www.suse.de/~werner/)
++ *
++ * Other credits are as listed on the XV Downloads page or in the respective
++ * patches (e.g., the jp-extension patches or within the PNG patch).
++ *
++ */
+diff -ru xv-3.10a/docs/bggen.man xv-3.10a-enhancements/docs/bggen.man
+--- xv-3.10a/docs/bggen.man	1994-12-22 14:35:22.000000000 -0800
++++ xv-3.10a-enhancements/docs/bggen.man	2007-04-22 17:32:11.000000000 -0700
+@@ -1,4 +1,4 @@
+-.TH bggen l
++.TH bggen 1
+ .SH NAME
+ bggen \- generates colored backgrounds on X11 displays
+ .SH SYNTAX
+diff -ru xv-3.10a/docs/xcmap.man xv-3.10a-enhancements/docs/xcmap.man
+--- xv-3.10a/docs/xcmap.man	1994-12-22 14:35:23.000000000 -0800
++++ xv-3.10a-enhancements/docs/xcmap.man	2007-04-22 17:32:31.000000000 -0700
+@@ -1,4 +1,4 @@
+-.TH xcmap 1X
++.TH xcmap 1
+ .SH NAME
+ xcmap \- displays the default colormap on X11 displays
+ .SH SYNTAX
+diff -ru xv-3.10a/docs/xv.man xv-3.10a-enhancements/docs/xv.man
+--- xv-3.10a/docs/xv.man	1994-12-22 14:35:22.000000000 -0800
++++ xv-3.10a-enhancements/docs/xv.man	2007-04-22 17:32:53.000000000 -0700
+@@ -1,4 +1,4 @@
+-.TH XV l "2 December 1994" "Rev. 3.10"
++.TH XV 1 "22 April 2007" "Rev. 3.10a-jumboFix+Enh"
+ .SH NAME
+ \fBxv\fP \- interactive image display for the X Window System
+ .SH SYNTAX
+@@ -8,14 +8,17 @@
+ .SH DESCRIPTION
+ The
+ .I xv
+-program displays images in the GIF, JPEG, TIFF,
+-PBM, PGM, PPM, X11 bitmap, Utah Raster Toolkit RLE, PDS/VICAR, Sun Rasterfile, 
+-BMP, PCX, IRIS RGB, XPM, Targa, XWD, possibly PostScript, and PM formats on 
+-workstations and terminals running the X Window System, Version 11.
++program displays images on workstations and terminals running the X Window
++System, Version 11.  Supported image formats include
++PBM, PGM, PPM, X11 bitmap, XWD, XPM, Utah Raster Toolkit RLE, PDS/VICAR,
++FITS, Sun Rasterfile, GIF, PCX, Targa/TGA, BMP, WBMP, IRIS RGB, Spectrum
++SCREEN$, PM, and optionally PNG, JPEG, JPEG 2000, JP2, TIFF, PostScript,
++PDF, G3 fax, MAG, PIC, MAKI (640x400), PI, and PIC2.
+ .LP
+-The documentation for XV is now distributed
++Aside from the usage screen (available by typing 'xv -help' at the command
++line), documentation for XV is now distributed
+ .I only
+-as a PostScript file, as it has gotten enormous, 
++as a PostScript (or PDF) file, as it has gotten enormous
+ and is no longer very well suited to the 'man' page format.
+ Print a copy of the (100-ish page) manual found in
+ .IR docs/xvdocs.ps .
+@@ -26,9 +29,14 @@
+ If you don't 
+ .I have
+ the PostScript file, it is part of the standard XV distribution, the
+-latest version of which can be obtained via anonymous ftp from 
++latest version of which can be obtained from
++.IR http://www.trilon.com/xv/
++or via anonymous ftp from 
+ .IR ftp.cis.upenn.edu
+-in the directory pub/xv
++in the directory pub/xv .
++.PP
++This version has been patched with the XV Jumbo Patches, available from
++.IR http://pobox.com/~newt/greg_xv.html .
+ .PP
+ .SH AUTHOR
+-John Bradley
++John Bradley (and many contributors)
+diff -ru xv-3.10a/docs/xvp2p.man xv-3.10a-enhancements/docs/xvp2p.man
+--- xv-3.10a/docs/xvp2p.man	1994-12-22 14:35:25.000000000 -0800
++++ xv-3.10a-enhancements/docs/xvp2p.man	2007-04-22 17:33:23.000000000 -0700
+@@ -1,4 +1,4 @@
+-.TH xvpictoppm 1X
++.TH xvpictoppm 1
+ .SH NAME
+ xvpictoppm \- converts XV 'thumbnail' files to standard PPM format
+ .SH SYNTAX
+diff -ru xv-3.10a/tiff/Makefile xv-3.10a-enhancements/tiff/Makefile
+--- xv-3.10a/tiff/Makefile	1994-12-22 14:35:12.000000000 -0800
++++ xv-3.10a-enhancements/tiff/Makefile	2005-04-17 14:45:28.000000000 -0700
+@@ -30,13 +30,15 @@
+ # OF THIS SOFTWARE.
+ #
+ 
+-AR=     ar
+-RANLIB=	./RANLIB.csh
++AR=	ar
++CHMOD=	chmod
++#RANLIB=	./RANLIB.csh
++RANLIB=	./RANLIB.sh
+ 
+ IPATH= -I.
+ 
+ COPTS=	-O
+-CFLAGS=	${COPTS} ${IPATH}
++CFLAGS=	${COPTS} ${IPATH} -D_BSD_SOURCE
+ 
+ INCS=	tiff.h tiffio.h
+ 
+@@ -60,6 +62,7 @@
+ 
+ ${ALL}:	${OBJS}
+ 	${AR} rc libtiff.a $?
++	${CHMOD} +x ${RANLIB}
+ 	${RANLIB} libtiff.a
+ 
+ ${OBJS}:	tiffio.h tiff.h tiffcomp.h tiffiop.h tiffconf.h
+diff -ru xv-3.10a/tiff/Makefile.std xv-3.10a-enhancements/tiff/Makefile.std
+--- xv-3.10a/tiff/Makefile.std	1994-12-22 14:35:16.000000000 -0800
++++ xv-3.10a-enhancements/tiff/Makefile.std	2004-05-16 18:50:39.000000000 -0700
+@@ -30,8 +30,10 @@
+ # OF THIS SOFTWARE.
+ #
+ 
+-AR=     /bin/ar
+-RANLIB=	./RANLIB.csh
++AR=	/bin/ar
++CHMOD=	chmod
++#RANLIB=	./RANLIB.csh
++RANLIB=	./RANLIB.sh
+ 
+ IPATH= -I.
+ 
+@@ -60,6 +62,7 @@
+ 
+ ${ALL}:	${OBJS}
+ 	${AR} rc libtiff.a $?
++	${CHMOD} +x ${RANLIB}
+ 	${RANLIB} libtiff.a
+ 
+ ${OBJS}:	tiffio.h tiff.h tiffcomp.h tiffiop.h tiffconf.h
+diff -ru xv-3.10a/vdcomp.c xv-3.10a-enhancements/vdcomp.c
+--- xv-3.10a/vdcomp.c	1994-12-22 14:34:47.000000000 -0800
++++ xv-3.10a-enhancements/vdcomp.c	2007-04-15 21:09:55.000000000 -0700
+@@ -5,8 +5,8 @@
+ /*  Decompresses images using Kris Becker's subroutine DECOMP.C     */
+ /*  which is included in this program in a shortened version.       */
+ /*                                                                  */
+-/*  Reads a variable length compressed PDS image and outputs a      */
+-/*  fixed length uncompressed image file in PDS format with         */
++/*  Reads a variable-length compressed PDS image and outputs a      */
++/*  fixed-length uncompressed image file in PDS format with         */
+ /*  labels, image histogram, engineering table, line header table   */
+ /*  and an image with PDS, FITS, VICAR or no labels.  If used on    */
+ /*  a non-byte-swapped machine the image histogram is un-swapped.   */
+@@ -96,40 +96,54 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ 
+-/* include a malloc.h, of some sort... */
+-#ifndef VMS   /* VMS hates multi-line '#if's */
+-# if !defined(ibm032)                    && \
+-     !defined(__convex__)                && \
+-     !(defined(vax) && !defined(ultrix)) && \
+-     !defined(mips)                      && \
+-     !defined(apollo)                    && \
+-     !defined(pyr)                       && \
+-     !defined(__UMAXV__)                 && \
+-     !defined(bsd43)                     && \
+-     !defined(aux)                       && \
+-     !defined(__bsdi__)                  && \
+-     !defined(sequent)
+-
+-#  if defined(hp300) || defined(hp800) || defined(NeXT)
+-#   include <sys/malloc.h>                /* it's in 'sys' on HPs and NeXT */
+-#  else
+-#   include <malloc.h>
+-#  endif
+-# endif
++/* include a malloc.h of some sort (if needed...most systems use stdlib.h) */
++#ifndef VMS   /* VMS hates multi-line "#if"s */
++   /*
++    * I want to use BSD macro for checking if this OS is *BSD or not,
++    * but the macro is defined in <sys/parm.h>, which I don't know all
++    * machine has or not.
++    */
++#  if !defined(ibm032)                    && \
++      !defined(__convex__)                && \
++      !(defined(vax) && !defined(ultrix)) && \
++      !defined(mips)                      && \
++      !defined(apollo)                    && \
++      !defined(pyr)                       && \
++      !defined(sequent)                   && \
++      !defined(__UMAXV__)                 && \
++      !defined(aux)                       && \
++      !defined(bsd43)                     && \
++      !defined(__bsd43)                   && \
++      !defined(__bsdi__)                  && \
++      !defined(__386BSD__)                && \
++      !defined(__FreeBSD__)               && \
++      !defined(__OpenBSD__)               && \
++      !defined(__NetBSD__)                && \
++      !defined(__DARWIN__)
++
++#    if defined(hp300) || defined(hp800) || defined(NeXT)
++#      include <sys/malloc.h>    /* it's in "sys" on HPs and NeXT */
++#    else
++#      include <malloc.h>        /* FIXME: should explicitly list systems that NEED this, not everyone that doesn't */
++#    endif
++
++#  endif /* !most modern systems */
+ #endif /* !VMS */
+ 
+ 
+ #include <X11/Xos.h>
+ 
+-#define TRUE                  1
+-#define FALSE                 0
++#define TRUE         1
++#define FALSE        0
++
++#define NAMELEN      1024           /* inname and outname sizes     */
+ 
+-                                    /* pc i/o defines               */
+-#define O_BINARY         0x8000     /* file mode is binary          */
++                                    /* PC I/O defines               */
++#define O_BINARY     0x8000         /* file mode is binary          */
+ 
+-                                    /* vax i/o defines              */
+-#define RECORD_TYPE      "rfm=fix"  /* VAX fixed length output      */
+-#define CTX              "ctx=bin"  /* no translation of \n         */
++                                    /* VAX/VMS I/O defines          */
++#define RECORD_TYPE  "rfm=fix"      /* VAX/VMS fixed-length output  */
++#define CTX          "ctx=bin"      /* no translation of \n         */
+ #define FOP          "fop=cif,sup"  /* file processing ops          */
+ 
+ typedef struct leaf { struct leaf *right;
+@@ -142,9 +156,9 @@
+  once the tree is created by the accompanying routine huff_tree.
+ **************************************************************************/
+ 
+-  NODE *tree;
++static NODE *tree;
+ 
+-/* subroutine definitions                                           */
++/* subroutine definitions */
+ 
+ #undef PARM
+ #ifdef __STDC__
+@@ -172,11 +186,11 @@
+ void free_tree    PARM((int *));
+ int  free_node    PARM((NODE *, int));
+ 
+-/* global variables                                                 */
++/* global variables */
+ 
+ int                infile;
+ FILE               *outfile;
+-char               inname[1024],outname[1024];
++char               inname[NAMELEN], outname[NAMELEN];
+ int                output_format;
+ int                record_bytes, max_lines;
+ int                line_samples, fits_pad;
+@@ -185,8 +199,8 @@
+ 
+ /*************************************************/
+ int main(argc,argv)
+-     int  argc;
+-     char **argv;
++  int  argc;
++  char **argv;
+ {
+   unsigned char ibuf[2048],obuf[2048];
+   unsigned char blank=32;
+@@ -200,12 +214,12 @@
+   /*                                                                   */
+   /*********************************************************************/
+ 
+-  strcpy(inname,"   ");  
++  strcpy(inname,"   ");
+   strcpy(outname,"   ");
+   output_format = 0;
+ 
+   if (argc == 1);                     /* prompt user for parameters */
+-  else if (argc == 2 && (strncmp(argv[1],"help",(size_t) 4) == 0 || 
++  else if (argc == 2 && (strncmp(argv[1],"help",(size_t) 4) == 0 ||
+ 			 strncmp(argv[1],"HELP",(size_t) 4) == 0 ||
+ 			 strncmp(argv[1],"?",   (size_t) 1) == 0)) {
+     fprintf(stderr,
+@@ -214,18 +228,22 @@
+     fprintf(stderr,"   infile        - name of compressed image file. \n");
+     fprintf(stderr,"   outfile       - name of uncompressed output file.\n");
+     fprintf(stderr,"   output format - selected from the following list:\n");
+-    fprintf(stderr,"\n");   
+-    fprintf(stderr,"     1  SFDU/PDS format [DEFAULT].\n");   
+-    fprintf(stderr,"     2  FITS format.              \n");   
+-    fprintf(stderr,"     3  VICAR format.             \n");   
+-    fprintf(stderr,"     4  Unlabelled binary array.  \n\n");   
++    fprintf(stderr,"\n");
++    fprintf(stderr,"     1  SFDU/PDS format [DEFAULT].\n");
++    fprintf(stderr,"     2  FITS format.              \n");
++    fprintf(stderr,"     3  VICAR format.             \n");
++    fprintf(stderr,"     4  Unlabelled binary array.  \n\n");
+     exit(1);
+-  }  
++  }
+   else {
+-    strcpy(inname,argv[1]);  
+-    if (argc >= 3) strcpy(outname,argv[2]); 
++    strncpy(inname, argv[1], sizeof(inname)-1);
++    inname[sizeof(inname)-1] = '\0';
++    if (argc >= 3) {
++      strncpy(outname, argv[2], sizeof(outname)-1);
++      outname[sizeof(outname)-1] = '\0';
++    }
+     if (argc == 3) output_format = 1;
+-    if (argc == 4) sscanf(argv[3],"%d",&output_format); 
++    if (argc == 4) sscanf(argv[3],"%d",&output_format);
+   }
+ 
+   host = check_host();
+@@ -244,13 +262,13 @@
+     case 4: no_labels(host);     break;
+   }
+ 
+-  if (record_bytes == 836) {  /* set up values for image sizes */ 
++  if (record_bytes == 836) {  /* set up values for image sizes */
+     max_lines    =  800;
+     fits_pad     = 2240;
+     line_samples =  800;
+   }
+   else {
+-    max_lines    = 1056;         
++    max_lines    = 1056;
+     fits_pad     = 1536;
+     line_samples = 1204;
+   }
+@@ -394,12 +412,12 @@
+     if (record_bytes == 1204) /* do checksum for viking */
+       for (i=0; i<record_bytes; i++) checksum += (int)obuf[i];
+ 
+-    if ((line % 100 == 0) && (outfile != stdout)) 
++    if ((line % 100 == 0) && (outfile != stdout))
+       fprintf(stderr,"\nline %d",line);
+ 
+   } while (length > 0 && line < max_lines);
+ 
+-  if (record_bytes == 1204  && (outfile  != stdout)) 
++  if (record_bytes == 1204  && (outfile  != stdout))
+     /* print checksum for viking */
+     fprintf(stderr,"\n Image label checksum = %d computed checksum = %d\n",
+ 	    label_checksum,checksum);
+@@ -425,33 +443,36 @@
+ /*********************************************************************/
+ 
+ int get_files(host)
+-int host;
++  int host;
+ {
+-  short   shortint;
+   typedef long    off_t;
++  short   shortint;
++  char    *s;
+ 
+   if (inname[0] == ' ') {
+     printf("\nEnter name of file to be decompressed: ");
+-    gets (inname);
++    fgets(inname, sizeof(inname), stdin);
++    if ((s = strchr(inname, '\n')) != NULL)
++      *s = '\0';
+   }
+ 
+-  if (host == 1 | host == 2) {
+-    if ((infile = open(inname,O_RDONLY | O_BINARY)) <= 0) {
+-      fprintf(stderr,"\ncan't open input file: %s\n",inname);
++  if (host == 1 || host == 2) {
++    if ((infile = open(inname, O_RDONLY | O_BINARY)) <= 0) {
++      fprintf(stderr,"\ncan't open input file: %s\n", inname);
+       exit(1);
+     }
+   }
+-  else if (host == 3 | host == 5) {
+-    if ((infile = open(inname,O_RDONLY)) <= 0) {
+-      fprintf(stderr,"\ncan't open input file: %s\n",inname);
++  else if (host == 3 || host == 5) {
++    if ((infile = open(inname, O_RDONLY)) <= 0) {
++      fprintf(stderr,"\ncan't open input file: %s\n", inname);
+       exit(1);
+     }
+ 
+     /****************************************************************/
+-    /* If we are on a vax see if the file is in var length format.  */
+-    /* This logic is in here in case the vax file has been stored   */
++    /* If we are on a VAX see if the file is in var length format.  */
++    /* This logic is in here in case the VAX file has been stored   */
+     /* in fixed or undefined format.  This might be necessary since */
+-    /* vax variable length files can't be moved to other computer   */
++    /* VAX variable-length files can't be moved to other computer   */
+     /* systems with standard comm programs (kermit, for example).   */
+     /****************************************************************/
+ 
+@@ -459,9 +480,9 @@
+        read(infile,&shortint, (size_t) 2);
+        if (shortint > 0 && shortint < 80) {
+ 	 host = 4;              /* change host to 4                */
+-	 printf("This is not a VAX variable length file.");
++	 printf("This is not a VAX variable-length file.");
+        }
+-       else printf("This is a VAX variable length file.");
++       else printf("This is a VAX variable-length file.");
+        lseek(infile,(off_t) 0,0);     /* reposition to beginning of file */
+      }
+   }
+@@ -474,13 +495,17 @@
+       printf("\n  3.  VICAR format.");
+       printf("\n  4.  Unlabelled binary array.\n");
+       printf("\n  Enter format number:");
+-      gets(inname);
++      fgets(inname, sizeof(inname), stdin);
++      if ((s = strchr(inname, '\n')) != NULL)
++        *s = '\0';
+       output_format = atoi(inname);
+     } while (output_format < 1 || output_format > 4);
+ 
+   if (outname[0] == ' ') {
+     printf("\nEnter name of uncompressed output file: ");
+-    gets (outname);
++    fgets(outname, sizeof(outname), stdin);
++    if ((s = strchr(outname, '\n')) != NULL)
++      *s = '\0';
+   }
+ 
+   return(host);
+@@ -495,68 +520,68 @@
+ /*********************************************************************/
+ 
+ void open_files(host)
+-int *host;
++  int *host;
+ {
+   if (*host == 1 || *host == 2 || *host == 5)  {
+     if (outname[0] == '-') outfile=stdout;
+-    else if ((outfile = fopen(outname,"wb"))==NULL) {
+-      fprintf(stderr,"\ncan't open output file: %s\n",outname);
++    else if ((outfile = fopen(outname, "wb"))==NULL) {
++      fprintf(stderr,"\ncan't open output file: %s\n", outname);
+       exit(1);
+     }
+   }
+ 
+   else if (*host == 3 || *host == 4) {
+     if (output_format == 1) {     /* write PDS format blocks */
+-      if (record_bytes == 836) { 
+-	if ((outfile=fopen(outname,"w"
++      if (record_bytes == 836) {
++	if ((outfile=fopen(outname, "w"
+ #ifdef VMS
+ 			   ,"mrs=836",FOP,CTX,RECORD_TYPE
+ #endif
+ 			   ))==NULL) {
+-	  fprintf(stderr,"\ncan't open output file: %s\n",outname);
++	  fprintf(stderr,"\ncan't open output file: %s\n", outname);
+ 	  exit(1);
+ 	}
+       }
+       else {
+-	if ((outfile=fopen(outname,"w"
++	if ((outfile=fopen(outname, "w"
+ #ifdef VMS
+ 			   ,"mrs=1204",FOP,CTX,RECORD_TYPE
+ #endif
+ 			   ))==NULL) {
+-	  fprintf(stderr,"\ncan't open output file: %s\n",outname);
++	  fprintf(stderr,"\ncan't open output file: %s\n", outname);
+ 	  exit(1);
+ 	}
+       }
+     }
+     else if (output_format == 2) {  /* write FITS format blocks */
+-      if ((outfile=fopen(outname,"w"
++      if ((outfile=fopen(outname, "w"
+ #ifdef VMS
+ 			 ,"mrs=2880",FOP,CTX,RECORD_TYPE
+ #endif
+ 			 ))==NULL) {
+-	fprintf(stderr,"\ncan't open output file: %s\n",outname);
++	fprintf(stderr,"\ncan't open output file: %s\n", outname);
+ 	exit(1);
+       }
+     }
+ 
+-    else {                       /* write fixed length records */
+-      if (record_bytes == 836) { 
+-	if ((outfile=fopen(outname,"w"
++    else {                       /* write fixed-length records */
++      if (record_bytes == 836) {
++	if ((outfile=fopen(outname, "w"
+ #ifdef VMS
+ 			   ,"mrs=800",FOP,CTX,RECORD_TYPE
+ #endif
+ 			   ))==NULL) {
+-	  fprintf(stderr,"\ncan't open output file: %s\n",outname);
++	  fprintf(stderr,"\ncan't open output file: %s\n", outname);
+ 	  exit(1);
+ 	}
+       }
+       else {
+-	if ((outfile=fopen(outname,"w"
++	if ((outfile=fopen(outname, "w"
+ #ifdef VMS
+ 			   ,"mrs=1204",FOP,CTX,RECORD_TYPE
+ #endif
+ 			   ))==NULL) {
+-	  fprintf(stderr,"\ncan't open output file: %s\n",outname);
++	  fprintf(stderr,"\ncan't open output file: %s\n", outname);
+ 	  exit(1);
+ 	}
+       }
+@@ -572,11 +597,11 @@
+ /*********************************************************************/
+ 
+ void pds_labels(host)
+-     int host;
++  int host;
+ {
+-  char          outstring[80],ibuf[2048];
++  char          ibuf[2048];
+   unsigned char cr=13,lf=10,blank=32;
+-  short         length,nlen,total_bytes,line,i;
++  short         length,total_bytes,i;
+ 
+ 
+   total_bytes = 0;
+@@ -613,11 +638,11 @@
+ 	       (size_t) 53,(size_t) 1,outfile);
+       else
+         fwrite("CCSD3ZF0000100000001NJPL3IF0PDS200000001 = SFDU_LABEL",
+-	       (size_t) 53,(size_t) 1,outfile);      
++	       (size_t) 53,(size_t) 1,outfile);
+ 
+       fprintf(outfile,"%c%c",cr,lf);
+       fwrite("/*          FILE FORMAT AND LENGTH */",(size_t) 37,(size_t) 1,
+-	     outfile);      
++	     outfile);
+       fprintf(outfile,"%c%c",cr,lf);
+       fwrite("RECORD_TYPE                      = FIXED_LENGTH",(size_t) 47,
+ 	     (size_t) 1,outfile);
+@@ -710,7 +735,7 @@
+       }
+       else {
+ 	strcpy(ibuf+35,"60");
+-	length = length - 2; 
++	length = length - 2;
+       }
+ 
+       fwrite(ibuf,(size_t) length,(size_t) 1,outfile);
+@@ -730,7 +755,7 @@
+     }
+ 
+     else if ((i = strncmp(ibuf," ENCODING",(size_t) 9)) == 0);
+-    
++
+     /*****************************************************************/
+     /* delete the encoding type label in the image object            */
+     /*****************************************************************/
+@@ -787,10 +812,10 @@
+ /*********************************************************************/
+ 
+ void fits_labels(host)
+-int host;
++  int host;
+ {
+   char          ibuf[2048],outstring[80];
+-  short         length,nlen,total_bytes,line,i;
++  short         length,total_bytes,i;
+   unsigned char cr=13,lf=10,blank=32;
+ 
+   do {
+@@ -799,7 +824,7 @@
+     /*****************************************************************/
+     /* find the checksum and store in label_checksum                 */
+     /*****************************************************************/
+-    if ((i = strncmp(ibuf," CHECKSUM",(size_t) 9)) == 0) { 
++    if ((i = strncmp(ibuf," CHECKSUM",(size_t) 9)) == 0) {
+       ibuf[length]   = '\0';
+       label_checksum = atol(ibuf+35);
+     }
+@@ -842,7 +867,7 @@
+ 
+   if (record_bytes == 836)
+     strcpy(outstring,"NAXIS1  =                  800");
+-  else 
++  else
+     strcpy(outstring,"NAXIS1  =                 1204");
+ 
+   strcat(outstring,"                                               ");
+@@ -862,7 +887,7 @@
+ 
+   strcpy(outstring,"END                             ");
+   strcat(outstring,"                                               ");
+-  
++
+   fwrite(outstring,(size_t) 78,(size_t) 1,outfile);
+   fprintf(outfile,"%c%c",cr,lf);
+   total_bytes = total_bytes + 80;
+@@ -871,6 +896,7 @@
+   for (i=total_bytes; i<2880; i++) fputc(blank,outfile);
+ }
+ 
++
+ /*********************************************************************/
+ /*                                                                   */
+ /* subroutine vicar_labels - write vicar labels to output file       */
+@@ -878,11 +904,10 @@
+ /*********************************************************************/
+ 
+ void vicar_labels(host)
+-int host;
+-
++  int host;
+ {
+   char          ibuf[2048],outstring[80];
+-  short         length,nlen,total_bytes,line,i;
++  short         length,total_bytes,i;
+   unsigned char cr=13,lf=10,blank=32;
+ 
+   do {
+@@ -890,7 +915,7 @@
+     /*****************************************************************/
+     /* find the checksum and store in label_checksum                 */
+     /*****************************************************************/
+-    if ((i = strncmp(ibuf," CHECKSUM",(size_t) 9)) == 0) { 
++    if ((i = strncmp(ibuf," CHECKSUM",(size_t) 9)) == 0) {
+       ibuf[length]   = '\0';
+       label_checksum = atol(ibuf+35);
+     }
+@@ -950,10 +975,10 @@
+ /*********************************************************************/
+ 
+ void no_labels(host)
+-int host;
++  int host;
+ {
+-  char          ibuf[2048],outstring[80];
+-  short         length,nlen,total_bytes,line,i;
++  char          ibuf[2048];
++  short         length,i;
+ 
+   do {
+     length = read_var(ibuf,host);
+@@ -961,7 +986,7 @@
+     /*****************************************************************/
+     /* find the checksum and store in label_checksum                 */
+     /*****************************************************************/
+-    if ((i = strncmp(ibuf," CHECKSUM",(size_t) 9)) == 0) { 
++    if ((i = strncmp(ibuf," CHECKSUM",(size_t) 9)) == 0) {
+       ibuf[length]   = '\0';
+       label_checksum = atol(ibuf+35);
+     }
+@@ -984,15 +1009,16 @@
+   open_files(&host);
+ }
+ 
++
+ /*********************************************************************/
+ /*                                                                   */
+-/* subroutine read_var - read variable length records from input file*/
++/* subroutine read_var - read variable-length records from input file*/
+ /*                                                                   */
+ /*********************************************************************/
+ 
+ int read_var(ibuf,host)
+-char  *ibuf;
+-int   host;
++  char  *ibuf;
++  int   host;
+ {
+   int   length,result,nlen;
+   char  temp;
+@@ -1027,19 +1053,19 @@
+     return (length);
+ 
+   case 3: /*******************************************************/
+-          /* VAX host with variable length support               */
++          /* VAX host with variable-length support               */
+           /*******************************************************/
+     length = read(infile,ibuf,(size_t) 2048/* upper bound */);
+     return (length);
+ 
+   case 4: /*******************************************************/
+-          /* VAX host, but not a variable length file            */
++          /* VAX host, but not a variable-length file            */
+           /*******************************************************/
+     length = 0;
+     result = read(infile,&length,(size_t) 2);
+     nlen =   read(infile,ibuf,(size_t) length+(length%2));
+ 
+-    /* check to see if we crossed a vax record boundary          */
++    /* check to see if we crossed a VAX record boundary          */
+     while (nlen < length)
+       nlen += read(infile,ibuf+nlen,(size_t) length+(length%2)-nlen);
+     return (length);
+@@ -1061,6 +1087,7 @@
+   return 0;
+ }
+ 
++
+ /*********************************************************************/
+ /*                                                                   */
+ /* subroutine check_host - find out what kind of machine we are on   */
+@@ -1115,23 +1142,23 @@
+ 	   "Host 5 - 32 bit integers without swapping, no var len support.");
+   }
+ 
+-  if ((*outname)!='-') fprintf(stderr,"%s\n",hostname);
++  if ((*outname) != '-') fprintf(stderr, "%s\n", hostname);
+   return(host);
+ }
+ 
+ 
+-int swap_int(inval)  /* swap 4 byte integer                       */
+-     int inval;
++int swap_int(inval)  /* swap 4 byte integer */
++  int inval;
+ {
+-  union /* this union is used to swap 16 and 32 bit integers          */
++  union /* this union is used to swap 16 and 32 bit integers */
+     {
+       char  ichar[4];
+       short slen;
+       int   llen;
+     } onion;
+   char   temp;
+-  
+-  /* byte swap the input field                                      */
++
++  /* byte swap the input field */
+   onion.llen   = inval;
+   temp   = onion.ichar[0];
+   onion.ichar[0]=onion.ichar[3];
+@@ -1146,17 +1173,13 @@
+ /****************************************************************************
+ *_TITLE decompress - decompresses image lines stored in compressed format   *
+ *_ARGS  TYPE       NAME      I/O        DESCRIPTION                         */
+-        char *ibuf;        /* I         Compressed data buffer              */
+-        char *obuf;        /* O         Decompressed image line             */
+-        int       *nin;   /* I         Number of bytes on input buffer     */
+-        int       *nout;  /* I         Number of bytes in output buffer    */
+-
++        char       *ibuf;  /* I         Compressed data buffer              */
++        char       *obuf;  /* O         Decompressed image line             */
++        int        *nin;   /* I         Number of bytes on input buffer     */
++        int        *nout;  /* I         Number of bytes in output buffer    */
+ {
+-  /* The external root pointer to tree */
+-  extern NODE *tree;
+-
+   dcmprs(ibuf,obuf,nin,nout,tree);
+-  
++
+   return;
+ }
+ 
+@@ -1165,10 +1188,8 @@
+ /***************************************************************************
+ *_TITLE decmpinit - initializes the Huffman tree                           *
+ *_ARGS  TYPE       NAME      I/O        DESCRIPTION                        */
+-        int      *hist;  /* I         First-difference histogram.        */
+-
++        int        *hist;  /* I         First-difference histogram.        */
+ {
+-  extern NODE *tree;          /* Huffman tree root pointer */
+   tree = huff_tree(hist);
+   return;
+ }
+@@ -1178,8 +1199,7 @@
+ /****************************************************************************
+ *_TITLE huff_tree - constructs the Huffman tree; returns pointer to root    *
+ *_ARGS  TYPE          NAME        I/O   DESCRIPTION                         */
+-        int     *hist;     /* I    First difference histogram          */
+-
++        int          *hist;     /* I    First difference histogram          */
+ {
+   /*  Local variables used */
+   int freq_list[512];      /* Histogram frequency list */
+@@ -1189,7 +1209,6 @@
+   NODE **np;        /* Node list pointer */
+ 
+   int num_freq;   /* Number non-zero frequencies in histogram */
+-  int sum;                 /* Sum of all frequencies */
+ 
+   short int num_nodes; /* Counter for DN initialization */
+   short int cnt;       /* Miscellaneous counter */
+@@ -1228,7 +1247,7 @@
+ 
+     j = 0;
+     for (i=4 ; --i >= 0 ; j = (j << 8) | *(cp+i));
+-    
++
+     /* Now make the assignment */
+     *fp++ = j;
+     temp = new_node(num_nodes);
+@@ -1341,7 +1360,7 @@
+       l--;
+       if ( j <= freq_list) break;
+     }
+-    
++
+   }
+   return;
+ }
+@@ -1362,9 +1381,9 @@
+   NODE *ptr = root;        /* pointer to position in tree */
+   unsigned char test;      /* test byte for bit set */
+   unsigned char idn;       /* input compressed byte */
+-  
++
+   char odn;                /* last dn value decompressed */
+-  
++
+   char *ilim = ibuf + *nin;         /* end of compressed bytes */
+   char *olim = obuf + *nout;        /* end of output buffer */
+ 
+@@ -1406,10 +1425,9 @@
+ /****************************************************************************
+ *_TITLE free_tree - free memory of all allocated nodes                      *
+ *_ARGS  TYPE       NAME       I/O        DESCRIPTION                        */
+-        int      *nfreed;  /* O        Return of total count of nodes     *
++        int        *nfreed;  /* O        Return of total count of nodes     *
+ *                                        freed.                             */
+-
+-/*
++/*                                                                          *
+ *_DESCR This routine is supplied to the programmer to free up all the       *
+ *       allocated memory required to build the huffman tree.  The count     *
+ *       of the nodes freed is returned in the parameter 'nfreed'.  The      *
+@@ -1417,16 +1435,13 @@
+ *       than one file per run, the program will not keep allocating new     *
+ *       memory without first deallocating all previous nodes associated     *
+ *       with the previous file decompression.                               *
+-
++*                                                                           *
+ *_HIST  16-AUG-89 Kris Becker   USGS, Flagstaff Original Version            *
+ *_END                                                                       *
+ ****************************************************************************/
+-
+ {
+   int total_free = 0;
+ 
+-  extern NODE *tree;      /* Huffman tree root pointer */
+-
+   *nfreed = free_node(tree,total_free);
+ 
+   return;
+@@ -1435,36 +1450,33 @@
+ 
+ int free_node(pnode,total_free)
+ /***************************************************************************
+-*_TITLE free_node - deallocates an allocated NODE pointer
++*_TITLE free_node - deallocates an allocated NODE pointer                  *
+ *_ARGS  TYPE     NAME          I/O   DESCRIPTION                           */
+         NODE     *pnode;       /* I  Pointer to node to free               */
+-        int       total_free;   /* I  Total number of freed nodes           */
+-
+-/*
++        int      total_free;   /* I  Total number of freed nodes           */
++/*                                                                         *
+ *_DESCR  free_node will check both right and left pointers of a node       *
+ *        and then free the current node using the free() C utility.        *
+ *        Note that all nodes attached to the node via right or left        *
+ *        pointers area also freed, so be sure that this is the desired     *
+ *        result when calling this routine.                                 *
+-
++*                                                                          *
+ *        This routine is supplied to allow successive calls to the         *
+ *        decmpinit routine.  It will free up the memory allocated          *
+ *        by previous calls to the decmpinit routine.  The call to free     *
+-*        a previous huffman tree is:  total = free_node(tree,(int) 0);    *
++*        a previous huffman tree is:  total = free_node(tree,(int) 0);     *
+ *        This call must be done by the programmer application routine      *
+ *        and is not done by any of these routines.                         *
+ *_HIST   16-AUG-89  Kris Becker U.S.G.S  Flagstaff Original Version        */
+ {
+   if (pnode == (NODE *) NULL) return(total_free);
+-  
++
+   if (pnode->right != (NODE *) NULL)
+     total_free = free_node(pnode->right,total_free);
+   if (pnode->left != (NODE *) NULL)
+     total_free = free_node(pnode->left,total_free);
+-  
++
+   free((char *) pnode);
+   return(total_free + 1);
+ }
+ 
+-
+-
+diff -ru xv-3.10a/xcmap.c xv-3.10a-enhancements/xcmap.c
+--- xv-3.10a/xcmap.c	1995-01-03 13:14:52.000000000 -0800
++++ xv-3.10a-enhancements/xcmap.c	2007-04-15 13:12:41.000000000 -0700
+@@ -9,6 +9,9 @@
+ 
+ /* include files */
+ #include <stdio.h>
++#ifdef __STDC__
++#  include <stdlib.h>   /* exit(), abs() */
++#endif
+ #include <sys/types.h>
+ #include <ctype.h>
+ 
+@@ -18,7 +21,7 @@
+ #include <X11/cursorfont.h>
+ 
+ #ifdef VMS
+-#define index strchr
++#  define index strchr
+ #endif
+ 
+ typedef unsigned char byte;
+@@ -58,7 +61,7 @@
+        int  main             PARM((int, char **));
+ static void HandleEvent      PARM((XEvent *));
+ static void Syntax           PARM((void));
+-static void FatalError       PARM((char *));
++static void FatalError       PARM((const char *));
+ static void Quit             PARM((void));
+ static void CreateMainWindow PARM((char *, char *, int, char **));
+ static void DrawWindow       PARM((int,int,int,int));
+@@ -75,50 +78,50 @@
+   int        i;
+   char      *display, *geom;
+   XEvent     event;
+-  
++
+   cmd = argv[0];
+   display = geom = NULL;
+-  
+-  
++
++
+   /*********************Options*********************/
+-  
++
+   for (i = 1; i < argc; i++) {
+     char *strind;
+-    
++
+     if (!strncmp(argv[i],"-g", (size_t)2)) {	/* geometry */
+       i++;
+       geom = argv[i];
+       continue;
+     }
+-    
++
+     if (argv[i][0] == '=') {		/* old-style geometry */
+       geom = argv[i];
+       continue;
+     }
+-    
++
+     if (!strncmp(argv[i],"-d",(size_t) 2)) {	/* display */
+       i++;
+       display = argv[i];
+       continue;
+     }
+-    
++
+     strind = (char *) index(argv[i], ':');	/* old-style display */
+     if(strind != NULL) {
+       display = argv[i];
+       continue;
+     }
+-    
++
+     Syntax();
+   }
+-  
+-  
++
++
+   /*****************************************************/
+-  
++
+   /* Open up the display. */
+-  
++
+   if ( (theDisp=XOpenDisplay(display)) == NULL)
+     FatalError("can't open display");
+-  
++
+   theScreen = DefaultScreen(theDisp);
+   theCmap   = DefaultColormap(theDisp, theScreen);
+   rootW     = RootWindow(theDisp,theScreen);
+@@ -126,9 +129,9 @@
+   fcol      = WhitePixel(theDisp,theScreen);
+   bcol      = BlackPixel(theDisp,theScreen);
+   theVisual = DefaultVisual(theDisp,theScreen);
+-  
++
+   dispcells = DisplayCells(theDisp, theScreen);
+-  
++
+   if (dispcells>256) {
+     sprintf(tmpstr,"dispcells = %d.  %s",
+ 	    dispcells, "This program can only deal with <= 8-bit displays.");
+@@ -140,27 +143,32 @@
+     nxcells = nycells = 8;
+   else if (dispcells>4)
+     nxcells = nycells = 4;
+-  else
++  else if (dispcells>2)
+     nxcells = nycells = 2;
+-  
++  else
++  {
++    nxcells = 2;
++    nycells = 1;
++  }
++
+   /**************** Create/Open X Resources ***************/
+   if ((mfinfo = XLoadQueryFont(theDisp,FONT))==NULL) {
+     sprintf(tmpstr,"couldn't open '%s' font",FONT);
+     FatalError(tmpstr);
+   }
+-  
++
+   mfont=mfinfo->fid;
+   XSetFont(theDisp,theGC,mfont);
+   XSetForeground(theDisp,theGC,fcol);
+   XSetBackground(theDisp,theGC,bcol);
+-  
++
+   CreateMainWindow(cmd,geom,argc,argv);
+-  Resize(WIDE,HIGH);
+-  
+-  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++  Resize((int)WIDE,(int)HIGH);
++
++  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 	       | StructureNotifyMask | ButtonPressMask);
+   XMapWindow(theDisp,mainW);
+-  
++
+   /**************** Main loop *****************/
+   while (1) {
+     XNextEvent(theDisp, &event);
+@@ -177,41 +185,41 @@
+   switch (event->type) {
+   case Expose: {
+     XExposeEvent *exp_event = (XExposeEvent *) event;
+-    
+-    if (exp_event->window==mainW) 
++
++    if (exp_event->window==mainW)
+       DrawWindow(exp_event->x,exp_event->y,
+ 		 exp_event->width, exp_event->height);
+   }
+     break;
+-    
++
+   case ButtonPress: {
+     XButtonEvent *but_event = (XButtonEvent *) event;
+-    
+-    if (but_event->window == mainW && but_event->button == Button1) 
++
++    if (but_event->window == mainW && but_event->button == Button1)
+       TrackMouse(but_event->x, but_event->y);
+   }
+     break;
+-    
++
+   case KeyPress: {
+     XKeyEvent *key_event = (XKeyEvent *) event;
+     KeySym ks;
+     XComposeStatus status;
+-    
++
+     XLookupString(key_event,tmpstr,128,&ks,&status);
+     if (tmpstr[0]=='q' || tmpstr[0]=='Q') Quit();
+   }
+     break;
+-    
++
+   case ConfigureNotify: {
+     XConfigureEvent *conf_event = (XConfigureEvent *) event;
+-    
+-    if (conf_event->window == mainW && 
+-	(conf_event->width != WIDE || conf_event->height != HIGH))
+-      Resize(conf_event->width, conf_event->height);
++    int w = conf_event->width, h = conf_event->height;
++
++    if (conf_event->window == mainW && (w != WIDE || h != HIGH))
++      Resize((int)(w ? w : WIDE), (int)(h ? h : HIGH));
+   }
+     break;
+-    
+-    
++
++
+   case CirculateNotify:
+   case MapNotify:
+   case DestroyNotify:
+@@ -220,7 +228,7 @@
+   case UnmapNotify:
+   case MappingNotify:
+   case ClientMessage:         break;
+-    
++
+   default:		/* ignore unexpected events */
+     break;
+   }  /* end of switch */
+@@ -237,10 +245,10 @@
+ 
+ 
+ /***********************************/
+-static void FatalError (identifier)
+-     char *identifier;
++static void FatalError(identifier)
++     const char *identifier;
+ {
+-  fprintf(stderr, "%s: %s\n",cmd, identifier);
++  fprintf(stderr, "%s: %s\n", cmd, identifier);
+   exit(-1);
+ }
+ 
+@@ -262,24 +270,33 @@
+   XSizeHints hints;
+   int i,x,y;
+   unsigned int w,h;
+-  
++
+   WIDE = HIGH = 256;			/* default window size */
+-  
++
+   x=y=w=h=1;
++  hints.flags = 0;
++
+   i=XParseGeometry(geom,&x,&y,&w,&h);
+-  if (i&WidthValue)  WIDE = (int) w;
+-  if (i&HeightValue) HIGH = (int) h;
+-  
+-  if (i&XValue || i&YValue) hints.flags = USPosition;  
+-  else hints.flags = PPosition;
+-  
+-  hints.flags |= USSize;
+-  
+-  if (i&XValue && i&XNegative) 
+-    x = XDisplayWidth(theDisp,theScreen)-WIDE-abs(x);
+-  if (i&YValue && i&YNegative) 
+-    y = XDisplayHeight(theDisp,theScreen)-HIGH-abs(y);
+-  
++  if (i&WidthValue)
++  {
++    WIDE = (int) w;
++    hints.flags |= USSize;
++  }
++  if (i&HeightValue)
++  {
++    HIGH = (int) h;
++    hints.flags |= USSize;
++  }
++
++  if (i&XValue || i&YValue)
++  {
++    if (i&XNegative)
++      x = XDisplayWidth(theDisp,theScreen)-WIDE-abs(x);
++    if (i&YNegative)
++      y = XDisplayHeight(theDisp,theScreen)-HIGH-abs(y);
++    hints.flags |= USPosition;
++  }
++
+   hints.x=x;             hints.y=y;
+   hints.width  = WIDE;   hints.height = HIGH;
+   hints.max_width  = DisplayWidth(theDisp,theScreen);
+@@ -288,22 +305,22 @@
+   hints.min_height = 16;
+   hints.width_inc = hints.height_inc = 16;
+   hints.flags |= PMaxSize | PMinSize | PResizeInc;
+-  
++
+   xswa.background_pixel = bcol;
+   xswa.border_pixel     = fcol;
+   xswa.cursor = XCreateFontCursor (theDisp, XC_top_left_arrow);
+   xswamask = CWBackPixel | CWBorderPixel | CWCursor;
+-  
++
+   mainW = XCreateWindow(theDisp,rootW,x,y,(unsigned int) WIDE,
+-			(unsigned int) HIGH, 2, 0, 
++			(unsigned int) HIGH, 2, 0,
+ 			(unsigned int) CopyFromParent,
+ 			CopyFromParent, xswamask, &xswa);
+-  
++
+   XSetStandardProperties(theDisp,mainW,"xcmap","xcmap",None,
+ 			 argv,argc,&hints);
+-  
++
+   if (!mainW) FatalError("Can't open main window");
+-  
++
+ }
+ 
+ 
+@@ -312,11 +329,11 @@
+      int x,y,w,h;
+ {
+   int i,j,x1,y1,x2,y2;
+-  
++
+   x1 = x / cWIDE;      y1 = y / cHIGH;	/* (x1,y1) (x2,y2): bounding */
+   x2 = ((x+w) + cWIDE - 1) / cWIDE;		/*       rect in cell coords */
+   y2 = ((y+h) + cHIGH - 1) / cHIGH;
+-  
++
+   for (i=y1; i<y2; i++) {
+     for (j=x1; j<x2; j++) {
+       XSetForeground(theDisp,theGC,(unsigned long) (i*nycells+j) );
+@@ -343,18 +360,18 @@
+ {
+   /* called when there's a button press in the window.  draws the pixel
+      value, and loops until button is released */
+-  
++
+   Window        rootW,childW;
+   int           rx,ry,x,y;
+   unsigned int  mask;
+-  
++
+   pvalup = 0;
+   DrawPixValue(mx,my);
+-  
++
+   while (1) {
+     if (XQueryPointer(theDisp,mainW,&rootW,&childW,&rx,&ry,&x,&y,&mask)) {
+       if (!(mask & Button1Mask)) break;    /* button released */
+-      
++
+       DrawPixValue(x,y);
+     }
+   }
+@@ -367,10 +384,10 @@
+ {
+   static unsigned long pix, lastpix;
+   static int           pvaly;
+-  
++
+   if (x<0) x=0;  if (x>=WIDE) x=WIDE-1;
+   if (y<0) y=0;  if (y>=HIGH) y=HIGH-1;
+-  
++
+   if (!pvalup) {	/* it's not up.  make it so */
+     if (y >= HIGH/2) pvaly = 0;  else pvaly = HIGH - 12;
+     pvalup = 1;
+@@ -378,30 +395,30 @@
+     XClearArea(theDisp,mainW,0,pvaly,
+ 	       (unsigned int) WIDE, (unsigned int) 13,True);
+   }
+-  
++
+   x /= cWIDE;  y /= cHIGH;
+-  
++
+   pix = y * nxcells + x;
+-  
++
+   if (pix != lastpix) {
+     XColor def;
+     char  *sp;
+-    
++
+     XSetForeground(theDisp,theGC,fcol);
+     lastpix = def.pixel = pix;
+     if (pix<dispcells) {
+       XQueryColor(theDisp, theCmap, &def);
+       sprintf(tmpstr, "Pix %3ld = ($%04x, $%04x, $%04x)",
+ 	      pix, def.red, def.green, def.blue);
+-      
+-      /* make the hex uppercase */        
+-      for (sp=tmpstr+4; *sp; sp++) 
++
++      /* make the hex uppercase */
++      for (sp=tmpstr+4; *sp; sp++)
+ 	if (islower(*sp)) *sp = toupper(*sp);
+     }
+     else {
+       sprintf(tmpstr, "Pix %3ld is out of legal range. ", pix);
+     }
+-    
++
+     XDrawImageString(theDisp,mainW,theGC,5,pvaly+10,tmpstr,
+ 		     (int) strlen(tmpstr));
+   }
+diff -ru xv-3.10a/xv.c xv-3.10a-enhancements/xv.c
+--- xv-3.10a/xv.c	1995-01-19 10:08:43.000000000 -0800
++++ xv-3.10a-enhancements/xv.c	2007-05-13 18:44:55.000000000 -0700
+@@ -33,9 +33,9 @@
+ 
+ /* a mono-spaced font needed for the 'pixel value tracking' feature */
+ #define MFONT1 "-misc-fixed-medium-r-normal-*-13-*"
+-#define MFONT2 "6x13"   
++#define MFONT2 "6x13"
+ #define MFONT3 "-*-courier-medium-r-*-*-12-*"
+-#define MFONT4 "fixed"   
++#define MFONT4 "fixed"
+ 
+ 
+ /* default positions for various windows */
+@@ -54,14 +54,35 @@
+ static int    randomShow = 0;   /* do a 'random' slideshow */
+ static int    startIconic = 0;  /* '-iconic' option */
+ static int    defaultVis  = 0;  /* true if using DefaultVisual */
++#ifdef HAVE_G3
++static int    fax = 0;          /* temporary(?) kludge */
++int           highresfax = 0;
++#endif
+ static double hexpand = 1.0;    /* '-expand' argument */
+ static double vexpand = 1.0;    /* '-expand' argument */
+-static char  *maingeom = NULL;
+-static char  *icongeom = NULL;
++static const char *maingeom = NULL;
++static const char *icongeom = NULL;
+ static Atom   __SWM_VROOT = None;
+ 
+ static char   basefname[128];   /* just the current fname, no path */
+ 
++#ifdef TV_L10N
++#  ifndef TV_FONTSET
++#    define TV_FONTSET "-*-fixed-medium-r-normal--%d-*"
++#  endif
++#  ifndef TV_FONTSIZE
++#    define TV_FONTSIZE 14,16
++#  endif
++static int    mfontsize[] = { TV_FONTSIZE, 0 };
++static char   mfontset[256];
++#endif
++
++#ifdef HAVE_JP2K
++static byte jp2k_magic[12] =
++  { 0, 0, 0, 0x0c, 'j', 'P', ' ', ' ', 0x0d, 0x0a, 0x87, 0x0a };
++#endif
++
++
+ /* things to do upon successfully loading an image */
+ static int    autoraw    = 0;   /* force raw if using stdcmap */
+ static int    autodither = 0;   /* dither */
+@@ -78,6 +99,12 @@
+ 
+ static int    force8     = 0;   /* force 8-bit mode */
+ static int    force24    = 0;   /* force 24-bit mode */
++#ifdef HAVE_PCD
++static int    PcdSize    = -1;  /* force dialog to ask */
++#endif
++
++static float  waitsec_nonfinal = -1;  /* "normal" waitsec value */
++static float  waitsec_final = -1;     /* final-image waitsec value */
+ 
+ /* used in DeleteCmd() and Quit() */
+ static char  **mainargv;
+@@ -92,7 +119,7 @@
+ static void parseResources           PARM((int, char **));
+ static void parseCmdLine             PARM((int, char **));
+ static void verifyArgs               PARM((void));
+-static void printoption              PARM((char *));
++static void printoption              PARM((const char *));
+ static void cmdSyntax                PARM((void));
+ static void rmodeSyntax              PARM((void));
+ static int  openPic                  PARM((int));
+@@ -103,32 +130,34 @@
+ static void openNextLoop             PARM((void));
+ static void openPrevPic              PARM((void));
+ static void openNamedPic             PARM((void));
+-static int  findRandomPic            PARM((void));
+ static void mainLoop                 PARM((void));
+-static void createMainWindow         PARM((char *, char *));
+-static void setWinIconNames          PARM((char *));
++static void createMainWindow         PARM((const char *, const char *));
++static void setWinIconNames          PARM((const char *));
+ static void makeDispNames            PARM((void));
+ static void fixDispNames             PARM((void));
+ static void deleteFromList           PARM((int));
+-static int  argcmp                   PARM((char *, char *, int, int, int *));
++static int  argcmp                   PARM((const char *, const char *,
++                                           int, int, int *));
+ static void add_filelist_to_namelist PARM((char *, char **, int *, int));
+ 
+ 
+ /* formerly local vars in main, made local to this module when
+    parseResources() and parseCmdLine() were split out of main() */
+-   
+-int   imap, ctrlmap, gmap, browmap, cmtmap, clrroot, nopos, limit2x;
+-char *display, *whitestr, *blackstr, *histr, *lostr,
+-     *infogeom, *fgstr, *bgstr, *ctrlgeom, *gamgeom, *browgeom, *tmpstr;
+-char *rootfgstr, *rootbgstr, *visualstr, *textgeom, *cmtgeom;
+-char *monofontname, *flistName;
+-int  curstype, stdinflag, browseMode, savenorm, preview, pscomp, preset, 
+-     rmodeset, gamset, cgamset, perfect, owncmap, rwcolor, stdcmap;
+-int  nodecor;
+-double gamval, rgamval, ggamval, bgamval;
+-
+-
+ 
++static int   imap, ctrlmap, gmap, browmap, cmtmap, clrroot, nopos, limit2x;
++static const char *histr, *lostr, *fgstr, *bgstr, *tmpstr;
++static const char *infogeom, *ctrlgeom, *gamgeom, *browgeom, *textgeom, *cmtgeom;
++static char *display, *whitestr, *blackstr;
++static char *rootfgstr, *rootbgstr, *imagebgstr, *visualstr;
++static char *monofontname, *flistName;
++#ifdef TV_L10N
++static char **misscharset, *defstr;
++static int nmisscharset;
++#endif
++static int  curstype, stdinflag, browseMode, savenorm, preview, pscomp, preset,
++            rmodeset, gamset, cgamset, perfect, owncmap, rwcolor, stdcmap;
++static int  nodecor;
++static double gamval, rgamval, ggamval, bgamval;
+ 
+ /*******************************************/
+ int main(argc, argv)
+@@ -137,6 +166,9 @@
+ /*******************************************/
+ {
+   int    i;
++#ifdef TV_L10N
++  int    j;
++#endif
+   XColor ecdef;
+   Window rootReturn, parentReturn, *children;
+   unsigned int numChildren, rootDEEP;
+@@ -153,6 +185,13 @@
+   /*** variable Initialization                       ***/
+   /*****************************************************/
+ 
++#ifdef TV_L10N
++  /* setlocale(LC_ALL, localeList[LOCALE_EUCJ]); */
++  setlocale(LC_ALL, "");
++  xlocale = (int)XSupportsLocale();	/* assume that (Bool) is (int) */
++	/* if X doesn't support ja_JP.ujis text viewer l10n doesn't work. */
++#endif
++
+   xv_getwd(initdir, sizeof(initdir));
+   searchdir[0] = '\0';
+   fullfname[0] = '\0';
+@@ -162,7 +201,7 @@
+ 
+   /* init internal variables */
+   display = NULL;
+-  fgstr = bgstr = rootfgstr = rootbgstr = NULL;
++  fgstr = bgstr = rootfgstr = rootbgstr = imagebgstr = NULL;
+   histr = lostr = whitestr = blackstr = NULL;
+   visualstr = monofontname = flistName = NULL;
+   winTitle = NULL;
+@@ -172,21 +211,26 @@
+ 
+   picComments = (char *) NULL;
+ 
++  if (picExifInfo) free(picExifInfo);
++  picExifInfo = (byte *) NULL;
++  picExifInfoSize = 0;
++
+   numPages = 1;  curPage = 0;
+   pageBaseName[0] = '\0';
+ 
+   LocalCmap = browCmap = 0;
+   stdinflag = 0;
+-  autoclose = autoDelete = 0; 
++  autoclose = autoDelete = 0;
+   cmapInGam = 0;
+   grabDelay = 0;
++  startGrab = 0;
+   showzoomcursor = 0;
+   perfect = owncmap = stdcmap = rwcolor = 0;
+ 
+   ignoreConfigs = 0;
+-  browPerfect = 1;  
++  browPerfect = 1;
+   gamval = rgamval = ggamval = bgamval = 1.0;
+-  
++
+   picType = -1;              /* gets set once file is loaded */
+   colorMapMode = CM_NORMAL;
+   haveStdCmap  = STD_NONE;
+@@ -221,24 +265,27 @@
+   cmd = (char *) rindex(argv[0],'/');
+   if (!cmd) cmd = argv[0]; else cmd++;
+ 
+-  tmpstr = (char *) getenv("TMPDIR");
+-  if (!tmpstr) tmpdir = "/tmp";
+-  else {
+-    tmpdir = (char *) malloc(strlen(tmpstr) + 1);
+-    if (!tmpdir) FatalError("can't malloc 'tmpdir'\n");
+-    strcpy(tmpdir, tmpstr);
+-  }
++  tmpstr = (const char *) getenv("TMPDIR");
++  if (!tmpstr) tmpstr = "/tmp";
++  tmpdir = (char *) malloc(strlen(tmpstr) + 1);
++  if (!tmpdir) FatalError("can't malloc 'tmpdir'\n");
++  strcpy(tmpdir, tmpstr);
++
++#ifdef AUTO_EXPAND
++  Vdinit();
++  vd_handler_setup();
++#endif
+ 
+   /* init command-line options flags */
+-  infogeom = DEFINFOGEOM;  ctrlgeom = DEFCTRLGEOM;  
++  infogeom = DEFINFOGEOM;  ctrlgeom = DEFCTRLGEOM;
+   gamgeom  = DEFGAMGEOM;   browgeom = DEFBROWGEOM;
+   textgeom = DEFTEXTGEOM;  cmtgeom  = DEFCMTGEOM;
+ 
+-  ncols = -1;  mono = 0;  
++  ncols = -1;  mono = 0;
+   ninstall = 0;  fixedaspect = 0;  noFreeCols = nodecor = 0;
+   DEBUG = 0;  bwidth = 2;
+   nolimits = useroot = clrroot = noqcheck = 0;
+-  waitsec = -1;  waitloop = 0;  automax = 0;
++  waitsec = waitsec_final = -1.0;  waitloop = 0;  automax = 0;
+   rootMode = 0;  hsvmode = 0;
+   rmodeset = gamset = cgamset = 0;
+   nopos = limit2x = 0;
+@@ -251,6 +298,10 @@
+   preset = 0;
+   viewonly = 0;
+ 
++#ifdef ENABLE_FIXPIX_SMOOTH
++  do_fixpix_smooth = 0;
++#endif
++
+   /* init 'xormasks' array */
+   xorMasks[0] = 0x01010101;
+   xorMasks[1] = 0x02020203;
+@@ -268,15 +319,38 @@
+   defaspect = normaspect = 1.0;
+   mainW = dirW = infoW = ctrlW = gamW = psW = (Window) NULL;
+   anyBrowUp = 0;
++  incrementalSearchTimeout = 30;
+ 
+ #ifdef HAVE_JPEG
+   jpegW = (Window) NULL;  jpegUp = 0;
+ #endif
+ 
++#ifdef HAVE_JP2K
++  jp2kW = (Window) NULL;  jp2kUp = 0; 
++#endif
++
+ #ifdef HAVE_TIFF
+   tiffW = (Window) NULL;  tiffUp = 0;
+ #endif
+ 
++#ifdef HAVE_PNG
++  pngW = (Window) NULL;  pngUp = 0;
++#endif
++
++  pcdW = (Window) NULL;  pcdUp = 0;
++
++#ifdef HAVE_PIC2
++  pic2W = (Window) NULL;  pic2Up = 0;
++#endif
++
++#ifdef HAVE_PCD
++  pcdW = (Window) NULL;  pcdUp = 0;
++#endif
++
++#ifdef HAVE_MGCSFX
++  mgcsfxW = (Window) NULL;  mgcsfxUp = 0;
++#endif
++
+   imap = ctrlmap = gmap = browmap = cmtmap = 0;
+ 
+   ch_offx = ch_offy = p_offx = p_offy = 0;
+@@ -303,13 +377,35 @@
+   verifyArgs();
+ 
+ 
++#if 0
++#ifdef XVEXECPATH
++  /* set up path to search for external executables */
++  {
++    char *systempath = getenv("PATH");
++    char *xvexecpath = getenv("XVPATH");
++    if (xvexecpath == NULL) xvexecpath = XVEXECPATH;
++    /* FIXME: can systempath == NULL? */
++    strcat(systempath, ":");		/* FIXME: writing to mem we don't own */
++    strcat(systempath, xvexecpath);	/* FIXME: writing to mem we don't own */
++    /* FIXME:  was there supposed to be a setenv() call in here? */
++    if (DEBUG)
++      fprintf(stderr, "DEBUG: executable search path: %s\n", systempath);
++  }
++#endif
++#endif
++
++
+   /*****************************************************/
+   /*** X Setup                                       ***/
+   /*****************************************************/
+-  
++
+   theScreen = DefaultScreen(theDisp);
+   theCmap   = DefaultColormap(theDisp, theScreen);
+-  rootW     = RootWindow(theDisp,theScreen);
++  if (spec_window) {
++	rootW = spec_window;
++  } else {
++	rootW = RootWindow(theDisp,theScreen);
++  }
+   theGC     = DefaultGC(theDisp,theScreen);
+   theVisual = DefaultVisual(theDisp,theScreen);
+   ncells    = DisplayCells(theDisp, theScreen);
+@@ -320,53 +416,67 @@
+ 
+   rootDEEP = dispDEEP;
+ 
+-  /* things dependant on theVisual:
+-   *    dispDEEP, theScreen, rootW, ncells, theCmap, theGC, 
++  /* things dependent on theVisual:
++   *    dispDEEP, theScreen, rootW, ncells, theCmap, theGC,
+    *    vrWIDE, dispWIDE, vrHIGH, dispHIGH, maxWIDE, maxHIGH
+    */
+ 
+ 
+-
+   /* if we *haven't* had a non-default visual specified,
+-     see if we have a TrueColor or DirectColor visual of 24 or 32 bits, 
++     see if we have a TrueColor or DirectColor visual of 24 or 32 bits,
+      and if so, use that as the default visual (prefer TrueColor) */
+ 
+   if (!visualstr && !useroot) {
++    VisualID     defvid;
+     XVisualInfo *vinfo, rvinfo;
+     int          best,  numvis;
+     long         flags;
+ 
+-    best = -1;
++    best          = -1;
+     rvinfo.class  = TrueColor;
+     rvinfo.screen = theScreen;
+-    flags = VisualClassMask | VisualScreenMask;
+-    
++    flags         = VisualClassMask | VisualScreenMask;
++    defvid        = XVisualIDFromVisual(DefaultVisual(theDisp,
++						      DefaultScreen(theDisp)));
++
+     vinfo = XGetVisualInfo(theDisp, flags, &rvinfo, &numvis);
+-    if (vinfo) {     /* look for a TrueColor, 24-bit or more (pref 24) */
+-      for (i=0, best = -1; i<numvis; i++) {
++    if (vinfo) {
++      /* Check list, use 'default', first 24-bit, or first >24-bit */
++      for (i=0; i<numvis && best==-1; i++) {   /* default? */
++	if ((vinfo[i].visualid == defvid) && (vinfo[i].depth >= 24)) best=i;
++      }
++      for (i=0; i<numvis && best==-1; i++) {   /* 24-bit ? */
+ 	if (vinfo[i].depth == 24) best = i;
+-	else if (vinfo[i].depth>24 && best<0) best = i;
++      }
++      for (i=0; i<numvis && best==-1; i++) {   /* >24-bit ? */
++	if (vinfo[i].depth >= 24) best = i;
+       }
+     }
+ 
+     if (best == -1) {   /* look for a DirectColor, 24-bit or more (pref 24) */
+       rvinfo.class = DirectColor;
+       if (vinfo) XFree((char *) vinfo);
++
+       vinfo = XGetVisualInfo(theDisp, flags, &rvinfo, &numvis);
+       if (vinfo) {
+-	for (i=0, best = -1; i<numvis; i++) {
++	for (i=0; i<numvis && best==-1; i++) {   /* default? */
++	  if ((vinfo[i].visualid == defvid) && (vinfo[i].depth >= 24)) best=i;
++	}
++	for (i=0; i<numvis && best==-1; i++) {   /* 24-bit ? */
+ 	  if (vinfo[i].depth == 24) best = i;
+-	  else if (vinfo[i].depth>24 && best<0) best = i;
++	}
++	for (i=0; i<numvis && best==-1; i++) {   /* >24-bit ? */
++	  if (vinfo[i].depth >= 24) best = i;
+ 	}
+       }
+     }
+-    
++
+     if (best>=0 && best<numvis) useOtherVisual(vinfo, best);
+     if (vinfo) XFree((char *) vinfo);
+   }
+ 
+ 
+-			   
++
+   if (visualstr && useroot) {
+     fprintf(stderr, "%s: %sUsing default visual.\n",
+ 	    cmd, "Warning:  Can't use specified visual on root.  ");
+@@ -401,11 +511,11 @@
+       long vinfomask;
+       int numvis, best;
+ 
+-      if (vclass >= 0) { 
++      if (vclass >= 0) {
+ 	rvinfo.class = vclass;   vinfomask = VisualClassMask;
+       }
+       else { rvinfo.visualid = vid;  vinfomask = VisualIDMask; }
+-      
++
+       rvinfo.screen = theScreen;
+       vinfomask |= VisualScreenMask;
+ 
+@@ -429,9 +539,9 @@
+   /* make linear colormap for DirectColor visual */
+   if (theVisual->class == DirectColor) makeDirectCmap();
+ 
+-  defaultVis = (XVisualIDFromVisual(theVisual) == 
++  defaultVis = (XVisualIDFromVisual(theVisual) ==
+        XVisualIDFromVisual(DefaultVisual(theDisp, DefaultScreen(theDisp))));
+-    
++
+ 
+   /* turn GraphicsExposures OFF in the default GC */
+   {
+@@ -441,9 +551,6 @@
+   }
+ 
+ 
+-  if (!useroot && limit2x) { maxWIDE *= 2;  maxHIGH *= 2; }
+-  if (nolimits) { maxWIDE = 65000; maxHIGH = 65000; }
+-
+   XSetErrorHandler(xvErrorHandler);
+ 
+   /* always search for virtual root window */
+@@ -456,14 +563,14 @@
+     Atom actual_type;
+     int actual_format;
+     unsigned long nitems, bytesafter;
+-    Window *newRoot = NULL;
++    byte *newRoot = NULL;   /* byte instead of Window avoids type-pun warning */
+     XWindowAttributes xwa;
+     if (XGetWindowProperty (theDisp, children[i], __SWM_VROOT, 0L, 1L,
+ 	  False, XA_WINDOW, &actual_type, &actual_format, &nitems,
+ 	  &bytesafter, (unsigned char **) &newRoot) == Success && newRoot) {
+-      vrootW = *newRoot;
++      vrootW = *(Window *)newRoot;
+       XGetWindowAttributes(theDisp, vrootW, &xwa);
+-      vrWIDE = xwa.width;  vrHIGH = xwa.height;
++      maxWIDE = vrWIDE = xwa.width;  maxHIGH = vrHIGH = xwa.height;
+       dispDEEP = xwa.depth;
+       break;
+     }
+@@ -472,7 +579,8 @@
+   vrootW = pseudo_root(theDisp, theScreen);
+ #endif
+ 
+-
++  if (!useroot && limit2x) { maxWIDE *= 2;  maxHIGH *= 2; }
++  if (nolimits) { maxWIDE = 65000; maxHIGH = 65000; }
+ 
+ 
+   if (clrroot || useroot) {
+@@ -486,13 +594,14 @@
+   arrow     = XCreateFontCursor(theDisp,(u_int) curstype);
+   cross     = XCreateFontCursor(theDisp,XC_crosshair);
+   tcross    = XCreateFontCursor(theDisp,XC_tcross);
++  tlcorner  = XCreateFontCursor(theDisp,XC_top_left_corner);
+   zoom      = XCreateFontCursor(theDisp,XC_sizing);
+ 
+   {
+     XColor fc, bc;
+     fc.red = fc.green = fc.blue = 0xffff;
+     bc.red = bc.green = bc.blue = 0x0000;
+-    
++
+     XRecolorCursor(theDisp, zoom, &fc, &bc);
+   }
+ 
+@@ -541,7 +650,7 @@
+ 
+ 
+   /* set up fg,bg colors */
+-  fg = black;   bg = white;  
++  fg = black;   bg = white;
+   if (fgstr && XParseColor(theDisp, theCmap, fgstr, &ecdef) &&
+       xvAllocColor(theDisp, theCmap, &ecdef)) {
+     fg = ecdef.pixel;
+@@ -561,6 +670,18 @@
+       xvAllocColor(theDisp, theCmap, &ecdef))  rootbg = ecdef.pixel;
+ 
+ 
++  /* GRR 19980308:  set up image bg color (for transparent images) */
++  have_imagebg = 0;
++  if (imagebgstr && XParseColor(theDisp, theCmap, imagebgstr, &ecdef) &&
++      xvAllocColor(theDisp, theCmap, &ecdef)) {
++    /* imagebg = ecdef.pixel; */
++    have_imagebg = 1;
++    imagebgR = ecdef.red;
++    imagebgG = ecdef.green;
++    imagebgB = ecdef.blue;
++  }
++
++
+   /* set up hi/lo colors */
+   i=0;
+   if (dispDEEP > 1) {   /* only if we're on a reasonable display */
+@@ -590,7 +711,7 @@
+     if (theVisual->class == StaticGray || theVisual->class == GrayScale)
+       mono = 1;
+   }
+-  
++
+ 
+ 
+   iconPix  = MakePix1(rootW, icon_bits,     icon_width,    icon_height);
+@@ -598,32 +719,32 @@
+   riconPix = MakePix1(rootW, runicon_bits,  runicon_width, runicon_height);
+   riconmask= MakePix1(rootW, runiconm_bits, runiconm_width,runiconm_height);
+ 
+-  if (!iconPix || !iconmask || !riconPix || !riconmask) 
++  if (!iconPix || !iconmask || !riconPix || !riconmask)
+     FatalError("Unable to create icon pixmaps\n");
+ 
+-  gray50Tile = XCreatePixmapFromBitmapData(theDisp, rootW, 
++  gray50Tile = XCreatePixmapFromBitmapData(theDisp, rootW,
+ 				(char *) cboard50_bits,
+-				cboard50_width, cboard50_height, 
++				cboard50_width, cboard50_height,
+ 				infofg, infobg, dispDEEP);
+   if (!gray50Tile) FatalError("Unable to create gray50Tile bitmap\n");
+ 
+-  gray25Tile = XCreatePixmapFromBitmapData(theDisp, rootW, 
++  gray25Tile = XCreatePixmapFromBitmapData(theDisp, rootW,
+ 				(char *) gray25_bits,
+-				gray25_width, gray25_height, 
++				gray25_width, gray25_height,
+ 				infofg, infobg, dispDEEP);
+   if (!gray25Tile) FatalError("Unable to create gray25Tile bitmap\n");
+ 
+ 
+   /* try to load fonts */
+-  if ( (mfinfo = XLoadQueryFont(theDisp,FONT1))==NULL && 
+-       (mfinfo = XLoadQueryFont(theDisp,FONT2))==NULL && 
+-       (mfinfo = XLoadQueryFont(theDisp,FONT3))==NULL && 
+-       (mfinfo = XLoadQueryFont(theDisp,FONT4))==NULL && 
++  if ( (mfinfo = XLoadQueryFont(theDisp,FONT1))==NULL &&
++       (mfinfo = XLoadQueryFont(theDisp,FONT2))==NULL &&
++       (mfinfo = XLoadQueryFont(theDisp,FONT3))==NULL &&
++       (mfinfo = XLoadQueryFont(theDisp,FONT4))==NULL &&
+        (mfinfo = XLoadQueryFont(theDisp,FONT5))==NULL) {
+-    sprintf(str,
++    sprintf(dummystr,
+ 	    "couldn't open the following fonts:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s",
+ 	    FONT1, FONT2, FONT3, FONT4, FONT5);
+-    FatalError(str);
++    FatalError(dummystr);
+   }
+   mfont=mfinfo->fid;
+   XSetFont(theDisp,theGC,mfont);
+@@ -632,45 +753,100 @@
+ 
+   if (monofontname) {
+     monofinfo = XLoadQueryFont(theDisp, monofontname);
+-    if (!monofinfo) fprintf(stderr,"xv: unable to load font '%s'\n", 
++    if (!monofinfo) fprintf(stderr,"xv: unable to load font '%s'\n",
+ 			    monofontname);
+-  }    
++  }
+ 
+   if (!monofinfo) {
+-    if ((monofinfo = XLoadQueryFont(theDisp,MFONT1))==NULL && 
+-	(monofinfo = XLoadQueryFont(theDisp,MFONT2))==NULL && 
+-	(monofinfo = XLoadQueryFont(theDisp,MFONT3))==NULL && 
++    if ((monofinfo = XLoadQueryFont(theDisp,MFONT1))==NULL &&
++	(monofinfo = XLoadQueryFont(theDisp,MFONT2))==NULL &&
++	(monofinfo = XLoadQueryFont(theDisp,MFONT3))==NULL &&
+ 	(monofinfo = XLoadQueryFont(theDisp,MFONT4))==NULL) {
+-      sprintf(str,"couldn't open %s fonts:\n\t%s\n\t%s\n\t%s\n\t%s",
++      sprintf(dummystr,"couldn't open %s fonts:\n\t%s\n\t%s\n\t%s\n\t%s",
+ 	      "any of the following",
+ 	      MFONT1, MFONT2, MFONT3, MFONT4);
+-      FatalError(str);
++      FatalError(dummystr);
+     }
+   }
+ 
+   monofont=monofinfo->fid;
+-  
+ 
+-  
+-  
++#ifdef TV_L10N
++  if (xlocale) {
++    i = 0;
++    while (mfontsize[i]) {
++      xlocale = 1;	/* True */
++
++      sprintf(mfontset, TV_FONTSET, mfontsize[i]);
++/*fprintf(stderr, "FontSet: %s\n", mfontset);*/
++
++      monofset = XCreateFontSet(theDisp, mfontset,
++				&misscharset, &nmisscharset, &defstr);
++#  if 0	/* not useful */
++      if (!monofset) {
++	/* the current locale is not supported */
++/*fprintf(stderr, "Current locale `%s' is not supported.\n", localeList[i]);*/
++	xlocale = 0;
++	break;
++      }
++#  endif
++/*fprintf(stderr, "# of misscharset in mfontsize[%d]: %d\n", i,nmisscharset);*/
++
++      for (j = 0; j < nmisscharset; j++) {
++	if (!strncmp(misscharset[j], "jisx0208", 8)) {
++	  /* font for JIS X 0208 is not found */
++	  xlocale = 0;
++	  break;
++	}
++      }
++
++      if (xlocale) {
++	monofsetinfo = XExtentsOfFontSet(monofset);
++	monofsetinfo->max_logical_extent.width = mfontsize[i];
++		/* correct size of TextViewer
++		   in case that JIS X 0208 is not found */
++	break;
++      }
++
++      i++;
++    } /* while (mfontsize[i]) */
++
++#  if 0
++    if (nmisscharset > 0) {
++      sprintf(dummystr,"missing %d charset:\n", nmisscharset);
++      for (i = 0; i < nmisscharset; i++) {
++	sprintf(dummystr, "%s\t%s\n", dummystr, misscharset[i]);
++      }
++#    if 0
++      FatalError(dummystr);
++#    else
++      fprintf(stderr, "%s", dummystr);
++#    endif
++    }
++#  endif
++  }
++#endif	/* TV_L10N */
++
++
++
+   /* if ncols wasn't set, set it to 2^dispDEEP, unless dispDEEP=1, in which
+      case ncols = 0;  (ncols = max number of colors allocated.  on 1-bit
+      displays, no colors are allocated */
+-  
++
+   if (ncols == -1) {
+     if (dispDEEP>1) ncols = 1 << ((dispDEEP>8) ? 8 : dispDEEP);
+     else ncols = 0;
+   }
+   else if (ncols>256) ncols = 256;       /* so program doesn't blow up */
+-  
+-  
++
++
+   GenerateFSGamma();  /* has to be done before 'OpenBrowse()' is called */
+-  
+-  
+-  
++
++
++
+   /* no filenames.  build one-name (stdio) list (if stdinflag) */
+   if (numnames==0) {
+-    if (stdinflag) {  
++    if (stdinflag) {
+       /* have to malloc namelist[0] so we can free it in deleteFromList() */
+       namelist[0] = (char *) malloc(strlen(STDINSTR) + 1);
+       if (!namelist[0]) FatalError("unable to to build namelist[0]");
+@@ -679,16 +855,28 @@
+     }
+     else namelist[0] = NULL;
+   }
+-  
++  else if (randomShow) {
++    int i, j;
++    char *tmp;
++
++    srandom((int)time((time_t *)0));
++    for (i = numnames; i > 1; i--) {
++      j = random() % i;
++      tmp = namelist[i-1];
++      namelist[i-1] = namelist[j];
++      namelist[j] = tmp;
++    }
++  }
++
+   if (numnames) makeDispNames();
+-  
+-  
+-  if (viewonly || autoquit) { 
+-    imap = ctrlmap = gmap = browmap = cmtmap = 0; 
++
++
++  if (viewonly || autoquit) {
++    imap = ctrlmap = gmap = browmap = cmtmap = 0;
+     novbrowse = 1;
+   }
+-  
+-  
++
++
+   /* create the info box window */
+   CreateInfo(infogeom);
+   XSelectInput(theDisp, infoW, ExposureMask | ButtonPressMask | KeyPressMask
+@@ -698,12 +886,12 @@
+     RedrawInfo(0,0,1000,1000);  /* explicit draw if mapped */
+     XFlush(theDisp);
+   }
+-  
+-  
++
++
+   /* create the control box window */
+   CreateCtrl(ctrlgeom);
+   epicMode = EM_RAW;   SetEpicMode();
+-  
++
+   XSelectInput(theDisp, ctrlW, ExposureMask | ButtonPressMask | KeyPressMask
+ 	       | StructureNotifyMask);
+   if (ctrlmap < 0) {    /* map iconified */
+@@ -719,22 +907,22 @@
+     RedrawCtrl(0,0,1000,1000);   /* explicit draw if mapped */
+     XFlush(theDisp);
+   }
+-  
++
+   fixDispNames();
+   ChangedCtrlList();
+-  
++
+   /* disable root modes if using non-default visual */
+   if (!defaultVis) {
+     for (i=RMB_ROOT; i<RMB_MAX; i++) rootMB.dim[i] = 1;
+   }
+-  
+-  
++
++
+   /* create the directory window */
+   CreateDirW(NULL);
+   XSelectInput(theDisp, dirW, ExposureMask | ButtonPressMask | KeyPressMask);
+   browseCB.val = browseMode;
+   savenormCB.val = savenorm;
+-  
++
+   /* create the gamma window */
+   CreateGam(gamgeom, (gamset) ? gamval : -1.0,
+ 	    (cgamset) ? rgamval : -1.0,
+@@ -744,60 +932,84 @@
+   XSelectInput(theDisp, gamW, ExposureMask | ButtonPressMask | KeyPressMask
+ 	       | StructureNotifyMask
+ 	       | (cmapInGam ? ColormapChangeMask : 0));
+-  
++
+   GamBox(gmap);     /* map it (or not) */
+-  
+-  
+-  
++
++
++
+   stdnfcols = 0;   /* so we don't try to free any if we don't create any */
+-  
++
+   if (!novbrowse) {
+     MakeBrowCmap();
+     /* create the visual browser window */
+     CreateBrowse(browgeom, fgstr, bgstr, histr, lostr);
+-    
++
+     if (browmap) OpenBrowse();
+   }
+   else windowMB.dim[WMB_BROWSE] = 1;    /* disable visual schnauzer */
+-  
+-  
++
++
+   CreateTextWins(textgeom, cmtgeom);
+   if (cmtmap) OpenCommentText();
+-  
+-  
++
++
+   /* create the ps window */
+   CreatePSD(NULL);
+   XSetTransientForHint(theDisp, psW, dirW);
+   encapsCB.val = preview;
+   pscompCB.val = pscomp;
+-  
+-  
++
++
+ #ifdef HAVE_JPEG
+   CreateJPEGW();
+   XSetTransientForHint(theDisp, jpegW, dirW);
+ #endif
+-  
++
++#ifdef HAVE_JP2K
++  CreateJP2KW();
++  XSetTransientForHint(theDisp, jp2kW, dirW);
++#endif
++
+ #ifdef HAVE_TIFF
+   CreateTIFFW();
+   XSetTransientForHint(theDisp, tiffW, dirW);
+ #endif
+-  
+-  
++
++#ifdef HAVE_PNG
++  CreatePNGW();
++  XSetTransientForHint(theDisp, pngW, dirW);
++#endif
++
++#ifdef HAVE_PCD
++  CreatePCDW();
++  XSetTransientForHint(theDisp, pcdW, dirW);
++#endif
++
++#ifdef HAVE_PIC2
++  CreatePIC2W();
++  XSetTransientForHint(theDisp, pic2W, dirW);
++#endif
++
++#ifdef HAVE_MGCSFX
++  CreateMGCSFXW();
++  XSetTransientForHint(theDisp, mgcsfxW, dirW);
++#endif
++
+   LoadFishCursors();
+   SetCursors(-1);
+-  
+-  
++
++
+   /* if we're not on a colormapped display, turn off rwcolor */
+   if (!CMAPVIS(theVisual)) {
+     if (rwcolor) fprintf(stderr, "xv: not a colormapped display.  %s\n",
+ 			 "'rwcolor' turned off.");
+-    
++
+     allocMode = AM_READONLY;
+     dispMB.flags[DMB_COLRW] = 0;  /* de-'check' */
+     dispMB.dim[DMB_COLRW] = 1;    /* and dim it */
+   }
+-  
+-  
++
++
+   if (force24) {
+     Set824Menus(PIC24);
+     conv24MB.flags[CONV24_LOCK]  = 1;
+@@ -812,15 +1024,15 @@
+     Set824Menus(PIC8);     /* default mode */
+     picType = PIC8;
+   }
+-  
+-  
+-  
++
++
++
+   /* make std colormap, maybe */
+   ChangeCmapMode(colorMapMode, 0, 0);
+ 
+ 
+-  
+-  
++
++
+   /* Do The Thing... */
+   mainLoop();
+   Quit(0);
+@@ -832,12 +1044,12 @@
+ /*****************************************************/
+ static void makeDirectCmap()
+ {
+-  int    i, j, cmaplen, numgot;
++  int    i, cmaplen, numgot;
+   byte   origgot[256];
+   XColor c;
+   u_long rmask, gmask, bmask;
+   int    rshift, gshift, bshift;
+-  
++
+ 
+   rmask = theVisual->red_mask;
+   gmask = theVisual->green_mask;
+@@ -849,22 +1061,22 @@
+ 
+   if (rshift<0) rmask = rmask << (-rshift);
+            else rmask = rmask >> rshift;
+-  
++
+   if (gshift<0) gmask = gmask << (-gshift);
+            else gmask = gmask >> gshift;
+-  
++
+   if (bshift<0) bmask = bmask << (-bshift);
+            else bmask = bmask >> bshift;
+ 
+ 
+   cmaplen = theVisual->map_entries;
+   if (cmaplen>256) cmaplen=256;
+-  
++
+ 
+   /* try to alloc a 'cmaplen' long grayscale colormap.  May not get all
+      entries for whatever reason.  Build table 'directConv[]' that
+      maps range [0..(cmaplen-1)] into set of colors we did get */
+-  
++
+   for (i=0; i<256; i++) {  origgot[i] = 0;  directConv[i] = 0; }
+ 
+   for (i=numgot=0; i<cmaplen; i++) {
+@@ -882,9 +1094,9 @@
+     }
+   }
+ 
+-  
++
+   if (numgot == 0) FatalError("Got no entries in DirectColor cmap!\n");
+-  
++
+   /* directConv may or may not have holes in it. */
+   for (i=0; i<cmaplen; i++) {
+     if (!origgot[i]) {
+@@ -892,10 +1104,10 @@
+       numbak = numfwd = 0;
+       while ((i - numbak) >= 0       && !origgot[i-numbak]) numbak++;
+       while ((i + numfwd) <  cmaplen && !origgot[i+numfwd]) numfwd++;
+-      
++
+       if (i-numbak<0        || !origgot[i-numbak]) numbak = 999;
+       if (i+numfwd>=cmaplen || !origgot[i+numfwd]) numfwd = 999;
+-      
++
+       if      (numbak<numfwd) directConv[i] = directConv[i-numbak];
+       else if (numfwd<999)    directConv[i] = directConv[i+numfwd];
+       else FatalError("DirectColor cmap:  can't happen!");
+@@ -926,14 +1138,14 @@
+ {
+   if (!vinfo || best<0) return;
+ 
+-  if (vinfo[best].visualid == 
++  if (vinfo[best].visualid ==
+       XVisualIDFromVisual(DefaultVisual(theDisp, theScreen))) return;
+ 
+   theVisual = vinfo[best].visual;
+ 
+   if (DEBUG) {
+     fprintf(stderr,"%s: using %s visual (0x%0x), depth = %d, screen = %d\n",
+-	    cmd, 
++	    cmd,
+ 	    (vinfo[best].class==StaticGray)  ? "StaticGray" :
+ 	    (vinfo[best].class==StaticColor) ? "StaticColor" :
+ 	    (vinfo[best].class==TrueColor)   ? "TrueColor" :
+@@ -947,41 +1159,45 @@
+ 	    (int) vinfo[best].red_mask, (int) vinfo[best].green_mask,
+ 	    (int) vinfo[best].blue_mask, vinfo[best].bits_per_rgb);
+   }
+-  
++
+   dispDEEP  = vinfo[best].depth;
+   theScreen = vinfo[best].screen;
+-  rootW     = RootWindow(theDisp, theScreen);
++  if (spec_window) {
++	rootW = spec_window;
++  } else {
++	rootW = RootWindow(theDisp,theScreen);
++  }
+   ncells    = vinfo[best].colormap_size;
+   theCmap   = XCreateColormap(theDisp, rootW, theVisual, AllocNone);
+-  
++
+   {
+     /* create a temporary window using this visual so we can
+        create a GC for this visual */
+-    
+-    Window win;  
++
++    Window win;
+     XSetWindowAttributes xswa;
+     XGCValues xgcv;
+     unsigned long xswamask;
+-    
++
+     XFlush(theDisp);
+     XSync(theDisp, False);
+-    
++
+     xswa.background_pixel = 0;
+     xswa.border_pixel     = 1;
+     xswa.colormap         = theCmap;
+     xswamask = CWBackPixel | CWBorderPixel | CWColormap;
+-    
++
+     win = XCreateWindow(theDisp, rootW, 0, 0, 100, 100, 2, (int) dispDEEP,
+ 			InputOutput, theVisual, xswamask, &xswa);
+-    
++
+     XFlush(theDisp);
+     XSync(theDisp, False);
+-    
++
+     theGC = XCreateGC(theDisp, win, 0L, &xgcv);
+-    
++
+     XDestroyWindow(theDisp, win);
+   }
+-  
++
+   vrWIDE = dispWIDE  = DisplayWidth(theDisp,theScreen);
+   vrHIGH = dispHIGH  = DisplayHeight(theDisp,theScreen);
+   maxWIDE = dispWIDE;  maxHIGH = dispHIGH;
+@@ -1000,25 +1216,25 @@
+   /* once through the argument list to find the display name
+      and DEBUG level, if any */
+ 
+-  for (i=1; i<argc; i++) {
++  for (i=1; i<argc; ++i) {
+     if (!strncmp(argv[i],"-help", (size_t) 5)) {  /* help */
+       cmdSyntax();
+       exit(0);
+     }
+ 
+     else if (!argcmp(argv[i],"-display",4,0,&pm)) {
+-      i++;
++      ++i;
+       if (i<argc) display = argv[i];
+       break;
+     }
+ 
+-#ifdef VMS    /* in VMS, cmd-line-opts are in lower case */
++#ifdef VMS    /* in VMS, cmd-line opts are in lower case */
+     else if (!argcmp(argv[i],"-debug",3,0,&pm)) {
+-      { if (++i<argc) DEBUG = atoi(argv[i]); }
++      if (++i<argc) DEBUG = atoi(argv[i]);
+     }
+ #else
+     else if (!argcmp(argv[i],"-DEBUG",2,0,&pm)) {
+-      { if (++i<argc) DEBUG = atoi(argv[i]); }
++      if (++i<argc) DEBUG = atoi(argv[i]);
+     }
+ #endif
+   }
+@@ -1037,8 +1253,8 @@
+       fprintf(stderr,"%s: unable to parse 'aspect' resource\n",cmd);
+     else defaspect = (float) n / (float) d;
+   }
+-      
+-  if (rd_flag("2xlimit"))        limit2x     = def_int;      
++
++  if (rd_flag("2xlimit"))        limit2x     = def_int;
+   if (rd_flag("auto4x3"))        auto4x3     = def_int;
+   if (rd_flag("autoClose"))      autoclose   = def_int;
+   if (rd_flag("autoCrop"))       autocrop    = def_int;
+@@ -1064,6 +1280,7 @@
+   if (rd_flag("ctrlMap"))        ctrlmap     = def_int;
+   if (rd_int ("cursor"))         curstype    = def_int;
+   if (rd_int ("defaultPreset"))  preset      = def_int;
++  if (rd_int ("incrementalSearchTimeout"))  incrementalSearchTimeout = def_int;
+ 
+   if (rd_str ("driftKludge")) {
+     if (sscanf(def_str,"%d %d", &kludge_offx, &kludge_offy) != 2) {
+@@ -1073,7 +1290,7 @@
+ 
+   if (rd_str ("expand")) {
+     if (index(def_str, ':')) {
+-      if (sscanf(def_str, "%lf:%lf", &hexpand, &vexpand)!=2) 
++      if (sscanf(def_str, "%lf:%lf", &hexpand, &vexpand)!=2)
+ 	{ hexpand = vexpand = 1.0; }
+     }
+     else hexpand = vexpand = atof(def_str);
+@@ -1081,6 +1298,9 @@
+ 
+   if (rd_str ("fileList"))       flistName   = def_str;
+   if (rd_flag("fixed"))          fixedaspect = def_int;
++#ifdef ENABLE_FIXPIX_SMOOTH
++  if (rd_flag("fixpix"))         do_fixpix_smooth = def_int;
++#endif
+   if (rd_flag("force8"))         force8      = def_int;
+   if (rd_flag("force24"))        force24     = def_int;
+   if (rd_str ("foreground"))     fgstr       = def_str;
+@@ -1092,23 +1312,39 @@
+   if (rd_str ("highlight"))      histr       = def_str;
+   if (rd_str ("iconGeometry"))   icongeom    = def_str;
+   if (rd_flag("iconic"))         startIconic = def_int;
++  if (rd_str ("imageBackground")) imagebgstr = def_str;
+   if (rd_str ("infoGeometry"))   infogeom    = def_str;
+   if (rd_flag("infoMap"))        imap        = def_int;
+   if (rd_flag("loadBrowse"))     browseMode  = def_int;
+   if (rd_str ("lowlight"))       lostr       = def_str;
++#ifdef MACBINARY
++  if (rd_flag("macbinary"))      handlemacb  = def_int;
++#endif
++#ifdef HAVE_MGCSFX
++  if (rd_flag("mgcsfx"))         mgcsfx      = def_int;
++#endif
+   if (rd_flag("mono"))           mono        = def_int;
+   if (rd_str ("monofont"))       monofontname = def_str;
+   if (rd_int ("ncols"))          ncols       = def_int;
+   if (rd_flag("ninstall"))       ninstall    = def_int;
+   if (rd_flag("nodecor"))        nodecor     = def_int;
+   if (rd_flag("nolimits"))       nolimits    = def_int;
++#ifdef HAVE_MGCSFX
++  if (rd_flag("nomgcsfx"))       nomgcsfx    = def_int;
++#endif
++#if defined(HAVE_PIC) || defined(HAVE_PIC2)
++  if (rd_flag("nopicadjust"))    nopicadjust = def_int;
++#endif
+   if (rd_flag("nopos"))          nopos       = def_int;
+   if (rd_flag("noqcheck"))       noqcheck    = def_int;
+   if (rd_flag("nostat"))         nostat      = def_int;
+   if (rd_flag("ownCmap"))        owncmap     = def_int;
+   if (rd_flag("perfect"))        perfect     = def_int;
++#ifdef HAVE_PIC2
++  if (rd_flag("pic2split"))      pic2split   = def_int;
++#endif
+   if (rd_flag("popupKludge"))    winCtrPosKludge = def_int;
+-  if (rd_str ("print"))          strncpy(printCmd, def_str, 
++  if (rd_str ("print"))          strncpy(printCmd, def_str,
+ 					 (size_t) PRINTCMDLEN);
+   if (rd_flag("pscompress"))     pscomp      = def_int;
+   if (rd_flag("pspreview"))      preview     = def_int;
+@@ -1117,18 +1353,34 @@
+   if (rd_flag("reverse"))        revvideo    = def_int;
+   if (rd_str ("rootBackground")) rootbgstr   = def_str;
+   if (rd_str ("rootForeground")) rootfgstr   = def_str;
+-  if (rd_int ("rootMode"))       { rootMode    = def_int;  rmodeset++; }
++  if (rd_int ("rootMode"))       { rootMode    = def_int;  ++rmodeset; }
+   if (rd_flag("rwColor"))        rwcolor     = def_int;
+   if (rd_flag("saveNormal"))     savenorm    = def_int;
+   if (rd_str ("searchDirectory"))  strcpy(searchdir, def_str);
+   if (rd_str ("textviewGeometry")) textgeom  = def_str;
+   if (rd_flag("useStdCmap"))     stdcmap     = def_int;
+   if (rd_str ("visual"))         visualstr   = def_str;
++#ifdef VS_ADJUST
++  if (rd_flag("vsadjust"))       vsadjust    = def_int;
++#endif
+   if (rd_flag("vsDisable"))      novbrowse   = def_int;
+   if (rd_str ("vsGeometry"))     browgeom    = def_str;
+   if (rd_flag("vsMap"))          browmap     = def_int;
+   if (rd_flag("vsPerfect"))      browPerfect = def_int;
+   if (rd_str ("white"))          whitestr    = def_str;
++  
++  /* Check for any command-bindings to the supported function keys */
++#define TMPLEN 80
++  for (i=0; i<FSTRMAX; ++i) {
++    char tmp[TMPLEN];
++
++    snprintf(tmp, TMPLEN, "F%dcommand", i+1);
++    if (rd_str(tmp))
++      fkeycmds[i] = def_str;
++    else
++      fkeycmds[i] = NULL;
++  }  
++#undef TMPLEN
+ }
+ 
+ 
+@@ -1146,7 +1398,7 @@
+ 
+     not_in_first_half = 0;
+ 
+-    if (argv[i][0] != '-' && argv[i][0] != '+') { 
++    if (argv[i][0] != '-' && argv[i][0] != '+') {
+       /* a file name.  put it in list */
+ 
+       if (!nostat) {
+@@ -1158,24 +1410,30 @@
+       }
+ 
+       if (numnames<MAXNAMES) {
++#ifdef AUTO_EXPAND
++	if(Isarchive(argv[i]) == 0){ /* Not archive file */
++	  namelist[numnames++] = argv[i];
++	}
++#else
+ 	namelist[numnames++] = argv[i];
++#endif
+ 	if (numnames==MAXNAMES) {
+-	  fprintf(stderr,"%s: too many filenames.  Only using first %d.\n",
++	  fprintf(stderr,"%s: too many filenames.  Using only first %d.\n",
+ 		  cmd, MAXNAMES);
+ 	}
+       }
+     }
+ 
+-    else if (!strcmp(argv[i],  "-"))                    /* stdin flag */
++    else if (!strcmp(argv[i],  "-"))                       /* stdin flag */
+       stdinflag++;
+ 
+-    else if (!argcmp(argv[i],"-24",     3,1,&force24 ));  /* force24 */
+-    else if (!argcmp(argv[i],"-2xlimit",3,1,&limit2x ));  /* 2xlimit */
+-    else if (!argcmp(argv[i],"-4x3",    2,1,&auto4x3 ));  /* 4x3 */
+-    else if (!argcmp(argv[i],"-8",      2,1,&force8  ));  /* force8 */
+-    else if (!argcmp(argv[i],"-acrop",  3,1,&autocrop));  /* autocrop */
+-
+-    else if (!argcmp(argv[i],"-aspect",3,0,&pm)) {        /* def. aspect */
++    else if (!argcmp(argv[i],"-24",     3,1,&force24 ));   /* force24 */
++    else if (!argcmp(argv[i],"-2xlimit",3,1,&limit2x ));   /* 2xlimit */
++    else if (!argcmp(argv[i],"-4x3",    2,1,&auto4x3 ));   /* 4x3 */
++    else if (!argcmp(argv[i],"-8",      2,1,&force8  ));   /* force8 */
++    else if (!argcmp(argv[i],"-acrop",  3,1,&autocrop));   /* autocrop */
++                                                          
++    else if (!argcmp(argv[i],"-aspect",3,0,&pm)) {         /* def. aspect */
+       int n,d;
+       if (++i<argc) {
+ 	if (sscanf(argv[i],"%d:%d",&n,&d)!=2 || n<1 || d<1)
+@@ -1184,57 +1442,65 @@
+       }
+     }
+ 
+-    else if (!argcmp(argv[i],"-best24",3,0,&pm))          /* -best */
++    else if (!argcmp(argv[i],"-windowid",3,0,&pm)) {
++      if (++i<argc) {
++	if (sscanf(argv[i], "%ld", &spec_window) != 1) {
++		fprintf(stderr,"%s: bad argument to -windowid '%s'\n",cmd,argv[i]);
++        }
++      }
++    }
++
++    else if (!argcmp(argv[i],"-best24",3,0,&pm))           /* -best */
+       conv24 = CONV24_BEST;
+-    
+-    else if (!argcmp(argv[i],"-bg",3,0,&pm))              /* bg color */
++
++    else if (!argcmp(argv[i],"-bg",3,0,&pm))               /* bg color */
+       { if (++i<argc) bgstr = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-black",3,0,&pm))           /* black color */
++
++    else if (!argcmp(argv[i],"-black",3,0,&pm))            /* black color */
+       { if (++i<argc) blackstr = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-bw",3,0,&pm))              /* border width */
++
++    else if (!argcmp(argv[i],"-bw",3,0,&pm))               /* border width */
+       { if (++i<argc) bwidth=atoi(argv[i]); }
+-    
+-    else if (!argcmp(argv[i],"-cecmap",4,1,&cmapInGam));  /* cmapInGam */
+-    
+-    else if (!argcmp(argv[i],"-cegeometry",4,0,&pm))      /* gammageom */
++
++    else if (!argcmp(argv[i],"-cecmap",4,1,&cmapInGam));   /* cmapInGam */
++
++    else if (!argcmp(argv[i],"-cegeometry",4,0,&pm))       /* gammageom */
+       { if (++i<argc) gamgeom = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-cemap",4,1,&gmap));        /* gmap */
+-    
+-    else if (!argcmp(argv[i],"-cgamma",4,0,&pm)) {        /* color gamma */
++
++    else if (!argcmp(argv[i],"-cemap",4,1,&gmap));         /* gmap */
++
++    else if (!argcmp(argv[i],"-cgamma",4,0,&pm)) {         /* color gamma */
+       if (i+3<argc) {
+-	rgamval = atof(argv[++i]); 
+-	ggamval = atof(argv[++i]); 
+-	bgamval = atof(argv[++i]); 
++	rgamval = atof(argv[++i]);
++	ggamval = atof(argv[++i]);
++	bgamval = atof(argv[++i]);
+       }
+       cgamset++;
+     }
+-    
+-    else if (!argcmp(argv[i],"-cgeometry",4,0,&pm))	  /* ctrlgeom */
++
++    else if (!argcmp(argv[i],"-cgeometry",4,0,&pm))	   /* ctrlgeom */
+       { if (++i<argc) ctrlgeom = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-clear",4,1,&clrroot));	  /* clear */
+-    else if (!argcmp(argv[i],"-close",4,1,&autoclose));	  /* close */
+-    else if (!argcmp(argv[i],"-cmap", 3,1,&ctrlmap));	  /* ctrlmap */
+ 
+-    else if (!argcmp(argv[i],"-cmtgeometry",5,0,&pm))	  /* comment geom */
++    else if (!argcmp(argv[i],"-clear",4,1,&clrroot));	   /* clear */
++    else if (!argcmp(argv[i],"-close",4,1,&autoclose));	   /* close */
++    else if (!argcmp(argv[i],"-cmap", 3,1,&ctrlmap));	   /* ctrlmap */
++
++    else if (!argcmp(argv[i],"-cmtgeometry",5,0,&pm))	   /* comment geom */
+       { if (++i<argc) cmtgeom = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-cmtmap",5,1,&cmtmap));	  /* map cmt window */
+-    
+-    else if (!argcmp(argv[i],"-crop",3,0,&pm)) {          /* crop */
++
++    else if (!argcmp(argv[i],"-cmtmap",5,1,&cmtmap));	   /* map cmt window */
++
++    else if (!argcmp(argv[i],"-crop",3,0,&pm)) {           /* crop */
+       if (i+4<argc) {
+-	acropX = atoi(argv[++i]); 
+-	acropY = atoi(argv[++i]); 
+-	acropW = atoi(argv[++i]); 
+-	acropH = atoi(argv[++i]); 
++	acropX = atoi(argv[++i]);
++	acropY = atoi(argv[++i]);
++	acropW = atoi(argv[++i]);
++	acropH = atoi(argv[++i]);
+       }
+       acrop++;
+     }
+-    
+-    else if (!argcmp(argv[i],"-cursor",3,0,&pm))	  /* cursor */
++
++    else if (!argcmp(argv[i],"-cursor",3,0,&pm))	   /* cursor */
+       { if (++i<argc) curstype = atoi(argv[i]); }
+ 
+ #ifdef VMS    /* in VMS, cmd-line-opts are in lower case */
+@@ -1247,84 +1513,100 @@
+     }
+ #endif
+ 
+-    else if (!argcmp(argv[i],"-dir",4,0,&pm))             /* search dir */
++    else if (!argcmp(argv[i],"-dir",4,0,&pm))              /* search dir */
+       { if (++i<argc) strcpy(searchdir, argv[i]); }
+ 
+-    else if (!argcmp(argv[i],"-display",4,0,&pm))         /* display */
++    else if (!argcmp(argv[i],"-display",4,0,&pm))          /* display */
+       { if (++i<argc) display = argv[i]; }
+ 
+-    else if (!argcmp(argv[i],"-dither",4,1,&autodither)); /* autodither */
++    else if (!argcmp(argv[i],"-dither",4,1,&autodither));  /* autodither */
+ 
+-    else if (!argcmp(argv[i],"-drift",3,0,&pm)) {         /* drift kludge */
++    else if (!argcmp(argv[i],"-drift",3,0,&pm)) {          /* drift kludge */
+       if (i<argc-2) {
+ 	kludge_offx = atoi(argv[++i]);
+ 	kludge_offy = atoi(argv[++i]);
+       }
+     }
+ 
+-    else if (!argcmp(argv[i],"-expand",2,0,&pm)) {	  /* expand factor */
++    else if (!argcmp(argv[i],"-expand",2,0,&pm)) {	   /* expand factor */
+       if (++i<argc) {
+ 	if (index(argv[i], ':')) {
+-	  if (sscanf(argv[i], "%lf:%lf", &hexpand, &vexpand)!=2) 
++	  if (sscanf(argv[i], "%lf:%lf", &hexpand, &vexpand)!=2)
+ 	    { hexpand = vexpand = 1.0; }
+ 	}
+ 	else hexpand = vexpand = atof(argv[i]);
+       }
+     }
+ 
+-    else if (!argcmp(argv[i],"-fg",3,0,&pm))              /* fg color */
++#ifdef HAVE_G3
++    else if (!argcmp(argv[i],"-fax",3,0,&highresfax));     /* fax */
++#endif
++
++    else if (!argcmp(argv[i],"-fg",3,0,&pm))               /* fg color */
+       { if (++i<argc) fgstr = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-fixed",3,1,&fixedaspect)); /* fix asp. ratio */
+-    
+-    else if (!argcmp(argv[i],"-flist",3,0,&pm))           /* file list */
++
++    else if (!argcmp(argv[i],"-fixed",5,1,&fixedaspect));  /* fix asp. ratio */
++
++#ifdef ENABLE_FIXPIX_SMOOTH
++    else if (!argcmp(argv[i],"-fixpix",5,1,&do_fixpix_smooth)); /* dithering */
++#endif
++
++    else if (!argcmp(argv[i],"-flist",3,0,&pm))            /* file list */
+       { if (++i<argc) flistName = argv[i]; }
+ 
+-    else if (!argcmp(argv[i],"-gamma",3,0,&pm))	          /* gamma */
++    else if (!argcmp(argv[i],"-gamma",3,0,&pm))	           /* gamma */
+       { if (++i<argc) gamval = atof(argv[i]);  gamset++; }
+-    
+-    else if (!argcmp(argv[i],"-geometry",3,0,&pm))	  /* geometry */
++
++    else if (!argcmp(argv[i],"-geometry",3,0,&pm))	   /* geometry */
+       { if (++i<argc) maingeom = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-grabdelay",3,0,&pm))	  /* grabDelay */
++
++    else if (!argcmp(argv[i],"-grabdelay",3,0,&pm))	   /* grabDelay */
+       { if (++i<argc) grabDelay = atoi(argv[i]); }
+-    
+-    else if (!argcmp(argv[i],"-gsdev",4,0,&pm))	          /* gsDevice */
++
++    else if (!argcmp(argv[i],"-gsdev",4,0,&pm))	           /* gsDevice */
+       { if (++i<argc) gsDev = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-gsgeom",4,0,&pm))          /* gsGeometry */
++
++    else if (!argcmp(argv[i],"-gsgeom",4,0,&pm))           /* gsGeometry */
+       { if (++i<argc) gsGeomStr = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-gsres",4,0,&pm))           /* gsResolution */
++
++    else if (!argcmp(argv[i],"-gsres",4,0,&pm))            /* gsResolution */
+       { if (++i<argc) gsRes=abs(atoi(argv[i])); }
+-    
+-    else if (!argcmp(argv[i],"-hflip",3,1,&autohflip));   /* hflip */
+ 
+-    else if (!argcmp(argv[i],"-hi",3,0,&pm))	          /* highlight */
++    else if (!argcmp(argv[i],"-hflip",3,1,&autohflip));    /* hflip */
++
++    else if (!argcmp(argv[i],"-hi",3,0,&pm))	           /* highlight */
+       { if (++i<argc) histr = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-hist", 4,1,&autohisteq));  /* hist eq */
++
++#ifdef HAVE_G3
++    else if (!argcmp(argv[i],"-highresfax",4,0,&highresfax));/* high res. fax */
++#endif
++
++    else if (!argcmp(argv[i],"-hist", 4,1,&autohisteq));   /* hist eq */
+ 
+     else if (!argcmp(argv[i],"-hsv",   3,1,&hsvmode));     /* hsvmode */
+ 
+     else if (!argcmp(argv[i],"-icgeometry",4,0,&pm))       /* icon geometry */
+       { if (++i<argc) icongeom = argv[i]; }
+-    
++
+     else if (!argcmp(argv[i],"-iconic",4,1,&startIconic)); /* iconic */
+-    
++
+     else if (!argcmp(argv[i],"-igeometry",3,0,&pm))        /* infogeom */
+       { if (++i<argc) infogeom = argv[i]; }
+-    
+-    else if (!argcmp(argv[i],"-imap",     3,1,&imap));        /* imap */
+-    else if (!argcmp(argv[i],"-lbrowse",  3,1,&browseMode));  /* browse mode */
+ 
+-    else if (!argcmp(argv[i],"-lo",3,0,&pm))	        /* lowlight */
++    else if (!argcmp(argv[i],"-imap",3,1,&imap));          /* imap */
++
++    else if (!argcmp(argv[i],"-ibg",3,0,&pm))             /* image bkgd color */
++      { if (++i<argc) imagebgstr = argv[i]; }
++
++    else if (!argcmp(argv[i],"-lbrowse",3,1,&browseMode)); /* browse mode */
++
++    else if (!argcmp(argv[i],"-lo",3,0,&pm))	           /* lowlight */
+       { if (++i<argc) lostr = argv[i]; }
+ 
+     else if (!argcmp(argv[i],"-loadclear",4,1,&clearonload)); /* clearonload */
+ 
+-    
+-    else not_in_first_half = 1;     
++
++    else not_in_first_half = 1;
+ 
+ 
+ 
+@@ -1339,103 +1621,130 @@
+     if (!argcmp(argv[i],"-max",4,1,&automax));	        /* auto maximize */
+     else if (!argcmp(argv[i],"-maxpect",5,1,&pm))       /* auto maximize */
+       { automax=pm; fixedaspect=pm; }
+-    
++
++#ifdef MACBINARY
++    else if (!argcmp(argv[i],"-macbinary",3,1,&handlemacb)); /* macbinary */
++#endif
++
+     else if (!argcmp(argv[i],"-mfn",3,0,&pm))           /* mono font name */
+       { if (++i<argc) monofontname = argv[i]; }
+ 
++#ifdef HAVE_MGCSFX
++    else if (!argcmp(argv[i],"-mgcsfx", 4,1,&mgcsfx));  /* mgcsfx */
++#endif
++
+     else if (!argcmp(argv[i],"-mono",3,1,&mono));	/* mono */
+-    
++
+     else if (!argcmp(argv[i],"-name",3,0,&pm))          /* name */
+       { if (++i<argc) winTitle = argv[i]; }
+-    
++
+     else if (!argcmp(argv[i],"-ncols",3,0,&pm))        /* ncols */
+       { if (++i<argc) ncols=abs(atoi(argv[i])); }
+-    
+-    else if (!argcmp(argv[i],"-ninstall",  3,1,&ninstall));   /* inst cmaps?*/
++
++    else if (!argcmp(argv[i],"-ninstall",  3,1,&ninstall));   /* inst cmaps? */
+     else if (!argcmp(argv[i],"-nodecor",   4,1,&nodecor));
+     else if (!argcmp(argv[i],"-nofreecols",4,1,&noFreeCols));
+     else if (!argcmp(argv[i],"-nolimits",  4,1,&nolimits));   /* nolimits */
++#ifdef HAVE_MGCSFX
++    else if (!argcmp(argv[i],"-nomgcsfx", 4,1,&nomgcsfx));    /* nomgcsfx */
++#endif
++#if defined(HAVE_PIC) || defined(HAVE_PIC2)
++    else if (!argcmp(argv[i],"-nopicadjust", 4,1,&nopicadjust));/*nopicadjust*/
++#endif
+     else if (!argcmp(argv[i],"-nopos",     4,1,&nopos));      /* nopos */
+     else if (!argcmp(argv[i],"-noqcheck",  4,1,&noqcheck));   /* noqcheck */
+-    else if (!argcmp(argv[i],"-noresetroot",5,1,&resetroot)); /* reset root*/
++    else if (!argcmp(argv[i],"-noresetroot",5,1,&resetroot)); /* reset root */
+     else if (!argcmp(argv[i],"-norm",      5,1,&autonorm));   /* norm */
+     else if (!argcmp(argv[i],"-nostat",    4,1,&nostat));     /* nostat */
+     else if (!argcmp(argv[i],"-owncmap",   2,1,&owncmap));    /* own cmap */
++#ifdef HAVE_PCD
++    else if (!argcmp(argv[i],"-pcd",       4,0,&pm))         /* pcd with size */
++      { if (i+1<argc) PcdSize = atoi(argv[++i]); }
++#endif
+     else if (!argcmp(argv[i],"-perfect",   3,1,&perfect));    /* -perfect */
++#ifdef HAVE_PIC2
++    else if (!argcmp(argv[i],"-pic2split", 3,1,&pic2split));  /* pic2split */
++#endif
+     else if (!argcmp(argv[i],"-pkludge",   3,1,&winCtrPosKludge));
+     else if (!argcmp(argv[i],"-poll",      3,1,&polling));    /* chk mod? */
+ 
+     else if (!argcmp(argv[i],"-preset",3,0,&pm))      /* preset */
+       { if (++i<argc) preset=abs(atoi(argv[i])); }
+-    
++
+     else if (!argcmp(argv[i],"-quick24",5,0,&pm))     /* quick 24-to-8 conv */
+       conv24 = CONV24_FAST;
+-    
++
+     else if (!argcmp(argv[i],"-quit",   2,1,&autoquit));   /* auto-quit */
+     else if (!argcmp(argv[i],"-random", 4,1,&randomShow)); /* random */
+     else if (!argcmp(argv[i],"-raw",    4,1,&autoraw));    /* force raw */
+ 
+     else if (!argcmp(argv[i],"-rbg",3,0,&pm))      /* root background color */
+       { if (++i<argc) rootbgstr = argv[i]; }
+-    
++
+     else if (!argcmp(argv[i],"-rfg",3,0,&pm))      /* root foreground color */
+       { if (++i<argc) rootfgstr = argv[i]; }
+-    
++
+     else if (!argcmp(argv[i],"-rgb",4,1,&pm))      /* rgb mode */
+       hsvmode = !pm;
+-    
++
+     else if (!argcmp(argv[i],"-RM",3,0,&pm))	   /* auto-delete */
+       autoDelete = 1;
+-    
++
+     else if (!argcmp(argv[i],"-rmode",3,0,&pm))	   /* root pattern */
+-      { if (++i<argc) rootMode = atoi(argv[i]); 
++      { if (++i<argc) rootMode = atoi(argv[i]);
+ 	useroot++;  rmodeset++;
+       }
+-    
++
+     else if (!argcmp(argv[i],"-root",4,1,&useroot));  /* use root window */
+-    
++
+     else if (!argcmp(argv[i],"-rotate",4,0,&pm))      /* rotate */
+       { if (++i<argc) autorotate = atoi(argv[i]); }
+-    
++
+     else if (!argcmp(argv[i],"-rv",3,1,&revvideo));   /* reverse video */
+     else if (!argcmp(argv[i],"-rw",3,1,&rwcolor));    /* use r/w color */
+ 
+     else if (!argcmp(argv[i],"-slow24",3,0,&pm))      /* slow 24->-8 conv.*/
+       conv24 = CONV24_SLOW;
+-    
++
+     else if (!argcmp(argv[i],"-smooth",3,1,&autosmooth));  /* autosmooth */
++    else if (!argcmp(argv[i],"-startgrab",3,1,&startGrab)); /* startGrab */
+     else if (!argcmp(argv[i],"-stdcmap",3,1,&stdcmap));    /* use stdcmap */
+ 
+     else if (!argcmp(argv[i],"-tgeometry",2,0,&pm))	   /* textview geom */
+       { if (++i<argc) textgeom = argv[i]; }
+-    
++
+     else if (!argcmp(argv[i],"-vflip",3,1,&autovflip));	   /* vflip */
+     else if (!argcmp(argv[i],"-viewonly",4,1,&viewonly));  /* viewonly */
+ 
+     else if (!argcmp(argv[i],"-visual",4,0,&pm))           /* visual */
+       { if (++i<argc) visualstr = argv[i]; }
+-    
++
++#ifdef VS_ADJUST
++    else if (!argcmp(argv[i],"-vsadjust", 3,1,&vsadjust));  /* vsadjust */
++#endif
++
+     else if (!argcmp(argv[i],"-vsdisable",4,1,&novbrowse)); /* disable sch? */
+-    
++
+     else if (!argcmp(argv[i],"-vsgeometry",4,0,&pm))	/* visSchnauzer geom */
+       { if (++i<argc) browgeom = argv[i]; }
+-    
++
+     else if (!argcmp(argv[i],"-vsmap",4,1,&browmap));	/* visSchnauzer map */
+-    
++
+     else if (!argcmp(argv[i],"-vsperfect",3,1,&browPerfect));	/* vs perf. */
+ 
+     else if (!argcmp(argv[i],"-wait",3,0,&pm)) {        /* secs betwn pics */
+       if (++i<argc) {
+-	waitsec = abs(atoi(argv[i]));
+-	if (waitsec<0) waitsec = 0;
++	char *comma = strchr(argv[i], ',');
++	waitsec_nonfinal = fabs(atof(argv[i]));
++	waitsec_final = comma? fabs(atof(comma+1)) : waitsec_nonfinal;
+       }
+     }
+-    
++
+     else if (!argcmp(argv[i],"-white",3,0,&pm))	        /* white color */
+       { if (++i<argc) whitestr = argv[i]; }
+-    
++
+     else if (!argcmp(argv[i],"-wloop",3,1,&waitloop));	/* waitloop */
+-    
++
+     else if (not_in_first_half) cmdSyntax();
+   }
+ 
+@@ -1453,7 +1762,11 @@
+   /* check options for validity */
+ 
+   if (strlen(searchdir)) {  /* got a search directory */
++#ifdef AUTO_EXPAND
++    if (Chvdir(searchdir)) {
++#else
+     if (chdir(searchdir)) {
++#endif
+       fprintf(stderr,"xv: unable to cd to directory '%s'.\n",searchdir);
+       fprintf(stderr,
+        "    Ignoring '-dir' option and/or 'xv.searchDirectory' resource\n");
+@@ -1462,7 +1775,7 @@
+   }
+ 
+ 
+-  if (flistName) 
++  if (flistName)
+     add_filelist_to_namelist(flistName, namelist, &numnames, MAXNAMES);
+ 
+   RANGE(curstype,0,254);
+@@ -1475,16 +1788,16 @@
+ 
+   /* if using root, generally gotta map ctrl window, 'cause there won't be
+      any way to ask for it.  (no kbd or mouse events from rootW) */
+-  if (useroot && !autoquit) ctrlmap = -1;    
++  if (useroot && !autoquit) ctrlmap = -1;
++
+ 
+-  
+   if (abs(autorotate) !=   0 && abs(autorotate) != 90 &&
+       abs(autorotate) != 180 && abs(autorotate) != 270) {
+     fprintf(stderr,"Invalid auto rotation value (%d) ignored.\n", autorotate);
+     fprintf(stderr,"  (Valid values:  0, +-90, +-180, +-270)\n");
+ 
+     autorotate = 0;
+-  } 
++  }
+ 
+ 
+   if (grabDelay < 0 || grabDelay > 15) {
+@@ -1498,9 +1811,9 @@
+     fprintf(stderr,"  (Valid values:  1, 2, 3, 4)\n");
+ 
+     preset = 0;
+-  } 
++  }
+ 
+-  if (waitsec < 0) noFreeCols = 0;   /* disallow nfc if not doing slideshow */
++  if (waitsec < 0.0) noFreeCols = 0;   /* disallow nfc if not doing slideshow */
+   if (noFreeCols && perfect) { perfect = 0;  owncmap = 1; }
+ 
+   /* decide what default color allocation stuff we've settled on */
+@@ -1512,24 +1825,24 @@
+ 
+   defaultCmapMode = colorMapMode;  /* default mode for 8-bit images */
+ 
+-  if (nopos) { 
+-    maingeom = infogeom = ctrlgeom = gamgeom = browgeom = textgeom = NULL;
+-    cmtgeom = NULL;
++  if (nopos) {
++    maingeom = infogeom = ctrlgeom = gamgeom = browgeom = textgeom = cmtgeom =
++      (const char *) NULL;
+   }
+ 
+   /* if -root and -maxp, disallow 'integer' tiling modes */
+-  if (useroot && fixedaspect && automax && !rmodeset && 
++  if (useroot && fixedaspect && automax && !rmodeset &&
+       (rootMode == RM_TILE || rootMode == RM_IMIRROR))
+     rootMode = RM_CSOLID;
+ }
+ 
+ 
+ 
++static int cpos = 0;
+ 
+ /***********************************/
+-static int cpos = 0;
+ static void printoption(st)
+-     char *st;
++     const char *st;
+ {
+   if (strlen(st) + cpos > 78) {
+     fprintf(stderr,"\n   ");
+@@ -1540,8 +1853,26 @@
+   cpos = cpos + strlen(st) + 1;
+ }
+ 
++
+ static void cmdSyntax()
+ {
++  /* GRR 19980605:  added version info for most common libraries */
++  fprintf(stderr, "XV - %s.\n", REVDATE);
++#ifdef HAVE_JPEG
++  VersionInfoJPEG();
++#endif
++#ifdef HAVE_JP2K
++  VersionInfoJP2K();
++#endif
++#ifdef HAVE_TIFF
++  VersionInfoTIFF();
++#endif
++#ifdef HAVE_PNG
++  VersionInfoPNG();
++#endif
++  /* pbm/pgm/ppm support is native, not via pbmplus/netpbm libraries */
++  fprintf(stderr, "\n");
++
+   fprintf(stderr, "Usage:\n");
+   printoption(cmd);
+   printoption("[-]");
+@@ -1579,8 +1910,14 @@
+   printoption("[-/+dither]");
+   printoption("[-drift dx dy]");
+   printoption("[-expand exp | hexp:vexp]");
++#ifdef HAVE_G3
++  printoption("[-fax]");
++#endif
+   printoption("[-fg color]");
+   printoption("[-/+fixed]");
++#ifdef ENABLE_FIXPIX_SMOOTH
++  printoption("[-/+fixpix]");
++#endif
+   printoption("[-flist fname]");
+   printoption("[-gamma val]");
+   printoption("[-geometry geom]");
+@@ -1591,8 +1928,12 @@
+   printoption("[-help]");
+   printoption("[-/+hflip]");
+   printoption("[-hi color]");
++#ifdef HAVE_G3
++  printoption("[-highresfax]");
++#endif
+   printoption("[-/+hist]");
+   printoption("[-/+hsv]");
++  printoption("[-ibg color]");  /* GRR 19980314 */
+   printoption("[-icgeometry geom]");
+   printoption("[-/+iconic]");
+   printoption("[-igeometry geom]");
+@@ -1600,9 +1941,15 @@
+   printoption("[-/+lbrowse]");
+   printoption("[-lo color]");
+   printoption("[-/+loadclear]");
++#ifdef MACBINARY
++  printoption("[-/+macbinary]");
++#endif
+   printoption("[-/+max]");
+   printoption("[-/+maxpect]");
+   printoption("[-mfn font]");
++#ifdef HAVE_MGCSFX
++  printoption("[-/+mgcsfx]");
++#endif
+   printoption("[-/+mono]");
+   printoption("[-name str]");
+   printoption("[-ncols #]");
+@@ -1610,13 +1957,25 @@
+   printoption("[-/+nodecor]");
+   printoption("[-/+nofreecols]");
+   printoption("[-/+nolimits]");
++#ifdef HAVE_MGCSFX
++  printoption("[-/+nomgcsfx]");
++#endif
++#if defined(HAVE_PIC) || defined(HAVE_PIC2)
++  printoption("[-/+nopicadjust]");
++#endif
+   printoption("[-/+nopos]");
+   printoption("[-/+noqcheck]");
+   printoption("[-/+noresetroot]");
+   printoption("[-/+norm]");
+   printoption("[-/+nostat]");
+   printoption("[-/+owncmap]");
++#ifdef HAVE_PCD
++  printoption("[-pcd size(0=192*128,1,2,3,4=3072*2048)]");
++#endif
+   printoption("[-/+perfect]");
++#ifdef HAVE_PIC2
++  printoption("[-/+pic2split]");
++#endif
+   printoption("[-/+pkludge]");
+   printoption("[-/+poll]");
+   printoption("[-preset #]");
+@@ -1635,17 +1994,22 @@
+   printoption("[-/+rw]");
+   printoption("[-slow24]");
+   printoption("[-/+smooth]");
++  printoption("[-/+startgrab]");
+   printoption("[-/+stdcmap]");
+   printoption("[-tgeometry geom]");
+   printoption("[-/+vflip]");
+   printoption("[-/+viewonly]");
+   printoption("[-visual type]");
++#ifdef VS_ADJUST
++  printoption("[-/+vsadjust]");
++#endif
+   printoption("[-/+vsdisable]");
+   printoption("[-vsgeometry geom]");
+   printoption("[-/+vsmap]");
+   printoption("[-/+vsperfect]");
+-  printoption("[-wait seconds]");
++  printoption("[-wait secs[,final_secs]]");
+   printoption("[-white color]");
++  printoption("[-windowid windowid]");
+   printoption("[-/+wloop]");
+   printoption("[filename ...]");
+   fprintf(stderr,"\n\n");
+@@ -1656,7 +2020,7 @@
+ /***********************************/
+ static void rmodeSyntax()
+ {
+-  fprintf(stderr,"%s: unknown root mode '%d'.  Valid modes are:\n", 
++  fprintf(stderr,"%s: unknown root mode '%d'.  Valid modes are:\n",
+ 	  cmd, rootMode);
+   fprintf(stderr,"\t0: tiling\n");
+   fprintf(stderr,"\t1: integer tiling\n");
+@@ -1668,6 +2032,7 @@
+   fprintf(stderr,"\t7: centered on a 'brick' background\n");
+   fprintf(stderr,"\t8: symmetrical tiling\n");
+   fprintf(stderr,"\t9: symmetrical mirrored tiling\n");
++  fprintf(stderr,"\t10: upper left corner\n");
+   fprintf(stderr,"\n");
+   Quit(1);
+ }
+@@ -1675,17 +2040,15 @@
+ 
+ /***********************************/
+ static int argcmp(a1, a2, minlen, plusallowed, plusminus)
+-     char *a1, *a2;
++     const char *a1, *a2;
+      int  minlen, plusallowed;
+      int *plusminus;
+ {
+-  /* does a string compare between a1 and a2.  To return '0', a1 and a2 
+-     must match to the length of a2, and that length has to
++  /* does a string compare between a1 and a2.  To return '0', a1 and a2
++     must match to the length of a1, and that length has to
+      be at least 'minlen'.  Otherwise, return non-zero.  plusminus set to '1'
+      if '-option', '0' if '+option' */
+ 
+-  int i;
+-
+   if ((strlen(a1) < (size_t) minlen) || (strlen(a2) < (size_t) minlen))
+     return 1;
+   if (strlen(a1) > strlen(a2)) return 1;
+@@ -1694,7 +2057,7 @@
+ 
+   if (a1[0]=='-' || (plusallowed && a1[0]=='+')) {
+     /* only set if we match */
+-    *plusminus = (a1[0] == '-');    
++    *plusminus = (a1[0] == '-');
+     return 0;
+   }
+ 
+@@ -1721,8 +2084,11 @@
+   int   oldCXOFF, oldCYOFF, oldCWIDE, oldCHIGH, wascropped;
+   char *tmp;
+   char *fullname,       /* full name of the original file */
+-        filename[512],  /* full name of file to load (could be /tmp/xxx)*/
+-        globnm[512];    /* globbed version of fullname of orig file */
++        filename[512];  /* full name of file to load (could be /tmp/xxx)*/
++#ifdef MACBINARY
++  char origname[512];	/* file name of original file (NO processing) */
++  origname[0] = '\0';
++#endif
+ 
+   xvbzero((char *) &pinfo, sizeof(PICINFO));
+ 
+@@ -1748,7 +2114,7 @@
+ 
+   /* if we're not loading next or prev page in a multi-page doc, kill off
+      page files */
+-  if (strlen(pageBaseName) && filenum!=OP_PAGEDN && filenum!=OP_PAGEUP) 
++  if (strlen(pageBaseName) && filenum!=OP_PAGEDN && filenum!=OP_PAGEUP)
+     killpage = 1;
+ 
+ 
+@@ -1799,14 +2165,13 @@
+   }
+ 
+   else if (filenum == PADDED) {
+-    /* need fullfname (used for window/icon name), 
++    /* need fullfname (used for window/icon name),
+        basefname(compute from fullfname) */
+ 
+     i = LoadPad(&pinfo, fullfname);
+     fullname = fullfname;
+     strcpy(filename, fullfname);
+-    tmp = BaseName(fullfname);
+-    strcpy(basefname, tmp);
++    strcpy(basefname, BaseName(fullfname));
+ 
+     if (!i) goto FAILED;   /* shouldn't happen */
+ 
+@@ -1855,33 +2220,48 @@
+       frompipe = 1;
+     }
+   }
++#ifdef AUTO_EXPAND
++  else {
++    fullname = (char *) malloc(MAXPATHLEN+2);
++    strcpy(fullname, namelist[filenum]);   // 1 of 2 places fullname != const
++    freename = 1;
++  }
++  tmp = (char *) rindex(fullname, '/');
++  if (tmp) {
++    *tmp = '\0';			   // 2 of 2 places fullname != const
++    Mkvdir(fullname);
++    *tmp = '/';
++  }
++  Dirtovd(fullname);
++#else
+   else fullname = namelist[filenum];
+-
++#endif
+ 
+   strcpy(fullfname, fullname);
+-  tmp = BaseName(fullname);
+-  strcpy(basefname, tmp);
++  strcpy(basefname, BaseName(fullname));
+ 
+ 
+   /* chop off trailing ".Z", ".z", or ".gz" from displayed basefname, if any */
+-  if (strlen(basefname) > (size_t) 2     && 
+-      strcmp(basefname+strlen(basefname)-2,".Z")==0)
++  if (strlen(basefname)>2 && strcmp(basefname+strlen(basefname)-2,".Z")==0)
+     basefname[strlen(basefname)-2]='\0';
+   else {
+ #ifdef GUNZIP
+-    if (strlen(basefname)>2 && strcmp(basefname+strlen(basefname)-2,".Z")==0)
++    if (strlen(basefname)>2 && strcmp(basefname+strlen(basefname)-2,".z")==0)
+       basefname[strlen(basefname)-2]='\0';
+-
+-    else if (strlen(basefname)>3 && 
+-	     strcmp(basefname+strlen(basefname)-3,".gz")==0)
++    else
++    if (strlen(basefname)>3 && strcmp(basefname+strlen(basefname)-3,".gz")==0)
+       basefname[strlen(basefname)-3]='\0';
+-#endif /* GUNZIP */
++#endif
++#ifdef BUNZIP2
++    if (strlen(basefname)>4 && strcmp(basefname+strlen(basefname)-4,".bz2")==0)
++      basefname[strlen(basefname)-4]='\0';
++#endif
+   }
+ 
+ 
+   if (filenum == LOADPIC && ISPIPE(fullname[0])) {
+     /* if we're reading from a pipe, 'filename' will have the /tmp/xvXXXXXX
+-       filename, and we can skip a lot of stuff:  (such as prepending 
++       filename, and we can skip a lot of stuff:  (such as prepending
+        'initdir' to relative paths, dealing with reading from stdin, etc. */
+ 
+     /* at this point, fullname = "! do some commands",
+@@ -1891,11 +2271,11 @@
+ 
+   else {  /* NOT reading from a PIPE */
+ 
+-    /* if fullname doesn't start with a '/' (ie, it's a relative path), 
+-       (and it's not LOADPIC and it's not the special case '<stdin>') 
++    /* if fullname doesn't start with a '/' (ie, it's a relative path),
++       (and it's not LOADPIC and it's not the special case '<stdin>')
+        then we need to prepend a directory name to it:
+-       
+-       prepend 'initdir', 
++
++       prepend 'initdir',
+        if we have a searchdir (ie, we have multiple places to look),
+              see if such a file exists (via fopen()),
+        if it does, we're done.
+@@ -1904,7 +2284,7 @@
+        if it does, we're done.
+        if it doesn't, remove all prepended directories, and fall through
+              to error code below.  */
+-    
++
+     if (filenum!=LOADPIC && fullname[0]!='/' && strcmp(fullname,STDINSTR)!=0) {
+       char *tmp1;
+ 
+@@ -1954,28 +2334,40 @@
+ 	}
+       }
+     }
+-    
++
+     strcpy(filename, fullname);
+-    
+-    
++
++
+     /* if the file is STDIN, write it out to a temp file */
+ 
+     if (strcmp(filename,STDINSTR)==0) {
+-      FILE *fp;
++      FILE *fp = NULL;
++#ifndef USE_MKSTEMP
++      int tmpfd;
++#endif
+ 
+-#ifndef VMS      
++#ifndef VMS
+       sprintf(filename,"%s/xvXXXXXX",tmpdir);
+ #else /* it is VMS */
+       sprintf(filename, "[]xvXXXXXX");
+ #endif
++
++#ifdef USE_MKSTEMP
++      fp = fdopen(mkstemp(filename), "w");
++#else
+       mktemp(filename);
++      tmpfd = open(filename,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR);
++      if (tmpfd < 0) FatalError("openPic(): can't create temporary file");
++      fp = fdopen(tmpfd,"w");
++#endif
++      if (!fp) FatalError("openPic(): can't write temporary file");
+ 
+       clearerr(stdin);
+-      fp = fopen(filename,"w");
+-      if (!fp) FatalError("openPic(): can't write temporary file");
+-    
+       while ( (i=getchar()) != EOF) putc(i,fp);
+       fclose(fp);
++#ifndef USE_MKSTEMP
++      close(tmpfd);
++#endif
+ 
+       /* and remove it from list, since we can never reload from stdin */
+       if (strcmp(namelist[0], STDINSTR)==0) deleteFromList(0);
+@@ -1990,20 +2382,26 @@
+     (no pipes or stdin, though it could be compressed) to be loaded */
+   filetype = ReadFileType(filename);
+ 
++#ifdef HAVE_MGCSFX
++  if (mgcsfx && filetype == RFT_UNKNOWN){ /* force use MgcSfx */
++    if(getInputCom() != 0) filetype = RFT_MGCSFX;
++  }
++#endif
+ 
+-  if (filetype == RFT_COMPRESS) {   /* a compressed file.  uncompress it */
++  /* if it's a compressed file, uncompress it: */
++  if ((filetype == RFT_COMPRESS) || (filetype == RFT_BZIP2)) {
+     char tmpname[128];
+ 
+     if (
+ #ifndef VMS
+-	UncompressFile(filename, tmpname)
++	UncompressFile(filename, tmpname, filetype)
+ #else
+-	UncompressFile(basefname, tmpname)
++	UncompressFile(basefname, tmpname, filetype)
+ #endif
+ 	) {
+ 
+       filetype = ReadFileType(tmpname);    /* and try again */
+-      
++
+       /* if we made a /tmp file (from stdin, etc.) won't need it any more */
+       if (strcmp(fullname,filename)!=0) unlink(filename);
+ 
+@@ -2013,7 +2411,58 @@
+ 
+     WaitCursor();
+   }
+-
++
++#ifdef MACBINARY
++  if (handlemacb && macb_file == True) {
++    char tmpname[128];
++
++    if (RemoveMacbinary(filename, tmpname)) {
++      if (strcmp(fullname,filename)!=0) unlink(filename);
++      strcpy(origname, filename);
++      strcpy(filename, tmpname);
++    }
++    else filetype = RFT_ERROR;
++
++    WaitCursor();
++  }
++#endif
++
++#ifdef HAVE_MGCSFX_AUTO
++  if (filetype == RFT_MGCSFX) {
++      char tmpname[128], tmp[256];
++      char *icom;
++
++      if ((icom = mgcsfx_auto_input_com(filename)) != NULL) {
++	sprintf(tmpname, "%s/xvmsautoXXXXXX", tmpdir);
++#ifdef USE_MKSTEMP
++	close(mkstemp(tmpname));
++#else
++	mktemp(tmpname);
++#endif
++	SetISTR(ISTR_INFO, "Converting to known format by MgcSfx auto...");
++	sprintf(tmp,"%s >%s", icom, tmpname);
++      }
++      else goto ms_auto_no;
++
++#ifndef VMS
++      if (system(tmp))
++#else
++      if (!system(tmp))
++#endif
++      {
++	SetISTR(ISTR_INFO, "Unable to convert '%s' by MgcSfx auto.",
++	  BaseName(filename));
++	Warning();
++	filetype = RFT_ERROR;
++	goto ms_auto_no;
++      }
++
++      filetype = ReadFileType(tmpname);
++      if (strcmp(fullname,filename)!=0) unlink(filename);
++      strcpy(filename, tmpname);
++  }
++ms_auto_no:
++#endif /* HAVE_MGCSFX_AUTO */
+ 
+   if (filetype == RFT_ERROR) {
+     char  foostr[512];
+@@ -2027,10 +2476,16 @@
+ 
+   if (filetype == RFT_UNKNOWN) {
+     /* view as a text/hex file */
+-    TextView(filename);
++#ifdef MACBINARY
++    if (origname[0])
++      i = TextView(origname);
++    else
++#endif
++      i = TextView(filename);
+     SetISTR(ISTR_INFO,"'%s' not in a recognized format.", basefname);
+     /* Warning();  */
+-    goto SHOWN_AS_TEXT;
++    if (i) goto SHOWN_AS_TEXT;
++    else   goto FAILED;
+   }
+ 
+   if (filetype < RFT_ERROR) {
+@@ -2058,8 +2513,9 @@
+   if (filetype == RFT_XBM && (!i || pinfo.w==0 || pinfo.h==0)) {
+     /* probably just a '.h' file or something... */
+     SetISTR(ISTR_INFO," ");
+-    TextView(filename);
+-    goto SHOWN_AS_TEXT;
++    i = TextView(filename);
++    if (i) goto SHOWN_AS_TEXT;
++    else   goto FAILED;
+   }
+ 
+   if (!i) {
+@@ -2084,7 +2540,7 @@
+   /**************/
+   /* SUCCESS!!! */
+   /**************/
+-    
++
+ 
+  GOTIMAGE:
+   /* successfully read this picture.  No failures from here on out
+@@ -2097,7 +2553,7 @@
+   if (conv24MB.flags[CONV24_LOCK]) {  /* locked */
+     if (pinfo.type==PIC24 && picType==PIC8) {           /* 24 -> 8 bit */
+       byte *pic8;
+-      pic8 = Conv24to8(pinfo.pic, pinfo.w, pinfo.h, ncols, 
++      pic8 = Conv24to8(pinfo.pic, pinfo.w, pinfo.h, ncols,
+ 		       pinfo.r, pinfo.g, pinfo.b);
+       free(pinfo.pic);
+       pinfo.pic = pic8;
+@@ -2108,7 +2564,7 @@
+ 
+     else if (pinfo.type!=PIC24 && picType==PIC24) {    /* 8 -> 24 bit */
+       byte *pic24;
+-      pic24 = Conv8to24(pinfo.pic, pinfo.w, pinfo.h, 
++      pic24 = Conv8to24(pinfo.pic, pinfo.w, pinfo.h,
+ 			pinfo.r, pinfo.g, pinfo.b);
+       free(pinfo.pic);
+       pinfo.pic  = pic24;
+@@ -2144,7 +2600,7 @@
+ 
+   if (mainW && !useroot) {
+     /* avoid generating excess configure events while we resize the window */
+-    XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++    XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 		 | StructureNotifyMask
+                  | ButtonPressMask | KeyReleaseMask
+                  | EnterWindowMask | LeaveWindowMask);
+@@ -2162,11 +2618,13 @@
+   pHIGH = pinfo.h;
+   if (pinfo.frmType >=0) SetDirSaveMode(F_FORMAT, pinfo.frmType);
+   if (pinfo.colType >=0) SetDirSaveMode(F_COLORS, pinfo.colType);
+-  
++
+   SetISTR(ISTR_FORMAT, pinfo.fullInfo);
+   strcpy(formatStr, pinfo.shrtInfo);
+   picComments = pinfo.comment;
+   ChangeCommentText();
++  picExifInfo = pinfo.exifInfo;
++  picExifInfoSize = pinfo.exifInfoSize;
+ 
+   for (i=0; i<256; i++) {
+     rMap[i] = pinfo.r[i];
+@@ -2194,12 +2652,15 @@
+   if (fullname && strcmp(fullname,filename)!=0) unlink(filename);
+ 
+ 
+-  SetISTR(ISTR_INFO,formatStr);
+-	
++  SetISTR(ISTR_INFO, "%s", formatStr);
++
+   SetInfoMode(INF_PART);
+-  SetISTR(ISTR_FILENAME, 
+-	  (filenum==DFLTPIC || filenum==GRABBED || frompipe)
+-	  ? "<none>" : basefname);
++  if (filenum==DFLTPIC || filenum==GRABBED || frompipe)
++    SetISTR(ISTR_FILENAME, "<none>");
++  else if (numPages > 1)
++    SetISTR(ISTR_FILENAME, "%s  Page %d of %d", basefname, curPage+1, numPages);
++  else
++    SetISTR(ISTR_FILENAME, "%s", basefname);
+ 
+   SetISTR(ISTR_RES,"%d x %d",pWIDE,pHIGH);
+   SetISTR(ISTR_COLOR, "");
+@@ -2219,7 +2680,7 @@
+ 
+ 
+   /* handle various 'auto-whatever' command line options
+-     Note that if 'frompoll' is set, things that have to do with 
++     Note that if 'frompoll' is set, things that have to do with
+      setting the expansion factor are skipped, as we'll want it to
+      display in the (already-existing) window at the same size */
+ 
+@@ -2254,7 +2715,7 @@
+       w = eWIDE;  h = (w*3) / 4;
+       eWIDE = w;  eHIGH = h;
+     }
+-    
++
+ 
+     if (eWIDE != cWIDE || eHIGH != cHIGH) epic = (byte *) NULL;
+ 
+@@ -2306,14 +2767,14 @@
+     aspWIDE = eWIDE;  aspHIGH = eHIGH;   /* aspect-corrected eWIDE,eHIGH */
+ 
+     if (hexpand < 0.0) eWIDE=(int)(aspWIDE / -hexpand);  /* neg:  reciprocal */
+-                  else eWIDE=(int)(aspWIDE *  hexpand);  
++                  else eWIDE=(int)(aspWIDE *  hexpand);
+     if (vexpand < 0.0) eHIGH=(int)(aspHIGH / -vexpand);  /* neg:  reciprocal */
+-                  else eHIGH=(int)(aspHIGH *  vexpand);  
++                  else eHIGH=(int)(aspHIGH *  vexpand);
+ 
+     if (maingeom) {
+       /* deal with geometry spec.  Note, they shouldn't have given us
+        *both* an expansion factor and a geomsize.  The geomsize wins out */
+-    
++
+       int i,x,y,gewide,gehigh;  u_int w,h;
+ 
+       gewide = eWIDE;  gehigh = eHIGH;
+@@ -2321,11 +2782,11 @@
+ 
+       if (i&WidthValue)  gewide = (int) w;
+       if (i&HeightValue) gehigh = (int) h;
+-      
++
+       /* handle case where the pinheads only specified width *or * height */
+       if (( i&WidthValue && ~i&HeightValue) ||
+ 	  (~i&WidthValue &&  i&HeightValue)) {
+-    
++
+ 	if (i&WidthValue) { gehigh = (aspHIGH * gewide) / pWIDE; }
+ 	             else { gewide = (aspWIDE * gehigh) / pHIGH; }
+       }
+@@ -2391,7 +2852,7 @@
+ 
+     /* if we're using an integer tiled root mode, truncate eWIDE/eHIGH to
+        be an integer divisor of the display size */
+-      
++
+     if (useroot && (rootMode == RM_TILE || rootMode == RM_IMIRROR)) {
+       /* make picture size a divisor of the rootW size.  round down */
+       i = (dispWIDE + eWIDE-1) / eWIDE;   eWIDE = (dispWIDE + i-1) / i;
+@@ -2409,7 +2870,7 @@
+     if (autodither && ncols>0) epicMode = EM_DITH;
+ 
+     /* if in CM_STDCMAP mode, and *not* in '-wait 0', then autodither */
+-    if (colorMapMode == CM_STDCMAP && waitsec != 0) epicMode = EM_DITH;
++    if (colorMapMode == CM_STDCMAP && waitsec != 0.0) epicMode = EM_DITH;
+ 
+     /* if -smooth or image has been shrunk to fit screen */
+     if (autosmooth || (pWIDE >maxWIDE || pHIGH>maxHIGH)
+@@ -2419,7 +2880,7 @@
+ 
+     /* 'dithering' makes no sense in 24-bit mode */
+     if (picType == PIC24 && epicMode == EM_DITH) epicMode = EM_RAW;
+-    
++
+     SetEpicMode();
+   } /* end of !frompoll */
+ 
+@@ -2450,7 +2911,7 @@
+   if (useroot) mainW = vrootW;
+   if (eWIDE != cWIDE || eHIGH != cHIGH) epic = (byte *) NULL;
+ 
+-  NewPicGetColors(autonorm, autohisteq); 
++  NewPicGetColors(autonorm, autohisteq);
+ 
+   GenerateEpic(eWIDE, eHIGH);     /* want to dither *after* color allocs */
+   CreateXImage();
+@@ -2474,7 +2935,7 @@
+   SetISTR(ISTR_INFO,"%s  %s  %s", formatStr,
+ 	  (picType==PIC8) ? "8-bit mode." : "24-bit mode.",
+ 	  tmp);
+-	
++
+   SetInfoMode(INF_FULL);
+   if (freename) free(fullname);
+ 
+@@ -2495,20 +2956,24 @@
+      to generate the correct exposes (particularly with 'BitGravity' turned
+      on */
+ 
+-  if (mainW && !useroot) GenExpose(mainW, 0, 0, (u_int) eWIDE, (u_int) eHIGH);
++  /*Brian T. Schellenberger: fix for X 4.2 refresh problem*/
++  if (mainW && !useroot) {
++    XSync(theDisp, False);
++    GenExpose(mainW, 0, 0, (u_int) eWIDE, (u_int) eHIGH);
++  }
+ 
+   return 1;
+ 
+-  
++
+  FAILED:
+   SetCursors(-1);
+   KillPageFiles(pinfo.pagebname, pinfo.numpages);
+ 
+-  if (fullname && strcmp(fullname,filename)!=0) 
++  if (fullname && strcmp(fullname,filename)!=0)
+     unlink(filename);   /* kill /tmp file */
+   if (freename) free(fullname);
+ 
+-  if (!fromint && !polling && filenum>=0 && filenum<nList.nstr) 
++  if (!fromint && !polling && filenum>=0 && filenum<nList.nstr)
+     deleteFromList(filenum);
+ 
+   if (polling) sleep(1);
+@@ -2527,6 +2992,9 @@
+ }
+ 
+ 
++extern byte ZXheader[128];	/* [JCE] Spectrum screen magic number is
++                                  defined in xvzx.c */
++
+ 
+ /********************************/
+ int ReadFileType(fname)
+@@ -2539,76 +3007,118 @@
+ 
+   FILE *fp;
+   byte  magicno[30];    /* first 30 bytes of file */
+-  int   rv, n;
++  int   rv=RFT_UNKNOWN, n;
++#ifdef MACBINARY
++  int   macbin_alrchk = False;
++#endif
+ 
+   if (!fname) return RFT_ERROR;   /* shouldn't happen */
+ 
+   fp = xv_fopen(fname, "r");
+   if (!fp) return RFT_ERROR;
+ 
+-  n = fread(magicno, (size_t) 1, (size_t) 30, fp);  
++  if (strlen(fname) > 4 &&
++      strcasecmp(fname+strlen(fname)-5, ".wbmp")==0)          rv = RFT_WBMP;
++
++  n = fread(magicno, (size_t) 1, sizeof(magicno), fp);
+   fclose(fp);
+ 
+-  if (n<30) return RFT_UNKNOWN;    /* files less than 30 bytes long... */
++  if (n<=0) return RFT_UNKNOWN;
++
++  /* it is just barely possible that a few files could legitimately be as small
++     as 30 bytes (e.g., binary P{B,G,P}M format), so zero out rest of "magic
++     number" buffer and don't quit immediately if we read something small but
++     not empty */
++  if (n<30) memset(magicno+n, 0, sizeof(magicno)-n);
+ 
+-  rv = RFT_UNKNOWN;
++#ifdef MACBINARY
++  macb_file = False;
++  while (1) {
++#endif
+ 
+-  if (strncmp((char *) magicno,"GIF87a", (size_t) 6)==0 ||
+-      strncmp((char *) magicno,"GIF89a", (size_t) 6)==0)        rv = RFT_GIF;
++#ifdef HAVE_MGCSFX
++  if (is_mgcsfx(fname, magicno, 30) != 0) rv = RFT_MGCSFX;
++  else
++#endif
++       if (strncmp((char *) magicno,"GIF87a", (size_t) 6)==0 ||
++	   strncmp((char *) magicno,"GIF89a", (size_t) 6)==0) rv = RFT_GIF;
+ 
+   else if (strncmp((char *) magicno,"VIEW", (size_t) 4)==0 ||
+-	   strncmp((char *) magicno,"WEIV", (size_t) 4)==0)     rv = RFT_PM;
++	   strncmp((char *) magicno,"WEIV", (size_t) 4)==0)   rv = RFT_PM;
++
++#ifdef HAVE_PIC2
++  else if (magicno[0]=='P' && magicno[1]=='2' &&
++	   magicno[2]=='D' && magicno[3]=='T')                rv = RFT_PIC2;
++#endif
+ 
+-  else if (magicno[0] == 'P' && magicno[1]>='1' && 
+-	   magicno[1]<='6')                             rv = RFT_PBM;
++  else if (magicno[0] == 'P' && magicno[1]>='1' &&
++	   (magicno[1]<='6' || magicno[1]=='8'))              rv = RFT_PBM;
+ 
+   /* note: have to check XPM before XBM, as first 2 chars are the same */
+   else if (strncmp((char *) magicno, "/* XPM */", (size_t) 9)==0) rv = RFT_XPM;
+ 
+   else if (strncmp((char *) magicno,"#define", (size_t) 7)==0 ||
+-	   (magicno[0] == '/' && magicno[1] == '*'))    rv = RFT_XBM;
++	   (magicno[0] == '/' && magicno[1] == '*'))          rv = RFT_XBM;
+ 
+   else if (magicno[0]==0x59 && (magicno[1]&0x7f)==0x26 &&
+-	   magicno[2]==0x6a && (magicno[3]&0x7f)==0x15) rv = RFT_SUNRAS;
++	   magicno[2]==0x6a && (magicno[3]&0x7f)==0x15)       rv = RFT_SUNRAS;
+ 
+-  else if (magicno[0] == 'B' && magicno[1] == 'M')      rv = RFT_BMP;
++  else if (magicno[0] == 'B' && magicno[1] == 'M')            rv = RFT_BMP;
+ 
+-  else if (magicno[0]==0x52 && magicno[1]==0xcc)        rv = RFT_UTAHRLE;
++  else if (magicno[0]==0x52 && magicno[1]==0xcc)              rv = RFT_UTAHRLE;
+ 
+   else if ((magicno[0]==0x01 && magicno[1]==0xda) ||
+-	   (magicno[0]==0xda && magicno[1]==0x01))      rv = RFT_IRIS;
++	   (magicno[0]==0xda && magicno[1]==0x01))            rv = RFT_IRIS;
+ 
+-  else if (magicno[0]==0x1f && magicno[1]==0x9d)        rv = RFT_COMPRESS;
++  else if (magicno[0]==0x1f && magicno[1]==0x9d)              rv = RFT_COMPRESS;
+ 
+ #ifdef GUNZIP
+-  else if (magicno[0]==0x1f && magicno[1]==0x8b)        rv = RFT_COMPRESS;
++  else if (magicno[0]==0x1f && magicno[1]==0x8b)              rv = RFT_COMPRESS;
++#endif
++
++#ifdef BUNZIP2
++  else if (magicno[0]==0x42 && magicno[1]==0x5a)              rv = RFT_BZIP2;
+ #endif
+ 
+-  else if (magicno[0]==0x0a && magicno[1] <= 5)         rv = RFT_PCX;
++  else if (magicno[0]==0x0a && magicno[1] <= 5)               rv = RFT_PCX;
+ 
+-  else if (strncmp((char *) magicno,   "FORM", (size_t) 4)==0 && 
+-	   strncmp((char *) magicno+8, "ILBM", (size_t) 4)==0)   rv = RFT_IFF;
++  else if (strncmp((char *) magicno,   "FORM", (size_t) 4)==0 &&
++	   strncmp((char *) magicno+8, "ILBM", (size_t) 4)==0) rv = RFT_IFF;
+ 
+   else if (magicno[0]==0 && magicno[1]==0 &&
+ 	   magicno[2]==2 && magicno[3]==0 &&
+ 	   magicno[4]==0 && magicno[5]==0 &&
+-	   magicno[6]==0 && magicno[7]==0)              rv = RFT_TARGA;
++	   magicno[6]==0 && magicno[7]==0)                    rv = RFT_TARGA;
+ 
+   else if (magicno[4]==0x00 && magicno[5]==0x00 &&
+-	   magicno[6]==0x00 && magicno[7]==0x07)        rv = RFT_XWD;
++	   magicno[6]==0x00 && magicno[7]==0x07)              rv = RFT_XWD;
+ 
+-  else if (strncmp((char *) magicno,"SIMPLE  ", (size_t) 8)==0 && 
+-	   magicno[29] == 'T')                          rv = RFT_FITS;
+-  
++  else if (strncmp((char *) magicno,"SIMPLE  ", (size_t) 8)==0 &&
++	   magicno[29] == 'T')                                rv = RFT_FITS;
++
++  /* [JCE] Spectrum screen */
++  else if (memcmp(magicno, ZXheader, (size_t) 18)==0)         rv = RFT_ZX;
+ 
+ #ifdef HAVE_JPEG
+-  else if (magicno[0]==0xff && magicno[1]==0xd8 && 
+-	   magicno[2]==0xff)                            rv = RFT_JFIF;
++  else if (magicno[0]==0xff && magicno[1]==0xd8 &&
++	   magicno[2]==0xff)                                  rv = RFT_JFIF;
++#endif
++
++#ifdef HAVE_JP2K
++  else if (magicno[0]==0xff && magicno[1]==0x4f && 
++           magicno[2]==0xff && magicno[3]==0x51)              rv = RFT_JPC;
++
++  else if (memcmp(magicno, jp2k_magic, sizeof(jp2k_magic))==0) rv = RFT_JP2;
+ #endif
+ 
+ #ifdef HAVE_TIFF
+   else if ((magicno[0]=='M' && magicno[1]=='M') ||
+-	   (magicno[0]=='I' && magicno[1]=='I'))        rv = RFT_TIFF;
++	   (magicno[0]=='I' && magicno[1]=='I'))              rv = RFT_TIFF;
++#endif
++
++#ifdef HAVE_PNG
++  else if (magicno[0]==0x89 && magicno[1]=='P' &&
++           magicno[2]=='N'  && magicno[3]=='G')               rv = RFT_PNG;
+ #endif
+ 
+ #ifdef HAVE_PDS
+@@ -2620,11 +3130,67 @@
+       rv = RFT_PDSVICAR;
+ #endif
+ 
+-#ifdef GS_PATH
++#ifdef GS_PATH   /* Ghostscript handles both PostScript and PDF */
+   else if (strncmp((char *) magicno, "%!",     (size_t) 2)==0 ||
+-	   strncmp((char *) magicno, "\004%!", (size_t) 3)==0)   rv = RFT_PS;
++	   strncmp((char *) magicno, "\004%!", (size_t) 3)==0 ||
++           strncmp((char *) magicno, "%PDF",   (size_t) 4)==0) rv = RFT_PS;
++#endif
++
++#ifdef HAVE_G3
++  else if ((magicno[0]==  1 && magicno[1]==  1 &&
++            magicno[2]== 77 && magicno[3]==154 &&
++            magicno[4]==128 && magicno[5]==  0 &&
++            magicno[6]==  1 && magicno[7]== 77)
++           || highresfax || fax) /* kludge! */                rv = RFT_G3;
++#endif
++
++#ifdef HAVE_MAG
++  else if (strncmp((char *) magicno,"MAKI02  ", (size_t) 8)==0) rv = RFT_MAG;
++#endif
++
++#ifdef HAVE_MAKI
++  else if (strncmp((char *) magicno,"MAKI01A ", (size_t) 8)==0 ||
++	   strncmp((char *) magicno,"MAKI01B ", (size_t) 8)==0) rv = RFT_MAKI;
++#endif
++
++#ifdef HAVE_PIC
++  else if (magicno[0]=='P' && magicno[1]=='I'&&magicno[2]=='C') rv = RFT_PIC;
++#endif
++
++#ifdef HAVE_PI
++  else if (magicno[0]=='P' && magicno[1]=='i')                rv = RFT_PI;
++#endif
++
++#ifdef HAVE_HIPS
++  else if (strstr((char *) magicno, "./digest"))              rv = RFT_HIPS;
++#endif
++
++#ifdef HAVE_PCD
++  else if (magicno[0]==0xff && magicno[1]==0xff &&
++           magicno[2]==0xff && magicno[3]==0xff)              rv = RFT_PCD;
+ #endif
+ 
++#ifdef MACBINARY
++    /* Now we try to handle MacBinary files, but the method is VERY dirty... */
++    if (macbin_alrchk == True) {
++      macb_file = True;
++      break;
++    }
++
++    if (rv != RFT_UNKNOWN)
++      break;
++
++    /* Skip MACBSIZE and recheck */
++    macbin_alrchk = True;
++    fp = xv_fopen(fname, "r");
++    if (!fp) return RFT_ERROR;
++    fseek(fp, MACBSIZE, SEEK_SET);
++    n = fread(magicno, (size_t) 1, (size_t) 30, fp);
++    fclose(fp);
++
++    if (n<30) return RFT_UNKNOWN;    /* files less than 30 bytes long... */
++  }
++#endif
+   return rv;
+ }
+ 
+@@ -2637,9 +3203,10 @@
+      PICINFO *pinfo;
+ {
+   /* if quick is set, we're being called to generate icons, or something
+-     like that.  We should load the image as quickly as possible.  Currently,
+-     this only affects the LoadPS routine, which, if quick is set, only
+-     generates the page file for the first page of the document */
++     like that.  We should load the image as quickly as possible.  Previously,
++     this affected only the LoadPS routine, which, if quick is set, only
++     generates the page file for the first page of the document.  Now it
++     also affects PCD, which loads only a thumbnail. */
+ 
+   int rv = 0;
+ 
+@@ -2650,7 +3217,11 @@
+   switch (ftype) {
+   case RFT_GIF:     rv = LoadGIF   (fname, pinfo);         break;
+   case RFT_PM:      rv = LoadPM    (fname, pinfo);         break;
++#ifdef HAVE_MGCSFX
++  case RFT_PBM:     rv = LoadPBM   (fname, pinfo, -1);     break;
++#else
+   case RFT_PBM:     rv = LoadPBM   (fname, pinfo);         break;
++#endif
+   case RFT_XBM:     rv = LoadXBM   (fname, pinfo);         break;
+   case RFT_SUNRAS:  rv = LoadSunRas(fname, pinfo);         break;
+   case RFT_BMP:     rv = LoadBMP   (fname, pinfo);         break;
+@@ -2662,21 +3233,69 @@
+   case RFT_XPM:     rv = LoadXPM   (fname, pinfo);         break;
+   case RFT_XWD:     rv = LoadXWD   (fname, pinfo);         break;
+   case RFT_FITS:    rv = LoadFITS  (fname, pinfo, quick);  break;
++  case RFT_ZX:      rv = LoadZX    (fname, pinfo);         break; /* [JCE] */
++  case RFT_WBMP:    rv = LoadWBMP  (fname, pinfo);         break;
++
++#ifdef HAVE_PCD
++  /* if quick is switched on, use the smallest image size; don't ask the user */
++  case RFT_PCD:     rv = LoadPCD   (fname, pinfo, quick ? 0 : PcdSize);  break;
++#endif
+ 
+ #ifdef HAVE_JPEG
+-  case RFT_JFIF:    rv = LoadJFIF  (fname, pinfo, quick);    break;
++  case RFT_JFIF:    rv = LoadJFIF  (fname, pinfo, quick);  break;
++#endif
++
++#ifdef HAVE_JP2K
++  case RFT_JPC:     rv = LoadJPC   (fname, pinfo, quick);  break;
++  case RFT_JP2:     rv = LoadJP2   (fname, pinfo, quick);  break;
+ #endif
+ 
+ #ifdef HAVE_TIFF
+-  case RFT_TIFF:    rv = LoadTIFF  (fname, pinfo);           break;
++  case RFT_TIFF:    rv = LoadTIFF  (fname, pinfo, quick);  break;
++#endif
++
++#ifdef HAVE_PNG
++  case RFT_PNG:     rv = LoadPNG   (fname, pinfo);         break;
+ #endif
+ 
+ #ifdef HAVE_PDS
+-  case RFT_PDSVICAR: rv = LoadPDS  (fname, pinfo);           break;
++  case RFT_PDSVICAR: rv = LoadPDS  (fname, pinfo);         break;
++#endif
++
++#ifdef HAVE_G3
++  case RFT_G3:      rv = LoadG3    (fname, pinfo);         break;
+ #endif
+ 
+ #ifdef GS_PATH
+-  case RFT_PS:      rv = LoadPS    (fname, pinfo, quick);    break;
++  case RFT_PS:      rv = LoadPS    (fname, pinfo, quick);  break;
++#endif
++
++#ifdef HAVE_MAG
++  case RFT_MAG:     rv = LoadMAG   (fname, pinfo);         break;
++#endif
++
++#ifdef HAVE_MAKI
++  case RFT_MAKI:    rv = LoadMAKI  (fname, pinfo);         break;
++#endif
++
++#ifdef HAVE_PIC
++  case RFT_PIC:     rv = LoadPIC   (fname, pinfo);         break;
++#endif
++
++#ifdef HAVE_PI
++  case RFT_PI:      rv = LoadPi    (fname, pinfo);         break;
++#endif
++
++#ifdef HAVE_PIC2
++  case RFT_PIC2:    rv = LoadPIC2  (fname, pinfo, quick);  break;
++#endif
++
++#ifdef HAVE_HIPS
++  case RFT_HIPS:    rv = LoadHIPS  (fname, pinfo);         break;
++#endif
++
++#ifdef HAVE_MGCSFX
++  case RFT_MGCSFX:  rv = LoadMGCSFX (fname, pinfo);        break;
+ #endif
+ 
+   }
+@@ -2685,13 +3304,17 @@
+ 
+ 
+ /********************************/
+-int UncompressFile(name, uncompname)
++int UncompressFile(name, uncompname, filetype)
+      char *name, *uncompname;
++     int filetype;
+ {
+   /* returns '1' on success, with name of uncompressed file in uncompname
+      returns '0' on failure */
+ 
+   char namez[128], *fname, buf[512];
++#ifndef USE_MKSTEMP
++  int tmpfd;
++#endif
+ 
+   fname = name;
+   namez[0] = '\0';
+@@ -2703,7 +3326,7 @@
+      to what it was.  necessary because uncompress doesn't handle files
+      that don't end with '.Z' */
+ 
+-  if (strlen(name) >= (size_t) 2            && 
++  if (strlen(name) >= (size_t) 2            &&
+       strcmp(name + strlen(name)-2,".Z")!=0 &&
+       strcmp(name + strlen(name)-2,".z")!=0) {
+     strcpy(namez, name);
+@@ -2721,34 +3344,50 @@
+ #endif   /* not VMS and not GUNZIP */
+ 
+ 
+-  
+ #ifndef VMS
+   sprintf(uncompname, "%s/xvuXXXXXX", tmpdir);
+-  mktemp(uncompname);
+-  sprintf(buf,"%s -c %s >%s", UNCOMPRESS, fname, uncompname);
+-#else /* it IS VMS */
++#else
+   strcpy(uncompname, "[]xvuXXXXXX");
++#endif
++
++#ifdef USE_MKSTEMP
++  close(mkstemp(uncompname));
++#else
+   mktemp(uncompname);
+-#  ifdef GUNZIP
+-  sprintf(buf,"%s %s %s", UNCOMPRESS, fname, uncompname);
+-#  else
+-  sprintf(buf,"%s %s", UNCOMPRESS, fname);
+-#  endif
++  tmpfd = open(uncompname,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR);
++  if (tmpfd < 0) FatalError("UncompressFile(): can't create temporary file");
++  close(tmpfd);
++#endif
++
++#ifndef VMS
++  if (filetype == RFT_COMPRESS)
++    sprintf(buf,"%s -c '%s' > '%s'", UNCOMPRESS, fname, uncompname);
++# ifdef BUNZIP2
++  else if (filetype == RFT_BZIP2)
++    sprintf(buf,"%s -c '%s' > '%s'", BUNZIP2, fname, uncompname);
++# endif
++#else /* it IS VMS */
++# ifdef GUNZIP
++  sprintf(buf,"%s '%s' '%s'", UNCOMPRESS, fname, uncompname);
++# else
++  sprintf(buf,"%s '%s'", UNCOMPRESS, fname);
++# endif
+ #endif
+ 
+   SetISTR(ISTR_INFO, "Uncompressing '%s'...", BaseName(fname));
+ #ifndef VMS
+-  if (system(buf)) {
++  if (system(buf))
+ #else
+-  if (!system(buf)) {
++  if (!system(buf))
+ #endif
++  {
+     SetISTR(ISTR_INFO, "Unable to uncompress '%s'.", BaseName(fname));
+     Warning();
+     return 0;
+   }
+ 
+-#ifndef VMS  
+-  /* if we renamed the file to end with a .Z for the sake of 'uncompress', 
++#ifndef VMS
++  /* if we renamed the file to end with a .Z for the sake of 'uncompress',
+      rename it back to what it once was... */
+ 
+   if (strlen(namez)) {
+@@ -2769,9 +3408,65 @@
+     }
+    */
+ #endif /* not VMS */
+-  
++
++  return 1;
++}
++
++
++#ifdef MACBINARY
++/********************************/
++int RemoveMacbinary(src, dst)
++     char *src, *dst;
++{
++  char buffer[8192]; /* XXX */
++  int n, eof;
++#ifndef USE_MKSTEMP
++  int tmpfd;
++#endif
++  FILE *sfp, *dfp;
++
++  sprintf(dst, "%s/xvmXXXXXX", tmpdir);
++#ifdef USE_MKSTEMP
++  close(mkstemp(dst));
++#else
++  mktemp(dst);
++  tmpfd = open(dst,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR);
++  if (tmpfd < 0) FatalError("RemoveMacbinary(): can't create temporary file");
++#endif
++
++  SetISTR(ISTR_INFO, "Removing MacBinary...");
++
++  sfp = xv_fopen(src, "r");
++#ifdef USE_MKSTEMP
++  dfp = xv_fopen(dst, "w");
++#else
++  dfp = fdopen(tmpfd, "w");
++#endif
++  if (!sfp || !dfp) {
++    SetISTR(ISTR_INFO, "Unable to remove a InfoFile header form '%s'.", src);
++    Warning();
++    return 0;
++  }
++  fseek(sfp, MACBSIZE, SEEK_SET);
++  while ((n = fread(buffer, 1, sizeof(buffer), sfp)) == 8192) /* XXX */
++    fwrite(buffer, 1, n, dfp);
++  if ((eof = feof(sfp)))
++    fwrite(buffer, 1, n, dfp);
++  fclose(sfp);
++  fflush(dfp);
++  fclose(dfp);
++#ifndef USE_MKSTEMP
++  close(tmpfd);
++#endif
++  if (!eof) {
++    SetISTR(ISTR_INFO, "Unable to remove a InfoFile header form '%s'.", src);
++    Warning();
++    return 0;
++  }
++
+   return 1;
+ }
++#endif
+ 
+ 
+ /********************************/
+@@ -2789,6 +3484,10 @@
+     sprintf(tmp, "%s%d", bname, i);
+     unlink(tmp);
+   }
++
++  /* GRR 20070506:  basename file doesn't go away, at least on Linux and for
++   *   GIF and TIFF images, so explicitly unlink() it, too */
++  unlink(bname);
+ }
+ 
+ 
+@@ -2798,11 +3497,11 @@
+ {
+   int i;
+ 
+-  /* some stuff that necessary whenever running an algorithm or 
++  /* some stuff that necessary whenever running an algorithm or
+      installing a new 'pic' (or switching 824 modes) */
+ 
+   numcols = 0;   /* gets set by SortColormap:  set to 0 for PIC24 images */
+-  for (i=0; i<256; i++) cols[i]=infobg;   
++  for (i=0; i<256; i++) cols[i]=infobg;
+ 
+   if (picType == PIC8) {
+     byte trans[256];
+@@ -2811,18 +3510,18 @@
+   }
+ 
+   if (picType == PIC8) {
+-    /* see if image is a b/w bitmap.  
++    /* see if image is a b/w bitmap.
+        If so, use '-black' and '-white' colors */
+     if (numcols == 2) {
+       if ((rMap[0] == gMap[0] && rMap[0] == bMap[0] && rMap[0] == 255) &&
+ 	  (rMap[1] == gMap[1] && rMap[1] == bMap[1] && rMap[1] ==   0)) {
+ 	/* 0=wht, 1=blk */
+-	rMap[0] = (whtRGB>>16)&0xff;  
+-	gMap[0] = (whtRGB>>8)&0xff;  
++	rMap[0] = (whtRGB>>16)&0xff;
++	gMap[0] = (whtRGB>>8)&0xff;
+ 	bMap[0] = whtRGB&0xff;
+ 
+ 	rMap[1] = (blkRGB>>16)&0xff;
+-	gMap[1] = (blkRGB>>8)&0xff;  
++	gMap[1] = (blkRGB>>8)&0xff;
+ 	bMap[1] = blkRGB&0xff;
+       }
+ 
+@@ -2852,10 +3551,10 @@
+     }
+ 
+     /* save the desired RGB colormap (before dicking with it) */
+-    for (i=0; i<numcols; i++) { 
+-      rorg[i] = rcmap[i] = rMap[i];  
+-      gorg[i] = gcmap[i] = gMap[i];  
+-      borg[i] = bcmap[i] = bMap[i];  
++    for (i=0; i<numcols; i++) {
++      rorg[i] = rcmap[i] = rMap[i];
++      gorg[i] = gcmap[i] = gMap[i];
++      borg[i] = bcmap[i] = bMap[i];
+     }
+   }
+ 
+@@ -2888,19 +3587,29 @@
+ {
+   /* cmd is something like: "! bggen 100 0 0"
+    *
+-   * runs command (with "> /tmp/xv******" appended).  
++   * runs command (with "> /tmp/xv******" appended).
+    * returns "/tmp/xv******" in fname
+    * returns '0' if everything's cool, '1' on error
+    */
+ 
+   char fullcmd[512], tmpname[64], str[512];
+   int i;
++#ifndef USE_MKSTEMP
++  int tmpfd;
++#endif
+ 
+   if (!cmd || (strlen(cmd) < (size_t) 2)) return 1;
+ 
+   sprintf(tmpname,"%s/xvXXXXXX", tmpdir);
++#ifdef USE_MKSTEMP
++  close(mkstemp(tmpname));
++#else
+   mktemp(tmpname);
+-  if (tmpname[0] == '\0') {   /* mktemp() blew up */
++  tmpfd = open(tmpname,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR);
++  if (tmpfd < 0) FatalError("openPic(): can't create temporary file");
++  close(tmpfd);
++#endif
++  if (tmpname[0] == '\0') {   /* mktemp() or mkstemp() blew up */
+     sprintf(str,"Unable to create temporary filename.");
+     ErrPopUp(str, "\nHow unlikely!");
+     return 1;
+@@ -2939,26 +3648,21 @@
+ {
+   int i;
+ 
++  waitsec = (numnames <= 1)? waitsec_final : waitsec_nonfinal;
++
+   if (!numnames) {  openPic(DFLTPIC);  return; }
+ 
+   i = 0;
+-  if (!randomShow) {
+-    while (numnames>0) {
+-      if (openPic(0)) return;  /* success */
+-      else {
+-	if (polling && !i) 
+-	  fprintf(stderr,"%s: POLLING: Waiting for file '%s' \n\tto %s\n",
+-		  cmd, namelist[0], "be created, or whatever...");
+-	i = 1;
+-      }
++  while (numnames>0) {
++    if (openPic(0)) return;  /* success */
++    else {
++      if (polling && !i)
++	fprintf(stderr,"%s: POLLING: Waiting for file '%s' \n\tto %s\n",
++		cmd, namelist[0], "be created, or whatever...");
++      i = 1;
+     }
+   }
+ 
+-  else {    /* pick random first picture */
+-    for (i=findRandomPic();  i>=0;  i=findRandomPic())
+-      if (openPic(i)) return;    /* success */
+-  }
+-
+   if (numnames>1) FatalError("couldn't open any pictures");
+   else Quit(-1);
+ }
+@@ -2970,11 +3674,11 @@
+   int i;
+ 
+   if (curname>=0) i = curname+1;
+-  else if (nList.selected >= 0 && nList.selected < numnames) 
++  else if (nList.selected >= 0 && nList.selected < numnames)
+        i = nList.selected;
+   else i = 0;
+ 
+- 
++
+   while (i<numnames && !openPic(i));
+   if (i<numnames) return;    /* success */
+ 
+@@ -2987,19 +3691,15 @@
+ {
+   int i;
+ 
+-  if (!randomShow) {
+-    if (curname>=0) i = curname+1;
+-    else if (nList.selected >= 0 && nList.selected < numnames) 
+-      i = nList.selected;
+-    else i = 0;
++  if (curname>=0) i = curname+1;
++  else if (nList.selected >= 0 && nList.selected < numnames)
++    i = nList.selected;
++  else i = 0;
+ 
+-    while (i<numnames && !openPic(i));
+-    if (i<numnames) return;    /* success */
+-  }
+-  else {
+-    for (i=findRandomPic(); i>=0; i=findRandomPic())
+-      if (openPic(i)) return;
+-  }
++  waitsec = (i == numnames-1)? waitsec_final : waitsec_nonfinal;
++
++  while (i<numnames && !openPic(i));
++  if (i<numnames) return;    /* success */
+ 
+   Quit(0);
+ }
+@@ -3012,25 +3712,21 @@
+ 
+   j = loop = 0;
+   while (1) {
+-    if (!randomShow) {
+ 
+-      if (curname>=0) i = curname+1;
+-      else if (nList.selected >= 0 && nList.selected < numnames) 
+-	i = nList.selected;
+-      else i = 0;
++    if (curname>=0) i = curname+1;
++    else if (nList.selected >= 0 && nList.selected < numnames)
++      i = nList.selected;
++    else i = 0;
++
++    if (loop) {  i = 0;   loop = 0; }
+ 
+-      if (loop) {  i = 0;   loop = 0; }
++    waitsec = (i == numnames-1)? waitsec_final : waitsec_nonfinal;
+ 
+-      while (i<numnames && !openPic(i));
+-      if (i<numnames) return;
+-    }
+-    else {
+-      for (i=findRandomPic(); i>=0; i=findRandomPic())
+-	if (openPic(i)) return;
+-    }
++    while (i<numnames && !openPic(i));
++    if (i<numnames) return;
+ 
+     loop = 1;        /* back to top of list */
+-    if (j) break;                         /* we're in a 'failure loop' */
++    if (j) break;    /* we're in a 'failure loop' */
+     j++;
+   }
+ 
+@@ -3044,7 +3740,7 @@
+   int i;
+ 
+   if (curname>0) i = curname-1;
+-  else if (nList.selected>0 && nList.selected < numnames) 
++  else if (nList.selected>0 && nList.selected < numnames)
+     i = nList.selected - 1;
+   else i = numnames-1;
+ 
+@@ -3063,64 +3759,24 @@
+   openPic(LOADPIC);
+ }
+ 
+-
+-
+-
+-/****************/
+-static int findRandomPic()
+-/****************/
+-{
+-  static byte *loadList;
+-  static int   left_to_load, listLen = -1;
+-  int          k;
+-  time_t       t;
+-
+-  /* picks a random name out of the list, and returns it's index.  If there
+-     are no more names to pick, it returns '-1' and resets itself */
+-
+-  if (!loadList || numnames!=listLen) {
+-    if (loadList) free(loadList);
+-    else {
+-      time(&t);
+-      srandom((unsigned int) t); /* seed the random */
+-    }
+-
+-    left_to_load = listLen = numnames;
+-    loadList = (byte *) malloc((size_t) listLen);
+-    for (k=0; k<listLen; k++) loadList[k] = 0;
+-  }
+-  
+-  if (left_to_load <= 0) {   /* we've loaded all the pics */
+-    for (k=0; k<listLen; k++) loadList[k] = 0;   /* clear flags */
+-    left_to_load = listLen;
+-    return -1;   /* 'done' return */
+-  }
+-
+-  for (k=abs(random()) % listLen;  loadList[k];  k = (k+1) % listLen);
+-  
+-  left_to_load--;
+-  loadList[k] = TRUE;
+-
+-  return k;
+-}
+-
+ /****************/
+ static void mainLoop()
+ {
+-  /* search forward until we manage to display a picture, 
+-     then call EventLoop.  EventLoop will eventually return 
++  /* search forward until we manage to display a picture,
++     then call EventLoop.  EventLoop will eventually return
+      NEXTPIC, PREVPIC, NEXTQUIT, QUIT, or, if >= 0, a filenum to GOTO */
+ 
+   int i;
+ 
+-  /* if curname<0 (there is no 'current' file), 'Next' means view the 
++  /* if curname<0 (there is no 'current' file), 'Next' means view the
+      selected file (or the 0th file, if no selection either), and 'Prev' means
+      view the one right before the selected file */
+ 
+-  openFirstPic();   /* find first displayable picture, exit if none */
++  /* find first displayable picture, exit if none */
++  if (!startGrab) openFirstPic();
+ 
+   if (!pic)  {  /* must've opened a text file...  display dflt pic */
+-    openPic(DFLTPIC);
++    if (!startGrab) openPic(DFLTPIC);
+     if (mainW && !useroot) RaiseTextWindows();
+   }
+ 
+@@ -3133,7 +3789,7 @@
+     }
+ 
+     else if (i==PREVPIC) {
+-      if (curname>0 || (curname<0 && nList.selected>0)) 
++      if (curname>0 || (curname<0 && nList.selected>0))
+ 	openPrevPic();
+     }
+ 
+@@ -3151,7 +3807,7 @@
+ 
+     else if (i==THISNEXT) {  /* open current sel, 'next' until success */
+       int j;
+-      j = nList.selected;  
++      j = nList.selected;
+       if (j<0) j = 0;
+       while (j<numnames && !openPic(j));
+       if (!pic) openPic(DFLTPIC);
+@@ -3169,7 +3825,7 @@
+ 
+ /***********************************/
+ static void createMainWindow(geom, name)
+-     char *geom, *name;
++     const char *geom, *name;
+ {
+   XSetWindowAttributes xswa;
+   unsigned long        xswamask;
+@@ -3195,22 +3851,35 @@
+   i = XParseGeometry(geom,&x,&y,&w,&h);
+ 
+   hints.flags = 0;
+-  if ((i&XValue || i&YValue)) hints.flags = USPosition;
++  if (i&XValue || i&YValue)
++      hints.flags |= USPosition;
+ 
+-  if (i&XValue && i&XNegative) x = vrWIDE - eWIDE - abs(x);
+-  if (i&YValue && i&YNegative) y = vrHIGH - eHIGH - abs(y);
++  hints.win_gravity = NorthWestGravity;
++  if (i&XValue && i&XNegative) {
++    hints.win_gravity = NorthEastGravity;
++    x = vrWIDE - (eWIDE + 2 * bwidth) - x;
++  }
++  if (i&YValue && i&YNegative) {
++    hints.win_gravity = (hints.win_gravity == NorthWestGravity) ?
++      SouthWestGravity : SouthEastGravity;
++    y = vrHIGH - (eHIGH + 2 * bwidth) - y;
++  }
++  hints.flags |= PWinGravity;
+ 
+-  if (x+eWIDE > vrWIDE) x = vrWIDE - eWIDE;   /* keep on screen */
++  /* keep on screen */
++  if (x+eWIDE > vrWIDE) x = vrWIDE - eWIDE;
+   if (y+eHIGH > vrHIGH) y = vrHIGH - eHIGH;
+-
++  if (x < 0) x = 0;
++  if (y < 0) y = 0;
+ 
+ #define VROOT_TRANS
+ #ifdef VROOT_TRANS
+-  if (vrootW != rootW) { /* virtual window manager running */
++  if (vrootW != rootW && !(hints.flags & USPosition)) { /* virtual window manager running */
+     int x1,y1;
+     Window child;
++
+     XTranslateCoordinates(theDisp, rootW, vrootW, x, y, &x1, &y1, &child);
+-    if (DEBUG) fprintf(stderr,"translate:  %d,%d -> %d,%d\n",x,y,x1,y1);
++    if (DEBUG) fprintf(stderr,"translate:  %d,%d -> %d,%d\n", x, y, x1, y1);
+     x = x1;  y = y1;
+   }
+ #endif
+@@ -3218,13 +3887,13 @@
+   hints.x = x;                  hints.y = y;
+   hints.width = eWIDE;          hints.height = eHIGH;
+   hints.max_width  = maxWIDE;   hints.max_height = maxHIGH;
+-  hints.flags |= USSize | PMaxSize;
+-    
+-  xswa.bit_gravity = StaticGravity;
++  hints.flags |= PSize | PMaxSize;
++
++  xswa.bit_gravity      = StaticGravity;
+   xswa.background_pixel = bg;
+   xswa.border_pixel     = fg;
+   xswa.colormap         = theCmap;
+-  
++
+   xswa.backing_store    = WhenMapped;
+ 
+   /* NOTE: I've turned 'backing-store' off on the image window, as some
+@@ -3233,9 +3902,9 @@
+      improvement anyway (for the image window), unless you're on a slow
+      network.  In any event, I'm not *turning off* backing store, I'm
+      just not explicitly turning it *on*.  If your X server is set up
+-     that windows, by default, have backing-store turned on, then the 
++     that windows, by default, have backing-store turned on, then the
+      image window will, too */
+-  
++
+   xswamask = CWBackPixel | CWBorderPixel | CWColormap /* | CWBackingStore */;
+   if (!clearonload) xswamask |= CWBitGravity;
+ 
+@@ -3244,18 +3913,18 @@
+     xwa.width = eWIDE;  xwa.height = eHIGH;
+ 
+     /* try to keep the damned thing on-screen, if possible */
+-    if (xwa.x + xwa.width  > dispWIDE) xwa.x = dispWIDE - xwa.width;
+-    if (xwa.y + xwa.height > dispHIGH) xwa.y = dispHIGH - xwa.height;
++    if (xwa.x + xwa.width  > vrWIDE) xwa.x = vrWIDE - xwa.width;
++    if (xwa.y + xwa.height > vrHIGH) xwa.y = vrHIGH - xwa.height;
+     if (xwa.x < 0) xwa.x = 0;
+     if (xwa.y < 0) xwa.y = 0;
+ 
+     SetWindowPos(&xwa);
+     hints.flags = PSize | PMaxSize;
+-  } 
++  }
+ 
+   else {
+     mainW = XCreateWindow(theDisp,rootW,x,y, (u_int) eWIDE, (u_int) eHIGH,
+-			  (u_int) bwidth, (int) dispDEEP, InputOutput, 
++			  (u_int) bwidth, (int) dispDEEP, InputOutput,
+ 			  theVisual, xswamask, &xswa);
+     if (!mainW) FatalError("can't create window!");
+ 
+@@ -3267,15 +3936,11 @@
+     }
+   }
+ 
+-
+-  XSetStandardProperties(theDisp,mainW,"","",None,NULL,0,&hints);
+-  setWinIconNames(name);
+-
+   xwmh.input = True;
+   xwmh.flags = InputHint;
+ 
+-  xwmh.icon_pixmap = iconPix;  
+-  xwmh.icon_mask   = iconmask;  
++  xwmh.icon_pixmap = iconPix;
++  xwmh.icon_mask   = iconmask;
+   xwmh.flags |= (IconPixmapHint | IconMaskHint);
+ 
+ 
+@@ -3295,14 +3960,15 @@
+       }
+     }
+   }
+-  XSetWMHints(theDisp, mainW, &xwmh);
+ 
+   classh.res_name = "xv";
+   classh.res_class = "XVroot";
+-  XSetClassHint(theDisp, mainW, &classh);
+ 
++  XmbSetWMProperties(theDisp, mainW, NULL, NULL, NULL, 0, &hints, &xwmh,
++                     &classh);
++  setWinIconNames(name);
+ 
+-  if (nodecor) {   /* turn of image window decorations (in MWM) */ 
++  if (nodecor) {   /* turn of image window decorations (in MWM) */
+     Atom mwm_wm_hints;
+     struct s_mwmhints {
+       long   flags;
+@@ -3311,7 +3977,7 @@
+       u_long input_mode;
+       long   status;
+     } mwmhints;
+-    
++
+     mwm_wm_hints = XInternAtom(theDisp, "_MOTIF_WM_HINTS", False);
+     if (mwm_wm_hints != None) {
+       xvbzero((char *) &mwmhints, sizeof(mwmhints));
+@@ -3319,20 +3985,20 @@
+       mwmhints.decorations = 4;
+ 
+       XChangeProperty(theDisp, mainW, mwm_wm_hints, mwm_wm_hints, 32,
+-		      PropModeReplace, (byte *) &mwmhints, 
+-		      (int) (sizeof(mwmhints))/4); 
++		      PropModeReplace, (byte *) &mwmhints,
++		      (int) (sizeof(mwmhints))/4);
+       XSync(theDisp, False);
+     }
+   }
+ 
+-    
++
+   firstTime = 0;
+ }
+ 
+ 
+ /***********************************/
+ static void setWinIconNames(name)
+-     char *name;
++     const char *name;
+ {
+   char winname[256], iconname[256];
+ 
+@@ -3362,12 +4028,12 @@
+ 
+ /***********************************/
+ void FixAspect(grow,w,h)
+-int   grow;
+-int   *w, *h;
++     int   grow;
++     int   *w, *h;
+ {
+   /* computes new values of eWIDE and eHIGH which will have aspect ratio
+-     'normaspect'.  If 'grow' it will preserve aspect by enlarging, 
+-     otherwise, it will shrink to preserve aspect ratio.  
++     'normaspect'.  If 'grow' it will preserve aspect by enlarging,
++     otherwise, it will shrink to preserve aspect ratio.
+      Returns these values in 'w' and 'h' */
+ 
+   float xr,yr,curaspect,a,exp;
+@@ -3380,14 +4046,14 @@
+   curaspect  = xr / yr;
+ 
+   /* if too narrow & shrink, shrink height.  too wide and grow, grow height */
+-  if ((curaspect < normaspect && !grow) || 
++  if ((curaspect < normaspect && !grow) ||
+       (curaspect > normaspect &&  grow)) {    /* modify height */
+     exp = curaspect / normaspect;
+     *h = (int) (eHIGH * exp + .5);
+   }
+ 
+   /* if too narrow & grow, grow width.  too wide and shrink, shrink width */
+-  if ((curaspect < normaspect &&  grow) || 
++  if ((curaspect < normaspect &&  grow) ||
+       (curaspect > normaspect && !grow)) {    /* modify width */
+     exp = normaspect / curaspect;
+     *w = (int) (eWIDE * exp + .5);
+@@ -3423,22 +4089,22 @@
+   suffix = namelist[0];
+   prelen = 0;   /* length of prefix to be removed */
+   n = i = 0;    /* shut up pesky compiler warnings */
+-  
++
+   done = 0;
+   while (!done) {
+     suffix = (char *) index(suffix,'/');    /* find next '/' in file name */
+     if (!suffix) break;
+-    
++
+     suffix++;                       /* go past it */
+     n = suffix - namelist[0];
+     for (i=1; i<numnames; i++) {
+       if (strncmp(namelist[0], namelist[i], (size_t) n)!=0) { done=1; break; }
+     }
+-    
++
+     if (!done) prelen = n;
+   }
+-  
+-  for (i=0; i<numnames; i++) 
++
++  for (i=0; i<numnames; i++)
+     dispnames[i] = namelist[i] + prelen;
+ }
+ 
+@@ -3447,20 +4113,20 @@
+ static void fixDispNames()
+ {
+   /* fix dispnames array so that names don't go off right edge */
+-  
++
+   int   i,j;
+   char *tmp;
+-  
++
+   for (i=j=0; i<numnames; i++) {
+     char *dname;
+-    
++
+     dname = dispnames[i];
+     if (StringWidth(dname) > (nList.w-10-16)) {  /* have to trunc. */
+       tmp = dname;
+       while (1) {
+ 	tmp = (char *) index(tmp,'/'); /* find next '/' in filename */
+ 	if (!tmp) { tmp = dname;  break; }
+-	
++
+ 	tmp++;                   /* move to char following the '/' */
+ 	if (StringWidth(tmp) <= (nList.w-10-16)) { /* is cool now */
+ 	  j++;  break;
+@@ -3484,9 +4150,9 @@
+ 
+   name = GetDirFName();
+   GetDirPath(cwd);
+-  
++
+   AddFNameToCtrlList(cwd, name);
+-  
++
+   if (select) {
+     nList.selected = numnames-1;
+     curname = numnames - 1;
+@@ -3498,35 +4164,35 @@
+ 
+ /***********************************/
+ void AddFNameToCtrlList(fpath,fname)
+-     char *fpath, *fname;
++     const char *fpath, *fname;
+ {
+   /* stick given path/name into 'namelist'.  Doesn't redraw list */
+-  
+-  char *fullname, *dname;
++
++  char *fullname;
+   char cwd[MAXPATHLEN], globnm[MAXPATHLEN+100];
+   int i;
+-  
++
+   if (!fpath) fpath = "";  /* bulletproofing... */
+-  if (!fname) fname = "";  
+-  
++  if (!fname) fname = "";
++
+   if (numnames == MAXNAMES) return;  /* full up */
+-  
++
+   /* handle globbing */
+   if (fname[0] == '~') {
+     strcpy(globnm, fname);
+     Globify(globnm);
+     fname = globnm;
+   }
+-  
++
+   if (fname[0] != '/') {  /* prepend path */
+     strcpy(cwd, fpath);   /* copy it to a modifiable place */
+-    
++
+     /* make sure fpath has a trailing '/' char */
+     if (strlen(cwd)==0 || cwd[strlen(cwd)-1]!='/') strcat(cwd, "/");
+-    
++
+     fullname = (char *) malloc(strlen(cwd) + strlen(fname) + 2);
+     if (!fullname) FatalError("couldn't alloc name in AddFNameToCtrlList()\n");
+-    
++
+     sprintf(fullname, "%s%s", cwd, fname);
+   }
+   else {                 /* copy name to fullname */
+@@ -3534,15 +4200,15 @@
+     if (!fullname) FatalError("couldn't alloc name in AddFNameToCtrlList()\n");
+     strcpy(fullname, fname);
+   }
+-  
+-  
++
++
+   /* see if this name is a duplicate.  Don't add it if it is. */
+   for (i=0; i<numnames; i++)
+     if (strcmp(fullname, namelist[i]) == 0) {
+       free(fullname);
+       return;
+     }
+-  
++
+   namelist[numnames] = fullname;
+   numnames++;
+   makeDispNames();
+@@ -3578,7 +4244,7 @@
+   /* called to enable/disable the Prev/Next buttons whenever curname and/or
+      numnames and/or nList.selected change */
+ 
+-  /* if curname<0 (there is no 'current' file), 'Next' means view the 
++  /* if curname<0 (there is no 'current' file), 'Next' means view the
+      selected file (or the 0th file, if no selection either), and 'Prev' means
+      view the one right before the selected file */
+ 
+@@ -3591,18 +4257,19 @@
+     BTSetActive(&but[BPREV], (curname>0));
+   }
+ }
+-  
++
+ 
+ /***********************************/
+ int DeleteCmd()
+ {
+   /* 'delete' button was pressed.  Pop up a dialog box to determine
+      what should be deleted, then do it.
+-     returns '1' if THE CURRENTLY VIEWED entry was deleted from the list, 
+-     in which case the 'selected' filename on the ctrl list is now 
++     returns '1' if THE CURRENTLY VIEWED entry was deleted from the list,
++     in which case the 'selected' filename on the ctrl list is now
+      different, and should be auto-loaded, or something */
+ 
+-  static char *bnames[] = { "\004Disk File", "\nList Entry", "\033Cancel" };
++  static const char *bnames[] =
++    { "\004Disk File", "\nList Entry", "\033Cancel" };
+   char str[512];
+   int  del, i, delnum, rv;
+ 
+@@ -3610,15 +4277,14 @@
+   delnum = nList.selected;
+   if (delnum < 0 || delnum >= numnames) return 0;
+ 
+-  sprintf(str,"Delete '%s'?\n\n%s%s",
+-	  namelist[delnum],
++  sprintf(str, "Delete '%s'?\n\n%s%s", namelist[delnum],
+ 	  "'List Entry' deletes selection from list.\n",
+ 	  "'Disk File' deletes file associated with selection.");
+ 
+   del = PopUp(str, bnames, 3);
+-  
++
+   if (del == 2) return 0;   /* cancel */
+-  
++
+   if (del == 0) {           /* 'Disk File' */
+     char *name;
+     if (namelist[delnum][0] != '/') {    /* prepend 'initdir' */
+@@ -3669,13 +4335,13 @@
+ 
+   if (delnum != numnames-1) {
+     /* snip out of namelist and dispnames lists */
+-    xvbcopy((char *) &namelist[delnum+1], (char *) &namelist[delnum], 
++    xvbcopy((char *) &namelist[delnum+1], (char *) &namelist[delnum],
+ 	  (numnames - delnum - 1) * sizeof(namelist[0]));
+ 
+-    xvbcopy((char *) &dispnames[delnum+1], (char *) &dispnames[delnum], 
++    xvbcopy((char *) &dispnames[delnum+1], (char *) &dispnames[delnum],
+ 	  (numnames - delnum - 1) * sizeof(dispnames[0]));
+   }
+-  
++
+   numnames--;
+   if (numnames==0) BTSetActive(&but[BDELETE],0);
+   windowMB.dim[WMB_TEXTVIEW] = (numnames==0);
+@@ -3686,7 +4352,7 @@
+   if (nList.selected >= numnames) nList.selected = numnames-1;
+   if (nList.selected < 0) nList.selected = 0;
+ 
+-  SCSetRange(&nList.scrl, 0, numnames - nList.nlines, 
++  SCSetRange(&nList.scrl, 0, numnames - nList.nlines,
+ 	     nList.scrl.val, nList.nlines-1);
+   ScrollToCurrent(&nList);
+   DrawCtrlNumFiles();
+@@ -3753,7 +4419,7 @@
+     if (useroot && resetroot) ClearRoot();
+ 
+     if (mainW == (Window) NULL || useroot) {  /* window not visible */
+-      useroot = 0;  
++      useroot = 0;
+ 
+       if (haveoldinfo) {             /* just remap mainW and resize it */
+ 	XWMHints xwmh;
+@@ -3771,8 +4437,8 @@
+ 	xwmh.input = True;
+ 	xwmh.flags = InputHint;
+ 
+-	xwmh.icon_pixmap = iconPix;  
+-	xwmh.icon_mask   = iconmask;  
++	xwmh.icon_pixmap = iconPix;
++	xwmh.icon_mask   = iconmask;
+ 	xwmh.flags |= ( IconPixmapHint | IconMaskHint) ;
+ 
+ 	xwmh.flags |= StateHint;
+@@ -3787,7 +4453,7 @@
+       else {                         /* first time.  need to create mainW */
+ 	mainW = (Window) NULL;
+ 	createMainWindow(maingeom, fnam);
+-	XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++	XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 		     | StructureNotifyMask | ButtonPressMask
+ 		     | KeyReleaseMask | ColormapChangeMask
+ 		     | EnterWindowMask | LeaveWindowMask );
+@@ -3802,7 +4468,7 @@
+ 
+     else {                            /* mainW already visible */
+       createMainWindow(maingeom, fnam);
+-      XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++      XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 		   | StructureNotifyMask | ButtonPressMask
+ 		   | KeyReleaseMask | ColormapChangeMask
+ 		   | EnterWindowMask | LeaveWindowMask );
+@@ -3845,13 +4511,13 @@
+       if (LocalCmap) regen=1;
+ 
+       /* this reallocs the colors */
+-      if (colorMapMode==CM_PERFECT || colorMapMode==CM_OWNCMAP) 
++      if (colorMapMode==CM_PERFECT || colorMapMode==CM_OWNCMAP)
+ 	ChangeCmapMode(CM_NORMAL, 0, 0);
+-      
+-      
++
++
+       XUnmapWindow(theDisp, mainW);
+       mainW = vrootW;
+-      
++
+       if (!ctrlUp) {    /* make sure ctrl is up when going to 'root' mode */
+ 	XWMHints xwmh;
+ 	xwmh.input         = True;
+@@ -3861,7 +4527,7 @@
+ 	CtrlBox(1);
+       }
+     }
+-      
++
+     useroot = 1;
+     rootMode = dispMode - RMB_ROOT;
+     ew = eWIDE;  eh = eHIGH;
+@@ -3877,7 +4543,7 @@
+       GenerateEpic(ew, eh);
+       CreateXImage();
+     }
+-    else if (regen) CreateXImage();                    
++    else if (regen) CreateXImage();
+ 
+     KillOldRootInfo();
+     MakeRootPic();
+@@ -3923,7 +4589,7 @@
+ 
+ 
+   if (*numn == maxn) {
+-    fprintf(stderr, "%s: too many filenames.  Only using first %d.\n",
++    fprintf(stderr, "%s: too many filenames.  Using only first %d.\n",
+ 	    flist, maxn);
+   }
+ 
+@@ -3947,14 +4613,14 @@
+ 
+ /***********************************/
+ int rd_int(name)
+-     char *name;
++     const char *name;
+ {
+   /* returns '1' if successful.  result in def_int */
+ 
+   if (rd_str_cl(name, "", 0)) {     /* sets def_str */
+     if (sscanf(def_str, "%d", &def_int) == 1) return 1;
+     else {
+-      fprintf(stderr, "%s: couldn't read integer value for %s resource\n", 
++      fprintf(stderr, "%s: couldn't read integer value for %s resource\n",
+ 	      cmd, name);
+       return 0;
+     }
+@@ -3965,7 +4631,7 @@
+ 
+ /***********************************/
+ int rd_str(name)
+-     char *name;
++     const char *name;
+ {
+   return rd_str_cl(name, "", 0);
+ }
+@@ -3973,17 +4639,17 @@
+ 
+ /***********************************/
+ int rd_flag(name)
+-char *name;
++     const char *name;
+ {
+   /* returns '1' if successful.  result in def_int */
+-  
++
+   char buf[256];
+ 
+   if (rd_str_cl(name, "", 0)) {  /* sets def_str */
+     strcpy(buf, def_str);
+     lower_str(buf);
+ 
+-    def_int = (strcmp(buf, "on")==0) || 
++    def_int = (strcmp(buf, "on")==0) ||
+               (strcmp(buf, "1")==0) ||
+ 	      (strcmp(buf, "true")==0) ||
+ 	      (strcmp(buf, "yes")==0);
+@@ -3992,16 +4658,16 @@
+ 
+   else return 0;
+ }
+-    
++
+ 
+ 
+ 
+ static int xrm_initted = 0;
+- 
++
+ /***********************************/
+ int rd_str_cl (name_str, class_str, reinit)
+-     char *name_str;
+-     char *class_str;
++     const char *name_str;
++     const char *class_str;
+      int  reinit;
+ {
+   /* note: *all* X resource reading goes through this routine... */
+@@ -4043,16 +4709,30 @@
+       unsigned long nitems, nleft;
+       byte *data;
+ 
+-      i = XGetWindowProperty(theDisp, RootWindow(theDisp, 0),
+-			     resAtom, 0L, 1L, False, 
+-			     XA_STRING, &actType, &actFormat, &nitems, &nleft, 
+-			     (unsigned char **) &data);
++      if (spec_window) {
++        i = XGetWindowProperty(theDisp, spec_window,
++			       resAtom, 0L, 1L, False,
++			       XA_STRING, &actType, &actFormat, &nitems, &nleft,
++			       (unsigned char **) &data);
++      } else {
++        i = XGetWindowProperty(theDisp, RootWindow(theDisp, 0),
++			       resAtom, 0L, 1L, False,
++			       XA_STRING, &actType, &actFormat, &nitems, &nleft,
++			       (unsigned char **) &data);
++      }
+       if (i==Success && actType==XA_STRING && actFormat==8) {
+ 	if (nitems>0 && data) XFree(data);
+-	i = XGetWindowProperty(theDisp, RootWindow(theDisp, 0), resAtom, 0L, 
+-			       (long) ((nleft+4+3)/4),
+-			       False, XA_STRING, &actType, &actFormat, 
+-			       &nitems, &nleft, (unsigned char **) &data);
++        if (spec_window) {
++	  i = XGetWindowProperty(theDisp, spec_window, resAtom, 0L,
++			         (long) ((nleft+4+3)/4),
++			         False, XA_STRING, &actType, &actFormat,
++			         &nitems, &nleft, (unsigned char **) &data);
++        } else {
++	  i = XGetWindowProperty(theDisp, RootWindow(theDisp, 0), resAtom, 0L,
++			         (long) ((nleft+4+3)/4),
++			         False, XA_STRING, &actType, &actFormat,
++			         &nitems, &nleft, (unsigned char **) &data);
++        }
+ 	if (i==Success && actType==XA_STRING && actFormat==8 && data) {
+ 	  def_resource = XrmGetStringDatabase((char *) data);
+ 	  XFree(data);
+@@ -4064,50 +4744,51 @@
+ 
+ 
+     if (!gotit) {
+-      xrm_str = XResourceManagerString(theDisp); 
+-      
++      xrm_str = XResourceManagerString(theDisp);
++
+       if (xrm_str) {
+ 	def_resource = XrmGetStringDatabase(xrm_str);
+ 	if (DEBUG) fprintf(stderr,"rd_str_cl: Using RESOURCE_MANAGER prop.\n");
+       }
+       else {    /* no RESOURCE_MANAGER prop.  read from 'likely' file */
+-	char foo[256], *homedir, *xenviron;
++	char foo[256], *xenviron;
++	const char *homedir;
+ 	XrmDatabase res1;
+-	
++
+ #ifdef VMS
+ 	strcpy(foo, "SYS$LOGIN:DECW$XDEFAULTS.DAT");
+ #else
+-	homedir = (char *) getenv("HOME");
++	homedir = (const char *) getenv("HOME");
+ 	if (!homedir) homedir = ".";
+ 	sprintf(foo,"%s/.Xdefaults", homedir);
+ #endif
+-	
++
+ 	def_resource = XrmGetFileDatabase(foo);
+-	
++
+ 	if (DEBUG) {
+ 	  fprintf(stderr,"rd_str_cl: No RESOURCE_MANAGER prop.\n");
+ 	  fprintf(stderr,"rd_str_cl: Using file '%s' (%s)  ",
+ 		  foo, (def_resource) ? "success" : "failure");
+ 	}
+-	
+-	
++
++
+ 	/* merge file pointed to by XENVIRONMENT */
+ 	xenviron = (char *) getenv("XENVIRONMENT");
+ 	if (xenviron) {
+ 	  res1 = XrmGetFileDatabase(xenviron);
+-	  
++
+ 	  if (DEBUG) {
+ 	    fprintf(stderr,"merging XENVIRONMENT='%s' (%s)  ",
+ 		    xenviron, (res1) ? "success" : "failure");
+ 	  }
+-	  
++
+ 	  if (res1) {    /* merge databases */
+ 	    if (!def_resource) def_resource = res1;
+ 	    else XrmMergeDatabases(res1, &def_resource);
+ 	  }
+ 	}
+-	
+-	
++
++
+ 	if (DEBUG) fprintf(stderr,"\n\n");
+       }
+     }
+@@ -4120,16 +4801,15 @@
+   strcpy (q_name, PROGNAME);
+   strcat (q_name, ".");
+   strcat (q_name, name_str);
+-  
++
+   strcpy (q_class, "Program");
+   strcat (q_class, ".");
+   strcat (q_class, class_str);
+ 
+   (void) XrmGetResource(def_resource, q_name, q_class, &type, &result);
+-  
++
+   def_str = result.addr;
+-  if (def_str) return (1);
+-  else return (0);
++  if (def_str) return 1;
++  else return 0;
+ }
+ 
+-
+diff -ru xv-3.10a/xv.h xv-3.10a-enhancements/xv.h
+--- xv-3.10a/xv.h	1995-01-23 12:22:23.000000000 -0800
++++ xv-3.10a-enhancements/xv.h	2007-05-20 21:26:40.000000000 -0700
+@@ -1,6 +1,6 @@
+ /*
+  *  xv.h  -  header file for xv, but you probably guessed as much
+- * 
++ *
+  *  Author:    John Bradley  (bradley at cis.upenn.edu)
+  */
+ 
+@@ -8,8 +8,16 @@
+ #include "config.h"
+ 
+ 
+-#define REVDATE   "Version 3.10a  Rev: 12/29/94"
+-#define VERSTR    "3.10a"
++/* xv 3.10a:				19941229 */
++/* PNG patch 1.2d:			19960731 */
++/* GRR orig jumbo fixes patch:		20000213 */
++/* GRR orig jumbo enhancements patch:	20000220 */
++/* GRR 1st public jumbo F+E patches:	20040531 */
++/* GRR 2nd public jumbo F+E patches:	20050410 */
++/* GRR 3rd public jumbo F+E patches:	20050501 */
++/* GRR 4th public jumbo F+E patch:  	20070520 */
++#define REVDATE   "version 3.10a-jumboFix+Enh of 20070520"
++#define VERSTR    "3.10a-20070520"
+ 
+ /*
+  * uncomment the following, and modify for your site, but only if you've
+@@ -43,6 +51,10 @@
+ /* START OF MACHINE-DEPENDENT CONFIGURATION INFO */
+ /*************************************************/
+ 
++
++#define ENABLE_FIXPIX_SMOOTH	/* GRR 19980607 */
++
++
+ /* Things to make xv more likely to just build, without the user tweaking
+    the makefile */
+ 
+@@ -61,16 +73,38 @@
+ #  define SVR4
+ #endif
+ 
++#if defined(__sony_news) && defined(bsd43) && !defined(__bsd43)
++#  define __bsd43
++#elif defined(__sony_news) && (defined(SYSTYPE_BSD) || defined(__SYSTYPE_BSD)) && !defined(bsd43) && !defined(__bsd43)
++#  define bsd43
++#  define __bsd43
++#endif
++
++#include <signal.h>      /* for interrupt handling */
++
++/* at least on Linux, the following file (1) includes sys/types.h and
++ * (2) defines __USE_BSD (which was not defined before here), so __linux__
++ * block is now moved after this #include */
++#include <X11/Xos.h>     /* need type declarations immediately */
++
+ 
+-#ifdef LINUX
++#ifdef __linux__
+ #  ifndef _LINUX_LIMITS_H
+ #    include <linux/limits.h>
+ #  endif
++#  ifndef USLEEP
++#    define USLEEP
++#  endif
++   /* want only one or the other defined, not both: */
++#  if !defined(BSDTYPES) && !defined(__USE_BSD)
++#    define BSDTYPES
++#  endif
++#  if defined(BSDTYPES) && defined(__USE_BSD)
++#    undef BSDTYPES
++#  endif
+ #endif
+ 
+ 
+-#include <X11/Xos.h>     /* need type declarations immediately */
+-
+ /*********************************************************/
+ 
+ 
+@@ -99,6 +133,16 @@
+ #endif
+ 
+ 
++#if defined(__sony_news) && defined(__bsd43)
++#  include <unistd.h>
++#endif
++
++
++#if defined(__FreeBSD__)
++#  include <sys/param.h>
++#endif
++
++
+ /* include files */
+ #include <stdio.h>
+ #include <math.h>
+@@ -114,18 +158,24 @@
+ 
+ #ifndef VMS
+ #  include <errno.h>
+-   extern int   errno;             /* SHOULD be in errno.h, but often isn't */
+ #  ifndef __NetBSD__
+-     extern char *sys_errlist[];     /* this too... */
++#    if !(defined __GLIBC__ && __GLIBC__ >= 2)
++       extern int   errno;         /* SHOULD be in errno.h, but often isn't */
++       extern char *sys_errlist[]; /* this too... */
++#    endif
+ #  endif
+ #endif
+ 
+ 
+ /* not everyone has the strerror() function, or so I'm told */
+-#ifndef VMS
+-#  define ERRSTR(x) sys_errlist[x]
+-#else
++#ifdef VMS
+ #  define ERRSTR(x) strerror(x, vaxc$errno)
++#else
++#  if defined(__BEOS__) || defined(__linux__) /* or all modern/glibc systems? */
++#    define ERRSTR(x) strerror(x)
++#  else
++#    define ERRSTR(x) sys_errlist[x]
++#  endif
+ #endif
+ 
+ 
+@@ -146,28 +196,20 @@
+ #endif
+ 
+ 
+-/* lots of things don't have <malloc.h> */
+-/* A/UX systems include it from stdlib, from Xos.h */
+-#ifndef VMS   /* VMS hates multi-line '#if's */
+-# if !defined(ibm032)                    && \
+-     !defined(__convex__)                && \
+-     !(defined(vax) && !defined(ultrix)) && \
+-     !defined(mips)                      && \
+-     !defined(apollo)                    && \
+-     !defined(pyr)                       && \
+-     !defined(__UMAXV__)                 && \
+-     !defined(bsd43)                     && \
+-     !defined(aux)                       && \
+-     !defined(__bsdi__)                  && \
+-     !defined(sequent)
+-
++/* GRR 20070512:  Very few modern systems even have a malloc.h anymore;
++ *                stdlib.h is, well, the standard.  (Former explicitly listed
++ *                "don't include" systems:  ibm032, __convex__, non-ultrix vax,
++ *                mips, apollo, pyr, sequent, __UMAXV__, aux, bsd43, __bsd43,
++ *                __bsdi__, __386BSD__, __FreeBSD__, __OpenBSD__, __NetBSD__,
++ *                __DARWIN__, VMS.)  Anyone who _does_ need it can explicitly
++ *                define NEED_MALLOC_H in the makefile. */
++#ifdef NEED_MALLOC_H
+ #  if defined(hp300) || defined(hp800) || defined(NeXT)
+-#   include <sys/malloc.h>                /* it's in 'sys' on HPs and NeXT */
++#    include <sys/malloc.h>    /* it's in "sys" on HPs and NeXT */
+ #  else
+-#   include <malloc.h>
++#    include <malloc.h>
+ #  endif
+-# endif
+-#endif /* !VMS */
++#endif
+ 
+ 
+ 
+@@ -179,9 +221,10 @@
+ #include <X11/Xatom.h>
+ #include <X11/Xmd.h>
+ 
++#ifdef TV_L10N
++#  include <X11/Xlocale.h>
++#endif
+ 
+-#undef SIGCHLD           /* defined in both Xos.h and signal.h */
+-#include <signal.h>      /* for interrupt handling */
+ 
+ #include <sys/types.h>
+ 
+@@ -205,6 +248,10 @@
+ #    include <limits.h>
+ #  endif
+ 
++#  ifdef __BEOS__
++#    include <socket.h>
++#  endif
++
+ /*** for select() call ***/
+ #  ifdef __hpux
+ #    define XV_FDTYPE (int *)
+@@ -259,7 +306,7 @@
+  * make them if missing, along with a few fictitious ones
+  *      Cameron Simpson  (cameron at cse.unsw.edu.au)
+  */
+- 
++
+ #ifndef         S_ISDIR         /* missing POSIX-type macros */
+ #  define       S_ISDIR(mode)   (((mode)&S_IFMT) == S_IFDIR)
+ #  define       S_ISBLK(mode)   (((mode)&S_IFMT) == S_IFBLK)
+@@ -288,7 +335,9 @@
+ #  endif
+ #endif
+ 
+-
++#ifndef S_IRWUSR
++#  define S_IRWUSR	(S_IRUSR|S_IWUSR)	/* or (S_IREAD|S_IWRITE) */
++#endif
+ 
+ #ifndef MAXPATHLEN
+ #  define MAXPATHLEN 256
+@@ -308,36 +357,90 @@
+ 
+ #ifndef VMS       /* VMS hates multi-line definitions */
+ #  if defined(SVR4)  || defined(SYSV) || defined(sco) || \
+-      defined(XENIX) || defined(__osf__) 
++      defined(XENIX) || defined(__osf__) || defined(__linux__)
+ #    undef  USE_GETCWD
+ #    define USE_GETCWD          /* use 'getcwd()' instead of 'getwd()' */
++#  endif                        /* >> SECURITY ISSUE << */
++#endif
++
++
++/* GRR 20040430:  This is new and still not fully deployed.  No doubt there
++ *                are other systems that have mkstemp() (SUSv3); we can add
++ *                them later. */
++#ifndef VMS       /* VMS hates multi-line definitions */
++#  if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
++      defined(__bsdi__)
++#    ifndef USE_MKSTEMP
++#      define USE_MKSTEMP       /* use 'mkstemp()' instead of 'mktemp()' */
++#    endif                      /* >> SECURITY ISSUE << */
+ #  endif
+ #endif
+ 
+ 
++/* GRR 20040503:  This is new and so far tested only under Linux.  But it
++ *                allows -wait to work with subsecond values as long as
++ *                times() exists and clock_t is a long int (latter matters
++ *                only if/when clocks wrap, which for Linux is multiples of
++ *                497.11 days since the last reboot). */
++#if defined(__linux__)
++#  define USE_TICKS             /* use times()/Timer(), not time()/sleep() */
++#  include <limits.h>           /* LONG_MAX (really want CLOCK_T_MAX) */
++#  include <sys/times.h>        /* times() */
++#  ifndef CLK_TCK               /* can be undefined in strict-ANSI mode */
++#    define CLK_TCK CLOCKS_PER_SEC   /* claimed to be same thing in time.h */
++#  endif
++#endif
++
++#if (defined(SYSV) || defined(SVR4) || defined(linux)) && !defined(USE_GETCWD)
++#  define USE_GETCWD
++#endif
++
++#ifndef SEEK_SET
++#  define SEEK_SET 0
++#  define SEEK_CUR 1
++#  define SEEK_END 2
++#endif
++
++#if defined(__mips) && defined(__SYSTYPE_BSD43)
++#  define strstr(A,B) pds_strstr((A),(B))
++#  undef S_IFIFO
++#endif /* !mips_bsd */
++
+ /*****************************/
+ /* END OF CONFIGURATION INFO */
+ /*****************************/
+ 
++
+ #ifdef DOJPEG
+-#define HAVE_JPEG
++#  define HAVE_JPEG
++#endif
++
++#ifdef DOJP2K
++#  define HAVE_JP2K
+ #endif
+ 
+ #ifdef DOTIFF
+-#define HAVE_TIFF
++#  define HAVE_TIFF
++#endif
++
++#ifdef DOPNG
++#  define HAVE_PNG
+ #endif
+ 
+ #ifdef DOPDS
+-#define HAVE_PDS
++#  define HAVE_PDS
+ #endif
+ 
++#ifdef DOG3
++#  define HAVE_G3
++#endif
+ 
+ 
+-#define PROGNAME  "xv"             /* used in resource database */
++#define PROGNAME   "xv"            /* used in resource database */
+ 
+-#define MAXNAMES 4096              /* max # of files in ctrlW list */
++#define MAXNAMES   65536           /* max # of files in ctrlW list */
+ 
+-#define MAXBRWIN   4               /* max # of vis browser windows */
++#define MAXBRWIN   16              /* max # of vis browser windows */
+ 
+ /* strings in the INFOBOX (used in SetISTR and GetISTR) */
+ #define NISTR         10    /* number of ISTRs */
+@@ -432,7 +535,7 @@
+ #define F_COLORS    0
+ #define F_FORMAT    1
+ 
+-/* the following list give indicies into saveColors[] array in xvdir.c */
++/* the following list give indices into saveColors[] array in xvdir.c */
+ #define F_FULLCOLOR 0
+ #define F_GREYSCALE 1
+ #define F_BWDITHER  2
+@@ -440,49 +543,115 @@
+ #define F_MAXCOLORS 4   /* length of saveColors[] array */
+ 
+ 
+-/* following list gives indicies into 'saveFormats[]' array in xvdir.c
+-   note that JPEG and TIFF entries may or may not exist, and following
+-   constants have to be adjusted accordingly.  Also, don't worry about 
+-   duplicate cases if JPGINC or TIFINC = 0.  All code that references
+-   F_JPEG or F_TIFF is #ifdef'd, so it won't be a problem */
++/* The following list gives indices into 'saveFormats[]' array in xvdir.c.
++   Note that JPEG, TIFF, and other entries may or may not exist, so the
++   following constants have to be adjusted accordingly.  Also, don't worry
++   about duplicate cases if, e.g., JPGINC or TIFINC = 0.  All code that
++   references F_JPEG, F_TIFF, etc., is #ifdef'd, so it won't be a problem. */
+ 
+ #ifdef HAVE_JPEG
+-#define F_JPGINC  1
++#  define F_JPGINC  1
+ #else
+-#define F_JPGINC  0
++#  define F_JPGINC  0
++#endif
++
++#ifdef HAVE_JP2K
++#  define F_JP2INC  1   /* provides both JPC and JP2 */
++#else
++#  define F_JP2INC  0
+ #endif
+ 
+ #ifdef HAVE_TIFF
+-#define F_TIFINC  1
++#  define F_TIFINC  1
++#else
++#  define F_TIFINC  0
++#endif
++
++#ifdef HAVE_PNG
++#  define F_PNGINC  1
++#else
++#  define F_PNGINC  0
++#endif
++
++#ifdef HAVE_MAG
++#  define F_MAGINC  1
++#else
++#  define F_MAGINC  0
++#endif
++
++#ifdef HAVE_PIC
++#  define F_PICINC  1
++#else
++#  define F_PICINC  0
++#endif
++
++#ifdef HAVE_MAKI
++#  define F_MAKINC  1
++#else
++#  define F_MAKINC  0
++#endif
++
++#ifdef HAVE_PI
++#  define F_PAIINC  1
++#else
++#  define F_PAIINC  0
++#endif
++
++#ifdef HAVE_PIC2
++#  define F_PC2INC  1
+ #else
+-#define F_TIFINC  0
++#  define F_PC2INC  0
+ #endif
+ 
++#ifdef HAVE_MGCSFX
++#  define F_MGCSFXINC  1
++#else
++#  define F_MGCSFXINC  0
++#endif
+ 
+-#define F_GIF         0
+-#define F_JPEG      ( 0 + F_JPGINC)
+-#define F_TIFF      ( 0 + F_JPGINC + F_TIFINC)
+-#define F_PS        ( 1 + F_JPGINC + F_TIFINC)
+-#define F_PBMRAW    ( 2 + F_JPGINC + F_TIFINC)
+-#define F_PBMASCII  ( 3 + F_JPGINC + F_TIFINC)
+-#define F_XBM       ( 4 + F_JPGINC + F_TIFINC)
+-#define F_XPM       ( 5 + F_JPGINC + F_TIFINC)
+-#define F_BMP       ( 6 + F_JPGINC + F_TIFINC)
+-#define F_SUNRAS    ( 7 + F_JPGINC + F_TIFINC)
+-#define F_IRIS      ( 8 + F_JPGINC + F_TIFINC)
+-#define F_TARGA     ( 9 + F_JPGINC + F_TIFINC)
+-#define F_FITS      (10 + F_JPGINC + F_TIFINC)
+-#define F_PM        (11 + F_JPGINC + F_TIFINC)
+-#define F_DELIM1    (12 + F_JPGINC + F_TIFINC)     /* ----- */
+-#define F_FILELIST  (13 + F_JPGINC + F_TIFINC)
+-#define F_MAXFMTS   (14 + F_JPGINC + F_TIFINC)     /* 15, normally */
++#ifdef MACBINARY
++#  define MACBSIZE 128
++#endif
++
++/* NOTE:  order must match saveFormats[] in xvdir.c */
++/* [this works best when first one is always present, but...we like PNG :-) ] */
++#define F_PNG         0
++#define F_JPEG      ( 0 + F_PNGINC)
++#define F_JPC       ( 0 + F_PNGINC + F_JPGINC)
++#define F_JP2       ( 0 + F_PNGINC + F_JPGINC + F_JP2INC)
++#define F_GIF       ( 0 + F_PNGINC + F_JPGINC + F_JP2INC + F_JP2INC)  /* always avail; index varies */
++#define F_TIFF      ( 0 + F_PNGINC + F_JPGINC + F_JP2INC + F_JP2INC + F_TIFINC)
++#define F_PS        ( 1 + F_TIFF)
++#define F_PBMRAW    ( 2 + F_TIFF)
++#define F_PBMASCII  ( 3 + F_TIFF)
++#define F_XBM       ( 4 + F_TIFF)
++#define F_XPM       ( 5 + F_TIFF)
++#define F_BMP       ( 6 + F_TIFF)
++#define F_SUNRAS    ( 7 + F_TIFF)
++#define F_IRIS      ( 8 + F_TIFF)
++#define F_TARGA     ( 9 + F_TIFF)
++#define F_FITS      (10 + F_TIFF)
++#define F_PM        (11 + F_TIFF)
++#define F_ZX        (12 + F_TIFF)   /* [JCE] */
++#define F_WBMP      (13 + F_TIFF)
++#define JP_EXT_F    (F_WBMP)
++#define F_MAG       (JP_EXT_F + F_MAGINC)
++#define F_PIC       (JP_EXT_F + F_MAGINC + F_PICINC)
++#define F_MAKI      (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC)
++#define F_PI        (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC + F_PAIINC)
++#define F_PIC2      (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC + F_PAIINC + F_PC2INC)
++#define F_MGCSFX    (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC + F_PAIINC + F_PC2INC + F_MGCSFXINC)
++#define JP_EXT_F_END (F_MGCSFX)
++#define F_DELIM1    (JP_EXT_F_END + 1)   /* ----- */
++#define F_FILELIST  (JP_EXT_F_END + 2)
++#define F_MAXFMTS   (JP_EXT_F_END + 3)   /* 27, normally (with all formats) */
+ 
+ 
+ 
+ /* return values from ReadFileType()
+  * positive values are *definitely* readable formats (HAVE_*** is defined)
+  * negative values are random files that XV can't read, but display as
+- *   different icons in the visual browser 
++ *   different icons in the visual browser
+  */
+ #define RFT_ERROR    -1    /* couldn't open file, or whatever... */
+ #define RFT_UNKNOWN   0
+@@ -505,6 +674,22 @@
+ #define RFT_XPM      17
+ #define RFT_XWD      18
+ #define RFT_FITS     19
++#define RFT_PNG      20
++#define RFT_ZX       21    /* [JCE] */
++#define RFT_WBMP     22
++#define RFT_PCD      23
++#define RFT_HIPS     24
++#define RFT_BZIP2    25
++#define RFT_JPC      26
++#define RFT_JP2      27
++#define RFT_G3       28
++#define JP_EXT_RFT   (RFT_G3)
++#define RFT_MAG      (JP_EXT_RFT + 1)
++#define RFT_MAKI     (JP_EXT_RFT + 2)
++#define RFT_PIC      (JP_EXT_RFT + 3)
++#define RFT_PI       (JP_EXT_RFT + 4)
++#define RFT_PIC2     (JP_EXT_RFT + 5)
++#define RFT_MGCSFX   (JP_EXT_RFT + 6)
+ 
+ /* definitions for page up/down, arrow up/down list control */
+ #define LS_PAGEUP   0
+@@ -563,7 +748,8 @@
+ #define RM_CBRICK  7     /* centered on a 'brick' bg */
+ #define RM_ECENTER 8     /* symmetrical tiled */
+ #define RM_ECMIRR  9     /* symmetrical mirror tiled */
+-#define RM_MAX     RM_ECMIRR
++#define RM_UPLEFT 10     /* just in upper left corner */
++#define RM_MAX     RM_UPLEFT
+ 
+ 
+ /* values of colorMapMode */
+@@ -613,10 +799,11 @@
+ #define RMB_CBRICK   8
+ #define RMB_ECENTER  9
+ #define RMB_ECMIRR   10
+-#define RMB_MAX      11
++#define RMB_UPLEFT   11
++#define RMB_MAX      12
+ 
+ 
+-/* indicies into conv24MB */
++/* indices into conv24MB */
+ #define CONV24_8BIT  0
+ #define CONV24_24BIT 1
+ #define CONV24_SEP1  2
+@@ -631,7 +818,7 @@
+ #define PIC8  CONV24_8BIT
+ #define PIC24 CONV24_24BIT
+ 
+-/* indicies into algMB */
++/* indices into algMB */
+ #define ALG_NONE      0
+ #define ALG_SEP1      1  /* separator */
+ #define ALG_BLUR      2
+@@ -648,7 +835,7 @@
+ #define ALG_MAX       13
+ 
+ 
+-/* indicies into sizeMB */
++/* indices into sizeMB */
+ #define SZMB_NORM     0
+ #define SZMB_MAXPIC   1
+ #define SZMB_MAXPECT  2
+@@ -663,7 +850,7 @@
+ #define SZMB_INTEXP   11
+ #define SZMB_MAX      12
+ 
+-/* indicies into windowMB */
++/* indices into windowMB */
+ #define WMB_BROWSE    0
+ #define WMB_COLEDIT   1
+ #define WMB_INFO      2
+@@ -742,15 +929,15 @@
+ 
+ typedef unsigned char byte;
+ 
+-typedef struct scrl { 
++typedef struct scrl {
+                  Window win;            /* window ID */
+ 		 int x,y,w,h;           /* window coords in parent */
+ 		 int len;               /* length of major axis */
+ 		 int vert;              /* true if vertical, else horizontal */
+ 		 int active;            /* true if scroll bar can do anything*/
+-		 int min,max;           /* min/max values 'pos' can take */
+-		 int val;               /* 'value' of scrollbar */
+-		 int page;              /* amt val change on pageup/pagedown */
++		 double min,max;        /* min/max values 'pos' can take */
++		 double val;            /* 'value' of scrollbar */
++		 double page;           /* amt val change on pageup/pagedown */
+ 		 int tpos;              /* thumb pos. (pixels from tmin) */
+ 		 int tmin,tmax;         /* min/max thumb offsets (from 0,0) */
+ 		 int tsize;             /* size of thumb (in pixels) */
+@@ -765,11 +952,12 @@
+ typedef struct { Window win;            /* window ID */
+ 		 int x,y,w,h;           /* window coords in parent */
+ 		 int active;            /* true if can do anything*/
+-		 int min,max;           /* min/max values 'pos' can take */
+-		 int val;               /* 'value' of dial */
+-		 int page;              /* amt val change on pageup/pagedown */
+-		 char *title;           /* title for this guage */
+-		 char *units;           /* string appended to value */
++		 double min,max;        /* min/max values 'pos' can take */
++		 double val;            /* 'value' of dial */
++		 double inc;            /* amt val change on up/down */
++		 double page;           /* amt val change on pageup/pagedown */
++		 const char *title;     /* title for this gauge */
++		 const char *units;     /* string appended to value */
+ 		 u_long fg,bg,hi,lo;    /* colors */
+ 		 int rad, cx, cy;       /* internals */
+ 		 int bx[4], by[4];      /* more internals */
+@@ -785,7 +973,7 @@
+ 		 int active;            /* if false, stipple gray */
+ 		 int toggle;            /* if true, clicking toggles state */
+ 		 u_long fg,bg,hi,lo;    /* colors */
+-		 char *str;             /* string in button */
++		 const char *str;       /* string in button */
+ 		 Pixmap pix;            /* use pixmap instead of string */
+ 		 u_int pw,ph;           /* size of pixmap */
+ 		 int colorpix;          /* multi-color pixmap */
+@@ -797,21 +985,23 @@
+ typedef struct rbutt {
+                  Window        win;      /* parent window */
+ 		 int           x,y;      /* position in parent */
+-		 char         *str;      /* the message string */
++		 const char    *str;     /* the message string */
+ 		 int           selected; /* selected or not */
+ 		 int           active;   /* selectable? */
+ 		 struct rbutt *next;     /* pointer to next in group */
+-		 u_long fg,bg,hi,lo;     /* colors */
++		 u_long        fg,bg;    /* colors */
++		 u_long        hi,lo;    /* colors */
+ 	       } RBUTT;
+ 
+ 
+ 
+ typedef struct { Window        win;      /* parent window */
+ 		 int           x,y;      /* position in parent */
+-		 char         *str;      /* the message string */
++		 const char   *str;      /* the message string */
+ 		 int           val;      /* 1=selected, 0=not */
+ 		 int           active;   /* selectable? */
+-		 u_long fg,bg,hi,lo;     /* colors */
++		 u_long        fg,bg;    /* colors */
++		 u_long        hi,lo;    /* colors */
+ 	       } CBUTT;
+ 
+ 
+@@ -819,11 +1009,11 @@
+ typedef struct { Window        win;            /* parent window */
+ 		 int           x,y;            /* position in parent */
+ 		 unsigned int  w,h;
+-		 char         *title;          /* title string in norm state */
++		 const char   *title;          /* title string in norm state */
+ 		 int           active;         /* selectable? */
+-		 char        **list;           /* list of strings in menu */
++		 const char  **list;           /* list of strings in menu */
+ 		 int           nlist;          /* # of strings in menu */
+-		 byte          flags[MAXMBLEN];  /* checkmarks on items */
++		 byte          flags[MAXMBLEN]; /* checkmarks on items */
+ 		 int           hascheck;       /* leave room for checkmark? */
+ 		 byte          dim[MAXMBLEN];  /* dim individual choices */
+ 		 Pixmap        pix;            /* use pixmap instd of string */
+@@ -833,17 +1023,18 @@
+ 	       } MBUTT;
+ 
+ 
+-typedef struct { Window win;            /* window */
+-		 int x,y;               /* size of window */
++typedef struct { Window       win;       /* window */
++		 int          x,y;       /* size of window */
+ 		 unsigned int w,h;
+-		 u_long fg,bg,hi,lo;    /* colors */
+-		 char **str;            /* ptr to list of strings */
+-		 int   nstr;            /* number of strings */
+-		 int   selected;        /* number of 'selected' string */
+-		 int   nlines;          /* number of lines shown at once */
+-		 SCRL  scrl;            /* scrollbar that controls list */
+-		 int   filetypes;       /* true if filetype icons to be drawn*/
+-		 int   dirsonly;        /* if true, only dirs selectable */
++		 u_long       fg,bg;     /* colors */
++		 u_long       hi,lo;     /* colors */
++		 /* const? */ char **str;   /* ptr to list of strings */
++		 int          nstr;      /* number of strings */
++		 int          selected;  /* number of 'selected' string */
++		 int          nlines;    /* number of lines shown at once */
++		 SCRL         scrl;      /* scrollbar that controls list */
++		 int          filetypes; /* true if filetype icons to be drawn*/
++		 int          dirsonly;  /* if true, only dirs selectable */
+ 	       } LIST;
+ 
+ 
+@@ -865,6 +1056,9 @@
+ 		 char  shrtInfo[128];        /* short format info */
+ 		 char *comment;              /* comment text */
+ 
++		 byte *exifInfo;             /* image info from digicam */
++		 int   exifInfoSize;         /* size of image info */
++
+ 		 int   numpages;             /* # of page files, if >1 */
+ 		 char  pagebname[64];        /* basename of page files */
+ 	       } PICINFO;
+@@ -881,18 +1075,18 @@
+ 
+ #define GVMAX 8
+ 
+-typedef struct {  Window win;          /* window ID */
+-		  Window gwin;         /* graph subwindow */
+-		  int    spline;       /* spline curve or lines? */
+-		  int    entergamma;   /* currently entering gamma value */
+-		  int    gammamode;    /* currently using gamma function */
+-		  double gamma;        /* gamma value (if gammamode) */
+-		  int    nhands;       /* current # of handles */
+-		  XPoint hands[MAX_GHANDS];   /* positions of handles */
+-		  byte   func[256];    /* output function of GRAF */
+-		  BUTT   butts[N_GFB]; /* control buttons */
+-		  u_long fg,bg;        /* colors */
+-		  char   *str;         /* title string */
++typedef struct {  Window win;               /* window ID */
++		  Window gwin;              /* graph subwindow */
++		  int    spline;            /* spline curve or lines? */
++		  int    entergamma;        /* currently entering gamma value */
++		  int    gammamode;         /* currently using gamma function */
++		  double gamma;             /* gamma value (if gammamode) */
++		  int    nhands;            /* current # of handles */
++		  XPoint hands[MAX_GHANDS]; /* positions of handles */
++		  byte   func[256];         /* output function of GRAF */
++		  BUTT   butts[N_GFB];      /* control buttons */
++		  u_long fg,bg;             /* colors */
++		  const char *str;          /* title string */
+ 		  char   gvstr[GVMAX+1];    /* gamma value input string */
+ 		  void   (*drawobj)PARM((void));
+ 		} GRAF;
+@@ -932,18 +1126,23 @@
+ /* X stuff */
+ WHERE Display       *theDisp;
+ WHERE int           theScreen;
+-WHERE unsigned int  ncells, dispWIDE, dispHIGH, dispDEEP;
+-WHERE unsigned int  vrWIDE, vrHIGH, maxWIDE, maxHIGH;
++WHERE unsigned int  ncells, dispDEEP; /* root color sizes */
++WHERE unsigned int  dispWIDE, dispHIGH; /* screen sizes */
++WHERE unsigned int  vrWIDE, vrHIGH, maxWIDE, maxHIGH; /* virtual root and max image sizes */
+ WHERE Colormap      theCmap, LocalCmap;
+-WHERE Window        rootW, mainW, vrootW;
++WHERE Window        spec_window, rootW, mainW, vrootW;
+ WHERE GC            theGC;
+ WHERE u_long        black, white, fg, bg, infofg, infobg;
+ WHERE u_long        hicol, locol;
+ WHERE u_long        blkRGB, whtRGB;
+ WHERE Font          mfont, monofont;
+ WHERE XFontStruct   *mfinfo, *monofinfo;
++#ifdef TV_L10N
++WHERE XFontSet      monofset;
++WHERE XFontSetExtents *monofsetinfo;
++#endif
+ WHERE Visual        *theVisual;
+-WHERE Cursor        arrow, cross, tcross, zoom, inviso;
++WHERE Cursor        arrow, cross, tcross, zoom, inviso, tlcorner;
+ WHERE Pixmap        iconPix, iconmask;
+ WHERE Pixmap        riconPix, riconmask;
+ WHERE int           showzoomcursor;
+@@ -959,6 +1158,12 @@
+ WHERE char           formatStr[80];         /* short-form 'file format' */
+ WHERE int            picType;               /* CONV24_8BIT,CONV24_24BIT,etc.*/
+ WHERE char          *picComments;           /* text comments on current pic */
++WHERE byte          *picExifInfo;           /* image info from digicam */
++WHERE int            picExifInfoSize;       /* size of image info */
++
++#ifdef TV_L10N
++WHERE int            xlocale;		    /* true if Xlib supports locale */
++#endif
+ 
+ WHERE int            numPages, curPage;     /* for multi-page files */
+ WHERE char           pageBaseName[64];      /* basename for multi-page files */
+@@ -972,12 +1177,12 @@
+                                    /* this is converted to 'theImage' */
+ WHERE int           eWIDE, eHIGH;  /* size of epic */
+ 
+-WHERE byte          *egampic;      /* expanded, gammified cpic 
++WHERE byte          *egampic;      /* expanded, gammified cpic
+ 				      (only used in 24-bit mode) */
+ 
+ WHERE int           p_offx, p_offy;  /* offset of reparented windows */
+ WHERE int           ch_offx,ch_offy; /* ChngAttr ofst for reparented windows */
+-WHERE int           kludge_offx,     /* WM kludges for SetWindowPos routine */ 
++WHERE int           kludge_offx,     /* WM kludges for SetWindowPos routine */
+                     kludge_offy;
+ WHERE int           winCtrPosKludge; /* kludge for popup positioning... */
+ 
+@@ -993,6 +1198,26 @@
+ WHERE unsigned long  cols[256];    /* maps pic pixel values to X pixel vals */
+ WHERE int            fc2pcol[256]; /* maps freecols into pic pixel values */
+ WHERE int            numcols;      /* # of desired colors in picture */
++#ifdef MACBINARY
++WHERE char           macb_file;    /* True if this file type is MacBinary */
++WHERE int            handlemacb;   /* True if we want to handle MacBinary */
++#endif
++#if defined(HAVE_PIC) || defined(HAVE_PIC2)
++WHERE int            nopicadjust;  /* True if we don't want to adjust aspect */
++#endif
++#ifdef HAVE_PIC2
++WHERE int            pic2split;    /* True if we want to split multiblocks */
++#endif
++#ifdef VS_ADJUST
++WHERE int            vsadjust; /* True if we want to adjust aspect of icons */
++#endif
++#ifdef HAVE_MGCSFX
++WHERE int            mgcsfx;    /* True if we want to force use MgcSfx */
++WHERE int            nomgcsfx;  /* True if we don't want to use MgcSfx */
++#endif
++
++#define FSTRMAX 12   /* Number of function keys to support. */
++WHERE char          *fkeycmds[FSTRMAX]; /* command to run when F# is pressed */
+ 
+ /* Std Cmap stuff */
+ WHERE byte           stdr[256], stdg[256], stdb[256];  /* std 3/3/2 cmap */
+@@ -1025,7 +1250,7 @@
+ 
+ WHERE int           ncols;         /* max # of (different) colors to alloc */
+ 
+-WHERE char          str[128];      /* dummy string used for error messages */
++WHERE char          dummystr[128]; /* dummy string used for error messages */
+ WHERE char          initdir[MAXPATHLEN];   /* cwd when xv was started */
+ WHERE char          searchdir[MAXPATHLEN]; /* '-dir' option */
+ WHERE char          fullfname[MAXPATHLEN]; /* full name of current file */
+@@ -1047,42 +1272,47 @@
+                     noFreeCols,    /* don't free colors when loading new pic */
+                     autoquit,      /* quit in '-root' or when click on win */
+                     xerrcode,      /* errorcode of last X error */
+-                    grabDelay;     /* # of seconds to sleep at start of Grab */
++                    grabDelay,     /* # of seconds to sleep at start of Grab */
++                    startGrab;     /* start immediate grab ? */
+ 
+ WHERE int           state824;      /* displays warning when going 8->24 */
+ 
+ WHERE float         defaspect,     /* default aspect ratio to use */
+                     normaspect;    /* normal aspect ratio of this picture */
+ 
+-WHERE unsigned long rootbg, rootfg;   /* fg/bg for root border */
+-WHERE int           waitsec;          /* secs btwn pics. -1=wait for event */
+-WHERE int           waitloop;         /* loop at end of slide show? */
+-WHERE int           automax;          /* maximize pic on open */
+-WHERE int           rootMode;         /* mode used for -root images */
++WHERE u_long        rootbg, rootfg; /* fg/bg for root border */
++WHERE u_short       imagebgR;
++WHERE u_short       imagebgG;      /* GRR 19980308:  bg for transpar. images */
++WHERE u_short       imagebgB;
++WHERE int           have_imagebg;
++WHERE double        waitsec;       /* secs btwn pics. -1.0=wait for event */
++WHERE int           waitloop;      /* loop at end of slide show? */
++WHERE int           automax;       /* maximize pic on open */
++WHERE int           rootMode;      /* mode used for -root images */
+ 
+-WHERE int           nostat;           /* if true, don't stat() in LdCurDir */
++WHERE int           nostat;        /* if true, don't stat() in LdCurDir */
+ 
+-WHERE int           ctrlColor;        /* whether or not to use colored butts */
++WHERE int           ctrlColor;     /* whether or not to use colored butts */
+ 
+-WHERE char         *def_str;          /* used by rd_*() routines */
++WHERE char         *def_str;       /* used by rd_*() routines */
+ WHERE int           def_int;
+-WHERE char         *tmpdir;           /* equal to "/tmp" or $TMPDIR env var */
+-WHERE Pixmap        gray25Tile,       /* used for 3d effect on 1-bit disp's */
++WHERE char         *tmpdir;        /* equal to "/tmp" or $TMPDIR env var */
++WHERE Pixmap        gray25Tile,    /* used for 3d effect on 1-bit disp's */
+                     gray50Tile;
+-WHERE int           autoDelete;       /* delete cmd-line files on exit? */
++WHERE int           autoDelete;    /* delete cmd-line files on exit? */
+ 
+ #define PRINTCMDLEN 256
+-WHERE char          printCmd[PRINTCMDLEN]; 
++WHERE char          printCmd[PRINTCMDLEN];
+ 
+ /* stuff used for 'info' box */
+ WHERE Window        infoW;
+-WHERE int           infoUp;       /* boolean:  whether infobox is visible */
++WHERE int           infoUp;        /* boolean:  whether infobox is visible */
+ WHERE int           infoMode;
+ 
+ 
+ /* stuff used for 'ctrl' box */
+ WHERE Window        ctrlW;
+-WHERE int           ctrlUp;       /* boolean:  whether ctrlbox is visible */
++WHERE int           ctrlUp;        /* boolean:  whether ctrlbox is visible */
+ WHERE char         *namelist[MAXNAMES];  /* list of file names from argv */
+ WHERE char         *origlist[MAXNAMES];  /* only names from argv (autoDelete)*/
+ WHERE int           orignumnames;
+@@ -1121,25 +1351,31 @@
+ 
+ 
+ /* stuff used for 'browse' box */
+-WHERE int           anyBrowUp;            /* whether *any* browser visible */
++WHERE int           anyBrowUp;              /* whether *any* browser visible */
++WHERE int           incrementalSearchTimeout;
+ 
+ /* stuff used for textview windows */
+-WHERE int           anyTextUp;            /* are any text windows visible? */
+-WHERE int           commentUp;            /* comment window up? */
++WHERE int           anyTextUp;              /* are any text windows visible? */
++WHERE int           commentUp;              /* comment window up? */
+ 
+ /* stuff used for xvcut.c */
+-WHERE int           forceClipFile;        /* don't use property clipboard */
+-WHERE int           clearR, clearG, clearB;  /* clear color in 24-bit mode */
++WHERE int           forceClipFile;          /* don't use property clipboard */
++WHERE int           clearR, clearG, clearB; /* clear color in 24-bit mode */
+ 
+ 
+ /* stuff used for 'ps' box */
+ WHERE Window        psW;
+-WHERE int           psUp;       /* is psW mapped, or what? */
+-WHERE CBUTT         encapsCB, pscompCB;   
+-WHERE char         *gsDev, *gsGeomStr;
++WHERE int           psUp;         /* is psW mapped, or what? */
++WHERE CBUTT         encapsCB, pscompCB;
++WHERE const char   *gsDev, *gsGeomStr;
+ WHERE int           gsRes;
+ 
+ 
++/* stuff used for 'pcd' box */
++WHERE Window        pcdW;
++WHERE int           pcdUp;        /* is pcdW mapped, or what? */
++
++
+ #ifdef HAVE_JPEG
+ /* stuff used for 'jpeg' box */
+ WHERE Window        jpegW;
+@@ -1147,6 +1383,13 @@
+ #endif
+ 
+ 
++#ifdef HAVE_JP2K
++/* stuff used for 'jp2k' box */
++WHERE Window        jp2kW;
++WHERE int           jp2kUp;       /* is jp2kW mapped, or what? */
++#endif
++
++
+ #ifdef HAVE_TIFF
+ /* stuff used for 'tiff' box */
+ WHERE Window        tiffW;
+@@ -1154,6 +1397,91 @@
+ #endif
+ 
+ 
++#ifdef HAVE_PNG
++/* stuff used for 'png' box */
++WHERE Window        pngW;
++WHERE int           pngUp;        /* is pngW mapped, or what? */
++#endif
++
++
++#ifdef ENABLE_FIXPIX_SMOOTH
++WHERE int           do_fixpix_smooth;  /* GRR 19980607: runtime FS dithering */
++#endif
++
++#ifdef HAVE_PIC2
++/* stuff used for 'pic2' box */
++WHERE Window        pic2W;
++WHERE int           pic2Up;      /* is pic2W mapped, or what? */
++#endif /* HAVE_PIC2 */
++
++#ifdef HAVE_PCD
++/* stuff used for 'pcd' box */
++WHERE Window        pcdW;
++WHERE int           pcdUp;       /* is pcdW mapped, or what? */
++#endif /* HAVE_PCD */
++
++#ifdef HAVE_MGCSFX
++/* stuff used for 'mgcsfx' box */
++WHERE Window        mgcsfxW;
++WHERE Window        mgcsfxNameW;
++WHERE int           mgcsfxUp;      /* is mgcsfxW mapped, or what? */
++#endif /* HAVE_MGCSFX */
++
++#ifdef TV_L10N
++/* stuff used for TextViewer Japanization */
++#  define LOCALE_USASCII    0
++#  define LOCALE_EUCJ       1
++#  define LOCALE_JIS        2
++#  define LOCALE_MSCODE     3
++
++#  ifndef LOCALE_DEFAULT
++#    define LOCALE_DEFAULT  0
++#  endif /* !LOCALE_DEFAULT */
++
++#  ifndef MAIN
++     extern char *localeList[];
++#  else
++#    ifndef LOCALE_NAME_EUC
++#      ifndef X_LOCALE
++#        if defined(__FreeBSD__)
++	   char *localeList[] = {"", "ja_JP.EUC", "none", "none"};
++#        elif defined(__linux__)
++	   char *localeList[] = {"", "ja_JP.eucJP", "none", "ja_JP.SJIS"};
++#        elif defined(__sun) || defined(sun)
++	   char *localeList[] = {"", "ja", "none", "none"};
++#        elif defined(__sgi)	/* sgi, __sgi, __sgi__ (gcc) */
++	   char *localeList[] = {"", "ja_JP.EUC", "none", "none"};
++#        elif defined(sony_news)
++	   char *localeList[] = {"", "ja_JP.EUC", "none", "ja_JP.SJIS"};
++#        elif defined(nec)
++	   char *localeList[] = {"", "japan", "none", "none"};
++#        elif defined(__hpux)
++	   char *localeList[] = {"", "japanese.euc", "none", "japanese"};
++#        elif defined(__osf__)
++	   char *localeList[] = {"", "ja_JP.deckanji", "none", "ja_JP.SJIS"};
++#        elif defined(_AIX)
++	   char *localeList[] = {"", "ja_JP", "none", "Ja_JP" };
++#        elif defined(__bsdi)
++	   char *localeList[] = {"", "Japanese-EUC", "none", "none" };
++#        else
++	   char *localeList[] = {"", "ja_JP.EUC", "ja_JP.JIS", "ja_JP.SJIS"};
++#        endif
++#      else
++#        if (XlibSpecificationRelease > 5)
++           char *localeList[] = {"", "ja_JP.eucJP", "ja_JP.JIS7",
++				 "ja_JP.SJIS"};
++#        else
++           char *localeList[] = {"", "ja_JP.ujis", "ja_JP.jis7",
++				 "ja_JP.mscode"};
++#        endif
++#      endif /* X_LOCALE */
++#    else
++       char *localeList[] = {"", LOCALE_NAME_EUC,
++			     LOCALE_NAME_JIS, LOCALE_NAME_MSCODE};
++#    endif /* LOCALE_NAME_EUC */
++#  endif /* MAIN */
++#endif /* TV_L10N */
++
+ #undef WHERE
+ 
+ 
+@@ -1161,172 +1489,115 @@
+ /* function declarations for externally-callable functions */
+ 
+ /****************************** XV.C ****************************/
+-int   ReadFileType      PARM((char *));
+-int   ReadPicFile       PARM((char *, int, PICINFO *, int));
+-int   UncompressFile    PARM((char *, char *));
+-void  KillPageFiles     PARM((char *, int));
+-
+-void NewPicGetColors    PARM((int, int));
+-void FixAspect          PARM((int, int *, int *));
+-void ActivePrevNext     PARM((void));
+-int  DeleteCmd          PARM((void));
+-void StickInCtrlList    PARM((int));
+-void AddFNameToCtrlList PARM((char *, char *));
+-void ChangedCtrlList    PARM((void));
+-void HandleDispMode     PARM((void));
+-char *lower_str         PARM((char *));
+-int  rd_int             PARM((char *));
+-int  rd_str             PARM((char *));
+-int  rd_flag            PARM((char *));
+-int  rd_str_cl          PARM((char *, char *, int));
++int   ReadFileType         PARM((char *));
++int   ReadPicFile          PARM((char *, int, PICINFO *, int));
++int   UncompressFile       PARM((char *, char *, int));
++void  KillPageFiles        PARM((char *, int));
++#ifdef MACBINARY          
++int   RemoveMacbinary      PARM((char *, char *));
++#endif                    
++
++void NewPicGetColors       PARM((int, int));
++void FixAspect             PARM((int, int *, int *));
++void ActivePrevNext        PARM((void));
++int  DeleteCmd             PARM((void));
++void StickInCtrlList       PARM((int));
++void AddFNameToCtrlList    PARM((const char *, const char *));
++void ChangedCtrlList       PARM((void));
++void HandleDispMode        PARM((void));
++char *lower_str            PARM((char *));
++int  rd_int                PARM((const char *));
++int  rd_str                PARM((const char *));
++int  rd_flag               PARM((const char *));
+ 
+-/****************************** XVEVENT.C ****************************/
+-int  EventLoop          PARM((void));
+-int  HandleEvent        PARM((XEvent *, int *));
+ 
+-void SelectDispMB       PARM((int));
+-void Select24to8MB      PARM((int));
+-void SelectRootMB       PARM((int));
+-void SelectWindowMB     PARM((int));
+-void SelectSizeMB       PARM((int));
+-
+-void DoPrint            PARM((void));
+-void NewCutBuffer       PARM((char *));
+-void DrawWindow         PARM((int,int,int,int));
+-void WResize            PARM((int, int));
+-void WRotate            PARM((void));
+-void WCrop              PARM((int, int, int, int));
+-void WUnCrop            PARM((void));
+-void GetWindowPos       PARM((XWindowAttributes *));
+-void SetWindowPos       PARM((XWindowAttributes *));
+-void SetEpicMode        PARM((void));
+-int  xvErrorHandler     PARM((Display *, XErrorEvent *));
+-
+-/****************************** XVROOT.C ****************************/
+-void MakeRootPic        PARM((void));
+-void ClearRoot          PARM((void));
+-void SaveRootInfo       PARM((void));
+-void KillOldRootInfo    PARM((void));
++/*************************** XV24TO8.C **************************/
++void Init24to8             PARM((void));
++byte *Conv24to8            PARM((byte *, int, int, int,
++				 byte *, byte *, byte *));
+ 
+-/*************************** XVMISC.C ***************************/
+-void StoreDeleteWindowProp  PARM((Window));
+-Window CreateWindow         PARM((char *, char *, char *, int, int, 
+-				  u_long, u_long, int));
+-void DrawString             PARM((Window, int, int, char *));
+-void CenterString           PARM((Window, int, int, char *));
+-void ULineString            PARM((Window, int, int, char *));
+-int  StringWidth            PARM((char *));
+-int  CursorKey              PARM((KeySym, int, int));
+-void FakeButtonPress        PARM((BUTT *));
+-void FakeKeyPress           PARM((Window, KeySym));
+-void GenExpose              PARM((Window, int, int, u_int, u_int));
+-void DimRect                PARM((Window, int, int, u_int, u_int, u_long));
+-
+-void Draw3dRect             PARM((Window, int, int, u_int, u_int, int, int, 
+-				    u_long, u_long, u_long));
+-
+-void RemapKeyCheck          PARM((KeySym, char *, int *));
+-void xvDestroyImage         PARM((XImage *));
+-void SetCropString          PARM((void));
+-void SetSelectionString     PARM((void));
+-void Warning                PARM((void));
+-void FatalError             PARM((char *));
+-void Quit                   PARM((int));
+-void LoadFishCursors        PARM((void));
+-void WaitCursor             PARM((void));
+-void SetCursors             PARM((int));
+-char *BaseName              PARM((char *));
+-
+-void DrawTempGauge          PARM((Window, int, int, int, int, double, 
+-				  u_long, u_long, u_long, u_long, char *));
+-void ProgressMeter          PARM((int, int, int, char *));
+-void XVDeletedFile          PARM((char *));
+-void XVCreatedFile          PARM((char *));
+-void xvbcopy                PARM((char *, char *, size_t));
+-int  xvbcmp                 PARM((char *, char *, size_t));
+-void xvbzero                PARM((char *, size_t));
+-void xv_getwd               PARM((char *, size_t));
+-char *xv_strstr             PARM((char *, char *));
+-FILE *xv_fopen              PARM((char *, char *));
+-void Timer                  PARM((int));
++byte *Conv8to24            PARM((byte *, int, int, byte *, byte *, byte *));
+ 
+-/*************************** XVCOLOR.C ***************************/
+-void   SortColormap         PARM((byte *, int, int, int *, byte*,byte*,byte*,
+-				  byte *, byte *));
+-void   ColorCompress8       PARM((byte *));
+-void   AllocColors          PARM((void));
+-Status xvAllocColor         PARM((Display *, Colormap, XColor *));
+-void   xvFreeColors         PARM((Display *, Colormap, u_long *, int, u_long));
+-void   FreeColors           PARM((void));
+-void   ApplyEditColor       PARM((int));
+-int    MakeStdCmaps         PARM((void));
+-void   MakeBrowCmap         PARM((void));
+-void   ChangeCmapMode       PARM((int, int, int));
+ 
+-/*************************** XVIMAGE.C ***************************/
+-void Resize                 PARM((int, int));
+-void GenerateCpic           PARM((void));
+-void GenerateEpic           PARM((int, int));
+-void DoZoom                 PARM((int, int, u_int));
+-void Crop                   PARM((void));
+-void UnCrop                 PARM((void));
+-void AutoCrop               PARM((void));
+-int  DoAutoCrop             PARM((void));
+-void DoCrop                 PARM((int, int, int, int));
+-void Rotate                 PARM((int));
+-void DoRotate               PARM((int));
+-void RotatePic              PARM((byte *, int, int *, int *, int));
+-void Flip                   PARM((int));
+-void FlipPic                PARM((byte *, int, int, int));
+-void InstallNewPic          PARM((void));
+-void DrawEpic               PARM((void));
+-void KillOldPics            PARM((void));
+-
+-byte *FSDither              PARM((byte *, int, int, int, 
+-				  byte *, byte *, byte *, int, int));
+-
+-void CreateXImage           PARM((void));
+-XImage *Pic8ToXImage        PARM((byte *, u_int, u_int, u_long *, 
+-				  byte *, byte *, byte *));
+-
+-XImage *Pic24ToXImage       PARM((byte *, u_int, u_int));
+-
+-void Set824Menus            PARM((int));
+-void Change824Mode          PARM((int));
+-void FreeEpic               PARM((void));
+-void InvertPic24            PARM((byte *, int, int));
++/*************************** XVALG.C ***************************/
++void AlgInit               PARM((void));
++void DoAlg                 PARM((int));
+ 
+-byte *XVGetSubImage         PARM((byte *, int, int,int, int,int,int,int));
+ 
+-int  DoPad                  PARM((int, char *, int, int, int, int));
+-int  LoadPad                PARM((PICINFO *, char *));
++/*************************** XVBROWSE.C ************************/
++void CreateBrowse          PARM((const char *, const char *, const char *,
++				 const char *, const char *));
++void OpenBrowse            PARM((void));
++void HideBrowseWindows     PARM((void));
++void UnHideBrowseWindows   PARM((void));
++void SetBrowseCursor       PARM((Cursor));
++void KillBrowseWindows     PARM((void));
++int  BrowseCheckEvent      PARM((XEvent *, int *, int *));
++int  BrowseDelWin          PARM((Window));
++void SetBrowStr            PARM((const char *));
++void RegenBrowseIcons      PARM((void));
++void BRDeletedFile         PARM((char *));
++void BRCreatedFile         PARM((char *));
+ 
+-/*************************** XVALG.C ***************************/
+-void AlgInit                PARM((void));
+-void DoAlg                  PARM((int));
+ 
+-/*************************** XVSMOOTH.C ***************************/
+-byte *SmoothResize          PARM((byte *, int, int, int, int, byte *, byte *, 
+-				  byte *, byte *, byte *, byte *, int));
++/**************************** XVBUTT.C ***************************/
++void BTCreate              PARM((BUTT *, Window, int, int, u_int, u_int,
++				 const char *, u_long, u_long, u_long, u_long));
+ 
+-byte *Smooth24              PARM((byte *, int, int, int, int, int, 
+-				  byte *, byte *, byte *));
++void BTSetActive           PARM((BUTT *, int));
++void BTRedraw              PARM((BUTT *));
++int  BTTrack               PARM((BUTT *));
+ 
+-byte *DoColorDither         PARM((byte *, byte *, int, int, byte *, byte *, 
+-				  byte *, byte *, byte *, byte *, int));
+ 
+-byte *Do332ColorDither      PARM((byte *, byte *, int, int, byte *, byte *, 
+-				  byte *, byte *, byte *, byte *, int));
++RBUTT *RBCreate            PARM((RBUTT *, Window, int, int, const char *,
++				 u_long, u_long, u_long, u_long));
+ 
+-/*************************** XV24TO8.C **************************/
+-void Init24to8             PARM((void));
+-byte *Conv24to8            PARM((byte *, int, int, int, 
+-				 byte *, byte *, byte *));
++void   RBRedraw            PARM((RBUTT *, int));
++void   RBSelect            PARM((RBUTT *, int));
++int    RBWhich             PARM((RBUTT *));
++int    RBCount             PARM((RBUTT *));
++void   RBSetActive         PARM((RBUTT *, int, int));
++int    RBClick             PARM((RBUTT *, int, int));
++int    RBTrack             PARM((RBUTT *, int));
++
++
++void   CBCreate            PARM((CBUTT *, Window, int, int, const char *,
++				 u_long, u_long, u_long, u_long));
++
++void   CBRedraw            PARM((CBUTT *));
++void   CBSetActive         PARM((CBUTT *, int));
++int    CBClick             PARM((CBUTT *,int,int));
++int    CBTrack             PARM((CBUTT *));
++
++
++void   MBCreate            PARM((MBUTT *, Window, int, int, u_int, u_int,
++				 const char *, const char * const *, int,
++				 u_long, u_long, u_long, u_long));
++
++void   MBRedraw            PARM((MBUTT *));
++void   MBSetActive         PARM((MBUTT *, int));
++int    MBWhich             PARM((MBUTT *));
++void   MBSelect            PARM((MBUTT *, int));
++int    MBClick             PARM((MBUTT *, int, int));
++int    MBTrack             PARM((MBUTT *));
++
++
++/*************************** XVCOLOR.C ***************************/
++void   SortColormap        PARM((byte *, int, int, int *, byte*,byte*,byte*,
++				 byte *, byte *));
++void   ColorCompress8      PARM((byte *));
++void   AllocColors         PARM((void));
++Status xvAllocColor        PARM((Display *, Colormap, XColor *));
++void   xvFreeColors        PARM((Display *, Colormap, u_long *, int, u_long));
++void   FreeColors          PARM((void));
++void   ApplyEditColor      PARM((int));
++int    MakeStdCmaps        PARM((void));
++void   MakeBrowCmap        PARM((void));
++void   ChangeCmapMode      PARM((int, int, int));
+ 
+-byte *Conv8to24            PARM((byte *, int, int, byte *, byte *, byte *));
+ 
+ /**************************** XVCTRL.C **************************/
+-void   CreateCtrl          PARM((char *));
++void   CreateCtrl          PARM((const char *));
+ void   SetButtPix          PARM((BUTT *, Pixmap, int, int));
+ Pixmap MakePix1            PARM((Window, byte *, int, int));
+ 
+@@ -1337,7 +1608,7 @@
+ void DrawCtrlStr           PARM((void));
+ void ScrollToCurrent       PARM((LIST *));
+ 
+-void LSCreate              PARM((LIST *, Window, int, int, int, int, int, 
++void LSCreate              PARM((LIST *, Window, int, int, int, int, int,
+ 				 char **, int, u_long, u_long, u_long, u_long,
+ 				 void (*)(int, SCRL *), int, int));
+ 
+@@ -1346,20 +1617,56 @@
+ void LSChangeData          PARM((LIST *, char **, int));
+ void LSNewData             PARM((LIST *, char **, int));
+ void LSKey                 PARM((LIST *, int));
++int  rd_str_cl             PARM((const char *, const char *, int));
+ 
+ 
+-/*************************** XVINFO.C ***************************/
+-void  CreateInfo           PARM((char *));
+-void  InfoBox              PARM((int));
+-void  RedrawInfo           PARM((int, int, int, int));
+-void  SetInfoMode          PARM((int));
+-char *GetISTR              PARM((int));
++/**************************** XVCUT.C ***************************/
++int  CutAllowed            PARM((void));
++int  PasteAllowed          PARM((void));
++void DoImgCopy             PARM((void));
++void DoImgCut              PARM((void));
++void DoImgClear            PARM((void));
++void DoImgPaste            PARM((void));
+ 
+-#if defined(__STDC__) && !defined(NOSTDHDRS)
+-void  SetISTR(int, ...);
+-#else
+-void  SetISTR();
+-#endif
++void SaveToClip            PARM((byte *));
++void InitSelection         PARM((void));
++int  HaveSelection         PARM((void));
++int  GetSelType            PARM((void));
++void GetSelRCoords         PARM((int *, int *, int *, int *));
++void EnableSelection       PARM((int));
++void DrawSelection         PARM((int));
++int  DoSelection           PARM((XButtonEvent *));
++void MoveGrowSelection     PARM((int, int, int, int));
++void BlinkSelection        PARM((int));
++void FlashSelection        PARM((int));
++
++void CropRect2Rect         PARM((int*,int*,int*,int*, int,int,int,int));
++void CoordE2C              PARM((int, int, int *, int *));
++void CoordC2E              PARM((int, int, int *, int *));
++void CoordP2C              PARM((int, int, int *, int *));
++void CoordC2P              PARM((int, int, int *, int *));
++void CoordP2E              PARM((int, int, int *, int *));
++void CoordE2P              PARM((int, int, int *, int *));
++
++
++/*************************** XVDFLT.C ***************************/
++void LoadDfltPic           PARM((PICINFO *));
++void xbm2pic               PARM((byte *, int, int, byte *, int, int, int, int,
++				 int));
++void DrawStr2Pic           PARM((char *, int, int, byte *, int, int, int));
++
++
++/*************************** XVDIAL.C ***************************/
++void DCreate               PARM((DIAL *, Window, int, int, int, int,
++                                 double, double, double, double, double,
++                                 u_long, u_long, u_long, u_long,
++                                 const char *, const char *));
++
++void DSetRange             PARM((DIAL *, double,double,double,double,double));
++void DSetVal               PARM((DIAL *, double));
++void DSetActive            PARM((DIAL *, int));
++void DRedraw               PARM((DIAL *));
++int  DTrack                PARM((DIAL *, int, int));
+ 
+ 
+ /**************************** XVDIR.C ***************************/
+@@ -1376,15 +1683,15 @@
+ void TrackDDirW            PARM((int,int));
+ int  DirKey                PARM((int));
+ int  DoSave                PARM((void));
+-void SetDirFName           PARM((char *));
++void SetDirFName           PARM((const char *));
+ char *GetDirFName          PARM((void));
+ char *GetDirFullName       PARM((void));
+ void SetDirSaveMode        PARM((int, int));
+ int  Globify               PARM((char *));
+-FILE *OpenOutFile          PARM((char *));
+-int  CloseOutFile          PARM((FILE *, char *, int));
++FILE *OpenOutFile          PARM((const char *));
++int  CloseOutFile          PARM((FILE *, const char *, int));
+ 
+-byte *GenSavePic           PARM((int*, int*,int*, int*, int*, 
++byte *GenSavePic           PARM((int*, int*,int*, int*, int*,
+ 				 byte**, byte**, byte**));
+ void GetSaveSize           PARM((int *, int *));
+ 
+@@ -1392,47 +1699,30 @@
+ int  CheckPoll             PARM((int));
+ void DIRDeletedFile        PARM((char *));
+ void DIRCreatedFile        PARM((char *));
++FILE *pic2_OpenOutFile     PARM((char *, int *));
++void pic2_KillNullFile     PARM((FILE *));
++int  OpenOutFileDesc       PARM((char *));
+ 
+ 
+-/*************************** XVBROWSE.C ************************/
+-void CreateBrowse          PARM((char *, char *, char *, char *, char *));
+-void OpenBrowse            PARM((void));
+-void HideBrowseWindows     PARM((void));
+-void UnHideBrowseWindows   PARM((void));
+-void SetBrowseCursor       PARM((Cursor));
+-void KillBrowseWindows     PARM((void));
+-int  BrowseCheckEvent      PARM((XEvent *, int *, int *));
+-int  BrowseDelWin          PARM((Window));
+-void SetBrowStr            PARM((char *));
+-void RegenBrowseIcons      PARM((void));
+-void BRDeletedFile         PARM((char *));
+-void BRCreatedFile         PARM((char *));
+-
+-
+-/*************************** XVTEXT.C ************************/
+-void CreateTextWins        PARM((char *, char *));
+-void TextView              PARM((char *));
+-void OpenTextView          PARM((char *, int, char *, int));
+-
+-void OpenCommentText       PARM((void));
+-void CloseCommentText      PARM((void));
+-void ChangeCommentText     PARM((void));
+-
+-void ShowLicense           PARM((void));
+-void ShowKeyHelp           PARM((void));
+-
+-void HideTextWindows       PARM((void));
+-void UnHideTextWindows     PARM((void));
+-void RaiseTextWindows      PARM((void));
+-void SetTextCursor         PARM((Cursor));
+-void KillTextWindows       PARM((void));
+-int  TextCheckEvent        PARM((XEvent *, int *, int *));
+-int  TextDelWin            PARM((Window));
++/****************************** XVEVENT.C ****************************/
++int  EventLoop             PARM((void));
++int  HandleEvent           PARM((XEvent *, int *));
+ 
++void NewCutBuffer          PARM((char *));
++void DrawWindow            PARM((int,int,int,int));
++void WResize               PARM((int, int));
++void WRotate               PARM((void));
++void WCrop                 PARM((int, int, int, int));
++void WUnCrop               PARM((void));
++void GetWindowPos          PARM((XWindowAttributes *));
++void SetWindowPos          PARM((XWindowAttributes *));
++void SetEpicMode           PARM((void));
++int  xvErrorHandler        PARM((Display *, XErrorEvent *));
+ 
+ 
+ /**************************** XVGAM.C **************************/
+-void CreateGam             PARM((char *, double, double, double, double, int));
++void CreateGam             PARM((const char *, double, double, double, double,
++				 int));
+ int  GamCheckEvent         PARM((XEvent *));
+ void GamBox                PARM((int));
+ void NewCMap               PARM((void));
+@@ -1450,173 +1740,344 @@
+ byte *GammifyPic24         PARM((byte *, int, int));
+ void GamSetAutoApply       PARM((int));
+ 
+-/*************************** XVSCRL.C ***************************/
+-void SCCreate              PARM((SCRL *, Window, int, int, int, int, 
+-				 int, int, int, int, u_long, u_long, 
+-				 u_long, u_long, void (*)(int, SCRL *)));
+ 
+-void SCChange              PARM((SCRL *, int, int, int, int, int, 
+-				 int, int, int));
++/**************************** XVGRAB.C ***************************/
++int Grab                   PARM((void));
++int LoadGrab               PARM((PICINFO *));
+ 
+-void SCSetRange            PARM((SCRL *, int, int, int, int));
+-int  SCSetVal              PARM((SCRL *, int));
+-void SCRedraw              PARM((SCRL *));
+-void SCTrack               PARM((SCRL *, int, int));
+ 
++/**************************** XVGRAF.C ***************************/
++void   CreateGraf          PARM((GRAF *, Window, int, int,
++				 u_long, u_long, const char *));
+ 
+-/*************************** XVDIAL.C ***************************/
+-void DCreate               PARM((DIAL *, Window, int, int, int, int, int, 
+-				 int, int, int, u_long, u_long, u_long, 
+-				 u_long, char *, char *));
++void   InitGraf            PARM((GRAF *));
++void   RedrawGraf          PARM((GRAF *, int));
++int    ClickGraf           PARM((GRAF *, Window, int, int));
++int    GrafKey             PARM((GRAF *, char *));
++void   GenerateGrafFunc    PARM((GRAF *, int));
++void   Graf2Str            PARM((GRAF_STATE *, char *));
++int    Str2Graf            PARM((GRAF_STATE *, const char *));
++void   GetGrafState        PARM((GRAF *, GRAF_STATE *));
++int    SetGrafState        PARM((GRAF *, GRAF_STATE *));
++void   InitSpline          PARM((int *, int *, int, double *));
++double EvalSpline          PARM((int *, int *, double *, int, double));
+ 
+-void DSetRange             PARM((DIAL *, int, int, int, int));
+-void DSetVal               PARM((DIAL *, int));
+-void DSetActive            PARM((DIAL *, int));
+-void DRedraw               PARM((DIAL *));
+-int  DTrack                PARM((DIAL *, int, int));
+ 
++/*************************** XVIMAGE.C ***************************/
++void Resize                PARM((int, int));
++void GenerateCpic          PARM((void));
++void GenerateEpic          PARM((int, int));
++void DoZoom                PARM((int, int, u_int));
++void Crop                  PARM((void));
++void UnCrop                PARM((void));
++void AutoCrop              PARM((void));
++int  DoAutoCrop            PARM((void));
++void DoCrop                PARM((int, int, int, int));
++void Rotate                PARM((int));
++void DoRotate              PARM((int));
++void RotatePic             PARM((byte *, int, int *, int *, int));
++void Flip                  PARM((int));
++void FlipPic               PARM((byte *, int, int, int));
++void InstallNewPic         PARM((void));
++void DrawEpic              PARM((void));
++void KillOldPics           PARM((void));
+ 
+-/**************************** XVBUTT.C ***************************/
+-void BTCreate              PARM((BUTT *, Window, int, int, u_int, u_int, 
+-				 char *, u_long, u_long, u_long, u_long));
++byte *FSDither             PARM((byte *, int, int, int,
++				 byte *, byte *, byte *, int, int));
+ 
+-void BTSetActive           PARM((BUTT *, int));
+-void BTRedraw              PARM((BUTT *));
+-int  BTTrack               PARM((BUTT *));
++void CreateXImage          PARM((void));
++XImage *Pic8ToXImage       PARM((byte *, u_int, u_int, u_long *,
++				 byte *, byte *, byte *));
+ 
++XImage *Pic24ToXImage      PARM((byte *, u_int, u_int));
+ 
+-RBUTT *RBCreate            PARM((RBUTT *, Window, int, int, char *, 
+-				 u_long, u_long, u_long, u_long));
++void Set824Menus           PARM((int));
++void Change824Mode         PARM((int));
++void FreeEpic              PARM((void));
++void InvertPic24           PARM((byte *, int, int));
+ 
+-void   RBRedraw            PARM((RBUTT *, int));
+-void   RBSelect            PARM((RBUTT *, int));
+-int    RBWhich             PARM((RBUTT *));
+-int    RBCount             PARM((RBUTT *));
+-void   RBSetActive         PARM((RBUTT *, int, int));
+-int    RBClick             PARM((RBUTT *, int, int));
+-int    RBTrack             PARM((RBUTT *, int));
++byte *XVGetSubImage        PARM((byte *, int, int,int, int,int,int,int));
+ 
++int  DoPad                 PARM((int, char *, int, int, int, int));
++int  LoadPad               PARM((PICINFO *, char *));
+ 
+-void   CBCreate            PARM((CBUTT *, Window, int, int, char *, 
+-				 u_long, u_long, u_long, u_long));
+ 
+-void   CBRedraw            PARM((CBUTT *));
+-void   CBSetActive         PARM((CBUTT *, int));
+-int    CBClick             PARM((CBUTT *,int,int));
+-int    CBTrack             PARM((CBUTT *));
++/*************************** XVINFO.C ***************************/
++void  CreateInfo           PARM((const char *));
++void  InfoBox              PARM((int));
++void  RedrawInfo           PARM((int, int, int, int));
++void  SetInfoMode          PARM((int));
++char *GetISTR              PARM((int));
+ 
++#if defined(__STDC__) && !defined(NOSTDHDRS)
++void  SetISTR(int, ...);
++#else
++void  SetISTR();
++#endif
+ 
+-void   MBCreate            PARM((MBUTT *, Window, int, int, u_int, u_int, 
+-				 char *, 
+-				 char **, int,u_long,u_long, u_long, u_long));
+ 
+-void   MBRedraw            PARM((MBUTT *));
+-void   MBSetActive         PARM((MBUTT *, int));
+-int    MBWhich             PARM((MBUTT *));
+-void   MBSelect            PARM((MBUTT *, int));
+-int    MBClick             PARM((MBUTT *, int, int));
+-int    MBTrack             PARM((MBUTT *));
++/*************************** XVMISC.C ***************************/
++void StoreDeleteWindowProp PARM((Window));
++Window CreateWindow        PARM((const char *, const char *, const char *,
++				 int, int, u_long, u_long, int));
++void DrawString            PARM((Window, int, int, const char *));
++void CenterString          PARM((Window, int, int, const char *));
++void ULineString           PARM((Window, int, int, const char *));
++int  StringWidth           PARM((const char *));
++int  CursorKey             PARM((KeySym, int, int));
++void FakeButtonPress       PARM((BUTT *));
++void FakeKeyPress          PARM((Window, KeySym));
++void GenExpose             PARM((Window, int, int, u_int, u_int));
++void DimRect               PARM((Window, int, int, u_int, u_int, u_long));
++
++void Draw3dRect            PARM((Window, int, int, u_int, u_int, int, int,
++				 u_long, u_long, u_long));
++
++void RemapKeyCheck         PARM((KeySym, char *, int *));
++void xvDestroyImage        PARM((XImage *));
++void SetCropString         PARM((void));
++void SetSelectionString    PARM((void));
++void Warning               PARM((void));
++void FatalError            PARM((const char *));
++void Quit                  PARM((int));
++void LoadFishCursors       PARM((void));
++void WaitCursor            PARM((void));
++void SetCursors            PARM((int));
++const char *BaseName       PARM((const char *));
++
++void DrawTempGauge         PARM((Window, int, int, int, int, double, u_long,
++				 u_long, u_long, u_long, const char *));
++void ProgressMeter         PARM((int, int, int, const char *));
++void XVDeletedFile         PARM((char *));
++void XVCreatedFile         PARM((char *));
++void xvbcopy               PARM((const char *, char *, size_t));
++int  xvbcmp                PARM((const char *, const char *, size_t));
++void xvbzero               PARM((char *, size_t));
++void xv_getwd              PARM((char *, size_t));
++char *xv_strstr            PARM((const char *, const char *));
++FILE *xv_fopen             PARM((const char *, const char *));
++void xv_mktemp             PARM((char *, const char *));
++void Timer                 PARM((int));
+ 
+ 
+-/**************************** XVGRAF.C ***************************/
+-void   CreateGraf          PARM((GRAF *, Window, int, int, 
+-				 u_long, u_long, char *));
++/*************************** XVPOPUP.C ***************************/
++void  CenterMapWindow      PARM((Window, int, int, int, int));
++int   PopUp                PARM((const char *, const char **, int));
++void  ErrPopUp             PARM((const char *, const char *));
++int   GetStrPopUp          PARM((const char *, const char **, int, char *, int,
++				 const char *, int));
++int   GrabPopUp            PARM((int *, int *));
++int   PadPopUp             PARM((int *, char **, int *, int *, int *, int *));
++void  ClosePopUp           PARM((void));
++void  OpenAlert            PARM((const char *));
++void  CloseAlert           PARM((void));
++int   PUCheckEvent         PARM((XEvent *));
+ 
+-void   InitGraf            PARM((GRAF *));
+-void   RedrawGraf          PARM((GRAF *, int));
+-int    ClickGraf           PARM((GRAF *, Window, int, int));
+-int    GrafKey             PARM((GRAF *, char *));
+-void   GenerateGrafFunc    PARM((GRAF *, int));
+-void   Graf2Str            PARM((GRAF_STATE *, char *));
+-int    Str2Graf            PARM((GRAF_STATE *, char *));
+-void   GetGrafState        PARM((GRAF *, GRAF_STATE *));
+-int    SetGrafState        PARM((GRAF *, GRAF_STATE *));
+-void   InitSpline          PARM((int *, int *, int, double *));
+-double EvalSpline          PARM((int *, int *, double *, int, double));
+ 
++/**************************** XVROOT.C ****************************/
++void MakeRootPic           PARM((void));
++void ClearRoot             PARM((void));
++void SaveRootInfo          PARM((void));
++void KillOldRootInfo       PARM((void));
+ 
+-/**************************** XVGIF.C ***************************/
+-int LoadGIF                PARM((char *, PICINFO *));
+ 
+-/*************************** XVGIFWR.C **************************/
+-int WriteGIF               PARM((FILE *, byte *, int, int, int, 
+-				 byte *, byte *, byte *, int, int, char *));
++/*************************** XVSCRL.C ***************************/
++void SCCreate              PARM((SCRL *, Window, int, int, int, int,
++				 int, int, int, int, u_long, u_long,
++				 u_long, u_long, void (*)(int, SCRL *)));
+ 
+-/**************************** XVPM.C ****************************/
+-int LoadPM                 PARM((char *, PICINFO *));
+-int WritePM                PARM((FILE *, byte *, int, int, int, byte *, 
+-				 byte *, byte *, int, int, char *));
++void SCChange              PARM((SCRL *, int, int, int, int, int,
++				 int, int, int));
+ 
+-/**************************** XVPBM.C ***************************/
+-int LoadPBM                PARM((char *, PICINFO *));
+-int WritePBM               PARM((FILE *, byte *, int, int, int, byte *, 
+-				 byte *, byte *, int, int, int, char *));
++void SCSetRange            PARM((SCRL *, int, int, int, int));
++int  SCSetVal              PARM((SCRL *, int));
++void SCRedraw              PARM((SCRL *));
++void SCTrack               PARM((SCRL *, int, int));
+ 
+-/**************************** XVXBM.C ***************************/
+-int LoadXBM                PARM((char *, PICINFO *));
+-int WriteXBM               PARM((FILE *, byte *, int, int, byte *, byte *, 
+-				 byte *, char *));
+ 
+-/**************************** XVSUNRAS.C ***************************/
+-int LoadSunRas             PARM((char *, PICINFO *));
+-int WriteSunRas            PARM((FILE *, byte *, int, int, int, byte *, 
+-				 byte *, byte*, int, int, int));
++/*************************** XVSMOOTH.C ***************************/
++byte *SmoothResize         PARM((byte *, int, int, int, int, byte *, byte *,
++				 byte *, byte *, byte *, byte *, int));
+ 
+-/**************************** XVBMP.C ***************************/
+-int LoadBMP                PARM((char *, PICINFO *));
+-int WriteBMP               PARM((FILE *, byte *, int, int, int, byte *, 
+-				 byte *, byte *, int, int));
++byte *Smooth24             PARM((byte *, int, int, int, int, int,
++				 byte *, byte *, byte *));
+ 
+-/**************************** XVRLE.C ***************************/
+-int LoadRLE                PARM((char *, PICINFO *));
++byte *DoColorDither        PARM((byte *, byte *, int, int, byte *, byte *,
++				 byte *, byte *, byte *, byte *, int));
+ 
+-/**************************** XVIRIS.C ***************************/
+-int LoadIRIS               PARM((char *, PICINFO *));
+-int WriteIRIS              PARM((FILE *, byte *, int, int, int, byte *, 
+-				 byte *, byte *, int, int));
++byte *Do332ColorDither     PARM((byte *, byte *, int, int, byte *, byte *,
++				 byte *, byte *, byte *, byte *, int));
+ 
+-/**************************** XVPCX.C ***************************/
+-int LoadPCX                PARM((char *, PICINFO *));
+ 
+-/**************************** XVIFF.C ***************************/
+-int LoadIFF                PARM((char *, PICINFO *));
++/*************************** XVTEXT.C ************************/
++void CreateTextWins        PARM((const char *, const char *));
++int  TextView              PARM((const char *));
++void OpenTextView          PARM((const char *, int, const char *, int));
+ 
+-/**************************** XVTARGA.C ***************************/
+-int LoadTarga              PARM((char *, PICINFO *));
+-int WriteTarga             PARM((FILE *, byte *, int, int, int, byte *, 
+-				 byte *, byte *, int, int));
++void OpenCommentText       PARM((void));
++void CloseCommentText      PARM((void));
++void ChangeCommentText     PARM((void));
+ 
+-/**************************** XVXPM.C ***************************/
+-int LoadXPM                PARM((char *, PICINFO *));
+-int WriteXPM               PARM((FILE *, byte *, int, int, int, byte *, 
+-				 byte *, byte *, int, int, char *, char *));
++void ShowLicense           PARM((void));
++void ShowKeyHelp           PARM((void));
+ 
+-/**************************** XVXWD.C ***************************/
+-int LoadXWD                PARM((char *, PICINFO *));
++void HideTextWindows       PARM((void));
++void UnHideTextWindows     PARM((void));
++void RaiseTextWindows      PARM((void));
++void SetTextCursor         PARM((Cursor));
++void KillTextWindows       PARM((void));
++int  TextCheckEvent        PARM((XEvent *, int *, int *));
++int  TextDelWin            PARM((Window));
++
++int  CharsetCheckEvent     PARM((XEvent *));
++int  CharsetDelWin         PARM((Window));
++
++
++/**************************** XVVD.C ****************************/
++void  Vdinit               PARM((void));
++void  Vdsettle             PARM((void));
++int   Chvdir               PARM((char *));
++void  Dirtovd              PARM((char *));
++void  Vdtodir              PARM((char *));
++void  Dirtosubst           PARM((char *));
++int   Mkvdir               PARM((char *));
++void  Mkvdir_force         PARM((char *));
++int   Rmvdir               PARM((char *));
++int   Movevdir             PARM((char *, char *));
++int   Isarchive            PARM((char *));
++int   Isvdir               PARM((char *));
++void  vd_HUPhandler        PARM((void));
++void  vd_handler           PARM((int));
++int   vd_Xhandler          PARM((Display *, XErrorEvent *));
++int   vd_XIOhandler        PARM((Display *));
++void  vd_handler_setup     PARM((void));
++
++
++
++/*=======================================================================*/
++/*                             IMAGE FORMATS                             */
++/*=======================================================================*/
++
++/**************************** XVBMP.C ***************************/
++int LoadBMP                PARM((char *, PICINFO *));
++int WriteBMP               PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int));
+ 
+ /**************************** XVFITS.C ***************************/
+ int LoadFITS               PARM((char *, PICINFO *, int));
+ int WriteFITS              PARM((FILE *, byte *, int, int, int, byte *,
+ 				 byte *, byte *, int, int, char *));
+ 
++/**************************** XVGIF.C ***************************/
++int LoadGIF                PARM((char *, PICINFO *));
++
++/**************************** XVGIFWR.C **************************/
++int WriteGIF               PARM((FILE *, byte *, int, int, int,
++				 byte *, byte *, byte *, int, int, char *));
++
++/**************************** XVHIPS.C ***************************/
++int   LoadHIPS             PARM((char *, PICINFO *));
++
++/**************************** XVIFF.C ***************************/
++int LoadIFF                PARM((char *, PICINFO *));
++
++/**************************** XVIRIS.C ***************************/
++int LoadIRIS               PARM((char *, PICINFO *));
++int WriteIRIS              PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int));
++
++/**************************** XVJP2K.C ***************************/
++int  LoadJPC               PARM((char *, register PICINFO *, int));
++int  LoadJP2               PARM((char *, register PICINFO *, int));
++void CreateJP2KW           PARM((void));
++void JP2KSaveParams        PARM((int, char *, int));
++void JP2KDialog            PARM((int vis));
++int  JP2KCheckEvent        PARM((register XEvent *));
++void VersionInfoJP2K       PARM((void));		/* GRR 20070304 */
++
+ /**************************** XVJPEG.C ***************************/
+ int  LoadJFIF              PARM((char *, PICINFO *, int));
+ void CreateJPEGW           PARM((void));
+ void JPEGDialog            PARM((int));
+ int  JPEGCheckEvent        PARM((XEvent *));
+ void JPEGSaveParams        PARM((char *, int));
++void VersionInfoJPEG       PARM((void));		/* GRR 19980605 */
+ 
+-/**************************** XVTIFF.C ***************************/
+-int   LoadTIFF             PARM((char *, PICINFO *));
+-void  CreateTIFFW          PARM((void));
+-void  TIFFDialog           PARM((int));
+-int   TIFFCheckEvent       PARM((XEvent *));
+-void  TIFFSaveParams       PARM((char *, int));
++/**************************** XVMAG.C ***************************/
++int   LoadMAG              PARM((char *, PICINFO *));
++int   WriteMAG             PARM((FILE *, byte *, int, int, int,
++				 byte *, byte *, byte *, int, int, char *));
++
++/**************************** XVMAKI.C ***************************/
++int   LoadMAKI             PARM((char *, PICINFO *));
++int   WriteMAKI            PARM((FILE *, byte *, int, int, int,
++				 byte *, byte *, byte *, int, int));
++
++/**************************** XVMGCSFX.C ***************************/
++int   is_mgcsfx            PARM((char *, unsigned char *, int));
++char *mgcsfx_auto_input_com PARM((char *));
++int   LoadMGCSFX           PARM((char *, PICINFO *));
++void  CreateMGCSFXW        PARM((void));
++void  MGCSFXDialog         PARM((int));
++int   MGCSFXCheckEvent     PARM((XEvent *));
++int   MGCSFXSaveParams     PARM((char *, int));
++
++int getInputCom            PARM((void));
++int getOutputCom           PARM((void));
++
++/**************************** XVPBM.C ***************************/
++#ifdef HAVE_MGCSFX
++int LoadPBM                PARM((char *, PICINFO *, int));
++#else
++int LoadPBM                PARM((char *, PICINFO *));
++#endif
++int WritePBM               PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int, int, char *));
++
++/**************************** XVPCD.C ***************************/
++int   LoadPCD              PARM((char *, PICINFO *, int));
++void  CreatePCDW           PARM((void));
++void  PCDDialog            PARM((int));
++int   PCDCheckEvent        PARM((XEvent *));
++void  PCDSetParamOptions   PARM((const char *));
++
++/**************************** XVPCX.C ***************************/
++int LoadPCX                PARM((char *, PICINFO *));
+ 
+ /**************************** XVPDS.C ***************************/
+ int LoadPDS                PARM((char *, PICINFO *));
+ 
+-/*************************** XVPS.C ***************************/
++/**************************** XVPI.C ***************************/
++int   LoadPi               PARM((char *, PICINFO *));
++int   WritePi              PARM((FILE *, byte *, int, int, int,
++				 byte *, byte *, byte *, int, int, char *));
++
++/**************************** XVPIC.C ***************************/
++int   LoadPIC              PARM((char *, PICINFO *));
++int   WritePIC             PARM((FILE *, byte *, int, int, int,
++				 byte *, byte *, byte *, int, int, char *));
++
++/**************************** XVPIC2.C ***************************/
++int   LoadPIC2             PARM((char *, PICINFO *, int));
++void  CreatePIC2W          PARM((void));
++void  PIC2Dialog           PARM((int));
++int   PIC2CheckEvent       PARM((XEvent *));
++int   PIC2SetParamOptions  PARM((char *));
++
++/**************************** XVPM.C ****************************/
++int LoadPM                 PARM((char *, PICINFO *));
++int WritePM                PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int, char *));
++
++/**************************** XVPNG.C ***************************/
++int  LoadPNG               PARM((char *, PICINFO *));
++void CreatePNGW            PARM((void));
++void PNGDialog             PARM((int));
++int  PNGCheckEvent         PARM((XEvent *));
++void PNGSaveParams         PARM((char *, int));
++void VersionInfoPNG        PARM((void));		/* GRR 19980605 */
++
++/**************************** XVPS.C ****************************/
+ void  CreatePSD            PARM((char *));
+ void  PSDialog             PARM((int));
+ int   PSCheckEvent         PARM((XEvent *));
+@@ -1624,56 +2085,46 @@
+ void  PSResize             PARM((void));
+ int   LoadPS               PARM((char *, PICINFO *, int));
+ 
+-/*************************** XVPOPUP.C ***************************/
+-void  CenterMapWindow      PARM((Window, int, int, int, int));
+-int   PopUp                PARM((char *, char **, int));
+-void  ErrPopUp             PARM((char *, char *));
+-int   GetStrPopUp          PARM((char *, char **, int, char *, int, 
+-				 char *, int));
+-int   GrabPopUp            PARM((int *, int *));
+-int   PadPopUp             PARM((int *, char **, int *, int *, int *, int *));
+-void  ClosePopUp           PARM((void));
+-void  OpenAlert            PARM((char *));
+-void  CloseAlert           PARM((void));
+-int   PUCheckEvent         PARM((XEvent *));
+-void  TextRect             PARM((Window, char *, int, int, int, int, u_long));
++/**************************** XVRLE.C ***************************/
++int LoadRLE                PARM((char *, PICINFO *));
+ 
+-/*************************** XVDFLT.C ***************************/
+-void LoadDfltPic           PARM((PICINFO *));
+-void xbm2pic               PARM((byte *, int, int, byte *, int, int, int, int,
+-				 int));
+-void DrawStr2Pic           PARM((char *, int, int, byte *, int, int, int));
++/**************************** XVSUNRAS.C ***************************/
++int LoadSunRas             PARM((char *, PICINFO *));
++int WriteSunRas            PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte*, int, int, int));
+ 
+-/**************************** XVGRAB.C ***************************/
+-int Grab                   PARM((void));
+-int LoadGrab               PARM((PICINFO *));
++/**************************** XVTARGA.C ***************************/
++int LoadTarga              PARM((char *, PICINFO *));
++int WriteTarga             PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int));
+ 
++/**************************** XVTIFF.C ***************************/
++int   LoadTIFF             PARM((char *, PICINFO *, int));
++void  CreateTIFFW          PARM((void));
++void  TIFFDialog           PARM((int));
++int   TIFFCheckEvent       PARM((XEvent *));
++void  TIFFSaveParams       PARM((char *, int));
++void  VersionInfoTIFF      PARM((void));		/* GRR 19980605 */
+ 
+-/**************************** XVCUT.C ***************************/
+-int  CutAllowed            PARM((void));
+-int  PasteAllowed          PARM((void));
+-void DoImgCopy             PARM((void));
+-void DoImgCut              PARM((void));
+-void DoImgClear            PARM((void));
+-void DoImgPaste            PARM((void));
++/**************************** XVWBMP.C ***************************/
++int LoadWBMP               PARM((char *, PICINFO *));
++int WriteWBMP              PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int));
+ 
+-void SaveToClip            PARM((byte *));
+-void InitSelection         PARM((void));
+-int  HaveSelection         PARM((void));
+-int  GetSelType            PARM((void));
+-void GetSelRCoords         PARM((int *, int *, int *, int *));
+-void EnableSelection       PARM((int));
+-void DrawSelection         PARM((int));
+-int  DoSelection           PARM((XButtonEvent *));
+-void MoveGrowSelection     PARM((int, int, int, int));
+-void BlinkSelection        PARM((int));
+-void FlashSelection        PARM((int));
++/**************************** XVXBM.C ***************************/
++int LoadXBM                PARM((char *, PICINFO *));
++int WriteXBM               PARM((FILE *, byte *, int, int, byte *, byte *,
++				 byte *, char *));
+ 
+-void CropRect2Rect         PARM((int*,int*,int*,int*, int,int,int,int));
+-void CoordE2C              PARM((int, int, int *, int *));
+-void CoordC2E              PARM((int, int, int *, int *));
+-void CoordP2C              PARM((int, int, int *, int *));
+-void CoordC2P              PARM((int, int, int *, int *));
+-void CoordP2E              PARM((int, int, int *, int *));
+-void CoordE2P              PARM((int, int, int *, int *));
++/**************************** XVXPM.C ***************************/
++int LoadXPM                PARM((char *, PICINFO *));
++int WriteXPM               PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int, char *, char *));
+ 
++/**************************** XVXWD.C ***************************/
++int LoadXWD                PARM((char *, PICINFO *));
++
++/**************************** XVZX.C [JCE] **********************/
++int LoadZX                 PARM((char *, PICINFO *));
++int WriteZX                PARM((FILE *, byte *, int, int, int, byte *,
++				 byte *, byte *, int, int, char *));
+diff -ru xv-3.10a/xv24to8.c xv-3.10a-enhancements/xv24to8.c
+--- xv-3.10a/xv24to8.c	1995-01-13 11:49:21.000000000 -0800
++++ xv-3.10a-enhancements/xv24to8.c	2007-05-12 13:56:44.000000000 -0700
+@@ -14,15 +14,15 @@
+  *
+  * The Conv24to8 procedure will set up the following:  it will allocate, make
+  * & return 'pic8', a 'w' by 'h' (passed in values) 8-bit picture.
+- * it will load up the rmap, gmap and bmap colormap arrays.  it will NOT 
++ * it will load up the rmap, gmap and bmap colormap arrays.  it will NOT
+  * calculate numcols, since the cmap sort procedure has to be called anyway
+  *
+- * Conv24to8 returns 'pic8' if successful, 'NULL' on failure (presumably on a 
++ * Conv24to8 returns 'pic8' if successful, 'NULL' on failure (presumably on a
+  * malloc())
+  *
+- * The 'slow' code, while still based on Heckbert's Median Cut algorithm, 
++ * The 'slow' code, while still based on Heckbert's Median Cut algorithm,
+  * has been shamelessly lifted from the Independent JPEG Group's software
+- * (jquant2.c), as (for a variety of reasons) theirs was far better than 
++ * (jquant2.c), as (for a variety of reasons) theirs was far better than
+  * the version I was previously using.  Thanks guys!
+  *
+  * Also, as is my way, I've stripped out most of the IJG's well-written
+@@ -65,10 +65,10 @@
+ {
+   /* returns pointer to new 8-bit-per-pixel image (w*h) if successful, or
+      NULL if unsuccessful */
+-  
++
+   int   i;
+   byte *pic8;
+-  
++
+   if (!pic24) return NULL;
+ 
+   pic8 = (byte *) malloc((size_t) (w * h));
+@@ -79,9 +79,9 @@
+ 
+   if (nc<=0) nc = 255;  /* 'nc == 0' breaks code */
+ 
+-  if (!noqcheck && quick_check(pic24, w,h, pic8, rm,gm,bm, nc)) { 
++  if (!noqcheck && quick_check(pic24, w,h, pic8, rm,gm,bm, nc)) {
+     SetISTR(ISTR_INFO,"No color compression was necessary.\n");
+-    return pic8;   
++    return pic8;
+   }
+ 
+   switch (conv24) {
+@@ -89,19 +89,19 @@
+     SetISTR(ISTR_INFO,"Doing 'quick' 24-bit to 8-bit conversion.");
+     i = quick_quant(pic24, w, h, pic8, rm, gm, bm, nc);
+     break;
+-    
++
+   case CONV24_BEST:
+     SetISTR(ISTR_INFO,"Doing 'best' 24-bit to 8-bit conversion.");
+     i = ppm_quant(pic24, w, h, pic8, rm, gm, bm, nc);
+     break;
+-    
++
+   case CONV24_SLOW:
+   default:
+     SetISTR(ISTR_INFO,"Doing 'slow' 24-bit to 8-bit conversion.");
+     i = slow_quant(pic24, w, h, pic8, rm, gm, bm, nc);
+     break;
+   }
+-  
++
+   if (i) { free(pic8);  pic8 = NULL; }
+   return pic8;
+ }
+@@ -134,7 +134,7 @@
+ 
+   return pic24;
+ }
+-  
++
+ 
+ /****************************/
+ static int quick_check(pic24, w,h, pic8, rmap,gmap,bmap, maxcol)
+@@ -154,10 +154,10 @@
+   if (maxcol>256) maxcol = 256;
+ 
+   /* put the first color in the table by hand */
+-  nc = 0;  mid = 0;  
++  nc = 0;  mid = 0;
+ 
+   for (i=w*h,p=pic24; i; i--) {
+-    col  = (((u_long) *p++) << 16);  
++    col  = (((u_long) *p++) << 16);
+     col += (((u_long) *p++) << 8);
+     col +=  *p++;
+ 
+@@ -184,7 +184,7 @@
+      pic24 into colormap offsets into 'colors' */
+ 
+   for (i=w*h,p=pic24, pix=pic8; i; i--,pix++) {
+-    col  = (((u_long) *p++) << 16);  
++    col  = (((u_long) *p++) << 16);
+     col += (((u_long) *p++) << 8);
+     col +=  *p++;
+ 
+@@ -206,7 +206,7 @@
+ 
+   /* and load up the 'desired colormap' */
+   for (i=0; i<nc; i++) {
+-    rmap[i] =  colors[i]>>16;  
++    rmap[i] =  colors[i]>>16;
+     gmap[i] = (colors[i]>>8) & 0xff;
+     bmap[i] =  colors[i]     & 0xff;
+   }
+@@ -224,7 +224,7 @@
+ {
+   /* called after 'pic8' has been alloced, pWIDE,pHIGH set up, mono/1-bit
+      checked already */
+-  
++
+ /* up to 256 colors:     3 bits R, 3 bits G, 2 bits B  (RRRGGGBB) */
+ #define RMASK      0xe0
+ #define RSHIFT        0
+@@ -252,7 +252,7 @@
+     gmap[i] = (((i<<GSHIFT) & GMASK) * 255 + GMASK/2) / GMASK;
+     bmap[i] = (((i<<BSHIFT) & BMASK) * 255 + BMASK/2) / BMASK;
+   }
+-  
++
+ 
+   thisline = (int *) malloc(pwide3 * sizeof(int));
+   nextline = (int *) malloc(pwide3 * sizeof(int));
+@@ -262,40 +262,40 @@
+     fprintf(stderr,"%s: unable to allocate memory in quick_quant()\n", cmd);
+     return(1);
+   }
+-  
++
+   /* get first line of picture */
+   for (j=pwide3, tmpptr=nextline; j; j--) *tmpptr++ = (int) *p24++;
+-  
++
+   for (i=0; i<h; i++) {
+     tmpptr = thisline;  thisline = nextline;  nextline = tmpptr;   /* swap */
+-    
++
+     if ((i&0x3f) == 0) WaitCursor();
+ 
+     if (i!=imax)   /* get next line */
+       for (j=pwide3, tmpptr=nextline; j; j--)
+ 	*tmpptr++ = (int) *p24++;
+-    
++
+     for (j=0, thisptr=thisline, nextptr=nextline; j<w; j++,pp++) {
+       r1 = *thisptr++;  g1 = *thisptr++;  b1 = *thisptr++;
+-      RANGE(r1,0,255);  RANGE(g1,0,255);  RANGE(b1,0,255);  
+-      
++      RANGE(r1,0,255);  RANGE(g1,0,255);  RANGE(b1,0,255);
++
+       /* choose actual pixel value */
+-      val = (((r1&RMASK)>>RSHIFT) | ((g1&GMASK)>>GSHIFT) | 
++      val = (((r1&RMASK)>>RSHIFT) | ((g1&GMASK)>>GSHIFT) |
+ 	     ((b1&BMASK)>>BSHIFT));
+       *pp = val;
+-      
++
+       /* compute color errors */
+       r1 -= rmap[val];
+       g1 -= gmap[val];
+       b1 -= bmap[val];
+-      
++
+       /* Add fractions of errors to adjacent pixels */
+       if (j!=jmax) {  /* adjust RIGHT pixel */
+ 	thisptr[0] += (r1*7) / 16;
+ 	thisptr[1] += (g1*7) / 16;
+ 	thisptr[2] += (b1*7) / 16;
+       }
+-      
++
+       if (i!=imax) {	/* do BOTTOM pixel */
+ 	nextptr[0] += (r1*5) / 16;
+ 	nextptr[1] += (g1*5) / 16;
+@@ -316,7 +316,7 @@
+       }
+     }
+   }
+-  
++
+   free(thisline);
+   free(nextline);
+   return 0;
+@@ -329,7 +329,7 @@
+ #undef BMASK
+ #undef BSHIFT
+ }
+-      
++
+ 
+ 
+ 
+@@ -381,7 +381,7 @@
+ 
+ /* Luminance macro. */
+ 
+-/* 
++/*
+  * #define PPM_LUMIN(p) \
+  *   ( 0.299 * PPM_GETR(p) + 0.587 * PPM_GETG(p) + 0.114 * PPM_GETB(p) )
+  */
+@@ -449,18 +449,18 @@
+      byte *pic24, *pic8, *rmap, *gmap, *bmap;
+      int  cols, rows, newcolors;
+ {
+-  pixel**          pixels;
+-  register pixel*  pP;
+-  int              row;
+-  register int     col, limitcol;
+-  pixval           maxval, newmaxval;
+-  int              colors;
+-  register int     index;
+-  chist_vec chv, colormap;
+-  chash_table  cht;
+-  int              i;
+-  unsigned char    *picptr;
+-  static char      *fn = "ppmquant()";
++  pixel**           pixels;
++  register pixel*   pP;
++  int               row;
++  register int      col, limitcol;
++  pixval            maxval, newmaxval;
++  int               colors;
++  register int      index;
++  chist_vec         chv, colormap;
++  chash_table       cht;
++  int               i;
++  unsigned char     *picptr;
++  static const char *fn = "ppmquant()";
+ 
+   index = 0;
+   maxval = 255;
+@@ -472,7 +472,7 @@
+ 
+   if (DEBUG) fprintf(stderr,"%s: remapping to ppm-style internal fmt\n", fn);
+   WaitCursor();
+-  
++
+   pixels = (pixel **) malloc(rows * sizeof(pixel *));
+   if (!pixels) FatalError("couldn't allocate 'pixels' array");
+   for (row=0; row<rows; row++) {
+@@ -488,7 +488,7 @@
+   if (DEBUG) fprintf(stderr,"%s: done format remapping\n", fn);
+ 
+ 
+-    
++
+ 
+   /*
+    *  attempt to make a histogram of the colors, unclustered.
+@@ -503,7 +503,7 @@
+ 
+     chv = ppm_computechist(pixels, cols, rows, MAXCOLORS, &colors);
+     if (chv != (chist_vec) 0) break;
+-    
++
+     if (DEBUG) fprintf(stderr, "%s: too many colors!\n", fn);
+     newmaxval = maxval / 2;
+     if (DEBUG) fprintf(stderr, "%s: rescaling colors (maxval=%d) %s\n",
+@@ -635,7 +635,7 @@
+   int boxes;
+ 
+   bv = (box_vector) malloc(sizeof(struct box) * newcolors);
+-  colormap = (chist_vec) 
++  colormap = (chist_vec)
+              malloc(sizeof(struct chist_item) * newcolors );
+ 
+   if (!bv || !colormap) FatalError("unable to malloc in mediancut()");
+@@ -723,7 +723,7 @@
+       else if (gl >= bl)
+ 	qsort((char*) &(chv[indx]), (size_t) clrs, sizeof(struct chist_item),
+ 	      greencompare );
+-      else 
++      else
+ 	qsort((char*) &(chv[indx]), (size_t) clrs, sizeof(struct chist_item),
+ 	      bluecompare );
+     }
+@@ -750,7 +750,7 @@
+     ++boxes;
+     qsort((char*) bv, (size_t) boxes, sizeof(struct box), sumcompare);
+   }  /* while (boxes ... */
+-  
++
+   /*
+    ** Ok, we've got enough boxes.  Now choose a representative color for
+    ** each box.  There are a number of possible ways to make this choice.
+@@ -761,7 +761,7 @@
+    ** method is used by switching the commenting on the REP_ defines at
+    ** the beginning of this source file.
+    */
+-  
++
+   for (bi=0; bi<boxes; bi++) {
+     /* REP_AVERAGE_PIXELS version */
+     register int indx = bv[bi].index;
+@@ -791,7 +791,7 @@
+ static int redcompare(p1, p2)
+      const void *p1, *p2;
+ {
+-  return (int) PPM_GETR( ((chist_vec)p1)->color ) - 
++  return (int) PPM_GETR( ((chist_vec)p1)->color ) -
+          (int) PPM_GETR( ((chist_vec)p2)->color );
+ }
+ 
+@@ -799,7 +799,7 @@
+ static int greencompare(p1, p2)
+      const void *p1, *p2;
+ {
+-  return (int) PPM_GETG( ((chist_vec)p1)->color ) - 
++  return (int) PPM_GETG( ((chist_vec)p1)->color ) -
+          (int) PPM_GETG( ((chist_vec)p2)->color );
+ }
+ 
+@@ -807,7 +807,7 @@
+ static int bluecompare(p1, p2)
+      const void *p1, *p2;
+ {
+-  return (int) PPM_GETB( ((chist_vec)p1)->color ) - 
++  return (int) PPM_GETB( ((chist_vec)p1)->color ) -
+          (int) PPM_GETB( ((chist_vec)p2)->color );
+ }
+ 
+@@ -821,7 +821,7 @@
+ 
+ 
+ /****************************************************************************/
+-static chist_vec 
++static chist_vec
+   ppm_computechist(pixels, cols, rows, maxcolors, colorsP)
+      pixel** pixels;
+      int cols, rows, maxcolors;
+@@ -840,7 +840,7 @@
+ 
+ 
+ /****************************************************************************/
+-static chash_table ppm_computechash(pixels, cols, rows, 
++static chash_table ppm_computechash(pixels, cols, rows,
+ 					    maxcolors, colorsP )
+      pixel** pixels;
+      int cols, rows, maxcolors;
+@@ -861,14 +861,14 @@
+ 
+       for (chl = cht[hash]; chl != (chist_list) 0; chl = chl->next)
+ 	if (PPM_EQUAL(chl->ch.color, *pP)) break;
+-      
++
+       if (chl != (chist_list) 0) ++(chl->ch.value);
+       else {
+ 	if ((*colorsP)++ > maxcolors) {
+ 	  ppm_freechash(cht);
+ 	  return (chash_table) 0;
+ 	}
+-	
++
+ 	chl = (chist_list) malloc(sizeof(struct chist_list_item));
+ 	if (!chl) FatalError("ran out of memory computing hash table");
+ 
+@@ -878,7 +878,7 @@
+ 	cht[hash] = chl;
+       }
+     }
+-  
++
+   return cht;
+ }
+ 
+@@ -1114,7 +1114,7 @@
+   register int i;
+   register long maxc = 0;
+   boxptr which = NULL;
+-  
++
+   for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+     if (boxp->colorcount > maxc && boxp->volume > 0) {
+       which = boxp;
+@@ -1133,7 +1133,7 @@
+   register int i;
+   register INT32 maxv = 0;
+   boxptr which = NULL;
+-  
++
+   for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+     if (boxp->volume > maxv) {
+       which = boxp;
+@@ -1153,11 +1153,11 @@
+   int c0min,c0max,c1min,c1max,c2min,c2max;
+   INT32 dist0,dist1,dist2;
+   long ccount;
+-  
++
+   c0min = boxp->c0min;  c0max = boxp->c0max;
+   c1min = boxp->c1min;  c1max = boxp->c1max;
+   c2min = boxp->c2min;  c2max = boxp->c2max;
+-  
++
+   if (c0max > c0min)
+     for (c0 = c0min; c0 <= c0max; c0++)
+       for (c1 = c1min; c1 <= c1max; c1++) {
+@@ -1229,7 +1229,7 @@
+   dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
+   dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
+   boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+-  
++
+   ccount = 0;
+   for (c0 = c0min; c0 <= c0max; c0++)
+     for (c1 = c1min; c1 <= c1max; c1++) {
+@@ -1315,11 +1315,11 @@
+   long c0total = 0;
+   long c1total = 0;
+   long c2total = 0;
+-  
++
+   c0min = boxp->c0min;  c0max = boxp->c0max;
+   c1min = boxp->c1min;  c1max = boxp->c1max;
+   c2min = boxp->c2min;  c2max = boxp->c2max;
+-  
++
+   for (c0 = c0min; c0 <= c0max; c0++)
+     for (c1 = c1min; c1 <= c1max; c1++) {
+       histp = & histogram[c0][c1][c2min];
+@@ -1332,7 +1332,7 @@
+ 	}
+       }
+     }
+-  
++
+   sl_colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
+   sl_colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
+   sl_colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+@@ -1505,12 +1505,12 @@
+   bptr = bestdist;
+   for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+     *bptr++ = 0x7FFFFFFFL;
+-  
++
+   /* Nominal steps between cell centers ("x" in Thomas article) */
+ #define STEP_C0  ((1 << C0_SHIFT) * C0_SCALE)
+ #define STEP_C1  ((1 << C1_SHIFT) * C1_SCALE)
+ #define STEP_C2  ((1 << C2_SHIFT) * C2_SCALE)
+-  
++
+   for (i = 0; i < numcolors; i++) {
+     icolor = colorlist[i];
+     /* Compute (square of) distance from minc0/c1/c2 to this color */
+@@ -1576,7 +1576,7 @@
+   minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
+   minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
+   minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
+-  
++
+   numcolors = find_nearby_colors(minc0, minc1, minc2, colorlist);
+ 
+   /* Determine the actually nearest colors. */
+diff -ru xv-3.10a/xvalg.c xv-3.10a-enhancements/xvalg.c
+--- xv-3.10a/xvalg.c	1994-12-22 14:34:47.000000000 -0800
++++ xv-3.10a-enhancements/xvalg.c	2007-05-12 16:07:37.000000000 -0700
+@@ -38,7 +38,7 @@
+ 				 double, int));
+ static void doPixel        PARM((byte *,int,int,byte *, int,int,int,int,
+ 				 int, int));
+-static void doSpread       PARM((byte *,int,int,byte *, int,int,int,int, 
++static void doSpread       PARM((byte *,int,int,byte *, int,int,int,int,
+ 				 int, int));
+ static void doMedianFilter PARM((byte *,int,int,byte *, int,int,int,int, int));
+ 
+@@ -53,7 +53,7 @@
+ static int  start24bitAlg  PARM((byte **, byte **));
+ static void end24bitAlg    PARM((byte *, byte *));
+ 
+-static void printUTime     PARM((char *));
++static void printUTime     PARM((const char *));
+ 
+ static byte *origPic = (byte *) NULL;
+ static int  origPicType;
+@@ -70,10 +70,11 @@
+ 
+ /***************************/
+ static void printUTime(str)
+-     char *str;
++     const char *str;
+ {
+ #ifdef TIMING_TEST
+-  int i;  struct rusage ru;
++  int i;
++  struct rusage ru;
+ 
+   i = getrusage(RUSAGE_SELF, &ru);
+   fprintf(stderr,"%s: utime = %d.%d seconds\n",
+@@ -89,7 +90,7 @@
+ /************************************************************/
+ void AlgInit()
+ {
+-  /* called whenver an image file is loaded.  disposes of origPic 
++  /* called whenver an image file is loaded.  disposes of origPic
+      if neccessary, and points it to null */
+ 
+   if (origPic) free(origPic);
+@@ -160,16 +161,16 @@
+ {
+   /* runs a n*n convolution mask (all 1's) over 'pic',
+      producing a 24-bit version.  Then calls 24to8 to generate a new 8-bit
+-     image, and installs it. 
++     image, and installs it.
+ 
+      Note that 'n' must be odd for things to work properly */
+ 
+-  byte        *pic24, *tmpPic;
+-  int          i, sx,sy,sw,sh, n;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char         txt[256];
+-  static char  buf[64] = { '3', '\0' };
+-  
++  byte              *pic24, *tmpPic;
++  int                i, sx,sy,sw,sh, n;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               txt[256];
++  static char        buf[64] = { '3', '\0' };
++
+   sprintf(txt, "Blur:                                   \n\n%s",
+ 	  "Enter mask size (ex. 3, 5, 7, ...)");
+ 
+@@ -178,7 +179,7 @@
+   n = atoi(buf);
+ 
+   if (n < 1 || (n&1)!=1) {
+-    ErrPopUp("Error:  The value entered must be odd and greater than zero.", 
++    ErrPopUp("Error:  The value entered must be odd and greater than zero.",
+ 	     "\nOh!");
+     return;
+   }
+@@ -194,7 +195,7 @@
+ 
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+   xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3));
+-    
++
+   doBlurConvolv(pic24, pWIDE,pHIGH, tmpPic, sx,sy,sw,sh, n);
+ 
+   end24bitAlg(pic24, tmpPic);
+@@ -207,12 +208,12 @@
+ {
+   /* runs an edge-enhancment algorithm */
+ 
+-  byte        *pic24, *tmpPic;
+-  int          i, sx,sy,sw,sh, n;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char         txt[256];
+-  static char  buf[64] = { '7', '5', '\0' };
+-  
++  byte              *pic24, *tmpPic;
++  int                i, sx,sy,sw,sh, n;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               txt[256];
++  static char        buf[64] = { '7', '5', '\0' };
++
+   sprintf(txt, "Sharpen:                                   \n\n%s",
+ 	  "Enter enhancement factor (0-99%)");
+ 
+@@ -236,7 +237,7 @@
+ 
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+   xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3));
+-    
++
+   doSharpConvolv(pic24, pWIDE,pHIGH, tmpPic, sx,sy,sw,sh, n);
+ 
+   end24bitAlg(pic24, tmpPic);
+@@ -248,7 +249,7 @@
+ static void EdgeDetect()
+ {
+   byte *pic24, *p24, *tmpPic, *tlp;
+-  char *str;
++  const char *str;
+   int  i, j, v, maxv, sx,sy,sw,sh;
+ 
+   WaitCursor();
+@@ -264,7 +265,7 @@
+   xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3));
+ 
+   doEdgeConvolv(pic24, pWIDE, pHIGH, tmpPic, sx,sy,sw,sh);
+-  
++
+   SetISTR(ISTR_INFO, "%snormalizing...", str);
+ 
+   /* Normalize results */
+@@ -292,19 +293,19 @@
+ /************************/
+ static void TinFoil()
+ {
+-  byte *pic24, *p24, *tmpPic, *tp, *tlp;
+-  char *str;
+-  int  i, j, v, maxv,sx,sy,sw,sh;
+-  
++  byte *pic24, *tmpPic, *tp, *tlp;
++  const char *str;
++  int  i, j, v, sx,sy,sw,sh;
++
+   WaitCursor();
+-  
++
+   str = "Doing cheesy embossing effect...";
+   SetISTR(ISTR_INFO, str);
+-  
++
+   if (HaveSelection()) GetSelRCoords(&sx,&sy,&sw,&sh);
+   else { sx = 0;  sy = 0;  sw = pWIDE;  sh = pHIGH; }
+   CropRect2Rect(&sx,&sy,&sw,&sh, 0,0,pWIDE,pHIGH);
+-  
++
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+   xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3));
+ 
+@@ -315,9 +316,9 @@
+       *tp++ = 128;  *tp++ = 128;  *tp++ = 128;
+     }
+   }
+-  
++
+   doAngleConvolv(pic24, pWIDE, pHIGH, tmpPic, sx,sy,sw,sh);
+-  
++
+   /* mono-ify selected area of tmpPic */
+   for (i=sy; i<sy+sh; i++) {
+     tp = tlp = tmpPic + (i*pWIDE + sx) * 3;
+@@ -327,9 +328,9 @@
+       tp[0] = tp[1] = tp[2] = (byte) v;
+     }
+   }
+-    
++
+   end24bitAlg(pic24, tmpPic);
+-}  
++}
+ 
+ 
+ /************************/
+@@ -345,7 +346,7 @@
+   if (HaveSelection()) GetSelRCoords(&sx,&sy,&sw,&sh);
+   else { sx = 0;  sy = 0;  sw = pWIDE;  sh = pHIGH; }
+   CropRect2Rect(&sx,&sy,&sw,&sh, 0,0,pWIDE,pHIGH);
+-  
++
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+   xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3));
+ 
+@@ -365,7 +366,7 @@
+   if (HaveSelection()) GetSelRCoords(&sx,&sy,&sw,&sh);
+   else { sx = 0;  sy = 0;  sw = pWIDE;  sh = pHIGH; }
+   CropRect2Rect(&sx,&sy,&sw,&sh, 0,0,pWIDE,pHIGH);
+-  
++
+   WaitCursor();
+ 
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+@@ -381,12 +382,12 @@
+ static void FineRotate(clr)
+      int clr;
+ {
+-  byte        *pic24, *tmpPic;
+-  int          i,sx,sy,sw,sh;
+-  double       rotval;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char         txt[256];
+-  static char  buf[64] = { '\0' };
++  byte              *pic24, *tmpPic;
++  int                i,sx,sy,sw,sh;
++  double             rotval;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               txt[256];
++  static char        buf[64] = { '\0' };
+ 
+   sprintf(txt, "Rotate (%s):\n\nEnter rotation angle, in degrees:  (>0 = CCW)",
+ 	  (clr ? "Clear" : "Copy"));
+@@ -396,12 +397,12 @@
+   rotval = atof(buf);
+ 
+   if (rotval == 0.0) return;
+-  
++
+ 
+   if (HaveSelection()) GetSelRCoords(&sx,&sy,&sw,&sh);
+   else { sx = 0;  sy = 0;  sw = pWIDE;  sh = pHIGH; }
+   CropRect2Rect(&sx,&sy,&sw,&sh, 0,0,pWIDE,pHIGH);
+-  
++
+   WaitCursor();
+ 
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+@@ -416,11 +417,11 @@
+ /************************/
+ static void Pixelize()
+ {
+-  byte        *pic24, *tmpPic;
+-  int          i,sx,sy,sw,sh, pixX,pixY,err;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char         txt[256];
+-  static char  buf[64] = { '4', '\0' };
++  byte              *pic24, *tmpPic;
++  int                i,sx,sy,sw,sh, pixX,pixY,err;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               txt[256];
++  static char        buf[64] = { '4', '\0' };
+ 
+   sprintf(txt, "Pixelize:\n\nEnter new pixel size, in image pixels:  %s",
+ 	  "(ex. '3', '5x8')");
+@@ -443,11 +444,11 @@
+     return;
+   }
+ 
+-  
++
+   if (HaveSelection()) GetSelRCoords(&sx,&sy,&sw,&sh);
+   else { sx = 0;  sy = 0;  sw = pWIDE;  sh = pHIGH; }
+   CropRect2Rect(&sx,&sy,&sw,&sh, 0,0,pWIDE,pHIGH);
+-  
++
+   WaitCursor();
+ 
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+@@ -463,11 +464,11 @@
+ /************************/
+ static void Spread()
+ {
+-  byte        *pic24, *tmpPic;
+-  int          i,sx,sy,sw,sh, pixX,pixY,err;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char         txt[256];
+-  static char  buf[64] = { '5', '\0' };
++  byte              *pic24, *tmpPic;
++  int                i,sx,sy,sw,sh, pixX,pixY,err;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               txt[256];
++  static char        buf[64] = { '5', '\0' };
+ 
+   sprintf(txt, "Spread:\n\nEnter spread factor (or x,y factors):  %s",
+ 	  "(ex. '10', '1x5')");
+@@ -493,11 +494,11 @@
+     return;
+   }
+ 
+-  
++
+   if (HaveSelection()) GetSelRCoords(&sx,&sy,&sw,&sh);
+   else { sx = 0;  sy = 0;  sw = pWIDE;  sh = pHIGH; }
+   CropRect2Rect(&sx,&sy,&sw,&sh, 0,0,pWIDE,pHIGH);
+-  
++
+   WaitCursor();
+ 
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+@@ -516,12 +517,12 @@
+   /* runs median filter algorithm (for n*n rect centered around each pixel,
+      replace with median value */
+ 
+-  byte        *pic24, *tmpPic;
+-  int          i, sx,sy,sw,sh, n;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char         txt[256];
+-  static char  buf[64] = { '3', '\0' };
+-  
++  byte              *pic24, *tmpPic;
++  int                i, sx,sy,sw,sh, n;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               txt[256];
++  static char        buf[64] = { '3', '\0' };
++
+   sprintf(txt, "DeSpeckle (median filter):                          \n\n%s",
+ 	  "Enter mask size (ex. 3, 5, 7, ...)");
+ 
+@@ -530,7 +531,7 @@
+   n = atoi(buf);
+ 
+   if (n < 1 || (n&1)!=1) {
+-    ErrPopUp("Error:  The value entered must be odd and greater than zero.", 
++    ErrPopUp("Error:  The value entered must be odd and greater than zero.",
+ 	     "\nOh!");
+     return;
+   }
+@@ -546,7 +547,7 @@
+ 
+   if (start24bitAlg(&pic24, &tmpPic)) return;
+   xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3));
+-    
++
+   doMedianFilter(pic24, pWIDE,pHIGH, tmpPic, sx,sy,sw,sh, n);
+ 
+   end24bitAlg(pic24, tmpPic);
+@@ -560,7 +561,7 @@
+      int   w,h, selx,sely,selw,selh, n;
+ {
+ 
+-  /* convolves with an n*n array, consisting of only 1's.  
++  /* convolves with an n*n array, consisting of only 1's.
+      Operates on rectangular region 'selx,sely,selw,selh' (in pic coords)
+      Region is guaranteed to be completely within pic boundaries
+      'n' must be odd */
+@@ -568,7 +569,7 @@
+   register byte *p24;
+   register int   rsum,gsum,bsum;
+   byte          *rp;
+-  int            i,j,k,x,y,x1,y1,count,n2;
++  int            x,y,x1,y1,count,n2;
+ 
+ 
+   printUTime("start of blurConvolv");
+@@ -589,7 +590,7 @@
+       for (y1=y-n2; y1<=y+n2; y1++) {
+ 
+ 	if (y1>=sely && y1<sely+selh) {
+-	  p24 = pic24 + y1*w*3 +(x-n2)*3; 
++	  p24 = pic24 + y1*w*3 +(x-n2)*3;
+ 
+ 	  for (x1=x-n2; x1<=x+n2; x1++) {
+ 	    if (x1>=selx && x1<selx+selw) {
+@@ -631,7 +632,7 @@
+   byte  *p24;
+   int    rv, gv, bv;
+   byte  *rp;
+-  int    i,j,k,x,y,x1,y1;
++  int    i,x,y;
+   double fact, ifact, hue,sat,val, vsum;
+   double *linem1, *line0, *linep1, *tmpptr;
+ 
+@@ -673,7 +674,7 @@
+   for (y=sely+1; y<(sely+selh)-1; y++) {
+     ProgressMeter(sely+1, (sely+selh)-2, y, "Sharpen");
+     if ((y & 15) == 0) WaitCursor();
+-    
++
+     tmpptr = linem1;   linem1 = line0;   line0 = linep1;   linep1 = tmpptr;
+ 
+     /* get next line */
+@@ -691,7 +692,7 @@
+       vsum = linem1[i-1] + linem1[i] + linem1[i+1] +
+ 	     line0 [i-1] + line0 [i] + line0 [i+1] +
+ 	     linep1[i-1] + linep1[i] + linep1[i+1];
+-      
++
+       rgb2hsv((int) p24[0], (int) p24[1], (int) p24[2], &hue, &sat, &val);
+ 
+       val = ((val - (fact * vsum) / 9) / ifact);
+@@ -723,22 +724,22 @@
+ {
+ 
+   /* convolves with two edge detection masks (vertical and horizontal)
+-     simultaneously, taking Max(abs(results)) 
+-     
++     simultaneously, taking Max(abs(results))
++
+      The two masks are (hard coded):
+ 
+           -1 0 1             -1 -1 -1
+       H = -1 0 1     and V =  0  0  0
+           -1 0 1              1  1  1
+ 
+-     divided into 
++     divided into
+            -1 0 0         0 0 0         0 0 1        0  1 0
+        a =  0 0 0 ,  b = -1 0 1 ,  c =  0 0 0 ,  d = 0  0 0 .
+             0 0 1         0 0 0        -1 0 0        0 -1 0
+ 
+      So H = a + b + c,  V = a - c - d.
+      gradient = max(abs(H),abs(V)).
+-          
++
+      Also, only does pixels in which the masks fit fully onto the picture
+      (no pesky boundary conditionals)  */
+ 
+@@ -746,7 +747,7 @@
+   register byte *p24;
+   register int   bperlin, a, b, c, d, rsum, gsum, bsum;
+   byte          *rp;
+-  int            i, x, y;
++  int            x, y;
+ 
+ 
+   printUTime("start of edgeConvolv");
+@@ -818,13 +819,13 @@
+ {
+ 
+   /* convolves with edge detection mask, at 45 degrees to horizontal.
+-     
++
+      The mask is (hard coded):
+ 
+              -2 -1 0
+              -1  0 1
+               0  1 2
+-          
++
+      Also, only does pixels in which the masks fit fully onto the picture
+      (no pesky boundary conditionals)
+ 
+@@ -833,7 +834,7 @@
+   register byte *p24;
+   register int   bperlin,rsum,gsum,bsum;
+   byte          *rp;
+-  int            i, x,y;
++  int            x,y;
+ 
+ 
+   printUTime("start of doAngleConvolv");
+@@ -912,14 +913,14 @@
+      for each pixel in the image (assume, for a second, a grayscale image),
+      compute a histogram of the n*n rectangle centered on the pixel.
+      replace the pixel with the color that had the greatest # of hits in
+-     the histogram.  Note that 'n' should be odd. 
++     the histogram.  Note that 'n' should be odd.
+ 
+      I've modified the algorithm to do the *right* thing for RGB images.
+      (jhb, 6/94)  */
+ 
+ 
+   register byte *pp;
+-  register int   bperlin, rsum,gsum,bsum;
++  register int   bperlin;
+   byte          *rp, *p24, *plin;
+   int            i,j,k,x,y,n2,col,cnt,maxcnt;
+   int           *nnrect;
+@@ -933,7 +934,7 @@
+ 
+   /* nnrect[] is an n*n array of ints, with '-1' meaning 'outside the region'
+      otherwise they'll have 24-bit RGB values */
+-  
++
+   nnrect = (int *) malloc(n * n * sizeof(int));
+   if (!nnrect) FatalError("can't malloc nnrect[] in doOilPaint()\n");
+ 
+@@ -943,13 +944,13 @@
+ 
+     p24 = pic24 + ((y-n2)*w + selx-n2)*3;   /* pts to top-left of mask */
+     rp  = results + (y*w + selx)*3;
+-    
++
+     for (x=selx; x<selx+selw; x++) {
+       /* fill 'nnrect' with valid pixels from n*n region centered round x,y */
+       pp = plin = p24;
+       for (i=y-n2, k=0; i<y+n2; i++) {
+ 	for (j=x-n2; j<x+n2; j++, k++, pp+=3) {
+-	  if (i>=sely && i<sely+selh && j>=selx && j<selx+selw) { 
++	  if (i>=sely && i<sely+selh && j>=selx && j<selx+selw) {
+ 	    nnrect[k] = (((int) pp[0])<<16) | (((int) pp[1])<<8) | pp[2];
+ 	  }
+ 	  else nnrect[k] = -1;
+@@ -957,7 +958,7 @@
+ 	plin += bperlin;  pp = plin;
+       }
+ 
+-      
++
+       /* find 'most popular color' in nnrect, not counting '-1' */
+       maxcnt = cnt = col = 0;
+       for (i=0; i<n*n; i++) {
+@@ -1021,7 +1022,7 @@
+     p24 = pic24 + (y*w + selx) * 3;
+     rf += (double) p24[0];  gf += (double) p24[1];  bf += (double) p24[2];
+     i++;
+-    
++
+     p24 = pic24 + (y*w + (selx+selw-1)) * 3;
+     rf += (double) p24[0];  gf += (double) p24[1];  bf += (double) p24[2];
+     i++;
+@@ -1047,7 +1048,7 @@
+       if (dx==0 && dy==0) { ex = selx;  ey = sely; }  /* don't care */
+       else if (dx==0) {	ex = cx;  ey = (dy<0) ? sely : sely+selh-1; }
+       else if (dy==0) {	ey = cy;  ex = (dx<0) ? selx : selx+selw-1; }
+-      else { 
++      else {
+ 	slope = ((double) dy) / dx;
+ 	if (fabs(slope) > fabs(dslope)) {   /* y axis is major */
+ 	  ey = (dy<0) ? sely : sely+selh-1;
+@@ -1092,7 +1093,7 @@
+   printUTime("end of blend");
+ }
+ 
+-  
++
+ 
+ /************************/
+ static void doRotate(pic24, w, h, results, selx,sely,selw,selh, rotval, clear)
+@@ -1104,7 +1105,7 @@
+      by the amount specified in degrees (rotval), and stores the result in
+      'results', which is also a w*h 24-bit image.  The rotated bits are
+      clipped to fit in 'results'.  If 'clear', the (unrotated) rectangular
+-     region is cleared (in results) first.  
++     region is cleared (in results) first.
+      sel[x,y,w,h] is guaranteed to be within image bounds */
+ 
+   byte  *pp, *dp;
+@@ -1118,7 +1119,7 @@
+   printUTime("start of rotate");
+ 
+   /*
+-   * cfx,cfy  -  center point of sel rectangle (double) 
++   * cfx,cfy  -  center point of sel rectangle (double)
+    * rx1,ry1  -  top-left  of sel, rotated
+    * rx2,ry2  -  bot-left  of sel, rotated
+    * rx3,ry3  -  top-right of sel, rotated
+@@ -1174,7 +1175,7 @@
+   /* now, for each pixel in rb[x,y,w,h], do the inverse rotation to see if
+      it would be in the original unrotated selection rectangle.  if it *is*,
+      compute and store an appropriate color, otherwise skip it */
+- 
++
+   for (y=rby; y<rby+rbh; y++) {
+     dp = results + (y * w + rbx) * 3;
+ 
+@@ -1194,7 +1195,7 @@
+ 	int    p0r,p0g,p0b, p1r,p1g,p1b, p2r,p2g,p2b, p3r,p3g,p3b;
+ 	int    rv,gv,bv;
+ 	double rd,gd,bd, p0wgt, p1wgt, p2wgt, p3wgt;
+-	
++
+ 	/* compute the color, same idea as in Smooth**().  The color
+ 	   will be a linear combination of the colors of the center pixel,
+ 	   its left-or-right neighbor, its top-or-bottom neighbor, and
+@@ -1265,9 +1266,9 @@
+ }
+ #endif /* ROTATE_FOO */
+ 
+-	dp[0] = (byte) (rv&0xff);  
+-	dp[1] = (byte) (gv&0xff);  
+-	dp[2] = (byte) (bv&0xff);  
++	dp[0] = (byte) (rv&0xff);
++	dp[1] = (byte) (gv&0xff);
++	dp[2] = (byte) (bv&0xff);
+       }
+     }
+   }
+@@ -1311,11 +1312,11 @@
+ #ifdef FOO
+   fprintf(stderr,"rotXfer:  rotating (%4d,%4d) %7.2f degrees around",
+ 	  x,y, rad*180.0 / M_PI);
+-  fprintf(stderr,"(%4d,%4d) -> %7.2f %7.2f  (d=%f ang=%f)\n", 
++  fprintf(stderr,"(%4d,%4d) -> %7.2f %7.2f  (d=%f ang=%f)\n",
+ 	  cx,cy, *rx,*ry, d, ang);
+ #endif
+ }
+-  
++
+ 
+ 
+ /************************/
+@@ -1323,29 +1324,29 @@
+      byte *pic24, *results;
+      int   w, h, selx,sely,selw,selh, pixX,pixY;
+ {
+-  /* runs 'pixelization' algorithm.  replaces each pixX-by-pixY region 
++  /* runs 'pixelization' algorithm.  replaces each pixX-by-pixY region
+      (smaller on edges) with the average color within that region */
+-  
++
+   byte  *pp;
+   int    nwide, nhigh, i,j, x,y, x1,y1, stx,sty;
+   int    nsum, rsum, gsum, bsum;
+-  
++
+   printUTime("start of pixelize");
+-  
++
+   /* center grid on selection */
+   nwide = (selw + pixX-1) / pixX;
+   nhigh = (selh + pixY-1) / pixY;
+-  
++
+   stx = selx - (nwide*pixX - selw)/2;
+   sty = sely - (nhigh*pixY - selh)/2;
+-  
++
+   y = sty;
+   for (i=0; i<nhigh; i++, y+=pixY) {
+     ProgressMeter(0, nhigh-1, i, "Pixelize");
+-    
++
+     x = stx;
+     for (j=0; j<nwide; j++, x+=pixX) {
+-      
++
+       /* COMPUTE AVERAGE COLOR FOR RECT:[x,y,pixX,pixY] */
+       nsum = rsum = gsum = bsum = 0;
+       for (y1=y; y1<y+pixY; y1++) {
+@@ -1357,17 +1358,17 @@
+ 	  }
+ 	}
+       }
+-      
++
+       if (nsum>0) {   /* just to be safe... */
+ 	rsum /= nsum;  gsum /= nsum;  bsum /= nsum;
+ 	RANGE(rsum,0,255);  RANGE(gsum,0,255);  RANGE(bsum,0,255);
+       }
+-      
+-      
++
++
+       /* STORE color in rect:[x,y,pixX,pixY] */
+       for (y1=y; y1<y+pixY; y1++) {
+ 	if (!j && (y1 & 255)==0) WaitCursor();
+-	
++
+ 	pp = results + (y1 * w + x) * 3;
+ 	for (x1=x; x1<x+pixX; x1++, pp+=3) {
+ 	  if (PTINRECT(x1,y1, selx,sely,selw,selh)) {
+@@ -1381,7 +1382,7 @@
+   printUTime("end of pixelize");
+ }
+ 
+-  
++
+ 
+ /************************/
+ static void doSpread(pic24, w, h, results, selx,sely,selw,selh, pixX, pixY)
+@@ -1393,17 +1394,17 @@
+      by pixX,pixY.  If pixX<0, it is treated as a single 'distance' value
+      (after being abs()'d). */
+ 
+-  /* assumes that initially 'results' is a copy of pic24.  Doesn't 
++  /* assumes that initially 'results' is a copy of pic24.  Doesn't
+      even look at pic24 */
+-  
++
+   byte  *pp, *dp, r,g,b;
+-  int    x,y, dx,dy, x1,y1, d, xrng, xoff, yrng, yoff, i,j;
++  int    x,y, x1,y1, d;
+   int    minx, maxx, miny, maxy, rdist;
+   time_t nowT;
+ 
+   time(&nowT);
+   srandom((unsigned int) nowT);
+-  
++
+   printUTime("start of spread");
+ 
+   for (y=sely; y<sely+selh; y++) {
+@@ -1453,7 +1454,7 @@
+   printUTime("end of spread");
+ }
+ 
+-  
++
+ 
+ /************************/
+ static void doMedianFilter(pic24, w, h, results, selx,sely,selw,selh, n)
+@@ -1468,7 +1469,7 @@
+   register byte *p24;
+   register int   rsum,gsum,bsum;
+   byte          *rp;
+-  int            i,j,k,x,y,x1,y1,count,n2,nsq,c2;
++  int            x,y,x1,y1,count,n2,nsq,c2;
+   int           *rtab, *gtab, *btab;
+ 
+   printUTime("start of doMedianFilter");
+@@ -1494,7 +1495,7 @@
+       for (y1=y-n2; y1<=y+n2; y1++) {
+ 
+ 	if (y1>=sely && y1<sely+selh) {
+-	  p24 = pic24 + y1*w*3 +(x-n2)*3; 
++	  p24 = pic24 + y1*w*3 +(x-n2)*3;
+ 
+ 	  for (x1=x-n2; x1<=x+n2; x1++) {
+ 	    if (x1>=selx && x1<selx+selw) {
+@@ -1509,12 +1510,12 @@
+       }
+ 
+ 
+-      /* now sort the rtab,gtab,btab arrays, (using shell sort) 
+-	 and pick the middle value.  doing it in-line, rather than 
++      /* now sort the rtab,gtab,btab arrays, (using shell sort)
++	 and pick the middle value.  doing it in-line, rather than
+ 	 as a function call (ie, 'qsort()') , for speed */
+-      {  
++      {
+ 	int i,j,t,d;
+-	
++
+ 	for (d=count/2;  d>0;  d=d/2) {
+ 	  for (i=d; i<count; i++) {
+ 	    for (j=i-d;  j>=0 && rtab[j]>rtab[j+d];  j-=d) {
+@@ -1531,14 +1532,14 @@
+ 	  }
+ 	}
+       }
+-      
++
+       c2 = count/2;
+       *rp++ = (byte) ( (count&1) ? rtab[c2] : (rtab[c2] + rtab[c2-1])/2);
+       *rp++ = (byte) ( (count&1) ? gtab[c2] : (gtab[c2] + gtab[c2-1])/2);
+       *rp++ = (byte) ( (count&1) ? btab[c2] : (btab[c2] + btab[c2-1])/2);
+     }
+   }
+-  
++
+   free(rtab);  free(gtab);  free(btab);
+   printUTime("end of doMedianFilter");
+ }
+@@ -1549,7 +1550,7 @@
+ static void intsort(a, n)
+      int *a, n;
+ {
+-  /* uses the shell-sort algorithm.  for the relatively small data sets 
++  /* uses the shell-sort algorithm.  for the relatively small data sets
+      we'll be using, should be quicker than qsort() because of all the
+      function calling overhead associated with qsort(). */
+ 
+@@ -1571,7 +1572,7 @@
+      byte **pic24, **tmpPic;
+ {
+   /* generates a 24-bit version of 'pic', if neccessary, and also mallocs
+-   * a pWIDE*pHIGH*3 24-bit output pic.  
++   * a pWIDE*pHIGH*3 24-bit output pic.
+    *
+    * Returns '1' if there's some sort of screwup, '0' if cool
+    */
+@@ -1588,7 +1589,7 @@
+   *tmpPic = (byte *) calloc((size_t) (pWIDE * pHIGH * 3), (size_t) 1);
+   if (!(*tmpPic)) {
+     SetCursors(-1);
+-    ErrPopUp("Unable to malloc() tmp 24-bit image in start24bitAlg()", 
++    ErrPopUp("Unable to malloc() tmp 24-bit image in start24bitAlg()",
+ 	     "\nTough!");
+     if (picType == PIC8) free(*pic24);
+     return 1;
+@@ -1609,16 +1610,16 @@
+   saveOrigPic();  /* also kills pic/cpic/epic/egampic/theImage, NOT pic24 */
+ 
+   /* copy results to pic24 */
+-  xvbcopy((char *) outPic, (char *) pic24, (size_t) (pWIDE*pHIGH*3)); 
++  xvbcopy((char *) outPic, (char *) pic24, (size_t) (pWIDE*pHIGH*3));
+   free(outPic);
+ 
+   if (picType == PIC8) {
+     pic = Conv24to8(pic24, pWIDE, pHIGH, ncols, rMap,gMap,bMap);
+     free(pic24);
+-    if (!pic) { 
++    if (!pic) {
+       SetCursors(-1);
+       ErrPopUp("Some sort of failure occured in 24to8 conversion\n","\nDamn!");
+-      NoAlg(); 
++      NoAlg();
+       return;
+     }
+   }
+@@ -1632,7 +1633,7 @@
+ static void saveOrigPic()
+ {
+   /* saves original picture into origPic, if it hasn't already been done.
+-     This allows us to undo algorithms...  
++     This allows us to undo algorithms...
+ 
+      Also, frees all pics, (except 'pic', if we're in PIC24 mode) */
+ 
+@@ -1649,7 +1650,7 @@
+     /* make a backup copy of 'pic' */
+     origPic = (byte *) malloc((size_t)(pWIDE*pHIGH*((picType==PIC8) ? 1 : 3)));
+     if (!origPic) FatalError("out of memory in 'saveOrigPic()'");
+-    xvbcopy((char *) pic, (char *) origPic, 
++    xvbcopy((char *) pic, (char *) origPic,
+ 	    (size_t) (pWIDE * pHIGH * ((picType==PIC8) ? 1 : 3)));
+ 
+     origPicType = picType;
+diff -ru xv-3.10a/xvbmp.c xv-3.10a-enhancements/xvbmp.c
+--- xv-3.10a/xvbmp.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvbmp.c	2007-05-13 17:46:16.000000000 -0700
+@@ -1,5 +1,5 @@
+ /*
+- * xvbmp.c - i/o routines for .BMP files (MS Windows 3.x)
++ * xvbmp.c - I/O routines for .BMP files (MS Windows 3.x and later; OS/2)
+  *
+  * LoadBMP(fname, numcols)
+  * WriteBMP(fp, pic, ptype, w, h, r, g, b, numcols, style);
+@@ -9,30 +9,39 @@
+ 
+ #include "xv.h"
+ 
+-/* comments on error handling:
+-   a truncated file is not considered a Major Error.  The file is loaded, the
+-   rest of the pic is filled with 0's.
+-
+-   a file with garbage characters in it is an unloadable file.  All allocated
+-   stuff is tossed, and LoadPBM returns non-zero
+-
+-   not being able to malloc is a Fatal Error.  The program is aborted. */
+-
+-
+-#define BI_RGB  0
+-#define BI_RLE8 1
+-#define BI_RLE4 2
++/* Comments on error-handling:
++   A truncated file is not considered a Major Error.  The file is loaded,
++   and the rest of the pic is filled with 0's.
++
++   A file with garbage characters in it is an unloadable file.  All allocated
++   stuff is tossed, and LoadBMP returns non-zero.
++
++   Not being able to malloc is a Fatal Error.  The program is aborted. */
++
++
++#define BI_RGB       0   /* a.k.a. uncompressed */
++#define BI_RLE8      1
++#define BI_RLE4      2
++#define BI_BITFIELDS 3   /* BMP version 4 */
++#define BI_JPEG      4   /* BMP version 5 (not yet supported) */
++#define BI_PNG       5   /* BMP version 5 (not yet supported) */
+ 
+ #define WIN_OS2_OLD 12
+ #define WIN_NEW     40
+ #define OS2_NEW     64
+ 
++#if (defined(UINT_MAX) && UINT_MAX != 0xffffffffU)
++#  error XV's BMP code requires 32-bit unsigned integer type, but u_int isn't
++#endif
++
+ static long filesize;
+ 
+ static int   loadBMP1   PARM((FILE *, byte *, u_int, u_int));
+ static int   loadBMP4   PARM((FILE *, byte *, u_int, u_int, u_int));
+ static int   loadBMP8   PARM((FILE *, byte *, u_int, u_int, u_int));
+-static int   loadBMP24  PARM((FILE *, byte *, u_int, u_int));
++static int   loadBMP16  PARM((FILE *, byte *, u_int, u_int, u_int *));
++static int   loadBMP24  PARM((FILE *, byte *, u_int, u_int, u_int));
++static int   loadBMP32  PARM((FILE *, byte *, u_int, u_int, u_int *));
+ static u_int getshort   PARM((FILE *));
+ static u_int getint     PARM((FILE *));
+ static void  putshort   PARM((FILE *, int));
+@@ -41,7 +50,7 @@
+ static void  writeBMP4  PARM((FILE *, byte *, int, int));
+ static void  writeBMP8  PARM((FILE *, byte *, int, int));
+ static void  writeBMP24 PARM((FILE *, byte *, int, int));
+-static int   bmpError   PARM((char *, char *));
++static int   bmpError   PARM((const char *, const char *));
+ 
+ 
+ #define FERROR(fp) (ferror(fp) || feof(fp))
+@@ -52,15 +61,15 @@
+      PICINFO *pinfo;
+ /*******************************************/
+ {
+-  FILE         *fp;
+-  int          i, c, c1, rv;
+-  unsigned int bfSize, bfOffBits, biSize, biWidth, biHeight, biPlanes;
+-  unsigned int biBitCount, biCompression, biSizeImage, biXPelsPerMeter;
+-  unsigned int biYPelsPerMeter, biClrUsed, biClrImportant;
+-  int bPad;
+-  char         *cmpstr;
+-  byte         *pic24, *pic8;
+-  char          buf[512], *bname;
++  FILE       *fp;
++  int        i, c, c1, rv, bPad;
++  u_int      bfSize, bfOffBits, biSize, biWidth, biHeight, biPlanes;
++  u_int      biBitCount, biCompression, biSizeImage, biXPelsPerMeter;
++  u_int      biYPelsPerMeter, biClrUsed, biClrImportant;
++  u_int      colormask[3];
++  char       buf[512], rgb_bits[16];
++  const char *cmpstr, *bname;
++  byte       *pic24, *pic8;
+ 
+   /* returns '1' on success */
+ 
+@@ -69,7 +78,7 @@
+ 
+   fp = xv_fopen(fname,"r");
+   if (!fp) return (bmpError(bname, "couldn't open file"));
+-  
++
+   fseek(fp, 0L, 2);      /* figure out the file size */
+   filesize = ftell(fp);
+   fseek(fp, 0L, 0);
+@@ -98,17 +107,16 @@
+     biClrUsed       = getint(fp);
+     biClrImportant  = getint(fp);
+   }
+-
+   else {    /* old bitmap format */
+     biWidth         = getshort(fp);          /* Types have changed ! */
+     biHeight        = getshort(fp);
+     biPlanes        = getshort(fp);
+     biBitCount      = getshort(fp);
+-    
+-    /* Not in old versions so have to compute them*/
++
++    /* not in old versions, so have to compute them */
+     biSizeImage = (((biPlanes * biBitCount*biWidth)+31)/32)*4*biHeight;
+-    
+-    biCompression   = BI_RGB; 
++
++    biCompression   = BI_RGB;
+     biXPelsPerMeter = biYPelsPerMeter = 0;
+     biClrUsed       = biClrImportant  = 0;
+   }
+@@ -126,22 +134,39 @@
+   if (FERROR(fp)) { bmpError(bname,"EOF reached in file header"); goto ERROR; }
+ 
+ 
+-  /* error checking */
+-  if ((biBitCount!=1 && biBitCount!=4 && biBitCount!=8 && biBitCount!=24) || 
+-      biPlanes!=1 || biCompression>BI_RLE4) {
++  /* error-checking */
++  if ((biBitCount!=1 && biBitCount!=4 && biBitCount!=8 &&
++       biBitCount!=16 && biBitCount!=24 && biBitCount!=32) ||
++      biPlanes!=1 || biCompression>BI_PNG ||
++      biWidth<=0 || biHeight<=0 ||
++      (biClrUsed && biClrUsed > (1 << biBitCount))) {
++
++    sprintf(buf,
++	    "Unsupported BMP type (%dx%d, Bits=%d, Colors=%d, Planes=%d, "
++	    "Compr=%d)",
++	    biWidth, biHeight, biBitCount, biClrUsed, biPlanes, biCompression);
+ 
+-    sprintf(buf,"Bogus BMP File!  (bitCount=%d, Planes=%d, Compression=%d)",
+-	    biBitCount, biPlanes, biCompression);
++    bmpError(bname, buf);
++    goto ERROR;
++  }
++
++  if (biCompression>BI_BITFIELDS) {
++    sprintf(buf, "Unsupported BMP compression method (%s)",
++	    biCompression == BI_JPEG? "JPEG" :
++	    biCompression == BI_PNG? "PNG" :
++	    "unknown/newer than v5");
+ 
+     bmpError(bname, buf);
+     goto ERROR;
+   }
+ 
+   if (((biBitCount==1 || biBitCount==24) && biCompression != BI_RGB) ||
+-      (biBitCount==4 && biCompression==BI_RLE8) ||
+-      (biBitCount==8 && biCompression==BI_RLE4)) {
++      (biBitCount==4 && biCompression!=BI_RGB && biCompression!=BI_RLE4) ||
++      (biBitCount==8 && biCompression!=BI_RGB && biCompression!=BI_RLE8) ||
++      ((biBitCount==16 || biBitCount==32) &&
++       biCompression!=BI_RGB && biCompression!=BI_BITFIELDS)) {
+ 
+-    sprintf(buf,"Bogus BMP File!  (bitCount=%d, Compression=%d)",
++    sprintf(buf,"Unsupported BMP type (bitCount=%d, Compression=%d)",
+ 	    biBitCount, biCompression);
+ 
+     bmpError(bname, buf);
+@@ -153,13 +178,21 @@
+   if (biSize != WIN_OS2_OLD) {
+     /* skip ahead to colormap, using biSize */
+     c = biSize - 40;    /* 40 bytes read from biSize to biClrImportant */
+-    for (i=0; i<c; i++) getc(fp);
+-    
++    for (i=0; i<c; i++)
++      getc(fp);
+     bPad = bfOffBits - (biSize + 14);
+   }
+ 
++  /* 16-bit or 32-bit color mask */
++  if (biCompression==BI_BITFIELDS) {
++    colormask[0] = getint(fp);
++    colormask[1] = getint(fp);
++    colormask[2] = getint(fp);
++    bPad -= 12;
++  }
++
+   /* load up colormap, if any */
+-  if (biBitCount!=24) {
++  if (biBitCount == 1 || biBitCount == 4 || biBitCount == 8) {
+     int i, cmaplen;
+ 
+     cmaplen = (biClrUsed) ? biClrUsed : 1 << biBitCount;
+@@ -173,7 +206,7 @@
+       }
+     }
+ 
+-    if (FERROR(fp)) 
++    if (FERROR(fp))
+       { bmpError(bname,"EOF reached in BMP colormap"); goto ERROR; }
+ 
+     if (DEBUG>1) {
+@@ -188,7 +221,7 @@
+   if (biSize != WIN_OS2_OLD) {
+     /* Waste any unused bytes between the colour map (if present)
+        and the start of the actual bitmap data. */
+-    
++
+     while (bPad > 0) {
+       (void) getc(fp);
+       bPad--;
+@@ -197,31 +230,57 @@
+ 
+   /* create pic8 or pic24 */
+ 
+-  if (biBitCount==24) {
+-    pic24 = (byte *) calloc((size_t) biWidth * biHeight * 3, (size_t) 1);
++  if (biBitCount==16 || biBitCount==24 || biBitCount==32) {
++    u_int npixels = biWidth * biHeight;
++    u_int count = 3 * npixels;
++
++    if (biWidth == 0 || biHeight == 0 || npixels/biWidth != biHeight ||
++        count/3 != npixels)
++      return (bmpError(bname, "image dimensions too large"));
++    pic24 = (byte *) calloc((size_t) count, (size_t) 1);
+     if (!pic24) return (bmpError(bname, "couldn't malloc 'pic24'"));
+   }
+   else {
+-    pic8 = (byte *) calloc((size_t) biWidth * biHeight, (size_t) 1);
++    u_int npixels = biWidth * biHeight;
++
++    if (biWidth == 0 || biHeight == 0 || npixels/biWidth != biHeight)
++      return (bmpError(bname, "image dimensions too large"));
++    pic8 = (byte *) calloc((size_t) npixels, (size_t) 1);
+     if (!pic8) return(bmpError(bname, "couldn't malloc 'pic8'"));
+   }
+ 
+   WaitCursor();
+ 
+   /* load up the image */
+-  if      (biBitCount == 1) rv = loadBMP1(fp,pic8,biWidth,biHeight);
+-  else if (biBitCount == 4) rv = loadBMP4(fp,pic8,biWidth,biHeight,
+-					  biCompression);
+-  else if (biBitCount == 8) rv = loadBMP8(fp,pic8,biWidth,biHeight,
+-					  biCompression);
+-  else                      rv = loadBMP24(fp,pic24,biWidth,biHeight);
++  switch (biBitCount) {
++  case 1:
++    rv = loadBMP1(fp, pic8, biWidth, biHeight);
++    break;
++  case 4:
++    rv = loadBMP4(fp, pic8, biWidth, biHeight, biCompression);
++    break;
++  case 8:
++    rv = loadBMP8(fp, pic8, biWidth, biHeight, biCompression);
++    break;
++  case 16:
++    rv = loadBMP16(fp, pic24, biWidth, biHeight,           /*  v-- BI_RGB */
++                   biCompression == BI_BITFIELDS? colormask : NULL);
++    break;
++  default:
++    if (biBitCount == 32 && biCompression == BI_BITFIELDS)
++      rv = loadBMP32(fp, pic24, biWidth, biHeight, colormask);
++    else /* 24 or (32 and BI_RGB) */
++      rv = loadBMP24(fp, pic24, biWidth, biHeight, biBitCount);
++    break;
++  }
++
++  if (rv) bmpError(bname, "File appears truncated.  Winging it.");
+ 
+-  if (rv) bmpError(bname, "File appears truncated.  Winging it.\n");
+ 
+   fclose(fp);
+ 
+ 
+-  if (biBitCount == 24) {
++  if (biBitCount > 8) {
+     pinfo->pic  = pic24;
+     pinfo->type = PIC24;
+   }
+@@ -233,6 +292,22 @@
+   cmpstr = "";
+   if      (biCompression == BI_RLE4) cmpstr = ", RLE4 compressed";
+   else if (biCompression == BI_RLE8) cmpstr = ", RLE8 compressed";
++  else if (biCompression == BI_BITFIELDS) {
++    int    bit, c[3], i;
++    u_int  mask;
++
++    for (i = 0; i < 3; ++i) {
++      mask = colormask[i];
++      c[i] = 0;
++      for (bit = 0; bit < 32; ++bit) {
++        if (mask & 1)
++          ++c[i];
++        mask >>= 1;
++      }
++    }
++    sprintf(rgb_bits, ", RGB%d%d%d", c[0], c[1], c[2]);
++    cmpstr = rgb_bits;
++  }
+ 
+   pinfo->w = biWidth;  pinfo->h = biHeight;
+   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
+@@ -254,7 +329,7 @@
+  ERROR:
+   fclose(fp);
+   return 0;
+-}  
++}
+ 
+ 
+ /*******************************************/
+@@ -264,12 +339,13 @@
+      u_int  w,h;
+ {
+   int   i,j,c,bitnum,padw;
+-  byte *pp;
++  byte *pp = pic8 + ((h - 1) * w);
++  size_t l = w*h;
+ 
+   c = 0;
+   padw = ((w + 31)/32) * 32;  /* 'w', padded to be a multiple of 32 */
+ 
+-  for (i=h-1; i>=0; i--) {
++  for (i=h-1; i>=0 && (pp - pic8 <= l); i--) {
+     pp = pic8 + (i * w);
+     if ((i&0x3f)==0) WaitCursor();
+     for (j=bitnum=0; j<padw; j++,bitnum++) {
+@@ -277,7 +353,7 @@
+ 	c = getc(fp);
+ 	bitnum = 0;
+       }
+-      
++
+       if (j<w) {
+ 	*pp++ = (c & 0x80) ? 1 : 0;
+ 	c <<= 1;
+@@ -287,7 +363,7 @@
+   }
+ 
+   return (FERROR(fp));
+-}  
++}
+ 
+ 
+ 
+@@ -298,25 +374,25 @@
+      u_int  w,h,comp;
+ {
+   int   i,j,c,c1,x,y,nybnum,padw,rv;
+-  byte *pp;
+-  
+-  
++  byte *pp = pic8 + ((h - 1) * w);
++  size_t l = w*h;
++
+   rv = 0;
+   c = c1 = 0;
+-  
++
+   if (comp == BI_RGB) {   /* read uncompressed data */
+     padw = ((w + 7)/8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */
+-    
+-    for (i=h-1; i>=0; i--) {
++
++    for (i=h-1; i>=0 && (pp - pic8 <= l); i--) {
+       pp = pic8 + (i * w);
+       if ((i&0x3f)==0) WaitCursor();
+-      
++
+       for (j=nybnum=0; j<padw; j++,nybnum++) {
+ 	if ((nybnum & 1) == 0) { /* read next byte */
+ 	  c = getc(fp);
+ 	  nybnum = 0;
+ 	}
+-	
++
+ 	if (j<w) {
+ 	  *pp++ = (c & 0xf0) >> 4;
+ 	  c <<= 4;
+@@ -325,55 +401,55 @@
+       if (FERROR(fp)) break;
+     }
+   }
+-  
++
+   else if (comp == BI_RLE4) {  /* read RLE4 compressed data */
+-    x = y = 0;  
++    x = y = 0;
+     pp = pic8 + x + (h-y-1)*w;
+-    
++
+     while (y<h) {
+       c = getc(fp);  if (c == EOF) { rv = 1;  break; }
+-      
++
+       if (c) {                                   /* encoded mode */
+ 	c1 = getc(fp);
+-	for (i=0; i<c; i++,x++,pp++) 
++	for (i=0; i<c && (pp - pic8 <= l); i++,x++,pp++)
+ 	  *pp = (i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f);
+       }
+-      
++
+       else {    /* c==0x00  :  escape codes */
+ 	c = getc(fp);  if (c == EOF) { rv = 1;  break; }
+-	
++
+ 	if      (c == 0x00) {                    /* end of line */
+ 	  x=0;  y++;  pp = pic8 + x + (h-y-1)*w;
+-	} 
+-	
++	}
++
+ 	else if (c == 0x01) break;               /* end of pic8 */
+-	
++
+ 	else if (c == 0x02) {                    /* delta */
+ 	  c = getc(fp);  x += c;
+ 	  c = getc(fp);  y += c;
+ 	  pp = pic8 + x + (h-y-1)*w;
+ 	}
+-	
++
+ 	else {                                   /* absolute mode */
+-	  for (i=0; i<c; i++, x++, pp++) {
++	  for (i=0; i<c && (pp - pic8 <= l); i++, x++, pp++) {
+ 	    if ((i&1) == 0) c1 = getc(fp);
+ 	    *pp = (i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f);
+ 	  }
+-	  
++
+ 	  if (((c&3)==1) || ((c&3)==2)) getc(fp);  /* read pad byte */
+ 	}
+       }  /* escape processing */
+       if (FERROR(fp)) break;
+     }  /* while */
+   }
+-  
++
+   else {
+     fprintf(stderr,"unknown BMP compression type 0x%0x\n", comp);
+   }
+-  
++
+   if (FERROR(fp)) rv = 1;
+   return rv;
+-}  
++}
+ 
+ 
+ 
+@@ -384,14 +460,18 @@
+      u_int  w,h,comp;
+ {
+   int   i,j,c,c1,padw,x,y,rv;
+-  byte *pp;
+-  
++  byte *pp = pic8 + ((h - 1) * w);
++  size_t l = w*h;
++  byte *pend;
++
+   rv = 0;
+ 
++  pend = pic8 + w * h;
++
+   if (comp == BI_RGB) {   /* read uncompressed data */
+     padw = ((w + 3)/4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
+ 
+-    for (i=h-1; i>=0; i--) {
++    for (i=h-1; i>=0 && (pp - pic8 <= l); i--) {
+       pp = pic8 + (i * w);
+       if ((i&0x3f)==0) WaitCursor();
+ 
+@@ -404,15 +484,15 @@
+   }
+ 
+   else if (comp == BI_RLE8) {  /* read RLE8 compressed data */
+-    x = y = 0;  
++    x = y = 0;
+     pp = pic8 + x + (h-y-1)*w;
+ 
+-    while (y<h) {
++    while (y<h && pp<=pend) {
+       c = getc(fp);  if (c == EOF) { rv = 1;  break; }
+ 
+       if (c) {                                   /* encoded mode */
+ 	c1 = getc(fp);
+-	for (i=0; i<c; i++,x++,pp++) *pp = c1;
++	for (i=0; i<c && pp<=pend; i++,x++,pp++) *pp = c1;
+       }
+ 
+       else {    /* c==0x00  :  escape codes */
+@@ -420,7 +500,7 @@
+ 
+ 	if      (c == 0x00) {                    /* end of line */
+ 	  x=0;  y++;  pp = pic8 + x + (h-y-1)*w;
+-	} 
++	}
+ 
+ 	else if (c == 0x01) break;               /* end of pic8 */
+ 
+@@ -431,49 +511,156 @@
+ 	}
+ 
+ 	else {                                   /* absolute mode */
+-	  for (i=0; i<c; i++, x++, pp++) {
++	  for (i=0; i<c && pp<=pend; i++, x++, pp++) {
+ 	    c1 = getc(fp);
+ 	    *pp = c1;
+ 	  }
+-	  
++
+ 	  if (c & 1) getc(fp);  /* odd length run: read an extra pad byte */
+ 	}
+       }  /* escape processing */
+       if (FERROR(fp)) break;
+     }  /* while */
+   }
+-  
++
+   else {
+     fprintf(stderr,"unknown BMP compression type 0x%0x\n", comp);
+   }
+ 
+   if (FERROR(fp)) rv = 1;
+   return rv;
+-}  
++}
+ 
+ 
+ 
+ /*******************************************/
+-static int loadBMP24(fp, pic24, w, h)
++static int loadBMP16(fp, pic24, w, h, mask)
++     FILE  *fp;
++     byte  *pic24;
++     u_int w, h, *mask;
++{
++  int	 x, y;
++  byte	*pp = pic24 + ((h - 1) * w * 3);
++  size_t l = w*h*3;
++  u_int	 buf, colormask[6];
++  int	 i, bit, bitshift[6], colorbits[6], bitshift2[6];
++
++  if (mask == NULL) {  /* RGB555 */
++    colormask[0] = 0x00007c00;
++    colormask[1] = 0x000003e0;
++    colormask[2] = 0x0000001f;
++    colormask[3] = 0x7c000000;
++    colormask[4] = 0x03e00000;
++    colormask[5] = 0x001f0000;
++    bitshift[0] =  7;	bitshift2[0] = 0;
++    bitshift[1] =  2;	bitshift2[1] = 0;
++    bitshift[2] =  0;	bitshift2[2] = 3;
++    bitshift[3] = 23;	bitshift2[3] = 0;
++    bitshift[4] = 18;	bitshift2[4] = 0;
++    bitshift[5] = 13;	bitshift2[5] = 0;
++  } else {
++    colormask[0] = mask[0];
++    colormask[1] = mask[1];
++    colormask[2] = mask[2];
++    colormask[3] = (mask[0] & 0xffff) << 16;
++    colormask[4] = (mask[1] & 0xffff) << 16;
++    colormask[5] = (mask[2] & 0xffff) << 16;
++
++    for (i = 0; i < 3; ++i) {
++      buf = colormask[i];
++
++      bitshift[i] = 0;
++      for (bit = 0; bit < 32; ++bit) {
++	if (buf & 1)
++	  break;
++	else
++	  ++bitshift[i];
++	buf >>= 1;
++      }
++      bitshift[i+3] = bitshift[i] + 16;
++
++      colorbits[i] = 0;
++      for (; bit < 32; ++bit) {
++	if (buf & 1)
++	  ++colorbits[i];
++	else
++	  break;
++	buf >>= 1;
++      }
++      if (colorbits[i] > 8) { /* over 8-bit depth */
++	bitshift[i] += (colorbits[i] - 8);
++	bitshift[i+3] = bitshift[i] + 16;
++	bitshift2[i] = bitshift2[i+3] = 0;
++      } else
++	bitshift2[i] = bitshift2[i+3] = 8 - colorbits[i];
++    }
++  }
++
++  if (DEBUG > 1)
++    fprintf(stderr, "loadBMP16: bitfields\n"
++	    "\tR: bits = %2d, mask = %08x, shift >>%2d, <<%2d\n"
++	    "\t             (mask = %08x, shift >>%2d, <<%2d)\n"
++	    "\tG: bits = %2d, mask = %08x, shift >>%2d, <<%2d\n"
++	    "\t             (mask = %08x, shift >>%2d, <<%2d)\n"
++	    "\tB: bits = %2d, mask = %08x, shift >>%2d, <<%2d\n"
++	    "\t             (mask = %08x, shift >>%2d, <<%2d)\n",
++	    colorbits[0], colormask[0], bitshift[0], bitshift2[0],
++	    colormask[3], bitshift[3], bitshift2[3],
++	    colorbits[1], colormask[1], bitshift[1], bitshift2[1],
++	    colormask[4], bitshift[4], bitshift2[4],
++	    colorbits[2], colormask[2], bitshift[2], bitshift2[2],
++	    colormask[5], bitshift[5], bitshift2[5]);
++
++  for (y = h-1; y >= 0 && (pp - pic24 <= l); y--) {
++    pp = pic24 + (3 * w * y);
++    if ((y&0x3f)==0) WaitCursor();
++
++    for (x = w; x > 1; x -= 2) {
++      buf = getint(fp);
++      *(pp++) = (buf & colormask[0]) >> bitshift[0] << bitshift2[0];
++      *(pp++) = (buf & colormask[1]) >> bitshift[1] << bitshift2[1];
++      *(pp++) = (buf & colormask[2]) >> bitshift[2] << bitshift2[2];
++      *(pp++) = (buf & colormask[3]) >> bitshift[3] << bitshift2[3];
++      *(pp++) = (buf & colormask[4]) >> bitshift[4] << bitshift2[4];
++      *(pp++) = (buf & colormask[5]) >> bitshift[5] << bitshift2[5];
++    }
++    if (w & 1) { /* padded to 2 pix */
++      buf = getint(fp);
++      *(pp++) = (buf & colormask[0]) >> bitshift[0];
++      *(pp++) = (buf & colormask[1]) >> bitshift[1];
++      *(pp++) = (buf & colormask[2]) >> bitshift[2];
++    }
++  }
++
++  return FERROR(fp)? 1 : 0;
++}
++
++
++
++/*******************************************/
++static int loadBMP24(fp, pic24, w, h, bits)   /* also handles 32-bit BI_RGB */
+      FILE *fp;
+      byte *pic24;
+-     u_int  w,h;
++     u_int  w,h, bits;
+ {
+   int   i,j,padb,rv;
+-  byte *pp;
++  byte *pp = pic24 + ((h - 1) * w * 3);
++  size_t l = w*h*3;
+ 
+   rv = 0;
+ 
+   padb = (4 - ((w*3) % 4)) & 0x03;  /* # of pad bytes to read at EOscanline */
++  if (bits==32) padb = 0;
+ 
+   for (i=h-1; i>=0; i--) {
+     pp = pic24 + (i * w * 3);
+     if ((i&0x3f)==0) WaitCursor();
+-    
+-    for (j=0; j<w; j++) {
++
++    for (j=0; j<w && (pp - pic24 <= l); j++) {
+       pp[2] = getc(fp);   /* blue */
+       pp[1] = getc(fp);   /* green */
+       pp[0] = getc(fp);   /* red */
++      if (bits==32) getc(fp);
+       pp += 3;
+     }
+ 
+@@ -484,30 +671,94 @@
+   }
+ 
+   return rv;
+-}  
++}
++
++
++
++/*******************************************/
++static int loadBMP32(fp, pic24, w, h, colormask) /* 32-bit BI_BITFIELDS only */
++     FILE  *fp;
++     byte  *pic24;
++     u_int w, h, *colormask;
++{
++  int	 x, y;
++  byte	*pp;
++  u_int	 buf;
++  int	 i, bit, bitshift[3], colorbits[3], bitshift2[3];
++
++  for (i = 0; i < 3; ++i) {
++    buf = colormask[i];
++
++    bitshift[i] = 0;
++    for (bit = 0; bit < 32; ++bit) {
++      if (buf & 1)
++	break;
++      else
++	++bitshift[i];
++      buf >>= 1;
++    }
++
++    colorbits[i] = 0;
++    for (; bit < 32; ++bit) {
++      if (buf & 1)
++	++colorbits[i];
++      else
++	break;
++      buf >>= 1;
++    }
++    if (colorbits[i] > 8) {  /* over 8-bit depth */
++      bitshift[i] += (colorbits[i] - 8);
++      bitshift2[i] = 0;
++    } else
++      bitshift2[i] = 8 - colorbits[i];
++  }
++
++  if (DEBUG > 1)
++    fprintf(stderr, "loadBMP32: bitfields\n"
++	    "\tR: bits = %2d, mask = %08x, shift >>%2d, <<%2d\n"
++	    "\tG: bits = %2d, mask = %08x, shift >>%2d, <<%2d\n"
++	    "\tB: bits = %2d, mask = %08x, shift >>%2d, <<%2d\n",
++	    colorbits[0], colormask[0], bitshift[0], bitshift2[0],
++	    colorbits[1], colormask[1], bitshift[1], bitshift2[1],
++	    colorbits[2], colormask[2], bitshift[2], bitshift2[2]);
++
++  for (y = h-1; y >= 0; y--) {
++    pp = pic24 + (3 * w * y);
++    if ((y&0x3f)==0) WaitCursor();
++
++    for(x = w; x > 0; x --) {
++      buf = getint(fp);
++      *(pp++) = (buf & colormask[0]) >> bitshift[0] << bitshift2[0];
++      *(pp++) = (buf & colormask[1]) >> bitshift[1] << bitshift2[1];
++      *(pp++) = (buf & colormask[2]) >> bitshift[2] << bitshift2[2];
++    }
++  }
++
++  return FERROR(fp)? 1 : 0;
++}
+ 
+ 
+ 
+ /*******************************************/
+-static unsigned int getshort(fp)
++static u_int getshort(fp)
+      FILE *fp;
+ {
+   int c, c1;
+   c = getc(fp);  c1 = getc(fp);
+-  return ((unsigned int) c) + (((unsigned int) c1) << 8);
++  return ((u_int) c) + (((u_int) c1) << 8);
+ }
+ 
+ 
+ /*******************************************/
+-static unsigned int getint(fp)
++static u_int getint(fp)
+      FILE *fp;
+ {
+   int c, c1, c2, c3;
+   c = getc(fp);  c1 = getc(fp);  c2 = getc(fp);  c3 = getc(fp);
+-  return ((unsigned int) c) +
+-         (((unsigned int) c1) << 8) + 
+-	 (((unsigned int) c2) << 16) +
+-	 (((unsigned int) c3) << 24);
++  return  ((u_int) c) +
++	 (((u_int) c1) << 8) +
++	 (((u_int) c2) << 16) +
++	 (((u_int) c3) << 24);
+ }
+ 
+ 
+@@ -518,7 +769,7 @@
+ {
+   int c, c1;
+ 
+-  c = ((unsigned int ) i) & 0xff;  c1 = (((unsigned int) i)>>8) & 0xff;
++  c = ((u_int) i) & 0xff;  c1 = (((u_int) i)>>8) & 0xff;
+   putc(c, fp);   putc(c1,fp);
+ }
+ 
+@@ -529,10 +780,10 @@
+      int i;
+ {
+   int c, c1, c2, c3;
+-  c  = ((unsigned int ) i)      & 0xff;  
+-  c1 = (((unsigned int) i)>>8)  & 0xff;
+-  c2 = (((unsigned int) i)>>16) & 0xff;
+-  c3 = (((unsigned int) i)>>24) & 0xff;
++  c  =  ((u_int) i)      & 0xff;
++  c1 = (((u_int) i)>>8)  & 0xff;
++  c2 = (((u_int) i)>>16) & 0xff;
++  c3 = (((u_int) i)>>24) & 0xff;
+ 
+   putc(c, fp);   putc(c1,fp);  putc(c2,fp);  putc(c3,fp);
+ }
+@@ -562,11 +813,11 @@
+    *    8-bit image
+    * note that PIC24 and F_BWDITHER/F_REDUCED won't happen
+    *
+-   * if colorstyle == F_BWDITHER, it writes a 1-bit image 
++   * if colorstyle == F_BWDITHER, it writes a 1-bit image
+    *
+    */
+ 
+-  int i,j, nc, nbits, bperlin, cmaplen;
++  int i,j, nc, nbits, bperlin, cmaplen, npixels;
+   byte *graypic, *sp, *dp, graymap[256];
+ 
+   nc = nbits = cmaplen = 0;
+@@ -576,10 +827,16 @@
+     /* generate a faked 8-bit per pixel image with a grayscale cmap,
+        so that it can just fall through existing 8-bit code */
+ 
+-    graypic = (byte *) malloc((size_t) w*h);
++    npixels = w * h;
++    if (w <= 0 || h <= 0 || npixels/w != h) {
++      SetISTR(ISTR_WARNING, "image dimensions too large");
++      return -1;
++    }
++
++    graypic = (byte *) malloc((size_t) npixels);
+     if (!graypic) FatalError("unable to malloc in WriteBMP()");
+ 
+-    for (i=0,sp=pic824,dp=graypic; i<w*h; i++,sp+=3, dp++) {
++    for (i=0,sp=pic824,dp=graypic; i<npixels; i++,sp+=3, dp++) {
+       *dp = MONO(sp[0],sp[1],sp[2]);
+     }
+ 
+@@ -611,7 +868,7 @@
+     for (i=0; i<numcols; i++) {
+       /* see if color #i is a duplicate */
+       for (j=0; j<i; j++) {
+-	if (rmap[i] == rmap[j] && gmap[i] == gmap[j] && 
++	if (rmap[i] == rmap[j] && gmap[i] == gmap[j] &&
+ 	    bmap[i] == bmap[j]) break;
+       }
+ 
+@@ -689,13 +946,13 @@
+ #else
+   if (!FERROR(fp)) return -1;
+ #endif
+-  
++
+   return 0;
+ }
+ 
+ 
+-	  
+-	  
++
++
+ /*******************************************/
+ static void writeBMP1(fp, pic8, w, h)
+      FILE *fp;
+@@ -708,7 +965,7 @@
+   padw = ((w + 31)/32) * 32;  /* 'w', padded to be a multiple of 32 */
+ 
+   for (i=h-1; i>=0; i--) {
+-    pp = pic8 + (i * w);  
++    pp = pic8 + (i * w);
+     if ((i&0x3f)==0) WaitCursor();
+ 
+     for (j=bitnum=c=0; j<=padw; j++,bitnum++) {
+@@ -716,7 +973,7 @@
+ 	putc(c,fp);
+ 	bitnum = c = 0;
+       }
+-      
++
+       c <<= 1;
+ 
+       if (j<w) {
+@@ -724,7 +981,7 @@
+       }
+     }
+   }
+-}  
++}
+ 
+ 
+ 
+@@ -758,7 +1015,7 @@
+       }
+     }
+   }
+-}  
++}
+ 
+ 
+ 
+@@ -768,7 +1025,7 @@
+      byte *pic8;
+      int  w,h;
+ {
+-  int   i,j,c,padw;
++  int   i,j,padw;
+   byte *pp;
+ 
+   padw = ((w + 3)/4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
+@@ -780,7 +1037,7 @@
+     for (j=0; j<w; j++) putc(pc2nc[*pp++], fp);
+     for ( ; j<padw; j++) putc(0, fp);
+   }
+-}  
++}
+ 
+ 
+ /*******************************************/
+@@ -789,7 +1046,7 @@
+      byte *pic24;
+      int  w,h;
+ {
+-  int   i,j,c,padb;
++  int   i,j,padb;
+   byte *pp;
+ 
+   padb = (4 - ((w*3) % 4)) & 0x03;  /* # of pad bytes to write at EOscanline */
+@@ -807,7 +1064,7 @@
+ 
+     for (j=0; j<padb; j++) putc(0, fp);
+   }
+-}  
++}
+ 
+ 
+ 
+@@ -816,7 +1073,7 @@
+ 
+ /*******************************************/
+ static int bmpError(fname, st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+diff -ru xv-3.10a/xvbrowse.c xv-3.10a-enhancements/xvbrowse.c
+--- xv-3.10a/xvbrowse.c	1995-01-19 09:49:17.000000000 -0800
++++ xv-3.10a-enhancements/xvbrowse.c	2007-05-13 17:50:18.000000000 -0700
+@@ -1,6 +1,6 @@
+ /*
+  *  xvbrowse.c  -  visual schnauzer routines
+- * 
++ *
+  *  includes:
+  *      void CreateBrowse(char *, char *, char *, char *, char *);
+  *      void OpenBrowse();
+@@ -19,11 +19,16 @@
+ 
+ #define NEEDSDIR
+ #include "xv.h"
++#include <unistd.h>   /* access() */
+ 
+ #if defined(VMS) || defined(isc)
+ typedef unsigned int mode_t;  /* file mode bits */
+ #endif
+ 
++#ifndef MAX
++#  define MAX(a,b) (((a)>(b))?(a):(b))   /* used only for wheelmouse support */
++#endif
++
+ 
+ /* load up built-in icons */
+ #include "bits/br_file"
+@@ -34,27 +39,40 @@
+ #include "bits/br_sock"
+ #include "bits/br_fifo"
+ #include "bits/br_error"
+-#include "bits/br_unknown"
++/* #include "bits/br_unknown"	commented out (near line 492) */
++
+ #include "bits/br_cmpres"
++#include "bits/br_bzip2"
+ 
+-#include "bits/br_gif"
+-#include "bits/br_pm"
+-#include "bits/br_pbm"
+-#include "bits/br_xbm"
+-#include "bits/br_sunras"
+ #include "bits/br_bmp"
+-#include "bits/br_utah"
++#include "bits/br_fits"
++#include "bits/br_gif"
++#include "bits/br_iff"
+ #include "bits/br_iris"
+-#include "bits/br_pcx"
+ #include "bits/br_jfif"
+-#include "bits/br_tiff"
++#include "bits/br_jp2"
++#include "bits/br_jpc"
++#include "bits/br_mag"
++#include "bits/br_maki"
++#include "bits/br_mgcsfx"
++#include "bits/br_pbm"
++#include "bits/br_pcd"
++#include "bits/br_pcx"
+ #include "bits/br_pds"
++#include "bits/br_pi"
++#include "bits/br_pic"
++#include "bits/br_pic2"
++#include "bits/br_pm"
++#include "bits/br_png"
+ #include "bits/br_ps"
+-#include "bits/br_iff"
++#include "bits/br_sunras"
+ #include "bits/br_targa"
++#include "bits/br_tiff"
++#include "bits/br_utah"
++#include "bits/br_xbm"
+ #include "bits/br_xpm"
+ #include "bits/br_xwd"
+-#include "bits/br_fits"
++#include "bits/br_zx"	/* [JCE] The Spectrum+3 icon */
+ 
+ #include "bits/br_trash"
+ #include "bits/fcurs"
+@@ -90,17 +108,28 @@
+ #define BF_COMPRESS 21
+ #define BF_PS       22
+ #define BF_IFF      23
+-#define BF_TARGA    24
++#define BF_TGA      24
+ #define BF_XPM      25
+ #define BF_XWD      26
+ #define BF_FITS     27
+-#define BF_MAX      28    /* # of built-in icons */
++#define BF_PNG      28
++#define BF_ZX       29    /* [JCE] Spectrum SCREEN$ */
++#define BF_PCD      30
++#define BF_BZIP2    31
++#define BF_JP2      32
++#define BF_JPC      33
++#define JP_EXT_BF   (BF_JPC)
++#define BF_MAG      (JP_EXT_BF + 1)
++#define BF_MAKI     (JP_EXT_BF + 2)
++#define BF_PIC      (JP_EXT_BF + 3)
++#define BF_PI       (JP_EXT_BF + 4)
++#define BF_PIC2     (JP_EXT_BF + 5)
++#define BF_MGCSFX   (JP_EXT_BF + 6)
++#define JP_EXT_BF_END  (BF_MGCSFX)
++#define BF_MAX      (JP_EXT_BF_END + 1)    /* # of built-in icons */
+ 
+ #define ISLOADABLE(ftyp) (ftyp!=BF_DIR  && ftyp!=BF_CHR && ftyp!=BF_BLK && \
+-			  ftyp!=BF_SOCK && ftyp!=BF_FIFO) 
+-
+-#define DEF_BROWWIDE 615   /* default size of window */
+-#define DEF_BROWHIGH 356
++			  ftyp!=BF_SOCK && ftyp!=BF_FIFO)
+ 
+ #define SCROLLVERT  8      /* height of scroll region at top/bottom of iconw */
+ #define PAGEVERT    40     /* during rect drag, if further than this, page */
+@@ -113,59 +142,93 @@
+ #define BOTMARGIN 58       /* room for a row of buttons and a line of text */
+ #define LRMARGINS 5        /* left and right margins */
+ 
+-#define ISIZE_WIDE   80    /* maximum size of an icon */
+-#define ISIZE_HIGH   60
++/* some people like bigger icons; 4:3 aspect ratio is recommended
++ * (NOTE:  standard XV binaries will not be able to read larger icons!) */
++#ifndef ISIZE_WIDE
++#  define ISIZE_WIDE 80    /* maximum size of an icon */
++#endif
++#ifndef ISIZE_HIGH
++#  define ISIZE_HIGH 60
++#endif
++
++#ifndef ISIZE_WPAD
++#  define ISIZE_WPAD 16    /* extra horizontal padding between icons */
++#endif
++
++#ifndef INUM_WIDE
++#  define INUM_WIDE 6      /* size initial window to hold this many icons */
++#endif
++#ifndef INUM_HIGH
++#  define INUM_HIGH 3
++#endif
+ 
+-#define ISPACE_WIDE (ISIZE_WIDE+16)   /* icon spacing */
++#define ISPACE_WIDE (ISIZE_WIDE+ISIZE_WPAD)   /* icon spacing */
+ #define ISPACE_TOP  4                 /* dist btwn top of ISPACE and ISIZE */
+ #define ISPACE_TTOP 4                 /* dist btwn bot of icon and title */
+ #define ISPACE_HIGH (ISIZE_HIGH+ISPACE_TOP+ISPACE_TTOP+16+4)
+ 
+ #define DBLCLICKTIME 300  /* milliseconds */
+ 
+-/* button/menu indicies */
+-#define BR_CHDIR    0
+-#define BR_DELETE   1
+-#define BR_MKDIR    2
+-#define BR_RENAME   3
+-#define BR_RESCAN   4
+-#define BR_UPDATE   5
+-#define BR_NEWWIN   6
+-#define BR_GENICON  7
+-#define BR_SELALL   8
+-#define BR_TEXTVIEW 9
+-#define BR_RECURSUP 10
+-#define BR_QUIT     11
+-#define BR_CLOSE    12
+-#define BR_NBUTTS   13   /* # of command buttons */
+-#define BR_SEP1     13   /* separator */
+-#define BR_HIDDEN   14
+-#define BR_SELFILES 15
+-#define BR_NCMDS    16   /* # of menu commands */
++#define COUNT(x) (sizeof (x) / sizeof (x)[0])
++
++/* button/menu indices */
++#define BR_CHDIR      0
++#define BR_DELETE     1
++#define BR_MKDIR      2
++#define BR_RENAME     3
++#define BR_RESCAN     4
++#define BR_UPDATE     5
++#define BR_NEWWIN     6
++#define BR_GENICON    7
++#define BR_SELALL     8
++#define BR_TEXTVIEW   9
++#define BR_RECURSUP   10
++#define BR_QUIT       11
++#define BR_CLOSE      12
++#define BR_NBUTTS     13   /* # of command buttons */
++#define BR_SEP1       13   /* separator */
++#define BR_HIDDEN     14
++#define BR_SELFILES   15
++#define BR_CLIPBRD    16
++#ifdef AUTO_EXPAND
++#  define BR_CLEARVD  17
++#  define BR_NCMDS    18   /* # of menu commands */
++#else
++#  define BR_NCMDS    17   /* # of menu commands */
++#endif
+ 
+ #define BUTTW 80
+ #define BUTTH 24
+ 
+-static char *showHstr = "Show hidden files";
+-static char *hideHstr = "Hide 'hidden' files";
+-
+-static char *cmdMList[] = { "Change directory...\t^c",
+-		            "Delete file(s)\t^d",  
+-			    "New directory...\t^n",   
+-			    "Rename file...\t^r",     
+-			    "Rescan directory\t^s",
+-			    "Update icons\t^u",    
+-			    "Open new window\t^w", 
+-			    "Generate icon(s)\t^g",
+-			    "Select all files\t^a",
+-			    "Text view\t^t",
+-			    "Recursive Update\t^e",
+-			    "Quit xv\t^q",
+-			    "Close window\t^c",
+-			    MBSEP,
+-			    "Show hidden files",     /* no equiv */
+-			    "Select files...\t^f"
+-			    };
++/* original size of window was 615 x 356 (for 80x60 thumbnails in 6x3 array) */
++#define DEF_BROWWIDE  (ISPACE_WIDE * INUM_WIDE + LRMARGINS * 2 + 29)
++#define DEF_BROWHIGH  (ISPACE_HIGH * INUM_HIGH + BUTTH * 2 + 16 + 28)
++/* last number is a fudge--e.g., extra spaces, borders, etc. -----^  */
++
++static const char *showHstr = "Show hidden files";
++static const char *hideHstr = "Hide 'hidden' files";
++
++static const char *cmdMList[] = { "Change directory...\t^c",
++				  "Delete file(s)\t^d",
++				  "New directory...\t^n",
++				  "Rename file...\t^r",
++				  "Rescan directory\t^s",
++				  "Update icons\t^u",
++				  "Open new window\t^w",
++				  "Generate icon(s)\t^g",
++				  "Select all files\t^a",
++				  "Text view\t^t",
++				  "Recursive Update\t^e",
++				  "Quit xv\t^q",
++				  "Close window\t^c",
++				  MBSEP,
++				  "Show hidden files",     /* no equiv */
++				  "Select files...\t^f",
++				  "Clipboard\t^x"
++#ifdef AUTO_EXPAND
++				  , "Clear virtual directory"
++#endif
++				  };
+ 
+ 
+ #define MAXDEEP 30     /* maximum directory depth */
+@@ -183,32 +246,43 @@
+ 	       } BFIL;
+ 
+ /* data needed per schnauzer window */
+-typedef struct {  Window win, iconW;
+-		  int    vis, wasvis;
++typedef struct {  Window        win, iconW;
++		  int           vis, wasvis;
+ 
+-		  int    wide, high;
+-		  int    iwWide, iwHigh;
+-		  int    numWide, numHigh, visHigh;
+-
+-		  SCRL   scrl;
+-		  BUTT   but[BR_NBUTTS];
+-		  MBUTT  dirMB, cmdMB;
+-		  char   dispstr[256];
+-		  int    numbutshown;
+-		  int    showhidden;
+-
+-		  int    numlit;
+-		  BFIL  *bfList;
+-		  int    bfLen;
+-		  int    lastIconClicked;
++		  int           wide, high;
++		  int           iwWide, iwHigh;
++		  int           numWide, numHigh, visHigh;
++
++		  SCRL          scrl;
++		  BUTT          but[BR_NBUTTS];
++		  MBUTT         dirMB, cmdMB;
++		  char          dispstr[256];
++		  int           numbutshown;
++		  int           showhidden;
++
++		  int           numlit;
++		  BFIL         *bfList;
++		  int           bfLen;
++		  int           lastIconClicked;
+ 		  unsigned long lastClickTime;
+ 
+-		  int    ndirs;
+-		  char  *mblist[MAXDEEP];
+-		  char   path[MAXPATHLEN+2];   /* '/' terminated */
++		  int           ndirs;
++		  const char   *mblist[MAXDEEP];
++		  char          path[MAXPATHLEN+2];   /* '/' terminated */
++
++		  char         *str;
++		  int           siz, len;
++		  time_t        lst;
+ 		} BROWINFO;
+ 
+ 
++/* keep track of last icon visible in each path */
++typedef struct IVIS IVIS;
++    struct IVIS { IVIS   *next;
++                  char   *name;
++                  int    icon;
++                };
++
+ static Cursor   movecurs, copycurs, delcurs;
+ static BROWINFO binfo[MAXBRWIN];
+ static Pixmap   bfIcons[BF_MAX], trashPix;
+@@ -220,7 +294,7 @@
+ static void closeBrowse      PARM((BROWINFO *));
+ static int  brChkEvent       PARM((BROWINFO *, XEvent *));
+ static void resizeBrowse     PARM((BROWINFO *, int, int));
+-static void setBrowStr       PARM((BROWINFO *, char *));
++static void setBrowStr       PARM((BROWINFO *, const char *));
+ static void doCmd            PARM((BROWINFO *, int));
+ static void drawBrow         PARM((BROWINFO *));
+ static void drawNumfiles     PARM((BROWINFO *));
+@@ -255,12 +329,12 @@
+ static void rescanDir        PARM((BROWINFO *));
+ static int  namcmp           PARM((const void *, const void *));
+ static void freeBfList       PARM((BROWINFO *br));
+-static char **getDirEntries  PARM((char *, int *, int));
++static char **getDirEntries  PARM((const char *, int *, int));
+ static void computeScrlVals  PARM((BROWINFO *, int *, int *));
+ static void genSelectedIcons PARM((BROWINFO *));
+ static void genIcon          PARM((BROWINFO *, BFIL *));
+ static void loadThumbFile    PARM((BROWINFO *, BFIL *));
+-static void writeThumbFile   PARM((BROWINFO *, BFIL *, byte *, int, 
++static void writeThumbFile   PARM((BROWINFO *, BFIL *, byte *, int,
+ 				      int, char *));
+ 
+ static void makeThumbDir     PARM((BROWINFO *));
+@@ -278,14 +352,14 @@
+ static void doSelFilesCmd    PARM((BROWINFO *));
+ 
+ static void doRecurseCmd     PARM((BROWINFO *));
+-static void recurseUpdate    PARM((BROWINFO *, char *));
++static void recurseUpdate    PARM((BROWINFO *, const char *));
+ 
+ static void rm_file          PARM((BROWINFO *, char *));
+ static void rm_dir           PARM((BROWINFO *, char *));
+ static void rm_dir1          PARM((BROWINFO *));
+ 
+-static void dragFiles        PARM((BROWINFO *, BROWINFO *, char *, char *, 
+-				   char *, char **, int, int));
++static void dragFiles        PARM((BROWINFO *, BROWINFO *, char *, char *,
++				   const char *, char **, int, int));
+ static int  moveFile         PARM((char *, char *));
+ static int  copyFile         PARM((char *, char *));
+ static void cp               PARM((void));
+@@ -294,16 +368,25 @@
+ static void cp_special       PARM((struct stat *, int));
+ static void cp_fifo          PARM((struct stat *, int));
+ 
++#ifdef AUTO_EXPAND
++static int  stat2bf          PARM((u_int, char *));
++#else
+ static int  stat2bf          PARM((u_int));
++#endif
+ 
+ static int  selmatch         PARM((char *, char *));
+ static int  selmatch1        PARM((char *, char *));
++static void recIconVisible   PARM((char *, int));
++static void restIconVisible  PARM((BROWINFO *));
++
++static void clipChanges      PARM((BROWINFO *));
+ 
+ 
+ 
+ /***************************************************************/
+ void CreateBrowse(geom, fgstr, bgstr, histr, lostr)
+-     char *geom, *fgstr, *bgstr, *histr, *lostr;
++     const char *geom;
++     const char *fgstr, *bgstr, *histr, *lostr;
+ {
+   int                   i;
+   XSizeHints            hints;
+@@ -369,8 +452,8 @@
+       if (gset & YNegative) gy1 = gy - i * 20;
+ 	               else gy1 = gy + i * 20;
+ 
+-      if ((gset & WidthValue) && (gset & HeightValue)) 
+-	sprintf(wgeom, "%dx%d%s%d%s%d", gw, gh, 
++      if ((gset & WidthValue) && (gset & HeightValue))
++	sprintf(wgeom, "%dx%d%s%d%s%d", gw, gh,
+ 		(gset & XNegative) ? "-" : "+", abs(gx1),
+ 		(gset & YNegative) ? "-" : "+", abs(gy1));
+       else
+@@ -402,11 +485,11 @@
+ 
+     /* note: everything is sized and positioned in ResizeBrowse() */
+ 
+-    br->iconW = XCreateSimpleWindow(theDisp, br->win, 1,1, 100,100, 
++    br->iconW = XCreateSimpleWindow(theDisp, br->win, 1,1, 100,100,
+ 				     1,browfg,browbg);
+     if (!br->iconW) FatalError("can't create schnauzer icon window!");
+ 
+-    SCCreate(&(br->scrl), br->win, 0,0, 1,100, 0,0,0,0, 
++    SCCreate(&(br->scrl), br->win, 0,0, 1,100, 0,0,0,0,
+ 	     browfg, browbg, browhi, browlo, drawIconWin);
+ 
+ 
+@@ -448,10 +531,12 @@
+ 	     "Text view",browfg,browbg,browhi,browlo);
+     BTCreate(&(br->but[BR_RECURSUP]), br->win, 0,0,BUTTW,BUTTH,
+ 	     "RecursUpd",browfg,browbg,browhi,browlo);
+-    BTCreate(&(br->but[BR_QUIT]),  br->win, 0,0,BUTTW,BUTTH,
++    BTCreate(&(br->but[BR_QUIT]), br->win, 0,0,BUTTW,BUTTH,
+ 	     "Quit xv",browfg,browbg,browhi,browlo);
+-    BTCreate(&(br->but[BR_CLOSE]),  br->win, 0,0,BUTTW,BUTTH,
++    BTCreate(&(br->but[BR_CLOSE]), br->win, 0,0,BUTTW,BUTTH,
+ 	     "Close",browfg,browbg,browhi,browlo);
++    BTCreate(&(br->but[BR_CLIPBRD]), br->win, 0,0,BUTTW,BUTTH,
++	     "Clipboard",browfg,browbg,browhi,browlo);
+ 
+     XMapSubwindows(theDisp, br->win);
+ 
+@@ -486,55 +571,62 @@
+   bfIcons[BF_SOCK]=MakePix1(br->win,br_sock_bits,br_sock_width,br_sock_height);
+   bfIcons[BF_FIFO]=MakePix1(br->win,br_fifo_bits,br_fifo_width,br_fifo_height);
+ 
+-  bfIcons[BF_ERROR]   = MakePix1(br->win, br_error_bits, 
++  bfIcons[BF_ERROR]   = MakePix1(br->win, br_error_bits,
+ 			       br_error_width,     br_error_height);
+ 
+ /* bfIcons[BF_UNKNOWN] = MakePix1(br->win, br_unknown_bits,
+                                 br_unknown_width, br_unknown_height); */
+-
+   bfIcons[BF_UNKNOWN] = bfIcons[BF_FILE];
+ 
+-  bfIcons[BF_GIF] =MakePix1(br->win,br_gif_bits, br_gif_width, br_gif_height);
+-  bfIcons[BF_PM]  =MakePix1(br->win,br_pm_bits,  br_pm_width,  br_pm_height);
+-  bfIcons[BF_PBM] =MakePix1(br->win,br_pbm_bits, br_pbm_width, br_pbm_height);
+-  bfIcons[BF_XBM] =MakePix1(br->win,br_xbm_bits, br_xbm_width, br_xbm_height);
+-
+-  bfIcons[BF_SUNRAS]  = MakePix1(br->win, br_sunras_bits,
+-				 br_sunras_width, br_sunras_height);
+-  bfIcons[BF_BMP]     = MakePix1(br->win,br_bmp_bits, 
+-				 br_bmp_width, br_bmp_height);
+-  bfIcons[BF_UTAHRLE] = MakePix1(br->win, br_utahrle_bits, 
+-				 br_utahrle_width, br_utahrle_height);
++  bfIcons[BF_COMPRESS] = MakePix1(br->win, br_cmpres_bits,
++				  br_cmpres_width, br_cmpres_height);
++  bfIcons[BF_BZIP2]    = MakePix1(br->win, br_bzip2_bits,
++				  br_bzip2_width, br_bzip2_height);
+ 
++  bfIcons[BF_BMP] =MakePix1(br->win,br_bmp_bits, br_bmp_width, br_bmp_height);
++  bfIcons[BF_FITS]=MakePix1(br->win,br_fits_bits,br_fits_width,br_fits_height);
++  bfIcons[BF_GIF] =MakePix1(br->win,br_gif_bits, br_gif_width, br_gif_height);
++  bfIcons[BF_IFF] =MakePix1(br->win,br_iff_bits, br_iff_width, br_iff_height);
+   bfIcons[BF_IRIS]=MakePix1(br->win,br_iris_bits,br_iris_width,br_iris_height);
+-  bfIcons[BF_PCX] =MakePix1(br->win,br_pcx_bits, br_pcx_width, br_pcx_height);
+   bfIcons[BF_JFIF]=MakePix1(br->win,br_jfif_bits,br_jfif_width,br_jfif_height);
+-  bfIcons[BF_TIFF]=MakePix1(br->win,br_tiff_bits,br_tiff_width,br_tiff_height);
++  bfIcons[BF_JP2] =MakePix1(br->win,br_jp2_bits, br_jp2_width, br_jp2_height);
++  bfIcons[BF_JPC] =MakePix1(br->win,br_jpc_bits, br_jpc_width, br_jpc_height);
++  bfIcons[BF_MAG] =MakePix1(br->win,br_mag_bits, br_mag_width, br_mag_height);
++  bfIcons[BF_MAKI]=MakePix1(br->win,br_maki_bits,br_maki_width,br_maki_height);
++  bfIcons[BF_PBM] =MakePix1(br->win,br_pbm_bits, br_pbm_width, br_pbm_height);
++  bfIcons[BF_PCD] =MakePix1(br->win,br_pcd_bits, br_pcd_width, br_pcd_height);
++  bfIcons[BF_PCX] =MakePix1(br->win,br_pcx_bits, br_pcx_width, br_pcx_height);
+   bfIcons[BF_PDS] =MakePix1(br->win,br_pds_bits, br_pds_width, br_pds_height);
+-
+-  bfIcons[BF_COMPRESS]= MakePix1(br->win, br_cmpres_bits,
+-				 br_cmpres_width, br_cmpres_height);
+-
++  bfIcons[BF_PIC2]=MakePix1(br->win,br_pic2_bits,br_pic2_width,br_pic2_height);
++  bfIcons[BF_PIC] =MakePix1(br->win,br_pic_bits, br_pic_width, br_pic_height);
++  bfIcons[BF_PI]  =MakePix1(br->win,br_pi_bits,  br_pi_width,  br_pi_height);
++  bfIcons[BF_PM]  =MakePix1(br->win,br_pm_bits,  br_pm_width,  br_pm_height);
++  bfIcons[BF_PNG] =MakePix1(br->win,br_png_bits, br_png_width, br_png_height);
+   bfIcons[BF_PS]  =MakePix1(br->win,br_ps_bits,  br_ps_width,  br_ps_height);
+-  bfIcons[BF_IFF] =MakePix1(br->win,br_iff_bits, br_iff_width, br_iff_height);
+-
+-  bfIcons[BF_TARGA]   = MakePix1(br->win, br_targa_bits,
+-				 br_targa_width, br_targa_height);
+-
++  bfIcons[BF_TGA] =MakePix1(br->win,br_tga_bits, br_tga_width, br_tga_height);
++  bfIcons[BF_TIFF]=MakePix1(br->win,br_tiff_bits,br_tiff_width,br_tiff_height);
++  bfIcons[BF_XBM] =MakePix1(br->win,br_xbm_bits, br_xbm_width, br_xbm_height);
+   bfIcons[BF_XPM] =MakePix1(br->win,br_xpm_bits, br_xpm_width, br_xpm_height);
+   bfIcons[BF_XWD] =MakePix1(br->win,br_xwd_bits, br_xwd_width, br_xwd_height);
+-  bfIcons[BF_FITS]=MakePix1(br->win,br_fits_bits,br_fits_width,br_fits_height);
++  bfIcons[BF_ZX]  =MakePix1(br->win,br_zx_bits,  br_zx_width,  br_zx_height);
++
++  bfIcons[BF_SUNRAS]  = MakePix1(br->win, br_sunras_bits,
++				 br_sunras_width, br_sunras_height);
++  bfIcons[BF_UTAHRLE] = MakePix1(br->win, br_utahrle_bits,
++				 br_utahrle_width, br_utahrle_height);
++  bfIcons[BF_MGCSFX]  = MakePix1(br->win, br_mgcsfx_bits,
++				 br_mgcsfx_width, br_mgcsfx_height);
+ 
+ 
+   /* check that they all got built */
+   for (i=0; i<BF_MAX && bfIcons[i]; i++);
+-  if (i<BF_MAX) 
++  if (i<BF_MAX)
+     FatalError("unable to create all built-in icons for schnauzer");
+ 
+   for (i=0; i<MAXBRWIN; i++) {
+     resizeBrowse(&binfo[i], DEF_BROWWIDE, DEF_BROWHIGH);
+ 
+-    XSelectInput(theDisp, binfo[i].win, ExposureMask | ButtonPressMask | 
++    XSelectInput(theDisp, binfo[i].win, ExposureMask | ButtonPressMask |
+ 		 KeyPressMask | StructureNotifyMask);
+   }
+ 
+@@ -557,7 +649,7 @@
+     movecurs = XCreatePixmapCursor(theDisp,mcpix,fcmpix,&cursfg,&cursbg,13,13);
+     copycurs = XCreatePixmapCursor(theDisp,ccpix,fcmpix,&cursfg,&cursbg,13,13);
+     delcurs  = XCreatePixmapCursor(theDisp,dcpix,fcmpix,&cursbg,&cursfg,13,13);
+-    if (!movecurs || !copycurs || !delcurs) 
++    if (!movecurs || !copycurs || !delcurs)
+       FatalError("unable to create schnauzer cursors...");
+   }
+   else FatalError("unable to create schnauzer cursors...");
+@@ -566,7 +658,7 @@
+   XFreePixmap(theDisp, ccpix);
+   XFreePixmap(theDisp, dcpix);
+   XFreePixmap(theDisp, fcmpix);
+-    
++
+ 
+   hasBeenSized = 1;  /* we can now start looking at browse events */
+ }
+@@ -576,9 +668,10 @@
+ void OpenBrowse()
+ {
+   /* opens up a single browser window */
+-  int i;
++
++  int       i;
+   BROWINFO *br;
+-  char     path[MAXPATHLEN+1];
++  char      path[MAXPATHLEN+1];
+ 
+   /* find next browser to be opened */
+   for (i=0; i<MAXBRWIN; i++) {
+@@ -586,11 +679,11 @@
+     if (!br->vis) break;
+   }
+   if (i==MAXBRWIN) return;  /* full up: shouldn't happen */
+-  
++
+   anyBrowUp = 1;
+   XMapRaised(theDisp, br->win);
+   br->vis = 1;
+-  
++
+   freeBfList(br);
+ 
+   /* see if some browser is pointing to the same path as CWD.  If so,
+@@ -645,7 +738,7 @@
+   /* free all info for this browse window */
+   freeBfList(br);
+   sprintf(br->path, BOGUSPATH);
+-  
++
+   /* turn on 'open new window' command doodads */
+   windowMB.dim[WMB_BROWSE] = 0;
+   for (i=0; i<MAXBRWIN; i++) {
+@@ -698,6 +791,9 @@
+   }
+ }
+ 
++#ifdef VS_RESCMAP
++static int _IfTempOut=0;
++#endif
+ 
+ /***************************************************************/
+ void KillBrowseWindows()
+@@ -730,7 +826,6 @@
+   return 0;
+ }
+ 
+-
+ /***************************************************************/
+ static int brChkEvent(br, xev)
+      BROWINFO *br;
+@@ -739,22 +834,36 @@
+   /* checks event to see if it's a browse-window related thing.  If it
+      is, it eats the event and returns '1', otherwise '0'. */
+ 
+-  int    i, rv;
+-  char buf[1024];
+-
+-  rv = 1;
++  int rv = 1;
+ 
+   if (!hasBeenSized) return 0;  /* ignore evrythng until we get 1st Resize */
+ 
++
++#ifdef VS_RESCMAP
++  /* force change color map if have LocalCmap */
++  if (browPerfect && browCmap && (_IfTempOut==2)) {
++    int i;
++    XSetWindowAttributes xswa;
++
++    xswa.colormap = LocalCmap? LocalCmap : theCmap;
++    for (i=0; i<MAXBRWIN; ++i)
++      XChangeWindowAttributes(theDisp, binfo[i].win, CWColormap, &xswa);
++    XFlush(theDisp);
++    _IfTempOut=1;
++  }
++#endif
++
+   if (xev->type == Expose) {
+     int x,y,w,h;
+     XExposeEvent *e = (XExposeEvent *) xev;
+     x = e->x;  y = e->y;  w = e->width;  h = e->height;
+ 
+     /* throw away excess redraws for 'dumb' windows */
+-    if (e->count > 0 && (e->window == br->scrl.win)) {}
++    if (e->count > 0 && (e->window == br->scrl.win))
++      ;
+ 
+-    else if (e->window == br->scrl.win) SCRedraw(&(br->scrl));
++    else if (e->window == br->scrl.win)
++      SCRedraw(&(br->scrl));
+ 
+     else if (e->window == br->win || e->window == br->iconW) { /* smart wins */
+       /* group individual expose rects into a single expose region */
+@@ -788,7 +897,7 @@
+ 	fprintf(stderr,"grouped %d expose events into %d,%d %dx%d rect\n",
+ 		count, rect.x, rect.y, rect.width, rect.height);
+       }
+-      
++
+       if      (e->window == br->win)   drawBrow(br);
+ 
+       else if (e->window == br->iconW)
+@@ -807,13 +916,55 @@
+     int i,x,y;
+     x = e->x;  y = e->y;
+ 
++#ifdef VS_RESCMAP
++    if (browCmap && browPerfect && (_IfTempOut!=0)) {
++      XSetWindowAttributes  xswa;
++      _IfTempOut--;
++      xswa.colormap = browCmap;
++      for(i=0;i<MAXBRWIN;i++)
++        XChangeWindowAttributes(theDisp, binfo[i].win, CWColormap, &xswa);
++      XFlush(theDisp);
++    }
++#endif
++
+     if (e->button == Button1) {
+       if      (e->window == br->win)      clickBrow(br,x,y);
+       else if (e->window == br->scrl.win) SCTrack(&(br->scrl),x,y);
+       else if (e->window == br->iconW) {
+-	i = clickIconWin(br, x,y,(unsigned long) e->time, 
++	i = clickIconWin(br, x,y,(unsigned long) e->time,
+ 			 (e->state&ControlMask) || (e->state&ShiftMask));
+-
++      }
++      else rv = 0;
++    }
++    else if (e->button == Button4) {   /* note min vs. max, + vs. - */
++      /* scroll regardless of where we are in the browser window */
++      if (e->window == br->win ||
++	  e->window == br->scrl.win ||
++	  e->window == br->iconW)
++      {
++	SCRL *sp=&(br->scrl);
++	int  halfpage=MAX(1,sp->page/2); /* user resize to 1 line? */
++
++	if (sp->val > sp->min+halfpage)
++	  SCSetVal(sp,sp->val-halfpage);
++	else
++	  SCSetVal(sp,sp->min);
++      }
++      else rv = 0;
++    }
++    else if (e->button == Button5) {   /* note max vs. min, - vs. + */
++      /* scroll regardless of where we are in the browser window */
++      if (e->window == br->win ||
++	  e->window == br->scrl.win ||
++	  e->window == br->iconW)
++      {
++	SCRL *sp=&(br->scrl);
++	int  halfpage=MAX(1,sp->page/2); /* user resize to 1 line? */
++
++	if (sp->val < sp->max-halfpage)
++	  SCSetVal(sp,sp->val+halfpage);
++	else
++	  SCSetVal(sp,sp->max);
+       }
+       else rv = 0;
+     }
+@@ -837,7 +988,7 @@
+ 
+       if (br->wide != e->width || br->high != e->height) {
+ 	if (DEBUG) fprintf(stderr,"Forcing a redraw!  (from configure)\n");
+-	XClearArea(theDisp, br->win, 0, 0, 
++	XClearArea(theDisp, br->win, 0, 0,
+ 		   (u_int) e->width, (u_int) e->height, True);
+ 	resizeBrowse(br, e->width, e->height);
+       }
+@@ -877,7 +1028,7 @@
+      int w,h;
+ {
+   XSizeHints hints;
+-  int        i, minv, maxv, curv, page, maxh;
++  int        i, maxv, page, maxh;
+ 
+   if (br->wide == w && br->high == h) return;  /* no change in size */
+ 
+@@ -895,7 +1046,7 @@
+   br->iwHigh = (maxh / ISPACE_HIGH) * ISPACE_HIGH;
+   if (br->iwHigh < ISPACE_HIGH) br->iwHigh = ISPACE_HIGH;
+ 
+-  XMoveResizeWindow(theDisp, br->iconW, LRMARGINS, TOPMARGIN, 
++  XMoveResizeWindow(theDisp, br->iconW, LRMARGINS, TOPMARGIN,
+ 		    (u_int) br->iwWide, (u_int) br->iwHigh);
+ 
+ 
+@@ -907,11 +1058,11 @@
+   for (i=0; i<BR_NBUTTS; i++) {
+     /* 'close' always goes on right-most edge */
+ 
+-    if (i<br->numbutshown) 
++    if (i<br->numbutshown)
+       br->but[i].x = br->wide - (1+br->numbutshown-i) * (BUTTW+5);
+     else if (i==BR_CLOSE)
+       br->but[i].x = br->wide - (BUTTW+5);
+-    else 
++    else
+       br->but[i].x = br->wide + 10;    /* offscreen */
+ 
+     br->but[i].y = br->high - BUTTH - 5;
+@@ -928,11 +1079,11 @@
+   br->numWide = br->iwWide / ISPACE_WIDE;
+   br->visHigh = br->iwHigh / ISPACE_HIGH;
+ 
+-  /* compute minv,maxv,curv,page values based on new current size */
++  /* compute maxv,page values based on new current size */
+   computeScrlVals(br, &maxv, &page);
+   if (br->scrl.val>maxv) br->scrl.val = maxv;
+-  
+-  SCChange(&br->scrl, LRMARGINS+br->iwWide+1, TOPMARGIN, 
++
++  SCChange(&br->scrl, LRMARGINS+br->iwWide+1, TOPMARGIN,
+ 	   1, br->iwHigh, 0, maxv, br->scrl.val, page);
+ }
+ 
+@@ -940,12 +1091,12 @@
+ 
+ /***************************************************************/
+ void SetBrowStr(str)
+-     char *str;
++     const char *str;
+ {
+   /* put string in *all* browse windows */
+   int i;
+ 
+-  for (i=0; i<MAXBRWIN; i++) 
++  for (i=0; i<MAXBRWIN; i++)
+     setBrowStr(&binfo[i], str);
+ }
+ 
+@@ -953,9 +1104,10 @@
+ /***************************************************************/
+ static void setBrowStr(br, str)
+      BROWINFO *br;
+-     char *str;
++     const char *str;
+ {
+   strncpy(br->dispstr, str, (size_t) 256);
++  br->dispstr[255] = '\0';
+   drawBrowStr(br);
+   XFlush(theDisp);
+ }
+@@ -992,7 +1144,7 @@
+ 
+ 	char tmp[64];
+ 
+-	sprintf(tmp, "Re-coloring icons:  processed %d out of %d...", 
++	sprintf(tmp, "Re-coloring icons:  processed %d out of %d...",
+ 		i+1, br->bfLen);
+ 	setBrowStr(br, tmp);
+       }
+@@ -1011,14 +1163,14 @@
+ {
+   /* called when file 'name' has been deleted.  If any of the browsers
+      were showing the directory that the file was in, does a rescan() */
+-  
++
+   int  i;
+   char buf[MAXPATHLEN + 2], *tmp;
+ 
+   strcpy(buf, name);
+-  tmp = BaseName(buf);
++  tmp = (char *) BaseName(buf);  /* intentionally losing constness */
+   *tmp = '\0';     /* truncate after last '/' */
+-  
++
+   for (i=0; i<MAXBRWIN; i++) {
+     if (strcmp(binfo[i].path, buf)==0) rescanDir(&binfo[i]);
+   }
+@@ -1043,6 +1195,8 @@
+      BROWINFO *br;
+      int cmd;
+ {
++  br->lst = 0;
++
+   switch (cmd) {
+   case BR_CHDIR:   doChdirCmd(br);
+                    break;
+@@ -1070,9 +1224,9 @@
+   case BR_GENICON: genSelectedIcons(br);  break;
+ 
+   case BR_SELALL:  {
+-                     int i;  char buf[128];
++                     int i;
+ 
+-		     for (i=0; i<br->bfLen; i++) 
++		     for (i=0; i<br->bfLen; i++)
+ 		       br->bfList[i].lit = 1;
+ 		     br->numlit = br->bfLen;
+ 
+@@ -1087,20 +1241,25 @@
+                    break;
+ 
+   case BR_TEXTVIEW: doTextCmd(br);       break;
+- 
++
+   case BR_QUIT:     Quit(0);             break;
+ 
+   case BR_CLOSE:    closeBrowse(br);     break;
+ 
+   case BR_HIDDEN:   br->showhidden = !br->showhidden;
+-                    br->cmdMB.list[cmd] = (br->showhidden) 
+-		                              ? hideHstr : showHstr;
++                    br->cmdMB.list[cmd] = br->showhidden ? hideHstr : showHstr;
+                     rescanDir(br);
+                     break;
+ 
+   case BR_SELFILES: doSelFilesCmd(br);   break;
+ 
+   case BR_RECURSUP: doRecurseCmd(br);    break;
++
++  case BR_CLIPBRD:  clipChanges(br);     break;
++
++#ifdef AUTO_EXPAND
++  case BR_CLEARVD:  Vdsettle();          break;
++#endif
+   }
+ }
+ 
+@@ -1137,16 +1296,16 @@
+ 
+   if (br->bfLen != 1) sprintf(foo, "%d files", br->bfLen);
+   else strcpy(foo, "1 file");
+-    
++
+   XSetForeground(theDisp, theGC, browbg);
+-  XFillRectangle(theDisp,br->win, theGC, x+1,y+1, 
++  XFillRectangle(theDisp,br->win, theGC, x+1,y+1,
+ 		 (u_int) StringWidth(foo)+6, (u_int) br->dirMB.h-1);
+ 
+   XSetForeground(theDisp,theGC,browfg);
+   XDrawRectangle(theDisp,br->win, theGC, x,y,
+ 		 (u_int) StringWidth(foo)+7, (u_int) br->dirMB.h);
+ 
+-  Draw3dRect(br->win, x+1, y+1, (u_int) StringWidth(foo)+5, 
++  Draw3dRect(br->win, x+1, y+1, (u_int) StringWidth(foo)+5,
+ 	     (u_int) br->dirMB.h-2, R3D_IN, 2,  browhi, browlo, browbg);
+ 
+   XSetForeground(theDisp,theGC,browfg);
+@@ -1163,7 +1322,7 @@
+ 
+   if (nf != 1) sprintf(foo,"%d files",nf);
+   else strcpy(foo,"1 file");
+-    
++
+   XClearArea(theDisp,br->win, 30, br->dirMB.y,
+ 	     (u_int) StringWidth(foo)+8, (u_int) br->dirMB.h+1, False);
+ }
+@@ -1185,13 +1344,13 @@
+ 
+   XSetForeground(theDisp,theGC,browfg);
+   XDrawRectangle(theDisp,br->win, theGC, x,y, (u_int) w, (u_int) h);
+-  Draw3dRect(br->win, x+1, y+1, (u_int) w-2, (u_int) h-2, 
++  Draw3dRect(br->win, x+1, y+1, (u_int) w-2, (u_int) h-2,
+ 	     R3D_IN, 2,  browhi, browlo, browbg);
+ 
+   XSetForeground(theDisp,theGC,browfg);
+   XSetBackground(theDisp,theGC,browbg);
+-  XCopyPlane(theDisp, trashPix, br->win, theGC, 
+-	     0,0,(u_int) br_trash_width, (u_int) br_trash_height, 
++  XCopyPlane(theDisp, trashPix, br->win, theGC,
++	     0,0,(u_int) br_trash_width, (u_int) br_trash_height,
+ 	     x+(w-br_trash_width)/2, y+(h-br_trash_height)/2,
+ 	     1L);
+ }
+@@ -1222,7 +1381,7 @@
+   y = br->high - (BUTTH+10) - (CHIGH + 6);
+ 
+   XSetForeground(theDisp, theGC, browbg);
+-  XFillRectangle(theDisp, br->win, theGC, 0, y+3, 
++  XFillRectangle(theDisp, br->win, theGC, 0, y+3,
+ 		 (u_int) br->wide, (u_int) CHIGH+1);
+ 
+   XSetForeground(theDisp, theGC, browfg);
+@@ -1250,6 +1409,19 @@
+   int i, allowtext;
+ 
+   if (!nostr) setSelInfoStr(br, sel);
++#ifdef AUTO_EXPAND
++  if (Isvdir(br->path)) {
++    BTSetActive(&br->but[BR_DELETE],  0);
++    br->cmdMB.dim[BR_DELETE] = 1;
++
++    BTSetActive(&br->but[BR_RENAME],  0);
++    br->cmdMB.dim[BR_RENAME] = 1;
++
++    BTSetActive(&br->but[BR_MKDIR],  0);
++    br->cmdMB.dim[BR_MKDIR] = 1;
++  }
++  else {
++#endif
+   BTSetActive(&br->but[BR_DELETE],  br->numlit>0);
+   br->cmdMB.dim[BR_DELETE] = !(br->numlit>0);
+ 
+@@ -1258,6 +1430,11 @@
+ 
+   BTSetActive(&br->but[BR_GENICON], br->numlit>0);
+   br->cmdMB.dim[BR_GENICON] = !(br->numlit>0);
++#ifdef AUTO_EXPAND
++  BTSetActive(&br->but[BR_MKDIR],  1);
++  br->cmdMB.dim[BR_MKDIR] = 0;
++  }
++#endif
+ 
+   /* turn on 'text view' cmd if exactly one non-dir is lit */
+   allowtext = 0;
+@@ -1277,7 +1454,7 @@
+ {
+   /* sets the '# files selected' string in the brow window appropriately */
+ 
+-  /* criteria:  
++  /* criteria:
+    *    if no files are lit, display ''
+    *    if 1 file is lit, pretend it was selected, fall through...
+    *    if 1 or more files are lit
+@@ -1316,10 +1493,13 @@
+ 
+ 	else if (bf->ftype != BF_DIR) {     /* no info.  display file size */
+ 	  struct stat st;
+-	      
++
+ 	  sprintf(buf, "%s%s", br->path, bf->name);  /* build filename */
++#ifdef AUTO_EXPAND
++	  Dirtovd(buf);
++#endif
+ 	  if (stat(buf, &st) == 0) {
+-	    sprintf(buf, "%s:  %ld bytes", bf->name, st.st_size);
++	    sprintf(buf, "%s:  %ld bytes", bf->name, (long)st.st_size);
+ 	    strcat(buf, buf1);
+ 	  }
+ 	}
+@@ -1360,8 +1540,8 @@
+       if (j>=0 && j < br->bfLen) drawIcon(br,j);
+     }
+   }
+-      
+-  Draw3dRect(br->iconW, 0, 0, (u_int) br->iwWide-1, (u_int) br->iwHigh-1, 
++
++  Draw3dRect(br->iconW, 0, 0, (u_int) br->iwWide-1, (u_int) br->iwHigh-1,
+ 	     R3D_IN, 2, browhi, browlo, browbg);
+ }
+ 
+@@ -1371,10 +1551,8 @@
+      int delta;
+      SCRL *sptr;
+ {
+-  int   i,indx, x,y, ix,iy, num;
+-  BFIL     *bf;
++  int   i,indx, num;
+   BROWINFO *br;
+-  char  tmpstr[64], *nstr;
+ 
+   /* figure out BROWINFO pointer from SCRL pointer */
+   for (i=0; i<MAXBRWIN; i++) {
+@@ -1385,7 +1563,7 @@
+   br = &binfo[i];
+ 
+   /* make sure we've been sized.  Necessary, as creating/modifying the
+-     scrollbar calls this routine directly, rather than through 
++     scrollbar calls this routine directly, rather than through
+      BrowseCheckEvent() */
+ 
+   if (!hasBeenSized) return;
+@@ -1413,12 +1591,12 @@
+ 	if (y+h > br->iwHigh-4) h = (br->iwHigh-4)-y + 2;
+       }
+       XFillRectangle(theDisp, br->iconW, theGC, x, y, ISPACE_WIDE, (u_int) h);
+-	
++
+       if (indx>=0 && indx < br->bfLen) drawIcon(br, indx);
+     }
+   }
+ 
+-  Draw3dRect(br->iconW, 0, 0, (u_int) br->iwWide-1, (u_int) br->iwHigh-1, 
++  Draw3dRect(br->iconW, 0, 0, (u_int) br->iwWide-1, (u_int) br->iwHigh-1,
+ 	     R3D_IN, 2, browhi, browlo, browbg);
+ }
+ 
+@@ -1431,7 +1609,11 @@
+ {
+   int i,x,y,ix,iy,sw,sh,sx,sy;
+   BFIL *bf;
+-  char  tmpstr[64], fixedname[64], *nstr, *str;
++  const char  *nstr, *cstr;
++  char  tmpstr[64];
++#ifdef VMS
++  char  fixedname[64];
++#endif
+ 
+ 
+   if (num<0 || num >= br->bfLen) return;
+@@ -1463,49 +1645,51 @@
+   }
+ 
+   else if (bf->ftype == BF_HAVEIMG && bf->ximage) {
+-    XPutImage(theDisp, br->iconW, theGC, bf->ximage, 0,0, ix,iy, 
++    XPutImage(theDisp, br->iconW, theGC, bf->ximage, 0,0, ix,iy,
+ 	      (u_int) bf->w, (u_int) bf->h);
+   }
+ 
+   else {  /* shouldn't happen */
+-    XDrawRectangle(theDisp, br->iconW, theGC, ix, iy, 
++    XDrawRectangle(theDisp, br->iconW, theGC, ix, iy,
+ 		   (u_int) bf->w, (u_int) bf->h);
+   }
+ 
+ 
+-  str = bf->name;
++  cstr = bf->name;
+ #ifdef VMS
+   if (bf->ftype == BF_DIR) {
++    char  *vstr;
+     strcpy(fixedname, bf->name);
+-    str = rindex(fixedname, '.');   /* lop off '.DIR' suffix, if any */
+-    if (str) *str = '\0';
+-    str = fixedname;
++    vstr = rindex(fixedname, '.');   /* lop off '.DIR' suffix, if any */
++    if (vstr) *vstr = '\0';
++    cstr = fixedname;
+   }
+ #endif /* VMS */
+ 
+-  if (!strcmp(bf->name,"..")) str = "<parent>";
++  if (!strcmp(bf->name,"..")) cstr = "<parent>";
+ 
+ 
+   /* decide if the title is too big, and shorten if neccesary */
+-  if (StringWidth(str) > ISPACE_WIDE-6) {
+-    int dotpos; 
+-    strncpy(tmpstr, str, (size_t) 56);
++  if (StringWidth(cstr) > ISPACE_WIDE-6) {
++    int dotpos;
++    strncpy(tmpstr, cstr, (size_t) 56);
++    tmpstr[56] = '\0'; /* MR: otherwise it dies on long file names */
+     dotpos = strlen(tmpstr);
+     strcat(tmpstr,"...");
+ 
+     while(StringWidth(tmpstr) > ISPACE_WIDE-6 && dotpos>0) {
+       /* change last non-dot char in tmpstr to a dot, and lop off
+ 	 last dot */
+-	    
++
+       dotpos--;
+       tmpstr[dotpos] = '.';
+       tmpstr[dotpos+3] = '\0';
+     }
+-    
++
+     nstr = tmpstr;
+   }
+-  else nstr = str;
+-  
++  else nstr = cstr;
++
+ 
+   /* draw the title */
+   sw = StringWidth(nstr);
+@@ -1516,12 +1700,12 @@
+ 
+   XSetForeground(theDisp, theGC,
+ 		 (bf->lit && bf->lit!=ICON_ONLY) ? browfg : browbg);
+-  XFillRectangle(theDisp, br->iconW, theGC, sx, sy, 
++  XFillRectangle(theDisp, br->iconW, theGC, sx, sy,
+ 		 (u_int) sw + 4, (u_int) sh + 2);
+ 
+   XSetForeground(theDisp, theGC,
+ 		 (bf->lit && bf->lit!=ICON_ONLY) ? browbg : browfg);
+-  CenterString(br->iconW, x + ISPACE_WIDE/2, 
++  CenterString(br->iconW, x + ISPACE_WIDE/2,
+ 	       y + ISPACE_TOP + ISIZE_HIGH + ISPACE_TTOP + CHIGH/2, nstr);
+ }
+ 
+@@ -1535,7 +1719,6 @@
+ 
+   int i,x,y,ix,iy,w,h;
+   BFIL *bf;
+-  char  tmpstr[64], *nstr;
+ 
+   if (num<0 || num >= br->bfLen) return;
+   bf = &(br->bfList[num]);
+@@ -1579,12 +1762,12 @@
+   y = (i / br->numWide) * ISPACE_HIGH;
+ 
+   XSetForeground(theDisp, theGC, browbg);
+-  XFillRectangle(theDisp, br->iconW, theGC, 
++  XFillRectangle(theDisp, br->iconW, theGC,
+ 		 x, y + ISPACE_TOP + ISIZE_HIGH + ISPACE_TTOP - 1,
+ 		 (u_int) ISPACE_WIDE, (u_int) LINEHIGH);
+ 
+-  if (ctrlColor) 
+-    Draw3dRect(br->iconW, 0, 0, (u_int) br->iwWide-1, (u_int) br->iwHigh-1, 
++  if (ctrlColor)
++    Draw3dRect(br->iconW, 0, 0, (u_int) br->iwWide-1, (u_int) br->iwHigh-1,
+ 	       R3D_IN, 2, browhi, browlo, browbg);
+ }
+ 
+@@ -1597,6 +1780,10 @@
+ {
+   int sval, first, numvis;
+ 
++  /* if we know what path we have, remember last visible icon for this path */
++  if (br->path)
++    recIconVisible(br->path, num);
++
+   /* if icon #i isn't visible, adjust scrollbar so it *is* */
+ 
+   sval = br->scrl.val;
+@@ -1648,29 +1835,14 @@
+   return;
+ }
+ 
+-
+ /***************************************************************/
+-static int clickIconWin(br, mx, my, mtime, multi)
+-     BROWINFO *br;
+-     int mx,my,multi;
+-     unsigned long mtime;
++static int updateSel(br, sel, multi, mtime)
++  BROWINFO *br;
++  int sel, multi;
++  unsigned long mtime;
+ {
+-  /* returns '-1' normally, returns an index into bfList[] if the user
+-     double-clicks an icon */
+-
+-  int       i,j, base, num, x,y,ix,iy, rv, sel, cpymode, dodel;
+-  BROWINFO *destBr;
+-  BFIL     *bf;
+-  char      buf[256], *destFolderName;
+-
+-  rv = -1;     /* default return value */
+-  if (!br->bfList || !br->bfLen) return rv;
+-
+-  destBr = br;  destFolderName = ".";
+-
+-  sel = mouseInWhichIcon(br, mx, my);
+-
+-  dodel = 0;
++  int i;
++  BFIL *bf;
+ 
+   if (sel == -1) {  /* clicked on nothing */
+     if (!multi) {   /* deselect all */
+@@ -1681,7 +1853,7 @@
+     }
+ 
+     changedNumLit(br, sel, 0);
+-    br->lastIconClicked = -1;  
++    br->lastIconClicked = -1;
+   }
+ 
+ 
+@@ -1725,14 +1897,14 @@
+ 
+     changedNumLit(br, sel, 0);
+ 
+-    
++
+     /* see if we've double-clicked something */
+-    if (sel==br->lastIconClicked && mtime-br->lastClickTime < DBLCLICKTIME) {
+-      int k;
++    if (mtime &&
++        sel==br->lastIconClicked && mtime-br->lastClickTime < DBLCLICKTIME) {
+       br->lastIconClicked = -1;    /* YES */
+ 
+       doubleClick(br, sel);
+-      return rv;
++      return -1;
+     }
+ 
+     else {
+@@ -1741,9 +1913,37 @@
+     }
+   }
+ 
+-
+   changedNumLit(br, -1, 0);
++  return 0;
++}
++
++
++/***************************************************************/
++static int clickIconWin(br, mx, my, mtime, multi)
++     BROWINFO *br;
++     int mx,my,multi;
++     unsigned long mtime;
++{
++  /* returns '-1' normally, returns an index into bfList[] if the user
++     double-clicks an icon */
++
++  int         i,j, sel, cpymode, dodel;
++  BROWINFO   *destBr;
++  BFIL       *bf;
++  char        buf[256];
++  const char *destFolderName;
++
++  if (!br->bfList || !br->bfLen) return -1;
++
++  destBr = br;  destFolderName = ".";
+ 
++  sel = mouseInWhichIcon(br, mx, my);
++  dodel = 0;
++
++  recIconVisible(br->path, sel);
++
++  if (updateSel(br, sel, multi, mtime))
++    return -1;
+ 
+ 
+   {    /* track mouse until button1 is released */
+@@ -1759,10 +1959,10 @@
+     first = 1;  hasrect = 0;  cpymode = 0;
+     origsval = br->scrl.val;
+ 
+-    if ( (sel>=0 && !multi) || sel==-1) {  
++    if ( (sel>=0 && !multi) || sel==-1) {
+       /* clicked on an icon, or clicked on nothing... */
+ 
+-      while (!XQueryPointer(theDisp, rootW, &rW, &cW, &rootx, &rooty, 
++      while (!XQueryPointer(theDisp, rootW, &rW, &cW, &rootx, &rooty,
+ 			    &x,&y,&mask));
+       if (mask & Button1Mask) {  /* still held down */
+ 
+@@ -1773,7 +1973,7 @@
+ 	else curs = movecurs;
+ 
+ 	/* change cursors */
+-	for (i=0; i<MAXBRWIN; i++) 
++	for (i=0; i<MAXBRWIN; i++)
+ 	  XDefineCursor(theDisp,binfo[i].iconW, curs);
+ 
+ 	samepos = oldx = oldy = oldbrnum = 0;
+@@ -1785,43 +1985,43 @@
+ 
+ 	  if (sel>=0) {  /* see if changed copy/move status (and cursor) */
+ 	    int cmod;
+-	    
++
+ 	    cmod = (mask&ControlMask || mask&ShiftMask) ? 1 : 0;
+ 
+ 	    if (cmod != cpymode && !dodel) {
+ 	      curs = (cmod) ? copycurs : movecurs;
+-	      	for (i=0; i<MAXBRWIN; i++) 
++	      	for (i=0; i<MAXBRWIN; i++)
+ 		  XDefineCursor(theDisp,binfo[i].iconW, curs);
+ 	    }
+ 	    cpymode = cmod;
+-	    
+-	    
++
++
+ 	    /* see if cursor is in any of the trash can areas */
+ 	    for (i=0; i<MAXBRWIN; i++) {
+ 	      if (binfo[i].vis) {
+-		XTranslateCoordinates(theDisp, rW, binfo[i].win, rootx,rooty, 
++		XTranslateCoordinates(theDisp, rW, binfo[i].win, rootx,rooty,
+ 				      &bwx,&bwy, &cW);
+ 		if (inTrash(&binfo[i], bwx, bwy)) break;
+ 	      }
+ 	    }
+-	    
++
+ 	    if (dodel && i==MAXBRWIN) {        /* moved out */
+ 	      dodel = 0;
+ 	      curs = (cpymode) ? copycurs : movecurs;
+-	      for (i=0; i<MAXBRWIN; i++) 
++	      for (i=0; i<MAXBRWIN; i++)
+ 		XDefineCursor(theDisp,binfo[i].iconW, curs);
+ 	    }
+-	    
++
+ 	    else if (!dodel && i<MAXBRWIN) {   /* moved in */
+ 	      dodel = 1;
+-	      for (i=0; i<MAXBRWIN; i++) 
++	      for (i=0; i<MAXBRWIN; i++)
+ 		XDefineCursor(theDisp,binfo[i].iconW, delcurs);
+ 	    }
+ 	  }
+ 
+ 
+ 
+-	  XTranslateCoordinates(theDisp, rW, br->iconW, rootx,rooty, 
++	  XTranslateCoordinates(theDisp, rW, br->iconW, rootx,rooty,
+ 				&iwx,&iwy, &cW);
+ 
+ 	  /* find deepest child that the mouse is in */
+@@ -1837,12 +2037,12 @@
+ 	  /* if it's in any icon window, and we're doing icon-dragging
+ 	     OR we're doing a rectangle-drag */
+ 
+-	  if (i<MAXBRWIN || sel == -1) {  
++	  if (i<MAXBRWIN || sel == -1) {
+ 	    if (i<MAXBRWIN) destBr = &binfo[i];
+ 	    if (sel == -1)  destBr = br;
+ 
+-	    /* AUTO-SCROLLING:  scroll any icon window if we're doing an 
+-	       icon-drag.  Only scroll the original window if we're doing 
++	    /* AUTO-SCROLLING:  scroll any icon window if we're doing an
++	       icon-drag.  Only scroll the original window if we're doing
+ 	       a rect drag */
+ 
+ 	    if (sel>=0 && (oldx!=x || oldy!=y || oldbrnum!=i)) {  /* moved */
+@@ -1873,7 +2073,7 @@
+ 	      }
+ 	    }
+ 
+-	    
++
+ 	    /* if we clicked on an icon (originally), and therefore are
+ 	       showing the 'move files' cursor, see if the cursor is within
+ 	       the icon region of any folders.  If so, light up *the icon
+@@ -1904,9 +2104,9 @@
+ 
+ 	    /* Dragging a selection rectangle. */
+ 
+-	    else { 
++	    else {
+ 	      static int prevx, prevy, prevcnt;
+-	      int        origy, top, left, wide, high, cnt;
++	      int        origy, cnt;
+ 
+ 	      if (first) { prevx = mx;  prevy = my;  first=0;  prevcnt = -1; }
+ 
+@@ -1922,18 +2122,18 @@
+ 
+ 		rx  = (mx    < x) ? mx    : x;
+ 		ry  = (origy < y) ? origy : y;
+-		rw  = abs(mx - x);  
++		rw  = abs(mx - x);
+ 		rh  = abs(origy - y);
+ 
+ 		/* figure out which icons need to be lit/unlit.  Only
+ 		   redraw those that have changed state */
+-		
++
+ 		for (i=0,cnt=0, bf=br->bfList; i<br->bfLen; i++,bf++) {
+-		  int ix, iy, isin, light;
++		  int ix, iy, isin;
+ 
+-		  ix = ((i%br->numWide) * ISPACE_WIDE) 
++		  ix = ((i%br->numWide) * ISPACE_WIDE)
+ 		                  + ISPACE_WIDE/2 - bf->w/2;
+-		  iy = ((i/br->numWide) * ISPACE_HIGH) 
++		  iy = ((i/br->numWide) * ISPACE_HIGH)
+ 		                  + ISPACE_TOP + ISIZE_HIGH - bf->h;
+ 
+ 		  iy = iy - br->scrl.val * ISPACE_HIGH;
+@@ -1994,7 +2194,7 @@
+ 	}
+ 
+ 	/* RELEASED BUTTON:  back to normal arrow cursor */
+-	for (i=0; i<MAXBRWIN; i++) 
++	for (i=0; i<MAXBRWIN; i++)
+ 	  XDefineCursor(theDisp, binfo[i].iconW, None);
+ 
+ 	if (sel == -1) {  /* was dragging rectangle */
+@@ -2007,7 +2207,7 @@
+ 	    if (bf->lit == TEMP_LIT || bf->lit == TEMP_LIT1) {
+ 	      bf->lit = 1;  drawIcon(br, i);
+ 	    }
+-	    
++
+ 	    if (bf->lit) br->numlit++;
+ 	  }
+ 
+@@ -2020,7 +2220,6 @@
+ 
+   /* if doing a copy or a move, do the thing to the files */
+   if (sel >= 0) {
+-    char *destFolder;
+ 
+     if (DEBUG) {
+       fprintf(stderr,"---------------\n");
+@@ -2029,7 +2228,7 @@
+       fprintf(stderr,"Dest Folder: '%s'\n", destFolderName);
+     }
+ 
+-    
++
+     if (!br->numlit) {
+       if (DEBUG) fprintf(stderr, "no selected files.  Nothing to do!\n");
+     }
+@@ -2042,7 +2241,7 @@
+       if (DEBUG) fprintf(stderr, "no destination.  Nothing to do!\n");
+     }
+ 
+-    else if (strcmp(destFolderName,".")     == 0 && 
++    else if (strcmp(destFolderName,".")     == 0 &&
+ 	     strcmp(br->path, destBr->path) == 0) {
+       if (DEBUG) fprintf(stderr,"source == destination.  Nothing to do!\n");
+     }
+@@ -2067,20 +2266,20 @@
+ 	}
+       }
+       if (DEBUG) fprintf(stderr,"\n\n");
+- 
++
+ #ifdef VMS
+       /*
+-       * For VMS, our directory file names are identifed by the 
+-       * special filename extension, ".DIR".  Unfortunately, this 
+-       * needs to be stripped before we ever actually use the name 
++       * For VMS, our directory file names are identifed by the
++       * special filename extension, ".DIR".  Unfortunately, this
++       * needs to be stripped before we ever actually use the name
+        * in a copy command... :(     RLD 26-FEB-1993
+        */
+ 
+-      *rindex ( destFolderName, '.' ) = '\0';
++      *rindex ( destFolderName, '.' ) = '\0';  /* FIXME: potentially writing into static strings! */
+ #endif
+ 
+ 
+-      dragFiles(br, destBr, br->path, destBr->path, destFolderName, nlist, 
++      dragFiles(br, destBr, br->path, destBr->path, destFolderName, nlist,
+ 		ncnt, cpymode);
+ 
+       /* free namelist */
+@@ -2099,7 +2298,7 @@
+     }
+   }      /* end of 'tracking' sub-function */
+ 
+-  return rv;
++  return -1;
+ }
+ 
+ /*******************************************/
+@@ -2113,6 +2312,8 @@
+ 
+   /* called to 'open' icon #sel, which could be a file or a dir */
+ 
++  br->lst = 0;
++
+   /* if sel == -1, then called via RETURN key.  just use first lit item
+      as thing that was double clicked on */
+ 
+@@ -2155,7 +2356,7 @@
+   }
+ 
+ 
+-  
++
+   /* double-clicked something.  We should do something about it */
+   if (br->bfList[sel].ftype == BF_DIR) {  /* try to cd */
+ #ifndef VMS
+@@ -2165,15 +2366,36 @@
+     else sprintf(buf, "%s%s", br->path, br->bfList[sel].name);
+ #endif
+ 
++#ifdef AUTO_EXPAND
++    if (Chvdir(buf)) {
++#else
+     if (chdir(buf)) {
++#endif
+       char str[512];
+       sprintf(str,"Unable to cd to '%s'\n", br->bfList[sel].name);
+       setBrowStr(br, str);
+       XBell(theDisp, 50);
+     }
+     else {
++#ifdef AUTO_EXPAND
++      if (Isvdir(buf)) {
++	BTSetActive(&br->but[BR_DELETE],  0);
++	br->cmdMB.dim[BR_DELETE] = 1;
++
++	BTSetActive(&br->but[BR_RENAME],  0);
++	br->cmdMB.dim[BR_RENAME] = 1;
++
++	BTSetActive(&br->but[BR_MKDIR],  0);
++	br->cmdMB.dim[BR_MKDIR] = 1;
++      }
++      else {
++	BTSetActive(&br->but[BR_MKDIR],  1);
++	br->cmdMB.dim[BR_MKDIR] = 0;
++      }
++#endif
+       scanDir(br);
+       SCSetVal(&(br->scrl), 0);  /* reset to top on a chdir */
++      restIconVisible(br);
+     }
+   }
+ 
+@@ -2193,7 +2415,26 @@
+       *event_retP = THISNEXT;
+     }
+     else { *event_retP = LOADPIC;  SetDirFName(buf);  }
+-    
++
++#ifdef VS_RESCMAP
++    /* Change Colormap for browser */
++    if (browPerfect && browCmap) {
++      int i;
++      XSetWindowAttributes  xswa;
++      if(LocalCmap) {
++	xswa.colormap = LocalCmap;
++	_IfTempOut=2;
++      }
++      else {
++	xswa.colormap = theCmap;
++	_IfTempOut=2;
++      }
++      for(i=0;i<MAXBRWIN;i++)
++	XChangeWindowAttributes(theDisp, binfo[i].win, CWColormap, &xswa);
++      XFlush(theDisp);
++    }
++#endif
++
+     *event_doneP = 1;     /* make MainLoop load image */
+   }
+ }
+@@ -2259,7 +2500,7 @@
+   stlen = XLookupString(kevt, buf, 128, &ks, (XComposeStatus *) NULL);
+   shift = kevt->state & ShiftMask;
+   ck    = CursorKey(ks, shift, 1);
+-  dealt = 1;  
++  dealt = 1;
+ 
+   RemapKeyCheck(ks, buf, &stlen);
+ 
+@@ -2289,6 +2530,7 @@
+   case '\021': doCmd(br, BR_QUIT);     break;      /* ^Q = Quit xv */
+ 
+   case '\006': doCmd(br, BR_SELFILES); break;      /* ^F = Select Files */
++  case '\030': doCmd(br, BR_CLIPBRD);  break;      /* ^X = Copy to clipboard */
+ 
+ 
+   /* case '\003': FakeButtonPress(&but[BCMTVIEW]); break; */    /* ^C */
+@@ -2299,6 +2541,9 @@
+   case '\n':   doubleClick(br, -1);   break;      /* RETURN = load selected */
+ 
+   case ' ':
++    if (br->lst && (time(NULL) <= br->lst + incrementalSearchTimeout))
++      goto do_default;
++    /* else fall through... */
+   case '\010':
+   case '\177':   /* SPACE = load next, BS/DEL = load prev */
+     if (br->bfLen && br->numlit >= 1) {
+@@ -2306,7 +2551,7 @@
+       char fname[MAXPATHLEN];
+ 
+       /* if 'shift-space' find last lit icon, select the next one after it,
+-	 and load it.  If 'space' do the same, but lose prior lit.  These 
++	 and load it.  If 'space' do the same, but lose prior lit.  These
+ 	 are the only cases where br->numlit >1 allowed */
+ 
+       if (br->numlit>1  && buf[0] != ' ') return;
+@@ -2314,7 +2559,7 @@
+       if (buf[0]==' ' && (br->numlit>1 || (br->numlit==1 && shift))) {
+ 	for (i=br->bfLen-1; i>=0 && !br->bfList[i].lit; i--);  /* i=last lit */
+ 	if (i==br->bfLen-1) return;
+-	
++
+ 	i++;
+ 	if (!shift) {
+ 	  for (j=0; j<br->bfLen; j++) {
+@@ -2348,6 +2593,9 @@
+ 
+ 	  /* try to open this file */
+ 	  sprintf(foo, "%s%s", br->path, br->bfList[i].name);
++#ifdef AUTO_EXPAND
++	Dirtovd(foo);
++#endif
+ 	  for (j=0; j<numnames && strcmp(namelist[j],foo); j++);
+ 	  if (j<numnames) {
+ 	    curname = nList.selected = j;
+@@ -2363,8 +2611,11 @@
+       else {          /* not SPACE, or SPACE and lit=1 and not shift */
+ 	for (i=0; i<br->bfLen && !br->bfList[i].lit; i++);  /* find lit one */
+ 	sprintf(fname, "%s%s", br->path, br->bfList[i].name);
++#ifdef AUTO_EXPAND
++	Dirtovd(fname);
++#endif
+ 	viewsel = !(strcmp(fname, fullfname));
+-	
++
+ 	if (viewsel) {
+ 	  if (buf[0]==' ') browKey(br, CK_RIGHT);
+ 	              else browKey(br, CK_LEFT);
+@@ -2372,7 +2623,7 @@
+ 
+ 	if (!br->bfList[i].lit || !viewsel) {   /* changed selection */
+ 	  for (i=0; i<br->bfLen && !br->bfList[i].lit; i++);  /* find it */
+-	  if (br->bfList[i].ftype != BF_DIR) 
++	  if (br->bfList[i].ftype != BF_DIR)
+ 	    doubleClick(br, -1);
+ 	}
+       }
+@@ -2381,7 +2632,8 @@
+ 
+ 
+   default:  /* unknown character.  Take it as an alpha accelerator */
+-    if (buf[0] > 32) browAlpha(br, buf[0]);
++  do_default:  /* (goto-label, not switch-label) */
++    if (buf[0] >= 32) browAlpha(br, buf[0]);
+                 else XBell(theDisp, 0);
+     break;
+   }
+@@ -2401,6 +2653,8 @@
+   /* an arrow key (or something like that) was pressed in icon window.
+      change selection/scrollbar accordingly */
+ 
++  br->lst = 0;
++
+   /* handle easy keys */
+   if (key == CK_PAGEUP)   SCSetVal(&br->scrl, br->scrl.val - br->scrl.page);
+   if (key == CK_PAGEDOWN) SCSetVal(&br->scrl, br->scrl.val + br->scrl.page);
+@@ -2410,10 +2664,10 @@
+   /* handle up/down/left/right keys
+    *
+    * if precisely *one* item is lit, than the up/down/left/right keys move
+-   * the selection.  
++   * the selection.
+    *
+    * if NO items are lit, then left/right select the first/last fully-displayed
+-   * icon, and up/down simply scroll window up or down, without selecting 
++   * icon, and up/down simply scroll window up or down, without selecting
+    * anything
+    *
+    * if more than one item is lit, up/down/left/right keys BEEP
+@@ -2443,8 +2697,8 @@
+ 	if (key == CK_DOWN)  j = i + br->numWide;
+ 	if (key == CK_LEFT)  j = i - 1;
+ 	if (key == CK_RIGHT) j = i + 1;
+-	
+-	if (j >= 0 && j < br->bfLen) {  
++
++	if (j >= 0 && j < br->bfLen) {
+ 	  br->bfList[i].lit = 0;
+ 	  br->bfList[j].lit = 1;
+ 	  makeIconVisible(br,j);
+@@ -2455,7 +2709,7 @@
+       }
+     }
+ 
+-  
++
+     if (br->numlit == 0) {   /* no current selection */
+       if (key == CK_UP)   SCSetVal(&br->scrl, br->scrl.val - 1);
+       if (key == CK_DOWN) SCSetVal(&br->scrl, br->scrl.val + 1);
+@@ -2482,15 +2736,28 @@
+   /* find first 'plain' file that is lexically >= than the given ch */
+ 
+   int i,j;
++  time_t now = time(NULL);
+ 
+   if (!br->bfLen) return;
+-  if (ch <= ' ' || ch > '\177')  return;    /* ignore 'funny' keys */
++  if (ch < ' ' || ch > '\177')  return;    /* ignore 'funny' keys */
+ 
+   for (i=0; i<br->bfLen && br->bfList[i].ftype==BF_DIR; i++);
+   if (i==br->bfLen) return;    /* only directories in this dir */
+ 
++  if (!br->lst || (br->lst + incrementalSearchTimeout < now)) br->len = 0;
++  br->lst = now;
++  
++  if (br->len + 2 > br->siz)
++    if ((br->str = (char *)realloc(br->str, (br->siz = br->len + 32))) == NULL)
++       br->siz = br->len = 0;
++  
++  if (br->len + 2 <= br->siz) {
++    br->str[br->len++] = ch;
++    br->str[br->len] = '\0';
++  }
++
+   for ( ; i<br->bfLen; i++) {
+-    if (br->bfList[i].name[0] >= ch) break;
++    if (strncmp(br->bfList[i].name, br->str, br->len) >= 0) break;
+   }
+ 
+   if (i==br->bfLen) i--;
+@@ -2541,20 +2808,24 @@
+        *  The VMS chdir always needs 2 components (device and directory),
+        *  so convert "/device" to "/device/000000" and convert
+        *  "/" to "/XV_Root_Device/000000" (XV_RootDevice will need to be
+-       *  a special concealed device setup to provide list of available 
++       *  a special concealed device setup to provide list of available
+        *  disks).
+        *
+        *  End 'tmppath' by changing trailing '/' (of dir name) to a '\0'
+        */
+       *rindex ( tmppath, '/') = '\0';
+-      if ( ((br->ndirs-sel) == 2) && (strlen(tmppath) > 1) ) 
++      if ( ((br->ndirs-sel) == 2) && (strlen(tmppath) > 1) )
+ 	strcat ( tmppath, "/000000" ); /* add root dir for device */
+       else if  ((br->ndirs-sel) == 1 )
+ 	strcpy ( tmppath, "/XV_Root_Device/000000" );  /* fake top level */
+     }
+ #endif
+ 
++#ifdef AUTO_EXPAND
++    if (Chvdir(tmppath)) {
++#else
+     if (chdir(tmppath)) {
++#endif
+       char str[512];
+       sprintf(str,"Unable to cd to '%s'\n", tmppath);
+       MBRedraw(&(br->dirMB));
+@@ -2562,8 +2833,25 @@
+       XBell(theDisp, 50);
+     }
+     else {
++#ifdef AUTO_EXPAND
++      if (Isvdir(tmppath)) {
++	BTSetActive(&br->but[BR_DELETE],  0);
++	br->cmdMB.dim[BR_DELETE] = 1;
++
++	BTSetActive(&br->but[BR_RENAME],  0);
++	br->cmdMB.dim[BR_RENAME] = 1;
++
++	BTSetActive(&br->but[BR_MKDIR],  0);
++	br->cmdMB.dim[BR_MKDIR] = 1;
++      }
++      else {
++	BTSetActive(&br->but[BR_MKDIR],  1);
++	br->cmdMB.dim[BR_MKDIR] = 0;
++      }
++#endif
+       scanDir(br);
+       SCSetVal(&br->scrl, 0);  /* reset to top of window on a chdir */
++      restIconVisible(br);
+     }
+   }
+ }
+@@ -2582,7 +2870,11 @@
+   if ((strlen(br->path) > (size_t) 2) && br->path[strlen(br->path)-1] == '/')
+     br->path[strlen(br->path)-1] = '\0';
+ 
++#ifdef AUTO_EXPAND
++  rv = Chvdir(br->path);
++#else
+   rv = chdir(br->path);
++#endif
+   if (rv) {
+     char str[512];
+     sprintf(str, "Unable to cd to '%s'\n", br->path);
+@@ -2590,6 +2882,24 @@
+     XBell(theDisp, 50);
+   }
+ 
++#ifdef AUTO_EXPAND
++  if (Isvdir(br->path)) {
++    BTSetActive(&br->but[BR_DELETE],  0);
++    br->cmdMB.dim[BR_DELETE] = 1;
++
++    BTSetActive(&br->but[BR_RENAME],  0);
++    br->cmdMB.dim[BR_RENAME] = 1;
++
++    BTSetActive(&br->but[BR_MKDIR],  0);
++    br->cmdMB.dim[BR_MKDIR] = 1;
++  }
++  else {
++    BTSetActive(&br->but[BR_MKDIR],  1);
++    br->cmdMB.dim[BR_MKDIR] = 0;
++  }
++#endif
++
++  restIconVisible(br);
+   strcat(br->path, "/");   /* put trailing '/' back on */
+   return rv;
+ }
+@@ -2599,7 +2909,7 @@
+ static void copyDirInfo(srcbr, dstbr)
+      BROWINFO *srcbr, *dstbr;
+ {
+-  /* copies br info from an already existing browser window 
++  /* copies br info from an already existing browser window
+      (ie, one that is already showing the same directory) */
+ 
+   int i, oldnum, maxv, page;
+@@ -2611,15 +2921,19 @@
+   /* copy mblist */
+   dstbr->ndirs = srcbr->ndirs;
+   for (i=0;  i<dstbr->ndirs;  i++) {
+-    dstbr->mblist[i] = (char *) malloc(strlen(srcbr->mblist[i]) + 1);
++    dstbr->mblist[i] = strdup(srcbr->mblist[i]);
+     if (!dstbr->mblist[i]) FatalError("unable to malloc brMBlist[]");
+-    strcpy(dstbr->mblist[i], srcbr->mblist[i]);
+   }
+ 
+-  dstbr->dirMB.list  = srcbr->mblist;
++#if 0
++  dstbr->dirMB.list  = srcbr->mblist;  /* original bug..? */
+   dstbr->dirMB.nlist = srcbr->ndirs;
++#else
++  dstbr->dirMB.list  = dstbr->mblist;  /* fixed by        */
++  dstbr->dirMB.nlist = dstbr->ndirs;   /*   jp-extension. */
++#endif
+ 
+-  XClearArea(theDisp, dstbr->dirMB.win, dstbr->dirMB.x, dstbr->dirMB.y, 
++  XClearArea(theDisp, dstbr->dirMB.win, dstbr->dirMB.x, dstbr->dirMB.y,
+ 	     dstbr->dirMB.w+3, dstbr->dirMB.h+3, False);
+ 
+   i = StringWidth(dstbr->mblist[0]) + 10;
+@@ -2644,7 +2958,7 @@
+ 
+     if ((i&0x03) == 0) drawTemp(dstbr, i, dstbr->bfLen);
+     if ((i & 0x3f) == 0) WaitCursor();
+-    
++
+     sbf = &(srcbr->bfList[i]);
+     dbf = &(dstbr->bfList[i]);
+ 
+@@ -2670,7 +2984,7 @@
+     if (sbf->pimage) {
+       dbf->pimage = (byte *) malloc((size_t) dbf->w * dbf->h);
+       if (!dbf->pimage) FatalError("ran out of memory for dbf->pimage");
+-      xvbcopy((char *) sbf->pimage, (char *) dbf->pimage, 
++      xvbcopy((char *) sbf->pimage, (char *) dbf->pimage,
+ 	      (size_t) (dbf->w * dbf->h));
+     }
+     else dbf->pimage = (byte *) NULL;
+@@ -2681,10 +2995,10 @@
+       xvbcopy((char *) sbf->ximage, (char *) dbf->ximage, sizeof(XImage));
+ 
+       if (sbf->ximage->data) {
+-	dbf->ximage->data = (char *) malloc((size_t) dbf->ximage->height * 
++	dbf->ximage->data = (char *) malloc((size_t) dbf->ximage->height *
+ 					    dbf->ximage->bytes_per_line);
+ 	if (!dbf->ximage->data) FatalError("ran out of memory for ximg data");
+-	xvbcopy((char *) sbf->ximage->data, (char *) dbf->ximage->data, 
++	xvbcopy((char *) sbf->ximage->data, (char *) dbf->ximage->data,
+ 		(size_t) dbf->ximage->height * dbf->ximage->bytes_per_line);
+       }
+     }
+@@ -2701,15 +3015,15 @@
+   computeScrlVals(dstbr, &maxv, &page);
+   if (dstbr->scrl.val > maxv) dstbr->scrl.val = maxv;
+ 
+-  XClearArea(theDisp, dstbr->iconW, 0, 0, (u_int) dstbr->iwWide, 
++  XClearArea(theDisp, dstbr->iconW, 0, 0, (u_int) dstbr->iwWide,
+ 	     (u_int) dstbr->iwHigh, True);
+   SCSetRange(&dstbr->scrl, 0, maxv, dstbr->scrl.val, page);
+ 
+   SetCursors(-1);
+ }
+ 
+-    
+-  
++
++
+ 
+ /***************************************************************/
+ static void scanDir(br)
+@@ -2726,7 +3040,7 @@
+    * and it's reasonable to expect folks to want to add their own bitmaps
+    */
+ 
+-  int   i,j,k,oldbflen,vmsparent;
++  int   i,j,oldbflen,vmsparent;
+   BFIL *bf;
+ 
+   DIR           *dirp;
+@@ -2753,7 +3067,7 @@
+   xv_getwd(path, sizeof(path));
+   if (path[strlen(path)-1] != '/') strcat(path,"/");   /* add trailing '/' */
+ 
+-  for (i=0; i<br->ndirs; i++) free(br->mblist[i]);  /* clear old dir names */
++  for (i=0; i<br->ndirs; i++) free((char *) br->mblist[i]);  /* clear old dir names */
+ 
+   /* path will be something like: "/u3/bradley/src/weiner/whatever/" */
+ 
+@@ -2775,22 +3089,24 @@
+ 
+   /* build brMBlist */
+   for (i = br->ndirs-1,j=0; i>=0; i--,j++) {
+-    size_t stlen = (i<(br->ndirs-1)) ? dirnames[i+1] - dirnames[i] 
++    size_t  stlen = (i<(br->ndirs-1)) ? dirnames[i+1] - dirnames[i]
+                                   : strlen(dirnames[i]);
++    char   *copy;
+ 
+-    br->mblist[j] = (char *) malloc(stlen+1);
+-    if (!br->mblist[j]) FatalError("unable to malloc brMBlist[]");
++    copy = malloc(stlen+1);
++    if (!copy) FatalError("unable to malloc brMBlist[]");
+ 
+-    strncpy(br->mblist[j], dirnames[i], stlen);
+-    br->mblist[j][stlen] = '\0';
++    strncpy(copy, dirnames[i], stlen);
++    copy[stlen] = '\0';
++    br->mblist[j] = copy;
+   }
+-    
++
+ 
+   /* refresh the brdirMB button */
+   br->dirMB.list  = br->mblist;
+   br->dirMB.nlist = br->ndirs;
+ 
+-  XClearArea(theDisp, br->dirMB.win, br->dirMB.x, br->dirMB.y, 
++  XClearArea(theDisp, br->dirMB.win, br->dirMB.x, br->dirMB.y,
+ 	     br->dirMB.w+3, br->dirMB.h+3, False);
+ 
+   i = StringWidth(br->mblist[0]) + 10;
+@@ -2815,7 +3131,7 @@
+   /* count how many files are in the list */
+ 
+   dirp = opendir(".");
+-  if (!dirp) {  
++  if (!dirp) {
+     endScan(br, oldbflen);
+     setBrowStr(br, "Couldn't read current directory.");
+     SetCursors(-1);
+@@ -2827,11 +3143,11 @@
+ #endif
+ 
+   while ( (dp = readdir(dirp)) != NULL) {
+-    if (strcmp(dp->d_name, ".") && 
++    if (strcmp(dp->d_name, ".") &&
+ 	strcmp(dp->d_name, THUMBDIR)) {
+-      if (!br->showhidden && dp->d_name[0] == '.' && 
++      if (!br->showhidden && dp->d_name[0] == '.' &&
+ 	  strcmp(dp->d_name,"..")!=0) continue;
+-      else 
++      else
+ 	br->bfLen++;
+     }
+     if ((br->bfLen & 0x3f) == 0) WaitCursor();
+@@ -2877,13 +3193,13 @@
+       }
+       else {
+ 	do { dp = readdir(dirp); }
+-	while (dp && (strcmp(dp->d_name, ".")==0                    || 
++	while (dp && (strcmp(dp->d_name, ".")==0                    ||
+ 		      strcmp(dp->d_name, THUMBDIR)==0               ||
+ 		      strcmp(dp->d_name, THUMBDIRNAME)==0           ||
+ 		      (br->ndirs==1 && strcmp(dp->d_name,"..")==0)  ||
+-		      (!br->showhidden && dp->d_name[0] == '.' && 
++		      (!br->showhidden && dp->d_name[0] == '.' &&
+ 		       strcmp(dp->d_name,"..")!=0)));
+-      
++
+ 	if (!dp) { br->bfLen = i;  break; }   /* dir got shorter... */
+       }
+ 
+@@ -2940,11 +3256,11 @@
+   if (w<1) w = 1;
+   if (h<1) h = 1;
+ 
+-  XClearArea(theDisp, br->iconW, (ctrlColor) ? 2 : 0, (ctrlColor) ? 2 : 0, 
++  XClearArea(theDisp, br->iconW, (ctrlColor) ? 2 : 0, (ctrlColor) ? 2 : 0,
+ 	     (u_int) w, (u_int) h, False);
+ 
+   SCSetRange(&br->scrl, 0, maxv, br->scrl.val, page);
+-  
++
+   SetCursors(-1);
+ }
+ 
+@@ -2972,10 +3288,14 @@
+   bf->pimage = (byte *) NULL;
+   bf->ximage = (XImage *) NULL;
+   bf->lit    = 0;
+-	
++
+ 
+   if (stat(bf->name, &st)==0) {
++#ifdef AUTO_EXPAND
++    bf->ftype = stat2bf((u_int) st.st_mode , bf->name);
++#else
+     bf->ftype = stat2bf((u_int) st.st_mode);
++#endif
+     if (bf->ftype == BF_FILE && (st.st_mode & 0111)) bf->ftype = BF_EXE;
+ 
+     switch (bf->ftype) {
+@@ -3007,6 +3327,7 @@
+     case RFT_XBM:      bf->ftype = BF_XBM;      break;
+     case RFT_SUNRAS:   bf->ftype = BF_SUNRAS;   break;
+     case RFT_BMP:      bf->ftype = BF_BMP;      break;
++    case RFT_WBMP:     bf->ftype = BF_BMP;      break;
+     case RFT_UTAHRLE:  bf->ftype = BF_UTAHRLE;  break;
+     case RFT_IRIS:     bf->ftype = BF_IRIS;     break;
+     case RFT_PCX:      bf->ftype = BF_PCX;      break;
+@@ -3014,12 +3335,22 @@
+     case RFT_TIFF:     bf->ftype = BF_TIFF;     break;
+     case RFT_PDSVICAR: bf->ftype = BF_PDS;      break;
+     case RFT_COMPRESS: bf->ftype = BF_COMPRESS; break;
++    case RFT_BZIP2:    bf->ftype = BF_BZIP2;    break;
+     case RFT_PS:       bf->ftype = BF_PS;       break;
+     case RFT_IFF:      bf->ftype = BF_IFF;      break;
+-    case RFT_TARGA:    bf->ftype = BF_TARGA;    break;
++    case RFT_TARGA:    bf->ftype = BF_TGA;      break;
+     case RFT_XPM:      bf->ftype = BF_XPM;      break;
+     case RFT_XWD:      bf->ftype = BF_XWD;      break;
+     case RFT_FITS:     bf->ftype = BF_FITS;     break;
++    case RFT_PNG:      bf->ftype = BF_PNG;      break;
++    case RFT_ZX:       bf->ftype = BF_ZX;       break;	/* [JCE] */
++    case RFT_PCD:      bf->ftype = BF_PCD;      break;
++    case RFT_MAG:      bf->ftype = BF_MAG;      break;
++    case RFT_MAKI:     bf->ftype = BF_MAKI;     break;
++    case RFT_PIC:      bf->ftype = BF_PIC;      break;
++    case RFT_PI:       bf->ftype = BF_PI;       break;
++    case RFT_PIC2:     bf->ftype = BF_PIC2;     break;
++    case RFT_MGCSFX:   bf->ftype = BF_MGCSFX;   break;
+     }
+   }
+ }
+@@ -3048,11 +3379,11 @@
+   bfcompares++;
+   if ((bfcompares & 0x7f)==0) WaitCursor();
+ 
+-  /* sort critera:  directories first, in alphabetical order, 
++  /* sort critera:  directories first, in alphabetical order,
+      followed by everything else, in alphabetical order */
+-  
++
+   if ((b1->ftype == BF_DIR && b2->ftype == BF_DIR) ||
+-      (b1->ftype != BF_DIR && b2->ftype != BF_DIR)) 
++      (b1->ftype != BF_DIR && b2->ftype != BF_DIR))
+     return strcmp(b1->name, b2->name);
+ 
+   else if (b1->ftype == BF_DIR && b2->ftype != BF_DIR) return -1;
+@@ -3108,7 +3439,7 @@
+     for (i=0; i<bflen; i++) {
+       bfnames[i] = (char *) malloc(strlen(br->bfList[i].name) + 1);
+       if (!bfnames[i]) FatalError("couldn't alloc bfnames in rescanDir()");
+-      
++
+       strcpy(bfnames[i], br->bfList[i].name);
+     }
+   }
+@@ -3121,7 +3452,7 @@
+ 
+   /* note, either (or both) dirnames/bfnames can be NULL, in which case
+      their respective 'len's will be zero */
+-  
++
+   /* sort the two name lists */
+   if (bflen)  qsort((char *) bfnames,  (size_t) bflen, sizeof(char *),namcmp);
+   if (dirlen) qsort((char *) dirnames, (size_t) dirlen,sizeof(char *),namcmp);
+@@ -3153,7 +3484,7 @@
+     }
+   }
+   bflen = j;
+-  
++
+ 
+   for (i=j=0; i<dirlen; i++) {
+     if (dirnames[i] && strcmp(dirnames[i],".") && strcmp(dirnames[i],"..") &&
+@@ -3162,21 +3493,21 @@
+     }
+   }
+   dirlen = j;
+-  
++
+ 
+   if (DEBUG) {
+     fprintf(stderr,"%d files seem to have gone away:  ", bflen);
+-    for (i=0; i<bflen; i++) 
++    for (i=0; i<bflen; i++)
+       fprintf(stderr,"%s ", bfnames[i]);
+     fprintf(stderr,"\n\n");
+ 
+     fprintf(stderr,"%d files seem to have appeared:  ", dirlen);
+-    for (i=0; i<dirlen; i++) 
++    for (i=0; i<dirlen; i++)
+       fprintf(stderr,"%s ", dirnames[i]);
+     fprintf(stderr,"\n\n");
+   }
+-   
+-  
++
++
+   /* create a new bfList */
+   newlen = br->bfLen - bflen + dirlen;  /* oldlen - #del'd + #created */
+   if (newlen>0) {
+@@ -3241,7 +3572,7 @@
+       if (bf->pimage)  free(bf->pimage);
+       if (bf->ximage)  xvDestroyImage(bf->ximage);
+     }
+-    
++
+     free(br->bfList);
+   }
+ 
+@@ -3263,17 +3594,17 @@
+ 
+ /***************************************************************/
+ static char **getDirEntries(dir, lenP, dohidden)
+-     char *dir;
++     const char *dir;
+      int  *lenP;
+      int   dohidden;
+ {
+-  /* loads up all directory entries into an array.  This *isn't* a great 
+-     way to do it, but I can't count on 'scandir()' existing on 
++  /* loads up all directory entries into an array.  This *isn't* a great
++     way to do it, but I can't count on 'scandir()' existing on
+      every system.  Returns 'NULL' on failure, or pointer to array of
+      'lenP' strings on success.  '.' and '..' ARE included in list
+      if !dohidden, all '.*' files are skipped (except . and ..) */
+ 
+-  int    i, j, dirlen;
++  int    i, dirlen;
+   DIR   *dirp;
+   char **names;
+ #ifdef NODIRENT
+@@ -3294,9 +3625,9 @@
+   /* count # of entries in dir (worst case) */
+   for (dirlen=0;  (dp = readdir(dirp)) != NULL;  dirlen++);
+   if (!dirlen) {
+-    closedir(dirp);  
++    closedir(dirp);
+     *lenP = dirlen;
+-    return (char **) NULL; 
++    return (char **) NULL;
+   }
+ 
+ 
+@@ -3312,7 +3643,7 @@
+ 
+     if (!dohidden) {
+ #ifndef VMS
+-      if (dp->d_name[0] == '.' && 
++      if (dp->d_name[0] == '.' &&
+ 	  strcmp(dp->d_name,"." )!=0 &&
+ 	  strcmp(dp->d_name,"..")!=0) continue;
+ #endif
+@@ -3324,7 +3655,7 @@
+     strcpy(names[i], dp->d_name);
+     i++;
+   }
+-  
++
+   if (i<dirlen) dirlen = i;     /* dir got shorter... */
+ 
+   closedir(dirp);
+@@ -3359,7 +3690,7 @@
+ static void genSelectedIcons(br)
+      BROWINFO *br;
+ {
+-  int i, sval, first, numvis, cnt;
++  int i, cnt;
+ 
+   setBrowStr(br, "");
+ 
+@@ -3395,7 +3726,7 @@
+      BFIL *bf;
+ {
+   /* given a BFIL entry, load up the file.
+-   * if we succeeded in loading up the file, 
++   * if we succeeded in loading up the file,
+    *      generate an aspect-correct 8-bit image using brow Cmap
+    * otherwise
+    *      replace this icon with the BF_UNKNOWN, or BF_ERR icons
+@@ -3406,22 +3737,22 @@
+   double  wexpand,hexpand;
+   int     iwide, ihigh;
+   byte   *icon24, *icon8;
+-  char    str[256], str1[256], *readname, uncompname[128];
++  char    str[256], str1[256], readname[128], uncompname[128];
+   char    basefname[128], *uncName;
+-  
+-  
++
++
+   if (!bf || !bf->name || bf->name[0] == '\0') return;   /* shouldn't happen */
+   str[0] = '\0';
+   basefname[0] = '\0';
+   pinfo.pic = (byte *) NULL;
+   pinfo.comment = (char *) NULL;
+-  readname = bf->name;
+-  
++  strncpy(readname, bf->name, sizeof(readname) - 1);
++
+   /* free any old info in 'bf' */
+   if (bf->imginfo) free          (bf->imginfo);
+   if (bf->pimage)  free          (bf->pimage);
+   if (bf->ximage)  xvDestroyImage(bf->ximage);
+-  
++
+   bf->imginfo = (char *)   NULL;
+   bf->pimage  = (byte *)   NULL;
+   bf->ximage  = (XImage *) NULL;
+@@ -3429,10 +3760,10 @@
+ 
+   /* skip all 'special' files */
+   if (!ISLOADABLE(bf->ftype)) return;
+-  
++
+   filetype = ReadFileType(bf->name);
+-  
+-  if (filetype == RFT_COMPRESS) {
++
++  if ((filetype == RFT_COMPRESS) || (filetype == RFT_BZIP2)) {
+ #if (defined(VMS) && !defined(GUNZIP))
+     /* VMS decompress doesn't like the file to have a trailing .Z in fname
+        however, GUnZip is OK with it, which we are calling UnCompress */
+@@ -3442,10 +3773,10 @@
+ #else
+     uncName = bf->name;
+ #endif
+-    
+-    if (UncompressFile(uncName, uncompname)) {
++
++    if (UncompressFile(uncName, uncompname, filetype)) {
+       filetype = ReadFileType(uncompname);
+-      readname = uncompname;
++      strncpy(readname, uncompname, sizeof(readname) - 1);
+     }
+     else {
+       sprintf(str, "Couldn't uncompress file '%s'", bf->name);
+@@ -3453,71 +3784,139 @@
+       bf->ftype = BF_ERROR;
+     }
+   }
+-  
++
++#ifdef MACBINARY
++  if (handlemacb && macb_file == True && bf->ftype != BF_ERROR) {
++    if (RemoveMacbinary(readname, uncompname)) {
++      if (strcmp(readname, bf->name)!=0) unlink(readname);
++      strncpy(readname, uncompname, sizeof(readname) - 1);
++    }
++    else {
++      sprintf(str, "Unable to remove a InfoFile header form '%s'.", bf->name);
++      setBrowStr(br, str);
++      bf->ftype = BF_ERROR;
++    }
++  }
++#endif
++
++#ifdef HAVE_MGCSFX_AUTO
++  if (bf->ftype != BF_ERROR) {
++    if(filetype == RFT_MGCSFX){
++      char tmpname[128];
++      char *icom;
++
++      if((icom = mgcsfx_auto_input_com(bf->name)) != NULL){
++	sprintf(tmpname, "%s/xvmsautoXXXXXX", tmpdir);
++#ifdef USE_MKSTEMP
++	close(mkstemp(tmpname));
++#else
++	mktemp(tmpname);
++#endif
++	SetISTR(ISTR_INFO, "Converting to known format by MgcSfx auto...");
++	sprintf(str,"%s >%s", icom, tmpname);
++      }else goto ms_auto_no;
++
++#ifndef VMS
++      if (system(str))
++#else
++      if (!system(str))
++#endif
++      {
++        sprintf(str, "Unable to convert '%s' by MgcSfx auto.", bf->name);
++        setBrowStr(br, str);
++        bf->ftype = BF_ERROR;
++      }
++      else {
++        filetype = ReadFileType(tmpname);
++        if (strcmp(readname, bf->name)!=0) unlink(readname);
++        strncpy(readname, tmpname, sizeof(readname) - 1);
++      }
++    }
++  }
++ms_auto_no:
++#endif /* HAVE_MGCSFX_AUTO */
++
+   /* get rid of comments.  don't need 'em */
+   if (pinfo.comment) free(pinfo.comment);  pinfo.comment = (char *) NULL;
+-  
+-  if (filetype == RFT_ERROR) { 
++
++  if (filetype == RFT_ERROR) {
+     sprintf(str,"Couldn't open file '%s'", bf->name);
+     setBrowStr(br, str);
+     bf->ftype = BF_ERROR;
+   }
+-  
++
+   else if (filetype == RFT_UNKNOWN) {
+     /* if it *was* an 'exe', leave it that way */
+     if (bf->ftype != BF_EXE) bf->ftype = BF_UNKNOWN;
+   }
+-  
++
+   else {
+     /* otherwise it's a known filetype... do the *hard* part now... */
+-    
++
++#ifdef VS_ADJUST
++    normaspect = defaspect;
++#endif
+     i = ReadPicFile(readname, filetype, &pinfo, 1);
+     KillPageFiles(pinfo.pagebname, pinfo.numpages);
+-    
++
+     if (!i) bf->ftype = BF_ERROR;
+-    
++
+     if (i && (pinfo.w<=0 || pinfo.h<=0)) {        /* bogus size */
+       bf->ftype = BF_ERROR;
+       free(pinfo.pic);  pinfo.pic = (byte *) NULL;
+     }
+-    
++
+     if (bf->ftype==BF_ERROR && filetype==RFT_XBM) bf->ftype = BF_UNKNOWN;
+   }
+-  
++
+   /* get rid of comment, as we don't need it */
+-  if (pinfo.comment) { 
++  if (pinfo.comment) {
+     free(pinfo.comment);  pinfo.comment = (char *) NULL;
+   }
+-  
++
+   /* if we made an uncompressed file, we can rm it now */
+-  if (readname != bf->name) unlink(readname);
+-  
+-  
++  if (strcmp(readname, bf->name)!=0) unlink(readname);
++
++
+   /* at this point either BF_ERROR, BF_UNKNOWN, BF_EXE or pic */
+-  
++
+   if (!pinfo.pic) {
+     if (bf->ftype == BF_EXE) return;  /* don't write thumbfiles for exe's */
+-    
++
+     bf->w = br_file_width;  bf->h = br_file_height;
+     writeThumbFile(br, bf, NULL, 0, 0, NULL);   /* BF_ERROR, BF_UNKNOWN */
+     return;
+   }
+-  
++
+   /* at this point, we have a pic, so it must be an image file */
+-  
+-  
++
++
+   /* compute size of icon  (iwide,ihigh) */
+-  
++
++#ifdef VS_ADJUST
++  if (!vsadjust) normaspect = 1;
++
++  wexpand = (double) (pinfo.w * normaspect) / (double) ISIZE_WIDE;
++#else
+   wexpand = (double) pinfo.w / (double) ISIZE_WIDE;
++#endif /* VS_ADJUST */
+   hexpand = (double) pinfo.h / (double) ISIZE_HIGH;
+ 
+   if (wexpand >= 1.0 || hexpand >= 1.0) {   /* don't expand small icons */
+     if (wexpand>hexpand) {
++#ifdef VS_ADJUST
++      iwide = (int) ((pinfo.w * normaspect) / wexpand + 0.5);
++#else
+       iwide = (int) (pinfo.w / wexpand + 0.5);
++#endif
+       ihigh = (int) (pinfo.h / wexpand + 0.5);
+     }
+     else {
++#ifdef VS_ADJUST
++      iwide = (int) ((pinfo.w * normaspect) / hexpand + 0.5);
++#else
+       iwide = (int) (pinfo.w / hexpand + 0.5);
++#endif
+       ihigh = (int) (pinfo.h / hexpand + 0.5);
+     }
+   }
+@@ -3527,13 +3926,13 @@
+ 
+ 
+   /* generate icon */
+-  icon24 = Smooth24(pinfo.pic, pinfo.type==PIC24, pinfo.w, pinfo.h, 
++  icon24 = Smooth24(pinfo.pic, pinfo.type==PIC24, pinfo.w, pinfo.h,
+ 		    iwide, ihigh, pinfo.r,pinfo.g,pinfo.b);
+   if (!icon24) { bf->ftype = BF_FILE;  free(pinfo.pic); return; }
+ 
+   sprintf(str, "%dx%d ", pinfo.normw, pinfo.normh);
+   switch (filetype) {
+-  case RFT_GIF:      if (xv_strstr(pinfo.shrtInfo, "GIF89")) 
++  case RFT_GIF:      if (xv_strstr(pinfo.shrtInfo, "GIF89"))
+                        strcat(str,"GIF89 file");
+                      else
+ 		       strcat(str,"GIF87 file");
+@@ -3543,12 +3942,12 @@
+ 
+   case RFT_PBM:      if (xv_strstr(pinfo.fullInfo, "raw")) strcat(str,"Raw ");
+                      else strcat(str,"Ascii ");
+-    
++
+                      for (i=0; i<3 && (strlen(pinfo.fullInfo)>(size_t)3); i++){
+ 		       str1[0] = pinfo.fullInfo[i];  str1[1] = '\0';
+ 		       strcat(str, str1);
+ 		     }
+-         
++
+                      strcat(str," file");
+                      break;
+ 
+@@ -3567,21 +3966,30 @@
+   case RFT_XPM:      strcat(str,"XPM file");              break;
+   case RFT_XWD:      strcat(str,"XWD file");              break;
+   case RFT_FITS:     strcat(str,"FITS file");             break;
++  case RFT_PNG:      strcat(str,"PNG file");              break;
++  case RFT_ZX:       strcat(str,"Spectrum SCREEN$");      break; /* [JCE] */
++  case RFT_PCD:      strcat(str,"PhotoCD file");          break;
++  case RFT_MAG:      strcat(str,"MAG file");              break;
++  case RFT_MAKI:     strcat(str,"MAKI file");             break;
++  case RFT_PIC:      strcat(str,"PIC file");              break;
++  case RFT_PI:       strcat(str,"PI file");               break;
++  case RFT_PIC2:     strcat(str,"PIC2 file");             break;
++  case RFT_MGCSFX:   strcat(str,"Magic Suffix file");     break;
+   default:           strcat(str,"file of unknown type");  break;
+   }
+-  
+-  
++
++
+   /* find out length of original file */
+   {  FILE *fp;
+      long  filesize;
+      char  buf[64];
+-     
++
+      fp = fopen(bf->name, "r");
+      if (fp) {
+        fseek(fp, 0L, 2);
+        filesize = ftell(fp);
+        fclose(fp);
+-       
++
+        sprintf(buf,"  (%ld bytes)", filesize);
+        strcat(str, buf);
+      }
+@@ -3609,17 +4017,17 @@
+   bf->w       = iwide;
+   bf->h       = ihigh;
+   bf->ftype   = BF_HAVEIMG;
+-  
++
+   bf->ximage = Pic8ToXImage(icon8, (u_int) iwide, (u_int) ihigh, browcols,
+ 			    browR, browG, browB);
+-  
++
+   free(icon24);
+   free(pinfo.pic);
+ }
+ 
+ 
+ 
+-    
++
+ 
+ 
+ /*
+@@ -3670,6 +4078,10 @@
+ 
+   sprintf(thFname, "%s%s/%s", br->path, THUMBDIR, bf->name);
+ 
++#ifdef AUTO_EXPAND
++  Dirtovd(thFname);
++#endif
++
+   fp = fopen(thFname, "r");
+   if (!fp) return;            /* nope, it doesn't have one */
+ 
+@@ -3682,7 +4094,7 @@
+   /* read comments until we see '#END_OF_COMMENTS', or hit EOF */
+   while (1) {
+     if (!fgets(buf, 256, fp)) goto errexit;
+-    
++
+     if      (!strncmp(buf, "#END_OF_COMMENTS", strlen("#END_OF_COMMENTS")))
+       break;
+ 
+@@ -3714,7 +4126,7 @@
+ 
+ 
+   /* read width, height, maxval */
+-  if (!fgets(buf, 256, fp) || sscanf(buf, "%d %d %d", &w, &h, &mv) != 3) 
++  if (!fgets(buf, 256, fp) || sscanf(buf, "%d %d %d", &w, &h, &mv) != 3)
+     goto errexit;
+ 
+ 
+@@ -3738,14 +4150,14 @@
+     bf->h       = h;
+     bf->ftype   = BF_HAVEIMG;
+     bf->imginfo = info;
+-    
+-    bf->ximage = Pic8ToXImage(icon8, (u_int) w, (u_int) h, browcols, 
++
++    bf->ximage = Pic8ToXImage(icon8, (u_int) w, (u_int) h, browcols,
+ 			      browR, browG, browB);
+   }
+   else {
+     if (info) free(info);
+   }
+-  
++
+   fclose(fp);
+   return;
+ 
+@@ -3757,7 +4169,7 @@
+ }
+ 
+ 
+-  
++
+ /***************************************************************/
+ static void writeThumbFile(br, bf, icon8, w, h, info)
+      BROWINFO *br;
+@@ -3785,9 +4197,14 @@
+ 
+   sprintf(thFname, "%s%s/%s", br->path, THUMBDIR, bf->name);
+ 
++#ifdef AUTO_EXPAND
++  Dirtovd(thFname);
++#endif
++
++  unlink(thFname);  /* just in case there's already an unwritable one */
+   fp = fopen(thFname, "w");
+   if (!fp) {
+-    sprintf(buf, "Can't create thumbnail file '%s':  %s", thFname, 
++    sprintf(buf, "Can't create thumbnail file '%s':  %s", thFname,
+ 	    ERRSTR(errno));
+     setBrowStr(br, buf);
+     return;            /* can't write... */
+@@ -3829,9 +4246,9 @@
+     setBrowStr(br, buf);
+     return;            /* can't write... */
+   }
+-  
++
+   fclose(fp);
+-  
++
+   chmod(thFname, (mode_t) perm);
+ }
+ 
+@@ -3849,15 +4266,29 @@
+ 
+   sprintf(thFname, "%s%s", br->path, THUMBDIRNAME);
+ 
++#ifdef AUTO_EXPAND
++  Dirtovd(thFname);
++#endif
++
+   i = stat(thFname, &st);
+   if (i) {                      /* failed, let's create it */
+     sprintf(thFname, "%s.", br->path);
++#ifdef AUTO_EXPAND
++    Dirtovd(thFname);
++#endif
+     i = stat(thFname, &st);     /* get permissions of parent dir */
+     if (!i) perm = st.st_mode & 07777;
+        else perm = 0755;
+ 
+     sprintf(thFname, "%s%s", br->path, THUMBDIRNAME);
+-    mkdir(thFname, (mode_t) perm);
++#ifdef AUTO_EXPAND
++    Dirtovd(thFname);
++#endif
++    i = mkdir(thFname, (mode_t) perm);
++#ifdef VIRTUAL_TD
++    if (i < 0)
++      Mkvdir_force(thFname);
++#endif
+   }
+ }
+ 
+@@ -3899,7 +4330,7 @@
+   for (i=0, bf=br->bfList; i<br->bfLen; i++, bf++) {
+     if (bf->ftype <= BF_FILE || bf->ftype >= BF_ERROR || bf->ftype==BF_EXE) {
+ 
+-      /* ie, not a 'special' file */
++      /* i.e., not a 'special' file */
+ 
+       int  s1, s2;
+       char thfname[256];
+@@ -3913,10 +4344,9 @@
+       sprintf(thfname, "%s/%s", THUMBDIR, bf->name);
+       s2 = stat(thfname, &thumbst);
+ 
+-      if (s1 || s2 || filest.st_mtime > thumbst.st_mtime ||
+-	              filest.st_ctime > thumbst.st_ctime) {
+-	/* either stat'ing the file or the thumbfile failed, or 
+-	   both stat's succeeded and the file has a newer mod or creation
++      if (s1 || s2 || filest.st_mtime > thumbst.st_mtime) {
++	/* either stat'ing the file or the thumbfile failed, or
++	   both stat's succeeded and the file has a newer mod
+ 	   time than the thumbnail file */
+ 
+ 	makeIconVisible(br, i);
+@@ -3926,11 +4356,16 @@
+ 
+ 	if (bf->ftype != BF_EXE) {
+ 	  iconsBuilt++;
+-	  if (DEBUG) 
+-	    fprintf(stderr,"icon made:fname='%s' thfname='%s' %d,%d,%d,%d\n",
+-		    bf->name, thfname, s1,s2,filest.st_mtime,thumbst.st_mtime);
++	  if (DEBUG)
++	    fprintf(stderr,"icon made:fname='%s' thfname='%s' %d,%d,%ld,%ld\n",
++		    bf->name, thfname, s1, s2,
++		    (long)filest.st_mtime, (long)thumbst.st_mtime);
+ 	}
+       }
++      else if (filest.st_ctime > thumbst.st_ctime) {
++        /* update protections */
++        chmod(thfname, (mode_t) (filest.st_mode & 07777));
++      }
+     }
+     statcount++;
+ 
+@@ -3964,7 +4399,11 @@
+       sprintf(thfname, "%s/%s", THUMBDIR, dp->d_name);
+       if (stat(thfname, &thumbst)==0) {  /* success */
+ 	int tmp;
++#ifdef AUTO_EXPAND
++	tmp  = stat2bf((u_int) thumbst.st_mode , thfname);
++#else
+ 	tmp  = stat2bf((u_int) thumbst.st_mode);
++#endif
+ 
+ 	if (tmp == BF_FILE) {  /* a plain file */
+ 	  /* see if this thumbfile has an associated pic file */
+@@ -3974,7 +4413,7 @@
+ 	}
+       }
+       statcount++;
+-      
++
+       if ((statcount % 30)==0) WaitCursor();
+     }
+     closedir(dirp);
+@@ -3998,16 +4437,16 @@
+ {
+   if (maxcnt<1) return;   /* none of that naughty ol' divide by zero stuff */
+ 
+-  DrawTempGauge(br->win, 5, br->dirMB.y, 
++  DrawTempGauge(br->win, 5, br->dirMB.y,
+ 		(int) br->dirMB.x-10, (int) br->dirMB.h,
+ 		(double) cnt / (double) maxcnt,
+ 		browfg, browbg, browhi, browlo, "");
+ }
+- 
++
+ static void clearTemp(br)
+   BROWINFO *br;
+ {
+-  XClearArea(theDisp, br->win, 5, br->dirMB.y, 
++  XClearArea(theDisp, br->win, 5, br->dirMB.y,
+ 	     (u_int) br->dirMB.x-10+1, (u_int) br->dirMB.h + 1, True);
+ }
+ 
+@@ -4038,17 +4477,26 @@
+      pops up a 'what do you want to rename it to' box, and attempts to
+      do the trick... */
+ 
+-  int  i, num;
+-  char buf[128], txt[256], *origname, txt1[256];
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  struct stat st;
++  int                i, num;
++  char               buf[128], txt[256], *origname, txt1[256];
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  struct stat        st;
++
++#ifdef AUTO_EXPAND
++  if (Isvdir(br->path)) {
++    sprintf(buf,"Sorry, you can't rename file in the virtual directory, '%s'",
++	    br->path);
++    ErrPopUp(buf, "\nBummer!");
++    return;
++  }
++#endif
+ 
+   if (cdBrow(br)) return;
+ 
+   /* find the selected file */
+   for (i=0; i<br->bfLen && !br->bfList[i].lit; i++);
+   if (i==br->bfLen) return;    /* shouldn't happen */
+-  
++
+   origname = br->bfList[i].name;   num = i;
+ 
+   if (strcmp(origname, "..")==0) {
+@@ -4058,7 +4506,7 @@
+     return;
+   }
+ 
+-  sprintf(txt, "Enter a new name for the %s '%s':", 
++  sprintf(txt, "Enter a new name for the %s '%s':",
+ 	  (br->bfList[i].ftype==BF_DIR) ? "directory" : "file",
+ 	  origname);
+ 
+@@ -4107,7 +4555,7 @@
+   drawIcon(br, num);
+ 
+   for (i=0; i<MAXBRWIN; i++) {
+-    if (&binfo[i] != br && strcmp(binfo[i].path, br->path)==0) 
++    if (&binfo[i] != br && strcmp(binfo[i].path, br->path)==0)
+       rescanDir(&binfo[i]);
+   }
+ 
+@@ -4125,15 +4573,24 @@
+      pops up a 'what do you want to call it' box, and attempts to
+      do the trick... */
+ 
+-  int          i;
+-  char         buf[128], txt[256];
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  struct stat  st;
++  int                i;
++  char               buf[128], txt[256];
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  struct stat        st;
++
++#ifdef AUTO_EXPAND
++  if (Isvdir(br->path)) {
++    sprintf(buf,"Sorry, you can't mkdir in the virtual directory, '%s'",
++	    br->path);
++    ErrPopUp(buf, "\nBummer!");
++    return;
++  }
++#endif
+ 
+   if (cdBrow(br)) return;
+ 
+   buf[0] = '\0';
+-  i = GetStrPopUp("Enter name for new directory:", labels, 2, 
++  i = GetStrPopUp("Enter name for new directory:", labels, 2,
+ 		  buf, 128, "/ |\'\"<>,", 0);
+   if (i) return;     /* cancelled */
+ 
+@@ -4161,7 +4618,7 @@
+ 
+   /* rescan current br, and all other br's pointing to same directory */
+   for (i=0; i<MAXBRWIN; i++) {
+-    if (strcmp(binfo[i].path, br->path)==0) 
++    if (strcmp(binfo[i].path, br->path)==0)
+       rescanDir(&binfo[i]);
+   }
+ 
+@@ -4176,10 +4633,10 @@
+ static void doChdirCmd(br)
+      BROWINFO *br;
+ {
+-  int          i;
+-  static char  buf[MAXPATHLEN+100];
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char str[512];		
++  int                i;
++  static char        buf[MAXPATHLEN+100];
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               str[512];
+ 
+   buf[0] = '\0';
+   i = GetStrPopUp("Change to directory:", labels, 2, buf, MAXPATHLEN, " ", 0);
+@@ -4198,14 +4655,35 @@
+     if (cdBrow(br)) return;     /* prints its own error message */
+   }
+ 
++#ifdef AUTO_EXPAND
++  if (Chvdir(buf)) {
++#else
+   if (chdir(buf)) {
++#endif
+     sprintf(str,"Unable to cd to '%s'\n", buf);
+     setBrowStr(br, str);
+     XBell(theDisp, 50);
+   }
+   else {
++#ifdef AUTO_EXPAND
++      if (Isvdir(buf)) {
++	BTSetActive(&br->but[BR_DELETE],  0);
++	br->cmdMB.dim[BR_DELETE] = 1;
++
++	BTSetActive(&br->but[BR_RENAME],  0);
++	br->cmdMB.dim[BR_RENAME] = 1;
++
++	BTSetActive(&br->but[BR_MKDIR],  0);
++	br->cmdMB.dim[BR_MKDIR] = 1;
++      }
++      else {
++	BTSetActive(&br->but[BR_MKDIR],  1);
++	br->cmdMB.dim[BR_MKDIR] = 0;
++      }
++#endif
+     scanDir(br);
+     SCSetVal(&(br->scrl), 0);	/* reset to top on a chdir */
++    restIconVisible(br);
+   }
+ }
+ 
+@@ -4225,10 +4703,19 @@
+    * call 'rm_dir()' for each of the directories
+    */
+ 
+-  BFIL  *bf;
+-  int    i, j, numdirs, numfiles, slen, firstdel;
+-  char   buf[512];
+-  static char *yesno[]  = { "\004Delete", "\033Cancel" };
++  BFIL              *bf;
++  int                i, numdirs, numfiles, slen, firstdel;
++  char               buf[512];
++  static const char *yesno[]  = { "\004Delete", "\033Cancel" };
++
++#ifdef AUTO_EXPAND
++  if (Isvdir(br->path)) {
++    sprintf(buf,"Sorry, you can't delete file at the virtual directory, '%s'",
++	    br->path);
++    ErrPopUp(buf, "\nBummer!");
++    return;
++  }
++#endif
+ 
+   if (!br->bfLen || !br->bfList || !br->numlit) return;
+ 
+@@ -4252,13 +4739,17 @@
+   for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) {
+     if (bf->lit) {
+       if (firstdel == -1) firstdel = i;
+-      if (bf->ftype == BF_DIR) numdirs++;
++      if (bf->ftype == BF_DIR
++#ifdef AUTO_EXPAND
++	  && (!Isarchive(bf->name))
++#endif
++			     ) numdirs++;
+       else numfiles++;
+     }
+   }
+ 
+ 
+-  /* if any plain files are being toasted, bring up the low-key 
++  /* if any plain files are being toasted, bring up the low-key
+      confirmation box */
+ 
+   if (numfiles) {
+@@ -4266,7 +4757,12 @@
+     slen = strlen(buf);
+ 
+     for (i=0, bf=br->bfList;  i<br->bfLen;  i++,bf++) {
++#ifdef AUTO_EXPAND
++      if (bf->lit && (bf->ftype != BF_DIR || Isarchive(bf->name))) {
++#else
+       if (bf->lit && bf->ftype != BF_DIR) {
++#endif
++
+ 	if ( (slen + strlen(bf->name) + 1) > 256) {
+ 	  strcat(buf,"...");
+ 	  break;
+@@ -4278,10 +4774,10 @@
+       }
+     }
+ 
+-    i = PopUp(buf, yesno, 2);
++    i = PopUp(buf, yesno, COUNT(yesno));
+     if (i) return;              /* cancelled */
+   }
+-     
++
+ 
+   /* if any directories are being toasted, bring up the are you REALLY sure
+      confirmation box */
+@@ -4291,7 +4787,11 @@
+     slen = strlen(buf);
+ 
+     for (i=0, bf=br->bfList;  i<br->bfLen;  i++,bf++) {
++#ifdef AUTO_EXPAND
++      if (bf->lit && (bf->ftype == BF_DIR || !Isarchive(bf->name))) {
++#else
+       if (bf->lit && bf->ftype == BF_DIR) {
++#endif
+ 	if ( (slen + strlen(bf->name) + 1) > 256) {
+ 	  strcat(buf,"...");
+ 	  break;
+@@ -4303,16 +4803,20 @@
+       }
+     }
+ 
+-    i = PopUp(buf, yesno, 2);
++    i = PopUp(buf, yesno, COUNT(yesno));
+     if (i) return;              /* cancelled */
+   }
+ 
+ 
+   /* okay, at this point they've been warned.  do the deletion */
+-  
++
+   for (i=0, bf=br->bfList;  i<br->bfLen;  i++,bf++) {
+     if (bf->lit) {
+-      if (bf->ftype == BF_DIR) rm_dir (br, bf->name);
++      if (bf->ftype == BF_DIR
++#ifdef AUTO_EXPAND
++	  && !Isarchive(bf->name)
++#endif
++			     ) rm_dir (br, bf->name);
+                           else rm_file(br, bf->name);
+     }
+   }
+@@ -4340,7 +4844,7 @@
+ 
+   /* rescan other br's that are looking at this directory */
+   for (i=0; i<MAXBRWIN; i++) {
+-    if (&binfo[i] != br && strcmp(binfo[i].path, br->path)==0) 
++    if (&binfo[i] != br && strcmp(binfo[i].path, br->path)==0)
+       rescanDir(&binfo[i]);
+   }
+ 
+@@ -4353,10 +4857,10 @@
+ static void doSelFilesCmd(br)
+      BROWINFO *br;
+ {
+-  int          i;
+-  static char  buf[MAXPATHLEN+100];
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char str[512];		
++  int                i;
++  static char        buf[MAXPATHLEN+100];
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               str[512];
+ 
+   buf[0] = '\0';
+   strcpy(str,"Select file name(s).  Wildcard '*' is allowed.  ");
+@@ -4394,9 +4898,9 @@
+ static void doRecurseCmd(br)
+      BROWINFO *br;
+ {
+-  int          i;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  char         str[512];		
++  int                i;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  char               str[512];
+ 
+   strcpy(str,"Recursive Update:  This could take *quite* a while.\n");
+   strcat(str,"Are you sure?");
+@@ -4415,9 +4919,9 @@
+ 
+ 
+ /*******************************************/
+-static void recurseUpdate(br, subdir) 
+-     BROWINFO *br;
+-     char     *subdir;
++static void recurseUpdate(br, subdir)
++     BROWINFO   *br;
++     const char *subdir;
+ {
+   /* note:  'br->path + subdir' is the full path to recurse down from */
+ 
+@@ -4430,7 +4934,7 @@
+    *      and for each subdir in this dir, recurse
+    *
+    * if cur dir != orig dir, cd back to orig dir and reload 'br'
+-   */ 
++   */
+ 
+   int  i;
+   char orgDir[MAXPATHLEN + 2];
+@@ -4441,7 +4945,11 @@
+   xv_getwd(orgDir, sizeof(orgDir));
+ 
+   sprintf(curDir, "%s%s", br->path, subdir);
++#ifdef AUTO_EXPAND
++  if (Chvdir(curDir)) {
++#else
+   if (chdir(curDir)) {
++#endif
+     char str[512];
+     sprintf(str, "Unable to cd to '%s'\n", curDir);
+     setBrowStr(br, str);
+@@ -4449,18 +4957,28 @@
+   }
+ 
+   xv_getwd(curDir, sizeof(curDir));
+-  
++
+   /* have we looped? */
+   for (i=0; i<dirStackLen && strcmp(curDir, dirStack[i]); i++);
+   if (i<dirStackLen) {   /* YES */
++#ifdef AUTO_EXPAND
++    Chvdir(orgDir);
++#else
+     chdir(orgDir);
++#endif
++    restIconVisible(br);
+     return;
+   }
+ 
+   sp = (char *) malloc((size_t) strlen(curDir) + 1);
+   if (!sp) {
+     setBrowStr(br, "malloc() error in recurseUpdate()\n");
++#ifdef AUTO_EXPAND
++    Chvdir(orgDir);
++#else
+     chdir(orgDir);
++#endif
++    restIconVisible(br);
+     return;
+   }
+ 
+@@ -4481,8 +4999,8 @@
+   /* do subdirectories of this directory, not counting .  .. and .xvpics */
+   for (i=0; i<br->bfLen; i++) {
+     bf = &(br->bfList[i]);
+-    if (bf                     && 
+-	bf->ftype == BF_DIR    && 
++    if (bf                     &&
++	bf->ftype == BF_DIR    &&
+ 	strcmp(bf->name, ".")  &&
+ 	strcmp(bf->name, "..") &&
+         strcmp(bf->name, THUMBDIRNAME) ) {
+@@ -4495,7 +5013,12 @@
+ 
+   xv_getwd(curDir, sizeof(curDir));
+   if (strcmp(orgDir, curDir)) {   /* change back to orgdir */
++#ifdef AUTO_EXPAND
++    Chvdir(orgDir);
++#else
+     chdir(orgDir);
++#endif
++    restIconVisible(br);
+     scanDir(br);
+   }
+ }
+@@ -4519,12 +5042,19 @@
+     setBrowStr(br, buf);
+   }
+ 
++#ifdef AUTO_EXPAND
++  if (Rmvdir(name)) {
++    sprintf(buf, "fail to remove virturl directory: %s", name);
++    setBrowStr(br, buf);
++  }
++#endif
++
+   /* try to delete a thumbnail file, as well.  ignore errors */
+   strcpy(buf1, name);          /* tmp1 = leading path of name */
+   tmp = (char *) rindex(buf1, '/');
+   if (!tmp) strcpy(buf1,".");
+   else *tmp = '\0';
+-  
++
+   sprintf(buf, "%s/%s/%s", buf1, THUMBDIR, BaseName(name));
+   if (DEBUG) fprintf(stderr,"   (%s)\n", buf);
+ 
+@@ -4548,7 +5078,7 @@
+      BROWINFO *br;
+ {
+   /* recursively delete this directory, and all things under it */
+-  
++
+   int    i, dirlen, longpath, oldpathlen;
+   char **names, *name, buf[512];
+   struct stat st;
+@@ -4569,7 +5099,7 @@
+       name = names[i];
+ 
+       /* skip . and .. (not that we should ever see them... */
+-      if (name[0] == '.' && (name[1]=='\0' || 
++      if (name[0] == '.' && (name[1]=='\0' ||
+ 			     (name[1]=='.' && name[2]=='\0'))) goto done;
+ 
+       if (strlen(name) + oldpathlen >= (MAXPATHLEN-3)) {
+@@ -4586,15 +5116,22 @@
+ 	rmdirPath[oldpathlen] = '\0';
+ 	goto done;
+       }
+-	
+-      if (stat2bf((u_int) st.st_mode) == BF_DIR) {  /* skip, for now */
++
++#ifdef AUTO_EXPAND
++      if ((stat2bf((u_int) st.st_mode , rmdirPath) == BF_DIR)
++	  && !Isarchive(rmdirPath))                /* skip, for now */
++#else
++
++      if (stat2bf((u_int) st.st_mode) == BF_DIR)   /* skip, for now */
++#endif
++      {
+ 	rmdirPath[oldpathlen] = '\0';
+ 	continue;   /* don't remove from list */
+       }
+ 
+       rm_file(br, rmdirPath);
+       rmdirPath[oldpathlen] = '\0';
+-      
++
+     done:     /* remove name from list */
+       free(name);
+       names[i] = (char *) NULL;
+@@ -4640,30 +5177,35 @@
+ 
+ static int overwrite;
+ #define OWRT_ASK    0
+-#define OWRT_NOASK  1
+-#define OWRT_CANCEL 2
+-
++#define OWRT_ALWAYS 1
++#define OWRT_NEVER  2
++#define OWRT_CANCEL 3
+ 
+ /*******************************************/
+-static void dragFiles(srcBr, dstBr, srcpath, dstpath, dstdir, 
++static void dragFiles(srcBr, dstBr, srcpath, dstpath, dstdir,
+ 		      names, nlen, cpymode)
+-     BROWINFO *srcBr, *dstBr;
+-     char     *srcpath, *dstpath, *dstdir, **names;
+-     int       nlen, cpymode;
++     BROWINFO   *srcBr, *dstBr;
++     char       *srcpath, *dstpath, **names;
++     const char *dstdir;
++     int         nlen, cpymode;
+ {
+-  /* move or copy file(s) and their associated thumbnail files.  
++  /* move or copy file(s) and their associated thumbnail files.
+      srcpath and dstpath will have trailing '/'s.  dstdir is name of
+      folder in dstpath (or "." or "..") to write to.  names is an nlen
+      long array of strings (the simple filenames of the files to move)
+      if 'cpymode' copy files, otherwise move them */
+ 
+-  int  i, j, k, dothumbs, fail;
++  int  i, j, dothumbs, fail;
+   char dstp[MAXPATHLEN + 1];
+   char src[MAXPATHLEN+1], dst[MAXPATHLEN+1];
+   char buf[128];
+   struct stat st;
+ 
+ 
++  /* if the source directory is read-only, don't move files; copy them */
++  if (!cpymode && (access(srcpath, W_OK) != 0))
++    cpymode = 1;
++
+   /* build real destination dir */
+   strcpy(dstp, dstpath);
+ 
+@@ -4677,11 +5219,26 @@
+   }
+   else if (strcmp(dstdir,".")!=0) sprintf(dstp, "%s%s/", dstpath, dstdir);
+ 
++#ifdef AUTO_EXPAND
++  if (Isvdir(dstp)) {
++    sprintf(buf,"Sorry, you can't %s to the virtual directory, '%s'",
++	    cpymode ? "copy" : "move", dstp);
++    ErrPopUp(buf, "\nBummer!");
++    SetCursors(-1);
++    return;
++  }
++  if (Isvdir(srcpath))
++      cpymode = 1;
++#endif
++
+ 
+ 
+   /* if there is a thumbnail directory in 'srcpath', make one for dstpath */
+   sprintf(src,"%s%s", srcpath, THUMBDIR);
+   dothumbs = 0;
++#ifdef AUTO_EXPAND
++  Dirtovd(src);
++#endif
+   if (stat(src, &st)==0) {
+     sprintf(dst,"%s%s", dstp, THUMBDIR);
+     mkdir(dst, st.st_mode & 07777);
+@@ -4712,6 +5269,14 @@
+     if (overwrite == OWRT_CANCEL) break;         /* abort move */
+     if (j==1) fail++;
+ 
++#ifdef AUTO_EXPAND
++    if (!cpymode && j==0)
++      if (Movevdir(src,dst)) {
++	sprintf(buf, "fail to move virturl directory: %s", names[i]);
++	setBrowStr(srcBr, buf);
++      }
++#endif
++
+     if (dothumbs && j==0) {
+       sprintf(src,"%s%s/%s", srcpath, THUMBDIR, names[i]);
+       sprintf(dst,"%s%s/%s", dstp,    THUMBDIR, names[i]);
+@@ -4749,8 +5314,17 @@
+   }
+ 
+ 
++  if (!cpymode) {
++    /* clear all lit files in the source folder (as they've been moved)
++       note:  this won't be the optimal behavior if any files failed to
++       move, but screw it, that's not going to happen too often... */
++    for (i=0; i<srcBr->bfLen; i++) srcBr->bfList[i].lit = 0;
++    srcBr->numlit = 0;
++  }
++
++
+   /* clear all files in the destination folder */
+-  for (i=0; i<dstBr->bfLen; i++) { 
++  for (i=0; i<dstBr->bfLen; i++) {
+     dstBr->bfList[i].lit = 0;
+   }
+   dstBr->numlit = 0;
+@@ -4760,10 +5334,10 @@
+   for (i=0; i<nlen; i++) {
+     char *name;  BFIL *bf;
+     name = names[i];
+-    for (j=0, bf=dstBr->bfList; 
++    for (j=0, bf=dstBr->bfList;
+ 	 j<dstBr->bfLen && strcmp(name, bf->name)!=0; j++, bf++);
+-    if (j<dstBr->bfLen) { 
+-      bf->lit = 1;  dstBr->numlit++; 
++    if (j<dstBr->bfLen) {
++      bf->lit = 1;  dstBr->numlit++;
+     }
+   }
+ 
+@@ -4783,10 +5357,10 @@
+   changedNumLit(srcBr, -1, 0);
+ 
+ 
+-  if (fail) sprintf(buf, "Some files were not %s because of errors.", 
++  if (fail) sprintf(buf, "Some files were not %s because of errors.",
+ 		    cpymode ? "copied" : "moved");
+ 
+-  else if (nlen>1) sprintf(buf, "%d files %s", nlen, 
++  else if (nlen>1) sprintf(buf, "%d files %s", nlen,
+ 			   (cpymode) ? "copied" : "moved");
+   else buf[0] = '\0';
+   setBrowStr(srcBr, buf);
+@@ -4794,7 +5368,51 @@
+   SetCursors(-1);
+ }
+ 
++static int recursive_remove(dir)
++     char *dir;
++{
++  DIR *dp = NULL;
++  struct dirent *di;
++  char name[MAXPATHLEN+1];
++
++  strncpy(name, dir, MAXPATHLEN);
++  name[MAXPATHLEN] = 0;
++
++  if (name[strlen(name) - 1] == '/')
++    name[strlen(name) - 1] = 0;
++
++  if ((dp = opendir(name)) == NULL)
++    goto err;
++
++  while ((di = readdir(dp)) != NULL) {
++    char buf[MAXPATHLEN+1];
++    struct stat st;
++
++    if (!strcmp(di->d_name, ".") || !strcmp(di->d_name, ".."))
++      continue;
++
++    snprintf(buf, MAXPATHLEN, "%s/%s", name, di->d_name);
++
++    if (stat(buf, &st) < 0)
++      continue;
++
++    if (S_ISDIR(st.st_mode)) {
++      if (recursive_remove(buf) < 0)
++	goto err;
++    } else
++      unlink(buf);
++  }
+ 
++  if (rmdir(name) < 0)
++    goto err;
++
++  closedir(dp);
++  return 0;
++
++err:
++  if (dp) closedir(dp);
++  return -1;
++}
+ 
+ /*************************************************/
+ static int moveFile(src,dst)
+@@ -4809,34 +5427,48 @@
+      One bit of noise:  if destination file exists, pop up a Overwrite?
+      warning box.  */
+ 
+-  int         i, srcdir, dstdir;
+-  struct stat st;
+-  char        buf[512];
+-  static char  *owbuts[4]  = { "\nOk", "dDon't ask", "nNo", "\033Cancel" };
++  int                i, srcdir, dstdir;
++  struct stat        st;
++  char               buf[512];
++  static const char *owbuts[]  = { "\nOk", "aAlways", "nNo", "NNever", "\033Cancel" };
+ 
+   if (DEBUG) fprintf(stderr,"moveFile %s %s\n", src, dst);
+ 
++#ifdef AUTO_EXPAND
++  Dirtosubst(src);
++#endif
++
+   if (stat(src, &st)) return 0;    /* src doesn't exist, it would seem */
++#ifdef AUTO_EXPAND
++  srcdir = (stat2bf((u_int) st.st_mode , src) == BF_DIR);
++#else
+   srcdir = (stat2bf((u_int) st.st_mode) == BF_DIR);
++#endif
+ 
+   /* see if destination exists */
++
+   if (stat(dst, &st)==0) {
++    if (overwrite==OWRT_NEVER) return -1;
++#ifdef AUTO_EXPAND
++    dstdir = (stat2bf((u_int) st.st_mode , dst) == BF_DIR);
++#else
+     dstdir = (stat2bf((u_int) st.st_mode) == BF_DIR);
++#endif
+ 
+     if (overwrite==OWRT_ASK) {
+-      sprintf(buf, "%s '%s' exists.\n\nOverwrite?", 
++      snprintf(buf, sizeof(buf), "%s '%s' exists.\n\nOverwrite?",
+ 	      dstdir ? "Directory" : "File", dst);
+-      i = PopUp(buf, owbuts, 4);
+-
+-      if      (i==1) overwrite = OWRT_NOASK;
+-      else if (i==2) return -1;
+-      else if (i==3) { overwrite = OWRT_CANCEL;  return 1; }
++      switch (PopUp(buf, owbuts, COUNT(owbuts))) {
++	case 1: overwrite = OWRT_ALWAYS; break;
++	case 2: return -1;
++	case 3: overwrite = OWRT_NEVER; return -1;
++	case 4: overwrite = OWRT_CANCEL;  return 1;
++      }
+     }
+ 
+     if (dstdir) {
+ #ifndef VMS  /* we don't delete directories in VMS */
+-      sprintf(buf, "rm -rf %s", dst);
+-      if (system(buf)) {     /* okay, so it's cheating... */
++      if (recursive_remove(dst)) {   /* okay, so it's cheating... */
+ 	SetISTR(ISTR_WARNING, "Unable to remove directory %s", dst);
+ 	return 1;
+       }
+@@ -4848,7 +5480,7 @@
+     }
+   }
+ 
+-  
++
+   if (!rename(src, dst)) return 0;   /* Ok */
+   if (errno != EXDEV) return 1;      /* failure, of some sort */
+ 
+@@ -4859,9 +5491,8 @@
+   if (i == 0) {    /* copied okay, kill the original */
+     if (srcdir) {
+ #ifndef VMS   /* we don't delete directories in VMS */
+-      sprintf(buf, "rm -rf %s", src);
+-      if (system(buf)) {     /* okay, so it's cheating... */
+-	SetISTR(ISTR_WARNING, "Unable to remove directory %s", dst);
++      if (recursive_remove(src)) {   /* okay, so it's cheating... */
++	SetISTR(ISTR_WARNING, "Unable to remove directory %s", src);
+ 	return 1;
+       }
+ #endif /* VMS */
+@@ -4896,7 +5527,7 @@
+   /* possible cases:  source is either a file or a directory, or doesn't exist,
+      destination is either a file, a directory, or doesn't exist.
+ 
+-     if source doesn't exist, nothing to do.  
++     if source doesn't exist, nothing to do.
+      if source is a file:
+         if dest is a file, popup 'overwriting' question, delete file if ok
+ 	if dest is a dir,  popup 'overwriting dir' question, delete dir if ok
+@@ -4907,38 +5538,51 @@
+ 	   fall through:  if dest doesn't exist, copy the directory, recurs */
+ 
+ 
+-  int         i, dstExists, srcdir, dstdir;
+-  struct stat srcSt, dstSt;
+-  char        buf[1024];
+-  static char *owdiff[3] = { "\nOk", "nNo", "\033Cancel" };
+-  static char *owsame[4] = { "\nOk", "dDon't Ask", "nNo", "\033Cancel" };
++  int                dstExists, srcdir, dstdir;
++  struct stat        srcSt, dstSt;
++  char               buf[1024];
++  static const char *owdiff[] = { "\nOk", "nNo", "\033Cancel" };
++  static const char *owsame[] = { "\nOk", "aAlways", "nNo", "NNever", "\033Cancel" };
+ 
+   if (DEBUG) fprintf(stderr,"copyFile %s %s\n", src, dst);
+ 
++#ifdef AUTO_EXPAND
++  Dirtosubst(src);
++#endif
++
+   if (stat(src,&srcSt)) return 0;  /* source doesn't exist, it would seem */
+ 
+   dstExists = (stat(dst, &dstSt)==0);
+ 
+   if (dstExists) {   /* ask about overwriting... */
+-    srcdir = (stat2bf((u_int) srcSt.st_mode) == BF_DIR);
+-    dstdir = (stat2bf((u_int) dstSt.st_mode) == BF_DIR);
++#ifdef AUTO_EXPAND
++  srcdir = (stat2bf((u_int) srcSt.st_mode , src) == BF_DIR);
++  dstdir = (stat2bf((u_int) dstSt.st_mode , dst) == BF_DIR);
++#else
++  srcdir = (stat2bf((u_int) srcSt.st_mode) == BF_DIR);
++  dstdir = (stat2bf((u_int) dstSt.st_mode) == BF_DIR);
++#endif
+ 
+     sprintf(buf, "%s '%s' already exists.  Replace it with %s '%s'?",
+ 	    (dstdir) ? "Directory" : "File", dst,
+ 	    (srcdir) ? "contents of directory" : "file", src);
+ 
+     if (srcdir == dstdir) {
++      if (overwrite==OWRT_NEVER) return -1;
+       if (overwrite==OWRT_ASK) {
+-	i = PopUp(buf, owsame, 4);
+-	if (i==1) overwrite = OWRT_NOASK;
+-	if (i==2) return -1;
+-	else if (i==3) { overwrite = OWRT_CANCEL;  return 1; }
++	switch (PopUp(buf, owsame, COUNT(owsame))) {
++	  case 1: overwrite = OWRT_ALWAYS; break;
++	  case 2: return -1;
++	  case 3: overwrite = OWRT_NEVER; return -1;
++	  case 4: overwrite = OWRT_CANCEL;  return 1;
++	}
+       }
+     }
+     else {     /* one's a dir, the other's a file.  *ALWAYS* ask! */
+-      i = PopUp(buf, owdiff, 3);
+-      if (i==1) return -1;
+-      else if (i==2) { overwrite = OWRT_CANCEL;  return 1; }
++      switch (PopUp(buf, owdiff, COUNT(owdiff))) {
++        case 1: return -1;
++        case 2: overwrite = OWRT_CANCEL;  return 1;
++      }
+     }
+ 
+ 
+@@ -4957,7 +5601,7 @@
+   /* destination doesn't exist no more, if it ever did... */
+   userMask = umask(0);  /* grab the umask */
+   umask((mode_t) userMask);      /* put it back... */
+-  
++
+ 
+   strcpy(cpSrcPath, src);
+   strcpy(cpDstPath, dst);
+@@ -5017,7 +5661,7 @@
+      called recursively by cp_dir, there are *no* guarantees that either file
+      exists or not */
+ 
+-  int         i, havedst;
++  int         havedst;
+   struct stat srcSt, dstSt;
+ 
+   if (stat(cpSrcPath, &srcSt)) {   /* src doesn't exist, usefully... */
+@@ -5036,8 +5680,11 @@
+     havedst = 1;
+   }
+ 
+-
+-  switch(stat2bf((u_int) srcSt.st_mode)) {   
++#ifdef AUTO_EXPAND
++  switch(stat2bf((u_int) srcSt.st_mode , cpDstPath)) {
++#else
++  switch(stat2bf((u_int) srcSt.st_mode)) {
++#endif
+     /* determine how to copy, by filetype */
+ 
+     /* NOTE:  There is no S_IFLNK case here, since we're using 'stat()' and
+@@ -5053,18 +5700,22 @@
+     }
+   }
+   else {
++#ifdef AUTO_EXPAND
++    if (stat2bf((u_int) dstSt.st_mode , cpDstPath) != BF_DIR) {
++#else
+     if (stat2bf((u_int) dstSt.st_mode) != BF_DIR) {
++#endif
+       SetISTR(ISTR_WARNING,"%s: not a directory", cpDstPath);
+       copyerr++;
+       return;
+     }
+   }
+-    
++
+     cp_dir();
+     if (!havedst) chmod(cpDstPath, srcSt.st_mode);
+-    
++
+     break;
+-    
++
+ 
+   case BF_CHR:
+   case BF_BLK:   cp_special(&srcSt, havedst);    break;
+@@ -5089,12 +5740,12 @@
+ {
+   int    i, dirlen, oldsrclen, olddstlen, longpath;
+   char **names, *name;
+-  struct stat  srcSt, dstSt;
++  struct stat  srcSt;
+ 
+ 
+   /* src and dst directories both exists now.  copy entries */
+ 
+-  if (DEBUG) fprintf(stderr,"cp_dir:   src='%s',  dst='%s'\n", 
++  if (DEBUG) fprintf(stderr,"cp_dir:   src='%s',  dst='%s'\n",
+ 		     cpSrcPath, cpDstPath);
+ 
+   longpath  = 0;
+@@ -5110,9 +5761,9 @@
+ 
+   for (i=0; i<dirlen && overwrite!=OWRT_CANCEL; i++) {
+     name = names[i];
+-    if (name[0] == '.' && (name[1]=='\0' || 
++    if (name[0] == '.' && (name[1]=='\0' ||
+ 			   (name[1]=='.' && name[2]=='\0'))) goto done;
+-    
++
+     /* add name to src and dst paths */
+     if ((strlen(name) + oldsrclen >= (MAXPATHLEN-3)) ||
+ 	(strlen(name) + olddstlen >= (MAXPATHLEN-3)))   {
+@@ -5130,12 +5781,17 @@
+       cpSrcPath[oldsrclen] = '\0';
+       goto done;
+     }
+-     
+-    if (stat2bf((u_int) srcSt.st_mode) == BF_DIR) {
++
++#ifdef AUTO_EXPAND
++    if (stat2bf((u_int) srcSt.st_mode , cpSrcPath) == BF_DIR)
++#else
++    if (stat2bf((u_int) srcSt.st_mode) == BF_DIR)
++#endif
++    {
+       cpSrcPath[oldsrclen] = '\0';
+       continue;                     /* don't remove from list, just skip */
+     }
+-     
++
+     strcat(cpDstPath, "/");
+     strcat(cpDstPath, name);
+     cp();                         /* RECURSE */
+@@ -5169,7 +5825,7 @@
+     strcat(cpDstPath, name);
+ 
+     cp();                        /* RECURSE */
+-    
++
+     cpSrcPath[oldsrclen] = '\0';
+     cpDstPath[olddstlen] = '\0';
+   }
+@@ -5190,11 +5846,11 @@
+      int exists;
+ /*****************************/
+ {
+-  register int srcFd, dstFd, rcount, wcount, i;
+-  char         str[512], buf[8192];
+-  static char  *owbuts[4] = { "\nOk", "dDon't Ask", "nNo", "\033Cancel" };
++  register int       srcFd, dstFd, rcount, wcount;
++  char               buf[8192];
++  static const char *owbuts[] = { "\nOk", "aAlways", "nNo", "NNever", "\033Cancel" };
+ 
+-  if (DEBUG) fprintf(stderr,"cp_file:  src='%s',  dst='%s'\n", 
++  if (DEBUG) fprintf(stderr,"cp_file:  src='%s',  dst='%s'\n",
+ 		     cpSrcPath, cpDstPath);
+ 
+   if ((srcFd = open(cpSrcPath, O_RDONLY, 0)) == -1) {
+@@ -5204,13 +5860,15 @@
+   }
+ 
+   if (exists) {
++    if (overwrite==OWRT_NEVER) return;
+     if (overwrite==OWRT_ASK) {
+       sprintf(buf, "File '%s' exists.\n\nOverwrite?", cpDstPath);
+-      i = PopUp(buf, owbuts, 4);
+-
+-      if      (i==1) overwrite = OWRT_NOASK;
+-      else if (i==2) return;
+-      else if (i==3) { overwrite = OWRT_CANCEL;  return; }
++      switch (PopUp(buf, owbuts, 4)) {
++        case 1: overwrite = OWRT_ALWAYS; break;
++        case 2: return;
++        case 3: overwrite = OWRT_NEVER; return;
++        case 4: overwrite = OWRT_CANCEL;  return;
++      }
+     }
+     dstFd = open(cpDstPath, O_WRONLY|O_TRUNC, 0);
+   }
+@@ -5255,7 +5913,7 @@
+      int exists;
+ /*********************************/
+ {
+-  if (DEBUG) fprintf(stderr,"cp_spec:  src='%s',  dst='%s'\n", 
++  if (DEBUG) fprintf(stderr,"cp_spec:  src='%s',  dst='%s'\n",
+ 		     cpSrcPath, cpDstPath);
+ 
+   if (exists && unlink(cpDstPath)) {
+@@ -5281,7 +5939,7 @@
+      int exists;
+ /*********************************/
+ {
+-  if (DEBUG) fprintf(stderr,"cp_fifo:  src='%s',  dst='%s'\n", 
++  if (DEBUG) fprintf(stderr,"cp_fifo:  src='%s',  dst='%s'\n",
+ 		     cpSrcPath, cpDstPath);
+ 
+ #ifdef S_IFIFO
+@@ -5302,12 +5960,18 @@
+ 
+ 
+ 
+-  
++
+ /*********************************/
++#ifdef AUTO_EXPAND
++static int stat2bf(uistmode, path)
++     u_int uistmode;
++     char *path;
++#else
+ static int stat2bf(uistmode)
+      u_int uistmode;
++#endif
+ {
+-  /* given the 'st.st_mode' field from a successful stat(), returns 
++  /* given the 'st.st_mode' field from a successful stat(), returns
+      BF_FILE, BF_DIR, BF_BLK, BF_CHR, BF_FIFO, or BF_SOCK.  Does *NOT*
+      return BF_EXE */
+ 
+@@ -5319,6 +5983,9 @@
+   else if (S_ISBLK(stmode))  rv = BF_BLK;
+   else if (S_ISFIFO(stmode)) rv = BF_FIFO;
+   else if (S_ISSOCK(stmode)) rv = BF_SOCK;
++#ifdef AUTO_EXPAND
++  else if (Isarchive(path))  rv = BF_DIR;
++#endif
+   else                       rv = BF_FILE;
+ 
+   return rv;
+@@ -5357,8 +6024,8 @@
+ static int selmatch1(name, arg)
+      char *name, *arg;
+ {
+-  /* returns non-zero if 'name' matches 'arg'.  Any '*' chars found in arg 
+-     are considered wildcards that match any number of characters, 
++  /* returns non-zero if 'name' matches 'arg'.  Any '*' chars found in arg
++     are considered wildcards that match any number of characters,
+      including zero. */
+ 
+   char *sp, *oldnp;
+@@ -5379,7 +6046,7 @@
+ 	while (*name) name++;
+ 	while (*arg ) arg++;
+ 	name--;  arg--;
+-	
++
+ 	while (*arg != '*') {
+ 	  if (*arg != *name || name<oldnp) return 0;
+ 	  arg--;  name--;
+@@ -5388,7 +6055,7 @@
+       }
+ 
+       else {  /* there are more '*'s in arg... */
+-	/* find the first occurrence of the string between the two '*'s.  
++	/* find the first occurrence of the string between the two '*'s.
+ 	   if the '*'s are next to each other, just throw away the first one */
+ 
+ 	arg++;  /* points to char after  first  '*' */
+@@ -5410,7 +6077,7 @@
+ 	  arg = sp+1;
+ 	}
+       }
+-    }	  
++    }
+   }
+ 
+   if (!*arg && !*name) return 1;
+@@ -5419,4 +6086,98 @@
+ }
+ 
+ 
++static IVIS *icon_vis_list = NULL;
++
++/***************************************************************/
++static void recIconVisible(name, icon)
++  char *name;
++  int   icon;
++{
++  IVIS *ptr, *prev = NULL;
++
++  for (ptr = icon_vis_list; ptr; prev = ptr, ptr = ptr->next) {
++    if (!strcmp(ptr->name, name)) {
++      ptr->icon = icon;
++      return;
++    }
++  }
++
++  ptr = calloc(sizeof(IVIS), 1);
++  if (!ptr)
++    return;
+ 
++  ptr->name = strdup(name);
++
++  if (!ptr->name) {
++    free(ptr);
++    return;
++  }
++
++  if (!prev) {
++    icon_vis_list = ptr;
++  } else {
++    prev->next = ptr;
++  }
++
++  ptr->next = NULL;
++  ptr->icon = icon;
++}
++
++/***************************************************************/
++static void restIconVisible(br)
++  BROWINFO *br;
++{
++  IVIS *ptr;
++
++  for (ptr = icon_vis_list; ptr; ptr = ptr->next) {
++    if (!strcmp(ptr->name, br->path)) {
++      if (ptr->icon >= 0) {
++        makeIconVisible(br, ptr->icon);
++        updateSel(br, ptr->icon, 0, 0);
++      }
++      return;
++    }
++  }
++}
++
++
++/*********************************/
++static void clipChanges(br)
++     BROWINFO *br;
++{
++  /* called whenever schnauzer activity should place file names in
++     the X11 clipboard, or change what it put there.
++
++     Implementation is simple because the UI is non-standard
++     (i.e., not like xterm(1)). The clipboard command causes the
++     current browser to dump all its currently selected files'
++     (if any) names to the clipboard, space-separated.
++     No effort is made to shell-escape blanks and other 'odd'
++     characters in the names. */
++
++  char buf[4000]; /* too much or too little, whatever... */
++  int n;
++  int i;
++
++  n = 0;
++  strcpy(buf, "");
++
++  for (i=0; i<br->bfLen; i++) {
++    if(br->bfList[i].lit == 1) {
++      int m;
++
++      m = strlen(br->bfList[i].name) + 1;
++
++      if(n+m+1 >= sizeof(buf)) return;  /* names probably won't fit in buf, abort */
++      strcat(buf, br->bfList[i].name);
++      strcat(buf, " ");
++      n += m;
++    }
++  }
++
++  if(n) {
++    buf[n-1] = 0; /* trim last space */
++
++    NewCutBuffer(buf);
++  }
++}
+diff -ru xv-3.10a/xvbutt.c xv-3.10a-enhancements/xvbutt.c
+--- xv-3.10a/xvbutt.c	1995-01-03 13:19:51.000000000 -0800
++++ xv-3.10a-enhancements/xvbutt.c	2007-04-15 20:59:15.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvbutt.c - regular, 'radio', 'checkbox', and 'menu' pushbuttons
+  *
+  * callable functions:
+@@ -16,7 +16,7 @@
+  *   RBSetActive()          -  sets active status of an RBUTT
+  *   RBClick()              -  finds clicked-on rb in a list
+  *   RBTrack()              -  tracks rb after click, until release
+- * 
++ *
+  *   CBCreate()             -  create a CBUTT (checkbox button)
+  *   CBRedraw()             -  redraw a CBUTT
+  *   CBSetActive()          -  change active status of a CBUTT
+@@ -26,7 +26,7 @@
+  *   MBCreate()             -  create a MBUTT (menu button)
+  *   MBRedraw()             -  redraw a MBUTT
+  *   MBSetActive()          -  change active status of a MBUTT
+- *   MBWhich()              -  returns # of first checked selection 
++ *   MBWhich()              -  returns # of first checked selection
+  *   MBSelect()             -  similar to RBSelect() ...
+  *   MBClick()              -  returns true if given MB was clicked on
+  *   MBTrack()              -  tracks MBUTT after click, until release
+@@ -76,7 +76,7 @@
+      Window        win;
+      int           x,y;
+      unsigned int  w,h;
+-     char         *str;
++     const char   *str;
+      unsigned long fg,bg,hi,lo;
+ {
+   bp->win = win;
+@@ -116,7 +116,7 @@
+ void BTRedraw(bp)
+ BUTT *bp;
+ {
+-  int          i,x,y,r,x1,y1;
++  int          x,y,r,x1,y1;
+   unsigned int w,h;
+   XPoint       tpts[10], bpts[10], ipts[5];
+ 
+@@ -170,13 +170,13 @@
+     XSetForeground(theDisp, theGC, bp->fg);
+     XDrawLines(theDisp, bp->win, theGC, ipts, 5, CoordModeOrigin);  /* inset */
+ 
+-    XDrawLine(theDisp, bp->win, theGC, x+1,             y + 1,  
++    XDrawLine(theDisp, bp->win, theGC, x+1,             y + 1,
+ 	      ipts[0].x, ipts[0].y);
+     XDrawLine(theDisp, bp->win, theGC, x+1,             y + (int) h - 1,
+ 	      ipts[1].x, ipts[1].y);
+     XDrawLine(theDisp, bp->win, theGC, x + (int) w - 1, y + (int) h - 1,
+ 	      ipts[2].x, ipts[2].y);
+-    XDrawLine(theDisp, bp->win, theGC, x + (int) w - 1, y+1,  
++    XDrawLine(theDisp, bp->win, theGC, x + (int) w - 1, y+1,
+ 	      ipts[3].x, ipts[3].y);
+ 
+     if (bp->lit) {
+@@ -184,12 +184,12 @@
+       XDrawRectangle(theDisp, bp->win, theGC, x+1, y+1, w-2, h-2);
+     }
+   }
+-    
++
+   else {   /* ctrlColor */
+     XSetForeground(theDisp, theGC, bp->bg);
+     XFillRectangle(theDisp, bp->win, theGC, x+1, y+1, w-1, h-1);
+ 
+-    Draw3dRect(bp->win, x+1, y+1, w-2, h-2, R3D_OUT, bp->fwidth, 
++    Draw3dRect(bp->win, x+1, y+1, w-2, h-2, R3D_OUT, bp->fwidth,
+ 	       bp->hi, bp->lo, bp->bg);
+ 
+     XSetForeground(theDisp, theGC, bp->fg);
+@@ -198,7 +198,7 @@
+     if (bp->lit)
+       XDrawRectangle(theDisp, bp->win, theGC, x+1, y+1, w-2, h-2);
+   }
+-    
++
+ 
+ 
+ 
+@@ -210,7 +210,7 @@
+ 
+     XSetBackground(theDisp, theGC, bp->bg);
+ 
+-    if (bp->colorpix) 
++    if (bp->colorpix)
+       XCopyArea (theDisp,bp->pix, bp->win, theGC, 0,0,bp->pw,bp->ph, x1,y1);
+     else
+       XCopyPlane(theDisp,bp->pix, bp->win, theGC, 0,0,bp->pw,bp->ph, x1,y1,1L);
+@@ -262,15 +262,15 @@
+     if (bp->lit==inval && PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) {
+       bp->lit = !inval;  BTRedraw(bp);  XFlush(theDisp);
+     }
+-    
++
+     if (bp->lit!=inval && !PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) {
+       bp->lit = inval;  BTRedraw(bp);  XFlush(theDisp);
+     }
+   }
+ 
+   rval = (bp->lit != inval);
+-  
+-  if (bp->lit && !bp->toggle) 
++
++  if (bp->lit && !bp->toggle)
+     { bp->lit = 0;  BTRedraw(bp);  XFlush(theDisp); }
+ 
+   return(rval);
+@@ -290,18 +290,18 @@
+       RBUTT        *rblist;
+       Window        win;
+       int           x,y;
+-      char         *str;
++      const char   *str;
+       unsigned long fg,bg,hi,lo;
+ {
+   /* mallocs an RBUTT, fills in the fields, and appends it to rblist
+      if rblist is NULL, this is the first rb in the list.  It will
+-     be made the 'selected' one 
++     be made the 'selected' one
+ 
+-     Note: no need to check return status.  It'll fatal error if it 
++     Note: no need to check return status.  It'll fatal error if it
+      can't malloc */
+ 
+   RBUTT *rb, *rbptr;
+-  Pixmap rb_frame, rb_frame1, rb_top, rb_bot, rb_dtop, rb_dbot, rb_body, 
++  Pixmap rb_frame, rb_frame1, rb_top, rb_bot, rb_dtop, rb_dbot, rb_body,
+          rb_dot;
+ 
+   rb = (RBUTT *) malloc(sizeof(RBUTT));
+@@ -348,7 +348,7 @@
+     rb_off    = XCreatePixmap(theDisp, rootW, RBSIZE, RBSIZE, dispDEEP);
+     rb_off1   = XCreatePixmap(theDisp, rootW, RBSIZE, RBSIZE, dispDEEP);
+ 
+-    if (!rb_frame || !rb_frame1 || !rb_top || !rb_bot || !rb_dtop || 
++    if (!rb_frame || !rb_frame1 || !rb_top || !rb_bot || !rb_dtop ||
+ 	!rb_dbot  || !rb_body   || !rb_dot || !rb_on  || !rb_on1  ||
+ 	!rb_off   || !rb_off1)
+       FatalError("unable to create radio-button pixmaps");
+@@ -410,7 +410,7 @@
+       XFillRectangle(theDisp, rb_on,   theGC, 0,0,RBSIZE,RBSIZE);
+       XFillRectangle(theDisp, rb_on1,  theGC, 0,0,RBSIZE,RBSIZE);
+     }
+-      
++
+     XSetStipple(theDisp, theGC, rb_frame);
+     XSetForeground(theDisp, theGC, fg);
+     XFillRectangle(theDisp, rb_on,   theGC, 0,0,RBSIZE,RBSIZE);
+@@ -437,7 +437,7 @@
+ 
+   return(rb);
+ }
+-  
++
+ 
+ 
+ 
+@@ -475,23 +475,23 @@
+      int   lit;
+ {
+   /* draws the rb being pointed at */
+-  
++
+   Pixmap pix;
+-  
++
+   if (!rb) return;  /* rb = NULL */
+-  
++
+   XSetForeground(theDisp, theGC, rb->fg);
+-  
++
+   if (rb->selected) { pix = (lit) ? rb_on1 : rb_on; }
+   else { pix = (lit) ? rb_off1 : rb_off; }
+-  
++
+   XCopyArea(theDisp, pix, rb->win, theGC, 0,0,RBSIZE,RBSIZE, rb->x, rb->y);
+-  DrawString(rb->win, rb->x + RBSIZE + 4, 
++  DrawString(rb->win, rb->x + RBSIZE + 4,
+ 	     rb->y + RBSIZE/2 - CHIGH/2 + ASCENT, rb->str);
+ 
+   if (!rb->active) {  /* if non-active, dim button and string */
+     DimRect(rb->win, rb->x, rb->y, RBSIZE, RBSIZE, rb->bg);
+-    DimRect(rb->win, rb->x + RBSIZE + 4, rb->y + RBSIZE/2 - CHIGH/2, 
++    DimRect(rb->win, rb->x + RBSIZE + 4, rb->y + RBSIZE/2 - CHIGH/2,
+ 	    (u_int) StringWidth(rb->str), (u_int) CHIGH, rb->bg);
+   }
+ }
+@@ -527,19 +527,19 @@
+ }
+ 
+ 
+-	      
++
+ /***********************************************/
+ int RBWhich(rblist)
+      RBUTT *rblist;
+ {
+   int i;
+-  
++
+   /* returns index of currently selected rb.  if none, returns -1 */
+-  
++
+   i = 0;
+-  while (rblist && !rblist->selected) 
++  while (rblist && !rblist->selected)
+     { rblist = (RBUTT *) rblist->next;  i++; }
+-  
++
+   if (!rblist) return -1;             /* didn't find one */
+   return i;
+ }
+@@ -550,9 +550,9 @@
+      RBUTT *rblist;
+ {
+   int i;
+-  
++
+   /* returns # of rb's in the list */
+-  
++
+   i = 0;
+   while (rblist) { rblist = (RBUTT *) rblist->next; i++; }
+   return i;
+@@ -566,13 +566,13 @@
+ {
+   RBUTT *rb;
+   int    i;
+-  
++
+   /* sets 'active' status of rb #n.  does redrawing */
+-  
++
+   rb=rblist;  i=0;
+   while (rb && i!=n) { rb = (RBUTT *) rb->next; i++; }
+   if (!rb) return;                         /* n out of range.  do nothing */
+-  
++
+   if (rb->active != act) {
+     rb->active = act;
+     drawRB(rb, 0);
+@@ -588,13 +588,13 @@
+   int i;
+ 
+   /* searches through rblist to see if mouse click at mx,my is in the
+-     clickable region of any of the rb's.  If it finds one, it returns 
++     clickable region of any of the rb's.  If it finds one, it returns
+      it's index in the list.  If not, returns -1 */
+ 
+   i = 0;
+   while (rblist) {
+     if (PTINRECT(mx, my, rblist->x, rblist->y, RBSIZE, RBSIZE)) break;
+-    
++
+     rblist = (RBUTT *) rblist->next;
+     i++;
+   }
+@@ -613,9 +613,9 @@
+   Window       rW, cW;
+   int          i, x, y, rx, ry, lit, rv;
+   unsigned int mask;
+-  
++
+   /* returns '1' if selection changed */
+-  
++
+   rb=rblist;  i=0;
+   while (rb && i!=n) { rb = (RBUTT *) rb->next; i++; }
+   if (!rb) return 0;                    /* n out of range */
+@@ -637,7 +637,7 @@
+       drawRB(rb, lit);
+       XFlush(theDisp);
+     }
+-    
++
+     if (lit && !PTINRECT(x, y, rb->x, rb->y, RBSIZE, RBSIZE)) {
+       lit=0;
+       drawRB(rb, lit);
+@@ -671,7 +671,7 @@
+       CBUTT        *cb;
+       Window        win;
+       int           x,y;
+-      char         *str;
++      const char   *str;
+       unsigned long fg,bg,hi,lo;
+ {
+   /* fill in the fields of the structure */
+@@ -690,14 +690,14 @@
+      do so.  We'll be needing them, y'see... */
+ 
+   if (!cbpixmade) {
+-    cbcheck = XCreatePixmapFromBitmapData(theDisp, rootW, 
++    cbcheck = XCreatePixmapFromBitmapData(theDisp, rootW,
+ 	     (char *) cb_check_bits,
+ 	     cb_check_width, cb_check_height, fg, bg, dispDEEP);
+ 
+     cbpixmade = 1;
+   }
+ }
+-  
++
+ 
+ 
+ 
+@@ -708,25 +708,25 @@
+   /* draws the cb being pointed at */
+ 
+   XSetForeground(theDisp, theGC, cb->bg);
+-  XFillRectangle(theDisp, cb->win, theGC, cb->x+2, cb->y+2, 
++  XFillRectangle(theDisp, cb->win, theGC, cb->x+2, cb->y+2,
+ 		 XVCBSIZE-3,XVCBSIZE-3);
+ 
+   XSetForeground(theDisp, theGC, cb->fg);
+   XDrawRectangle(theDisp, cb->win, theGC, cb->x, cb->y, XVCBSIZE, XVCBSIZE);
+   Draw3dRect(cb->win, cb->x+1, cb->y+1, XVCBSIZE-2, XVCBSIZE-2, R3D_OUT, 2,
+-	     cb->hi, cb->lo, cb->bg); 
++	     cb->hi, cb->lo, cb->bg);
+ 
+-  if (cb->val) XCopyArea(theDisp, cbcheck, cb->win, theGC, 
+-			 0, 0, cb_check_width, cb_check_height, 
++  if (cb->val) XCopyArea(theDisp, cbcheck, cb->win, theGC,
++			 0, 0, cb_check_width, cb_check_height,
+ 			 cb->x+3, cb->y+3);
+- 
++
+   XSetForeground(theDisp, theGC, cb->fg);
+-  DrawString(cb->win, cb->x + XVCBSIZE+4, 
++  DrawString(cb->win, cb->x + XVCBSIZE+4,
+ 	     cb->y+XVCBSIZE/2 - CHIGH/2 + ASCENT, cb->str);
+ 
+   if (!cb->active) {  /* if non-active, dim button and string */
+     DimRect(cb->win, cb->x, cb->y, XVCBSIZE, XVCBSIZE, cb->bg);
+-    DimRect(cb->win, cb->x + XVCBSIZE+4, cb->y+XVCBSIZE/2 - CHIGH/2, 
++    DimRect(cb->win, cb->x + XVCBSIZE+4, cb->y+XVCBSIZE/2 - CHIGH/2,
+ 	    (u_int) StringWidth(cb->str), (u_int) CHIGH, cb->bg);
+   }
+ }
+@@ -761,7 +761,6 @@
+   Window       rW, cW;
+   int          x, y, rx, ry, lit;
+   unsigned int mask;
+-  Pixmap litpix, darkpix;
+ 
+   /* called once we've figured out that the mouse clicked in 'cb' */
+ 
+@@ -782,7 +781,7 @@
+       drawCB(cb,lit);
+       XFlush(theDisp);
+     }
+-    
++
+     if (lit && !PTINRECT(x, y, cb->x, cb->y, XVCBSIZE, XVCBSIZE)) {
+       lit=0;
+       drawCB(cb,lit);
+@@ -809,28 +808,28 @@
+ {
+   /* draws highlighting */
+   if (lit) {
+-    if (ctrlColor) 
++    if (ctrlColor)
+       Draw3dRect(cb->win, cb->x+1, cb->y+1, XVCBSIZE-2, XVCBSIZE-2, R3D_IN, 2,
+ 		 cb->hi, cb->lo, cb->bg);
+     else {
+       XSetForeground(theDisp, theGC, cb->fg);
+-      XDrawRectangle(theDisp, cb->win, theGC, cb->x+1, cb->y+1, 
++      XDrawRectangle(theDisp, cb->win, theGC, cb->x+1, cb->y+1,
+ 		     XVCBSIZE-2, XVCBSIZE-2);
+     }
+   }
+ 
+   else {
+-    if (ctrlColor) 
++    if (ctrlColor)
+       Draw3dRect(cb->win, cb->x+1, cb->y+1, XVCBSIZE-2, XVCBSIZE-2, R3D_OUT, 2,
+ 		 cb->hi, cb->lo, cb->bg);
+     else {
+       XSetForeground(theDisp, theGC, cb->bg);
+-      XDrawRectangle(theDisp, cb->win, theGC, cb->x+1, cb->y+1, 
++      XDrawRectangle(theDisp, cb->win, theGC, cb->x+1, cb->y+1,
+ 		     XVCBSIZE-2, XVCBSIZE-2);
+     }
+   }
+ }
+-    
++
+ 
+ 
+ /******************* MBUTT ROUTINES ************************/
+@@ -838,20 +837,20 @@
+ 
+ 
+ /***********************************************/
+-void MBCreate(mb, win, x,y,w,h, str, list, nlist, fg, bg, hi, lo)
++void MBCreate(mb, win, x, y, w, h, title, list, nlist, fg, bg, hi, lo)
+      MBUTT        *mb;
+      Window        win;
+      int           x,y;
+      unsigned int  w,h;
+-     char         *str;
+-     char        **list;
++     const char   *title;
++     const char  * const *list;
+      int           nlist;
+      unsigned long fg,bg,hi,lo;
+ {
+   XSetWindowAttributes xswa;
+   unsigned long        xswamask;
+   int i;
+-  
++
+   if (!mbpixmade) {
+     mbchk = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) mb_chk_bits,
+ 	     mb_chk_width, mb_chk_height, fg, bg, dispDEEP);
+@@ -865,7 +864,7 @@
+   mb->y        = y;
+   mb->w        = w;
+   mb->h        = h;
+-  mb->title    = str;
++  mb->title    = title;
+   mb->active   = 1;
+   mb->list     = list;
+   mb->nlist    = nlist;
+@@ -889,7 +888,7 @@
+   xswa.save_under       = True;
+   xswamask = CWBackPixel | CWBorderPixel | CWSaveUnder;
+ 
+-  mb->mwin = XCreateWindow(theDisp, mb->win, x, y, w, h, 
++  mb->mwin = XCreateWindow(theDisp, mb->win, x, y, w, h,
+ 			   (u_int) 2, (int) dispDEEP, InputOutput,
+ 			   theVisual, xswamask, &xswa);
+ 
+@@ -898,7 +897,7 @@
+   XSelectInput(theDisp, mb->mwin, ExposureMask | VisibilityChangeMask);
+   XSetTransientForHint(theDisp, mb->mwin, mb->win);
+ }
+-  
++
+ 
+ 
+ 
+@@ -908,15 +907,15 @@
+ {
+   /* draws a menu button in it's normal state.  (When it's actively being
+      used (to select an item), all drawing is handled in MBTrack) */
+-  
++
+   int          x,y,i,r,x1,y1;
+   unsigned int w,h;
+-  
++
+   r = 2;  /* amt of shadow */
+   x = mb->x;  y = mb->y;  w = mb->w;  h = mb->h;
+-  x1 = x + (int) w;  
++  x1 = x + (int) w;
+   y1 = y + (int) h;
+-  
++
+   XSetForeground(theDisp, theGC, mb->bg);
+   XFillRectangle(theDisp, mb->win, theGC, x+1, y+1, w-1, h-1);
+ 
+@@ -940,12 +939,14 @@
+     XSetBackground(theDisp, theGC, mb->bg);
+     XCopyPlane(theDisp, mb->pix, mb->win, theGC, 0,0,
+ 	       (u_int) mb->pw, (u_int) mb->ph, x1,y1, 1L);
+-    if (!mb->active) 
++    if (!mb->active)
+       DimRect(mb->win, x1,y1, (u_int) mb->pw, (u_int) mb->ph, mb->bg);
+   }
+ 
+   else {                                    /* draw string centered in butt */
+-    char *str, stbuf[256];
++    const char *str;
++    char       *tmp;
++    char        stbuf[256];
+ 
+     if (mb->title) str = mb->title;
+     else {  /* find first checked item, and show that as the title */
+@@ -961,7 +962,7 @@
+ 
+     /* truncate at TAB, if any */
+     strcpy(stbuf, str);
+-    if ((str = (char *) index(stbuf, '\t')) != NULL) *str = '\0';
++    if ((tmp = (char *) index(stbuf, '\t')) != NULL) *tmp = '\0';
+     str = stbuf;
+ 
+     x1 = CENTERX(mfinfo, x + w/2, str);
+@@ -997,14 +998,14 @@
+      MBUTT *mb;
+ {
+   /* returns index of first checked selection, or '-1' if nothing selected */
+-  
++
+   int i;
+ 
+   if (!mb->hascheck) return -1;
+ 
+   for (i=0; i<mb->nlist; i++)
+     if (mb->flags[i]) return i;
+-  
++
+   return -1;
+ }
+ 
+@@ -1017,13 +1018,13 @@
+   /* makes entry #n the selected entry (ie, the only one with a check mark)
+      Does all redrawing.  Does nothing if entry #n already selected.
+      Don't let it select 'dim' entries */
+-  
++
+   int i;
+-  
++
+   if (n<0 || n>mb->nlist) return;               /* # out of range */
+   if (!mb->hascheck)      return;               /* shouldn't happen */
+   if (mb->flags[n])       return;               /* already selected */
+-  
++
+   for (i=0; i<MAXMBLEN; i++) mb->flags[i] = 0;
+ 
+   mb->flags[n] = 1;
+@@ -1083,7 +1084,7 @@
+     }
+   }
+   mwide += 8;                             /* extra room at edges */
+-  
++
+   /* make wider if any checked menu items */
+   for (i=0; i<mb->nlist && !mb->flags[i]; i++);
+   hascheck = (i<mb->nlist || mb->hascheck);
+@@ -1091,7 +1092,7 @@
+   if (hascheck && mb->title) mwide += 8;
+ 
+   if (mwide < (mb->w+1)) mwide = mb->w+1; /* at least as wide as button */
+-    
++
+   mhigh = mb->nlist * LINEHIGH + 2 + extratop;
+ 
+   mx = mb->x-1;  my = mb->y - 1;
+@@ -1138,16 +1139,17 @@
+   y = ASCENT + SPACING + extratop;
+   for (i=0; i<mb->nlist; i++) {
+     char txtstr[256], *tabstr;
++
+     strcpy(txtstr, mb->list[i]);
+     if ((tabstr = (char *) index(txtstr, '\t'))) {
+       *tabstr = '\0';  tabstr++;
+     }
+ 
+     if (mb->flags[i]) {
+-      XCopyArea(theDisp, mbchk, win, theGC, 0, 0, mb_chk_width, mb_chk_height, 
++      XCopyArea(theDisp, mbchk, win, theGC, 0, 0, mb_chk_width, mb_chk_height,
+ 		x - 10, y - 8);
+     }
+-    
++
+     if (!strcmp(mb->list[i], MBSEP)) {
+       mb->dim[i] = 1;    /* don't select this one */
+       if (ctrlColor) {
+@@ -1161,15 +1163,15 @@
+ 	XDrawLine(theDisp,win,theGC,4,y-(ASCENT/2)+1, mwide-5, y-(ASCENT/2)+1);
+ 	XSetForeground(theDisp, theGC, mb->fg);
+       }
+-      else 
++      else
+ 	XDrawLine(theDisp, win, theGC, 4, y-(ASCENT/2), mwide-5, y-(ASCENT/2));
+     }
+     else {
+       DrawString(win, x, y, txtstr);
+-      if (tabstr) 
++      if (tabstr)
+ 	DrawString(win, mwide - mtabwide - 4, y, tabstr);
+ 
+-      if (mb->dim[i]) 
++      if (mb->dim[i])
+ 	DimRect(win, x, y-ASCENT, (u_int) mwide, (u_int) CHIGH, mb->bg);
+       XSetForeground(theDisp, theGC, mb->fg);
+     }
+diff -ru xv-3.10a/xvcolor.c xv-3.10a-enhancements/xvcolor.c
+--- xv-3.10a/xvcolor.c	1995-01-06 11:29:23.000000000 -0800
++++ xv-3.10a-enhancements/xvcolor.c	2007-05-12 13:55:36.000000000 -0700
+@@ -52,7 +52,7 @@
+      int   pwide, phigh, *pnumcols;
+ {
+   /* operates on 8-bit images.  sorts the colormap into 'best' order
+-   * 'order' is the 'best' order to allocate the colors.  'trans' is a 
++   * 'order' is the 'best' order to allocate the colors.  'trans' is a
+    * transformation to be done to pic, cpic, and epic (in PIC8 mode) to
+    * compress the colormap
+    */
+@@ -67,22 +67,22 @@
+   /* initialize histogram and compute it */
+   for (i=0; i<256; i++) hist[i]=0;
+   for (i=pwide*phigh, p=pic; i; i--, p++) hist[*p]++;
+-  
++
+   if (DEBUG>1) {
+     fprintf(stderr,"%s: Desired colormap\n",cmd);
+-    for (i=0; i<256; i++) 
++    for (i=0; i<256; i++)
+       if (hist[i]) fprintf(stderr,"(%3d  %02x,%02x,%02x %d)\n",
+ 			   i,rmap[i],gmap[i],bmap[i], hist[i]);
+     fprintf(stderr,"\n\n");
+   }
+-  
+-  
++
++
+   /* put the actually-used colors into the 'c' array in the order they occur
+      also, while we're at it, calculate ncols, and close up gaps in
+      colortable */
+-  
++
+   for (i=ncols=0; i<256; i++) {
+-    if (hist[i]) { 
++    if (hist[i]) {
+       rmap[ncols] = rmap[i];
+       gmap[ncols] = gmap[i];
+       bmap[ncols] = bmap[i];
+@@ -104,8 +104,8 @@
+   }
+   xvbcopy((char *) &c[entry], (char *) &c1[0], sizeof(CMAPENT));
+   c[entry].use = 0;   /* dealt with */
+-  
+-  
++
++
+   /* sort rest of colormap.  Half of the entries are allocated on the
+      basis of distance from already allocated colors, and half on the
+      basis of usage.  (NB: 'taxicab' distance is used throughout this file.)
+@@ -116,7 +116,7 @@
+      To obtain O(n^2) performance, we keep each unselected color
+      (in c[], with use>0) marked with the minimum distance to any of
+      the selected colors (in c1[]).  Each time we select a color, we
+-     can update the minimum distances in O(n) time. 
++     can update the minimum distances in O(n) time.
+ 
+      mod by Tom Lane   Tom.Lane at g.gp.cs.cmu.edu */
+ 
+@@ -134,8 +134,8 @@
+       for (j=0, cj=c; j<ncols; j++,cj++) {
+ 	if (cj->use) {      /* this color has not been marked already */
+ 	  /* update mindist */
+-          d = (cj->r - ckR)*(cj->r - ckR) + 
+-	      (cj->g - ckG)*(cj->g - ckG) + 
++          d = (cj->r - ckR)*(cj->r - ckR) +
++	      (cj->g - ckG)*(cj->g - ckG) +
+ 	      (cj->b - ckB)*(cj->b - ckB);
+           if (cj->mindist > d) cj->mindist = d;
+ 	  if (cj->mindist > mdist) { mdist = cj->mindist;  entry = j; }
+@@ -148,8 +148,8 @@
+       for (j=0, cj=c; j<ncols; j++,cj++) {
+ 	if (cj->use) {  /* this color has not been marked already */
+ 	  /* update mindist */
+-          d = (cj->r - ckR)*(cj->r - ckR) + 
+-	      (cj->g - ckG)*(cj->g - ckG) + 
++          d = (cj->r - ckR)*(cj->r - ckR) +
++	      (cj->g - ckG)*(cj->g - ckG) +
+     	      (cj->b - ckB)*(cj->b - ckB);
+           if (cj->mindist > d) cj->mindist = d;
+ 	  if (cj->use > mdist) { mdist = cj->use;  entry = j; }
+@@ -162,18 +162,18 @@
+     xvbcopy((char *) &c[entry], (char *) &c1[i], sizeof(CMAPENT));
+     c[entry].use = 0;
+   }
+-  
++
+ 
+   for (i=0; i<ncols; i++) order[i] = (byte) c1[i].oldindex;
+ 
+   if (DEBUG>1) {
+     fprintf(stderr,"%s: result of sorting colormap\n",cmd);
+-    for (i=0; i<ncols; i++) 
++    for (i=0; i<ncols; i++)
+       fprintf(stderr,"(%3d  %02x,%02x,%02x)     ",i,rmap[i],gmap[i],bmap[i]);
+     fprintf(stderr,"\n\n");
+-    
++
+     fprintf(stderr,"%s: allocation order table\n",cmd);
+-    for (i=0; i<ncols; i++) 
++    for (i=0; i<ncols; i++)
+       fprintf(stderr,"order[%d] = -> %d\n", i, order[i]);
+     fprintf(stderr,"\n");
+   }
+@@ -240,7 +240,7 @@
+       SetISTR(ISTR_COLOR,"Using %s colormap.",
+ 	      (haveStdCmap == STD_111 ? "2x2x2" :
+ 	       haveStdCmap == STD_222 ? "4x4x4" :
+-	       haveStdCmap == STD_232 ? "4x8x4" : 
++	       haveStdCmap == STD_232 ? "4x8x4" :
+                haveStdCmap == STD_666 ? "6x6x6" : "8x8x4"));
+ 
+       if (ncols>0) SetISTR(ISTR_COLOR2,stdCmapSuccess);
+@@ -251,7 +251,7 @@
+ 
+     for (i=0; i<numcols; i++) {
+       int i332;
+-      i332 = ((int)rMap[i]&0xe0) | (((int)gMap[i]&0xe0)>>3) | 
++      i332 = ((int)rMap[i]&0xe0) | (((int)gMap[i]&0xe0)>>3) |
+ 	     (((int)bMap[i]&0xc0)>>6);
+ 
+       cols[i]  = stdcols[i332];
+@@ -291,7 +291,7 @@
+   }
+ 
+   else {
+-    for (i=0; i<nfcols; i++) 
++    for (i=0; i<nfcols; i++)
+       xvFreeColors(theDisp, theCmap, &freecols[i], 1, 0L);
+ 
+     nfcols = 0;
+@@ -314,19 +314,19 @@
+   unique = p2alloc = 0;
+   rwthistime = 0;
+ 
+-  /* FIRST PASS COLOR ALLOCATION:  
++  /* FIRST PASS COLOR ALLOCATION:
+      for each color in the 'desired colormap', try to get it via
+      xvAllocColor().  If for any reason it fails, mark that pixel
+      'unallocated' and worry about it later.  Repeat. */
+ 
+-  /* attempt to allocate first ncols entries in colormap 
++  /* attempt to allocate first ncols entries in colormap
+      note: On displays with less than 8 bits per RGB gun, it's quite
+      possible that different colors in the original picture will be
+      mapped to the same color on the screen.  X does this for you
+-     silently.  However, this is not-desirable for this application, 
++     silently.  However, this is not-desirable for this application,
+      because when I say 'allocate me 32 colors' I want it to allocate
+      32 different colors, not 32 instances of the same 4 shades... */
+-  
++
+ 
+   for (i=0; i<256; i++) failed[i] = 1;
+ 
+@@ -334,7 +334,7 @@
+ 
+   for (i=0; i<numcols && unique<ncols; i++) {
+     c = colAllocOrder[i];
+-    if (mono) { 
++    if (mono) {
+       int intens = MONO(rMap[c], gMap[c], bMap[c]);
+       defs[c].red = defs[c].green = defs[c].blue = intens<<8;
+     }
+@@ -346,8 +346,8 @@
+ 
+     defs[c].flags = DoRed | DoGreen | DoBlue;
+ 
+-    if (!(colorMapMode==CM_OWNCMAP && cmap==theCmap && CMAPVIS(theVisual)) 
+-	&& xvAllocColor(theDisp,cmap,&defs[c])) { 
++    if (!(colorMapMode==CM_OWNCMAP && cmap==theCmap && CMAPVIS(theVisual))
++	&& xvAllocColor(theDisp,cmap,&defs[c])) {
+       unsigned long pixel, *fcptr;
+ 
+       pixel = cols[c] = defs[c].pixel;
+@@ -355,7 +355,7 @@
+       gdisp[c] = defs[c].green >> 8;
+       bdisp[c] = defs[c].blue  >> 8;
+       failed[c]= 0;
+-      
++
+       /* see if the newly allocated color is new and different */
+       for (j=0, fcptr=freecols; j<nfcols && *fcptr!=pixel; j++,fcptr++);
+       if (j==nfcols) unique++;
+@@ -365,24 +365,24 @@
+     }
+ 
+     else {
+-      /* the allocation failed.  If we want 'perfect' color, and we haven't 
++      /* the allocation failed.  If we want 'perfect' color, and we haven't
+ 	 already created our own colormap, we'll want to do so */
+       if ((colorMapMode == CM_PERFECT || colorMapMode == CM_OWNCMAP)
+ 	  && !LocalCmap && CMAPVIS(theVisual)) {
+ 	LocalCmap = XCreateColormap(theDisp, vrootW, theVisual, AllocNone);
+-	
++
+ 	if (LocalCmap) {  /* succeeded, presumably */
+ 	  /* free all colors that were allocated, and try again with the
+ 	     new colormap.  This is necessary because 'XCopyColormapAndFree()'
+ 	     has the unpleasant side effect of freeing up the various
+ 	     colors I need for the control panel, etc. */
+ 
+-	  for (i=0; i<nfcols; i++) 
++	  for (i=0; i<nfcols; i++)
+ 	    xvFreeColors(theDisp, theCmap, &freecols[i], 1, 0L);
+-	  
++
+ 	  if (mainW && !useroot) XSetWindowColormap(theDisp,mainW, LocalCmap);
+ 
+-	  if (mainW && !useroot && cmapInGam) 
++	  if (mainW && !useroot && cmapInGam)
+ 	    XSetWindowColormap(theDisp,gamW, LocalCmap);
+ 	  cmap = LocalCmap;
+ 
+@@ -402,9 +402,9 @@
+       }
+     }
+   }  /* FIRST PASS */
+-  
+-  
+-  
++
++
++
+   if (nfcols==numcols) {
+     if (numcols != unique)
+       SetISTR(ISTR_COLOR,"Got all %d colors.  (%d unique)", numcols,
+@@ -415,7 +415,7 @@
+     SetISTR(ISTR_COLOR2,"");
+     return;
+   }
+-  
++
+ 
+ 
+   /* SECOND PASS COLOR ALLOCATION:
+@@ -427,7 +427,7 @@
+      is in the X colormap.  Try to allocate that color (read only).
+      If that fails, the THIRD PASS will deal with it */
+ 
+-  SetISTR(ISTR_COLOR,"Got %d of %d colors.  (%d unique)", 
++  SetISTR(ISTR_COLOR,"Got %d of %d colors.  (%d unique)",
+ 	  nfcols,numcols,unique);
+ 
+   /* read entire colormap (or first 256 entries) into 'ctab' */
+@@ -436,28 +436,28 @@
+   if (dc>0) {  /* only do SECOND PASS if there IS a colormap to read */
+     for (i=0; i<dc; i++) ctab[i].pixel = (unsigned long) i;
+     XQueryColors(theDisp, cmap, ctab, dc);
+-    
++
+     for (i=0; i<numcols && unique<ncols; i++) {
+       c = colAllocOrder[i];
+-      
++
+       if (failed[c]) {  /* an unallocated pixel */
+ 	int d, mdist, close;
+ 	int rd, gd, bd, ri, gi, bi;
+-	
++
+ 	mdist = 1000000;   close = -1;
+ 	ri = rMap[c];  gi = gMap[c];  bi = bMap[c];
+-	
++
+ 	for (j=0; j<dc; j++) {
+ 	  rd = ri - (ctab[j].red  >>8);
+ 	  gd = gi - (ctab[j].green>>8);
+ 	  bd = bi - (ctab[j].blue >>8);
+-	  
++
+ 	  d = rd*rd + gd*gd + bd*bd;
+ 	  if (d<mdist) { mdist=d; close=j; }
+ 	}
+-	
++
+ 	if (close<0) FatalError("This Can't Happen! (How reassuring.)");
+-	if (xvAllocColor(theDisp, cmap, &ctab[close])) { 
++	if (xvAllocColor(theDisp, cmap, &ctab[close])) {
+ 	  xvbcopy((char *) &ctab[close], (char *) &defs[c], sizeof(XColor));
+ 	  failed[c]= 0;
+ 	  cols[c]  = ctab[close].pixel;
+@@ -487,7 +487,7 @@
+ 
+       mdist = 1000000;   close = -1;
+       ri = rMap[c];  gi = gMap[c];  bi = bMap[c];
+-      
++
+       /* search the alloc'd colors */
+       for (j=0; j<nfcols; j++) {
+ 	k = fc2pcol[j];
+@@ -535,7 +535,7 @@
+     unsigned long pmr[1], pix[1];
+     c = colAllocOrder[i];
+ 
+-    if (cellgroup[c]) {  
++    if (cellgroup[c]) {
+       int n;
+       /* this color is part of a group.  see if its group's
+ 	 been seen already, and if so, skip this */
+@@ -548,11 +548,11 @@
+       }
+     }
+ 
+-    if (!(colorMapMode==CM_OWNCMAP && cmap==theCmap && CMAPVIS(theVisual)) && 
++    if (!(colorMapMode==CM_OWNCMAP && cmap==theCmap && CMAPVIS(theVisual)) &&
+ 	XAllocColorCells(theDisp, cmap, False, pmr, 0, pix, 1)) {
+       defs[c].pixel = cols[c] = pix[0];
+       failed[c] = 0;
+-      if (mono) { 
++      if (mono) {
+ 	int intens = MONO(rMap[c], gMap[c], bMap[c]);
+ 	defs[c].red = defs[c].green = defs[c].blue = intens<<8;
+       }
+@@ -573,20 +573,20 @@
+     }
+ 
+     else {
+-      if ((colorMapMode == CM_PERFECT || colorMapMode == CM_OWNCMAP) 
++      if ((colorMapMode == CM_PERFECT || colorMapMode == CM_OWNCMAP)
+ 	  && !LocalCmap && CMAPVIS(theVisual)) {
+ 	LocalCmap = XCreateColormap(theDisp, vrootW, theVisual, AllocNone);
+-	
++
+ 	/* free all colors that were allocated, and try again with the
+ 	   new colormap.  This is necessary because 'XCopyColormapAndFree()'
+ 	   has the unpleasant side effect of freeing up the various
+ 	   colors I need for the control panel, etc. */
+ 
+-	for (i=0; i<nfcols; i++) 
++	for (i=0; i<nfcols; i++)
+ 	  xvFreeColors(theDisp, theCmap, &freecols[i], 1, 0L);
+-	
++
+ 	if (mainW && !useroot) XSetWindowColormap(theDisp,mainW, LocalCmap);
+-	if (mainW && !useroot && cmapInGam) 
++	if (mainW && !useroot && cmapInGam)
+ 	  XSetWindowColormap(theDisp,gamW, LocalCmap);
+ 	cmap = LocalCmap;
+ 
+@@ -608,12 +608,12 @@
+   }
+ 
+   else {
+-    /* Failed to allocate all colors in picture.  Map remaining desired 
++    /* Failed to allocate all colors in picture.  Map remaining desired
+        colors into closest allocated desired colors */
+ 
+       if (nfcols==0 && !LocalCmap) {
+-	char tstr[128], *tmp,
+-	    *foo = "No r/w cells available.  Using r/o color.";
++	char tstr[128], *tmp;
++	const char *foo = "No r/w cells available.  Using r/o color.";
+ 
+ 	tmp = GetISTR(ISTR_WARNING);
+ 	if (strlen(tmp) > (size_t) 0) sprintf(tstr, "%s  %s", tmp, foo);
+@@ -623,7 +623,7 @@
+ 	allocROColors();
+ 	return;
+       }
+-	
++
+       SetISTR(ISTR_COLOR,"Got %d of %d colors.",  nfcols,numcols);
+ 
+       for (i=0; i<numcols; i++) {
+@@ -662,7 +662,7 @@
+     j = fc2pcol[i];
+     defs[j].pixel = freecols[i];
+ 
+-    if (mono) { 
++    if (mono) {
+       int intens = MONO(rMap[j], gMap[j], bMap[j]);
+       defs[j].red = defs[j].green = defs[j].blue = intens<<8;
+     }
+@@ -706,9 +706,9 @@
+   if (theVisual->class == TrueColor || theVisual->class == DirectColor) {
+     unsigned long r, g, b, rmask, gmask, bmask, origr, origg, origb;
+     int rshift, gshift, bshift;
+-    
+-    /* shift r,g,b so that high bit of 16-bit color specification is 
+-     * aligned with high bit of r,g,b-mask in visual, 
++
++    /* shift r,g,b so that high bit of 16-bit color specification is
++     * aligned with high bit of r,g,b-mask in visual,
+      * AND each component with its mask,
+      * and OR the three components together
+      */
+@@ -781,7 +781,7 @@
+ 	      "         mask=%04lx,%04lx,%04lx  pix=%08lx\n",
+ 	      rmask, gmask, bmask, cdef->pixel);
+     }
+-    
++
+     return 1;
+   }
+   else {
+@@ -811,7 +811,7 @@
+ {
+   int i, j;
+ 
+-  /* if regroup is set, we *must* do a full realloc, as the cols[] array 
++  /* if regroup is set, we *must* do a full realloc, as the cols[] array
+      isn't correct anymore.  (cell groupings changed) */
+ 
+   ApplyECctrls();  /* set {r,g,b}cmap[editColor] based on dial settings */
+@@ -830,16 +830,16 @@
+     }
+   }
+ 
+-    
++
+   /* do something clever if we're using R/W color and this colorcell isn't
+      shared */
+ 
+   if (!regroup && allocMode==AM_READWRITE && rwthistime) {
+     /* let's try to be clever */
+-    /* determine if the editColor cell is unique, or shared (among 
++    /* determine if the editColor cell is unique, or shared (among
+        non-group members, that is) */
+ 
+-    for (i=j=0; i<numcols; i++) 
++    for (i=j=0; i<numcols; i++)
+       if (rwpc2pc[i] == rwpc2pc[editColor]) j++;
+ 
+     /* if this is a group, subtract off the non-this-one pixels from group */
+@@ -901,7 +901,7 @@
+   }
+ 
+   /* shift 0..i-1 down one position */
+-  xvbcopy((char *) colAllocOrder, (char *) colAllocOrder+1, 
++  xvbcopy((char *) colAllocOrder, (char *) colAllocOrder+1,
+ 	  i * sizeof(colAllocOrder[0]));
+   colAllocOrder[0] = editColor;
+ }
+@@ -930,9 +930,9 @@
+    *   stdfreecols[256]    - list of colors to free on exit
+    *   stdnfcols           - # of colors to free
+    *
+-   * possibly modifies browR, browG, browB, and browcols arrays 
++   * possibly modifies browR, browG, browB, and browcols arrays
+    *     (if !browPerfect)
+-   */       
++   */
+ 
+   /* returns '1' if the colors were reallocated, '0' otherwise */
+ 
+@@ -946,18 +946,18 @@
+ 
+   /* note:
+    *   if (ncols==0) (ie, we're either on, or emulating a b/w display),
+-   *   build std*[], std*disp[], colormaps, but don't actually 
++   *   build std*[], std*disp[], colormaps, but don't actually
+    *   allocate any colors.
+    */
+ 
+-  int i,j,r,g,b, desMode, screwed;
++  int i, r,g,b, desMode, screwed;
+   XColor def;
+   byte rmap[256],gmap[256],bmap[256],order[256];
+   unsigned long descols[256];
+   int des2got[256], failed[256];
+   int maplen, exactCnt, nearCnt;
+-  
+-  
++
++
+   /* generate stdr,stdg,stdb cmap.  Same in all cases */
+   for (r=0, i=0; r<8; r++)
+     for (g=0; g<8; g++)
+@@ -966,10 +966,10 @@
+ 	stdg[i] = (g*255)/7;
+ 	stdb[i] = (b*255)/3;
+       }
+-  
+-  
++
++
+   /* determine what size cmap we should build */
+-  if (theVisual->class == TrueColor || 
++  if (theVisual->class == TrueColor ||
+       theVisual->class == DirectColor) desMode = STD_332;
+   else if (colorMapMode == CM_STDCMAP) desMode = STD_232;
+   else desMode = STD_222;
+@@ -983,9 +983,9 @@
+   }
+ 
+ 
+-  if (DEBUG) fprintf(stderr,"MakeStdCmaps: have=%d, des=%d, ncols=%d\n", 
++  if (DEBUG) fprintf(stderr,"MakeStdCmaps: have=%d, des=%d, ncols=%d\n",
+ 		     haveStdCmap, desMode, ncols);
+-  
++
+   if (haveStdCmap != STD_NONE && haveStdCmap == desMode) return 0;
+   freeStdCmaps();
+ 
+@@ -997,7 +997,7 @@
+   for (i=0; i<256; i++) des2got[i] = i;
+   exactCnt = nearCnt = 0;
+ 
+-  
++
+   if (desMode == STD_111) {   /* try to alloc 8 colors */
+     /* generate a 1/1/1 desired colormap */
+     maplen = 8;
+@@ -1009,7 +1009,7 @@
+ 	  bmap[i] = (b*255);
+ 	}
+   }
+-  
++
+   else if (desMode == STD_222) {   /* try to alloc 64 colors */
+     /* generate a 2/2/2 desired colormap */
+     maplen = 64;
+@@ -1021,7 +1021,7 @@
+ 	  bmap[i] = (b*255)/3;
+ 	}
+   }
+-  
++
+   else if (desMode == STD_232) {   /* try to alloc 128 colors */
+     /* generate a 2/3/2 desired colormap */
+     maplen = 128;
+@@ -1033,7 +1033,7 @@
+ 	  bmap[i] = (b*255)/3;
+ 	}
+   }
+-  
++
+   else if (desMode == STD_666) {   /* try to alloc 216 colors */
+     /* generate a 6*6*6 desired colormap */
+     maplen = 216;
+@@ -1045,14 +1045,14 @@
+ 	  bmap[i] = (b*255)/5;
+ 	}
+   }
+-  
++
+   else {   /* desMode == STD_332 */
+     maplen = 256;
+     for (i=0; i<maplen; i++) {
+       rmap[i] = stdr[i];  gmap[i] = stdg[i];  bmap[i] = stdb[i];
+     }
+   }
+-  
++
+ 
+   /* sort the colors according to the diversity algorithm... */
+   diverseOrder(rmap,gmap,bmap,maplen,order);
+@@ -1072,7 +1072,7 @@
+       def.red   = rmap[order[i]] << 8;
+       def.green = gmap[order[i]] << 8;
+       def.blue  = bmap[order[i]] << 8;
+-      
++
+       def.flags = DoRed | DoGreen | DoBlue;
+ 
+       if (xvAllocColor(theDisp, theCmap, &def)) {  /* success */
+@@ -1090,34 +1090,34 @@
+ 
+     if (numgot != maplen) {
+       /* PHASE 2:  find 'close' colors in colormap, try to alloc those */
+-      
++
+       /* read entire colormap (or first 256 entries) into 'ctab' */
+       dc = (ncells<256) ? ncells : 256;
+       if (dc>0) {
+ 	for (i=0; i<dc; i++) ctab[i].pixel = (unsigned long) i;
+ 	XQueryColors(theDisp, theCmap, ctab, dc);
+-	
++
+ 	for (i=0; i<maplen; i++) {
+ 	  if (failed[i]) {
+-	    
++
+ 	    /* find closest color in colormap, and try to alloc it */
+ 	    mind = 1000000;   /* greater than 3 * (256^2) */
+ 	    for (j=0,num = -1; j<dc; j++) {
+ 	      rd = rmap[i] - (ctab[j].red  >>8);
+ 	      gd = gmap[i] - (ctab[j].green>>8);
+ 	      bd = bmap[i] - (ctab[j].blue >>8);
+-	      
++
+ 	      d = CDIST(rd, gd, bd);
+ 	      if (d<mind) { mind = d;  num = j; }
+ 	    }
+-	    
++
+ 	    if (num < 0) screwed = 1;
+ 	    else if (xvAllocColor(theDisp, theCmap, &ctab[num])) {  /*success*/
+ 	      des2got[i] = i;
+ 	      descols[i] = ctab[num].pixel;
+ 	      failed[i]  = 0;
+-	      nearCnt++; 
+-	      /* for (j=0; j<stdnfcols && stdfreecols[j]!=ctab[num].pixel; 
++	      nearCnt++;
++	      /* for (j=0; j<stdnfcols && stdfreecols[j]!=ctab[num].pixel;
+ 		 j++); */
+ 	      stdfreecols[stdnfcols++] = ctab[num].pixel;
+ 	    }
+@@ -1125,12 +1125,12 @@
+ 	}
+       }
+     }
+-      
+-    /* PHASE 3:  map remaining unallocated colors into closest we got */  
+-    
++
++    /* PHASE 3:  map remaining unallocated colors into closest we got */
++
+     for (i=0; i<maplen; i++) {
+       if (failed[i]) {
+-	
++
+ 	/* find closest alloc'd color */
+ 	mind = 1000000;   /* greater than 3 * (256^2) */
+ 	for (j=0,num=0; j<maplen; j++) {
+@@ -1139,7 +1139,7 @@
+ 	    if (d<mind) { mind = d;  num = j; }
+ 	  }
+ 	}
+-	
++
+ 	if (failed[num]) screwed = 1;
+ 	else {
+ 	  descols[i] = descols[num];
+@@ -1151,8 +1151,8 @@
+   }
+ 
+ 
+-  /* at this point, we have 'descols', a maplen long array of 
+-     X pixel values that maps 1/1/1, 2/2/2, 6*6*6, or 3/3/2 values 
++  /* at this point, we have 'descols', a maplen long array of
++     X pixel values that maps 1/1/1, 2/2/2, 6*6*6, or 3/3/2 values
+      into an X pixel value */
+ 
+   /* build stdcols and stdrdisp,stdgdisp,stdbdisp colormap */
+@@ -1170,7 +1170,7 @@
+ 
+ 	  stdcols[i332] = descols[des2got[i111]];
+ 	}
+-  } 
++  }
+ 
+   else if (desMode == STD_222) {
+     for (r=0; r<8; r++)
+@@ -1186,7 +1186,7 @@
+ 
+ 	  stdcols[i332] = descols[des2got[i222]];
+ 	}
+-  } 
++  }
+ 
+   else if (desMode == STD_232) {
+     for (r=0; r<8; r++)
+@@ -1201,7 +1201,7 @@
+ 	  stdbdisp[i332] = bmap[des2got[i232]];
+ 	  stdcols[i332]  = descols[des2got[i232]];
+ 	}
+-  } 
++  }
+ 
+   else if (desMode == STD_666) {
+     for (r=0,i=0; r<8; r++)
+@@ -1221,7 +1221,7 @@
+ 
+ 	  stdcols[i]  = descols[des2got[i666]];
+ 	}
+-  } 
++  }
+ 
+   else {  /* desMode == STD_332 */
+     for (i=0; i<256; i++) {
+@@ -1249,22 +1249,22 @@
+   if (DEBUG > 1) {
+     fprintf(stderr,"MakeStdCmaps:  ncols=%d  maplen=%d\n", ncols, maplen);
+     fprintf(stderr,"  std*[]= ");
+-    for (i=0; i<256; i++) 
++    for (i=0; i<256; i++)
+       fprintf(stderr,"%02x,%02x,%02x  ",stdr[i],stdg[i],stdb[i]);
+     fprintf(stderr,"\n\n");
+ 
+     fprintf(stderr,"  disp[]= ");
+-    for (i=0; i<256; i++) 
++    for (i=0; i<256; i++)
+       fprintf(stderr,"%02x,%02x,%02x  ",stdrdisp[i],stdgdisp[i],stdbdisp[i]);
+     fprintf(stderr,"\n\n");
+ 
+     fprintf(stderr,"  stdcols[]= ");
+-    for (i=0; i<256; i++) 
++    for (i=0; i<256; i++)
+       fprintf(stderr,"%02lx ",stdcols[i]);
+     fprintf(stderr,"\n\n");
+ 
+     fprintf(stderr,"  stdfreecols[%d] = ", stdnfcols);
+-    for (i=0; i<stdnfcols; i++) 
++    for (i=0; i<stdnfcols; i++)
+       fprintf(stderr,"%02lx ",stdfreecols[i]);
+     fprintf(stderr,"\n\n");
+   }
+@@ -1272,8 +1272,8 @@
+   if (exactCnt == maplen)
+     sprintf(stdCmapSuccess, "Got all %d colors.", exactCnt);
+   else {
+-    if (nearCnt>0) 
+-      sprintf(stdCmapSuccess, "Got %d out of %d colors.  (%d close color%s)", 
++    if (nearCnt>0)
++      sprintf(stdCmapSuccess, "Got %d out of %d colors.  (%d close color%s)",
+ 	      exactCnt, maplen, nearCnt, (nearCnt>1) ? "s" : "");
+     else
+       sprintf(stdCmapSuccess, "Got %d out of %d colors.", exactCnt, maplen);
+@@ -1292,11 +1292,11 @@
+   /* This function should only be called once, at the start of the program.
+    *
+    * produces many things:
+-   *   browR,browG,browB[256] 
++   *   browR,browG,browB[256]
+    *                       - a 3/3/2 colormap used by genIcon
+    *   browcols[256]       - maps 3/3/2 values into X colors
+    *   browCmap            - local cmap used in browse window, if browPerfect
+-   */       
++   */
+ 
+   int    i,j,r,g,b, screwed, num, exactCnt, nearCnt;
+   XColor def;
+@@ -1306,8 +1306,8 @@
+   long   d, mind;
+ 
+ 
+-  if (DEBUG) 
+-    fprintf(stderr,"MakeBrowCmap:  perfect = %d, ncols = %d\n", 
++  if (DEBUG)
++    fprintf(stderr,"MakeBrowCmap:  perfect = %d, ncols = %d\n",
+ 	    browPerfect, ncols);
+ 
+   if (ncols == 0 || !CMAPVIS(theVisual)) browPerfect = 0;
+@@ -1350,7 +1350,7 @@
+     def.red   = rmap[order[i]] << 8;
+     def.green = gmap[order[i]] << 8;
+     def.blue  = bmap[order[i]] << 8;
+-      
++
+     def.flags = DoRed | DoGreen | DoBlue;
+ 
+     if (xvAllocColor(theDisp, browCmap, &def)) {  /* success */
+@@ -1358,14 +1358,14 @@
+       descols[order[i]] = def.pixel;
+ 
+       if (DEBUG>1)
+-	fprintf(stderr,"makebrowcmap: Phase 1: Alloc %x,%x,%x succeeded!\n", 
++	fprintf(stderr,"makebrowcmap: Phase 1: Alloc %x,%x,%x succeeded!\n",
+ 		rmap[order[i]], gmap[order[i]], bmap[order[i]]);
+     }
+     else failed[order[i]] = 1;
+   }
+ 
+-    
+-  /* PHASE 2:  map remaining unallocated colors into closest we got */  
++
++  /* PHASE 2:  map remaining unallocated colors into closest we got */
+ 
+   for (i=0; i<256; i++) {
+     if (failed[i]) {
+@@ -1377,9 +1377,9 @@
+ 	  if (d<mind) { mind = d;  num = j; }
+ 	}
+       }
+-	  
++
+       if (DEBUG>1)
+-	fprintf(stderr,"makebrowcmap: closest to %x,%x,%x = %x,%x,%x\n", 
++	fprintf(stderr,"makebrowcmap: closest to %x,%x,%x = %x,%x,%x\n",
+ 		rmap[i],gmap[i],bmap[i], rmap[num], gmap[num], bmap[num]);
+ 
+       if (failed[num]) screwed = 1;
+@@ -1406,7 +1406,7 @@
+      byte *rmap, *gmap, *bmap, *order;
+      int   maplen;
+ {
+-  /* takes a colormap (maxlen 256) and produces an order array that 
++  /* takes a colormap (maxlen 256) and produces an order array that
+      contains the most-diverse order for allocating these colors */
+ 
+   int dist[256], i, pick, maxv, ocnt, d;
+@@ -1422,7 +1422,7 @@
+ 
+   ocnt = 0;
+   order[ocnt++] = pick;
+-  
++
+   /* init dist[] array */
+   for (i=0; i<maplen; i++) dist[i] = 1000000;
+ 
+@@ -1509,14 +1509,14 @@
+   else if (cmode == CM_NORMAL) {
+     if (novbrowse || browPerfect || haveStdCmap != iconCmapSize)
+       freeStdCmaps();
+-    
++
+     /* if using browser, and killed stdcmap, make icon stdcmap */
+     if (!novbrowse && !browPerfect && haveStdCmap == STD_NONE) {
+       if (MakeStdCmaps() && anyBrowUp && CMAPVIS(theVisual))
+ 	RegenBrowseIcons();
+     }
+   }
+-  
++
+   else if (cmode == CM_PERFECT) { }
+   else if (cmode == CM_OWNCMAP) { }
+ 
+@@ -1540,7 +1540,7 @@
+     SetEpicMode();
+     if (genepic) GenerateEpic(eWIDE, eHIGH);
+   }
+-  else { 
++  else {
+     if (oldmode == CM_STDCMAP && cmode != CM_STDCMAP && epicMode != EM_RAW) {
+       /* just left STDCMAP mode.  Switch to using 'RAW' */
+       epicMode = EM_RAW;
+diff -ru xv-3.10a/xvctrl.c xv-3.10a-enhancements/xvctrl.c
+--- xv-3.10a/xvctrl.c	1994-12-22 14:34:41.000000000 -0800
++++ xv-3.10a-enhancements/xvctrl.c	2007-05-13 14:11:33.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvctrl.c - Control box handling functions
+  *
+  * callable functions:
+@@ -9,7 +9,7 @@
+  *   RedrawCtrl(x,y,w,h)    -  called by 'expose' events
+  *   ClickCtrl(x,y)
+  *   DrawCtrlStr()          -  called to redraw 'ISTR_INFO' string in ctrlW
+- *   ScrollToCurrent()      -  called when list selection is changed 
++ *   ScrollToCurrent()      -  called when list selection is changed
+  *
+  *   LSCreate()             -  creates a listbox
+  *   LSRedraw()             -  redraws 'namelist' box
+@@ -49,7 +49,10 @@
+ #include "bits/uicon"
+ #include "bits/oicon1"
+ #include "bits/oicon2"
+-#include "bits/icon"
++#ifdef REGSTR
++#  define OMIT_ICON_BITS
++#  include "bits/icon"
++#endif
+ 
+ #define CTRLWIDE 440               /* (fixed) size of control window */
+ #define CTRLHIGH 348 /* 379 */
+@@ -80,73 +83,74 @@
+    in xv.h */
+ 
+ 
+-static char *dispMList[] = { "Raw\tr", 
+-			     "Dithered\td",
+-			     "Smooth\ts",
+-			     MBSEP,
+-			     "Read/Write Colors",
+-			     MBSEP,
+-			     "Normal Colors",
+-			     "Perfect Colors",
+-			     "Use Own Colormap",
+-			     "Use Std. Colormap" };
+-
+-static char *rootMList[] = { "Window", 
+-			     "Root: tiled",
+-			     "Root: integer tiled",
+-			     "Root: mirrored",
+-			     "Root: integer mirrored",
+-			     "Root: center tiled",
+-			     "Root: centered",
+-			     "Root: centered, warp",
+-			     "Root: centered, brick",
+-    		             "Root: symmetrical tiled",
+-			     "Root: symmetrical mirrored" };
+-
+-static char *conv24MList[] = { "8-bit mode\t\2448",
+-			       "24-bit mode\t\2448",
+-			       MBSEP,
+-			       "Lock current mode",
+-			       MBSEP,
+-                               "Quick 24->8",
+-			       "Slow 24->8",
+-			       "Best 24->8" };
+-
+-static char *algMList[]    = { "Undo All\t\244u",
+-			       MBSEP,
+- 			       "Blur...\t\244b",
+-			       "Sharpen...\t\244s",
+-			       "Edge Detect\t\244e",
+-			       "Emboss\t\244m",
+-			       "Oil Painting\t\244o",
+-			       "Blend\t\244B",
+-			       "Copy Rotate...\t\244t",
+-			       "Clear Rotate...\t\244T",
+-			       "Pixelize...\t\244p",
+-			       "Spread...\t\244S",
+-			       "DeSpeckle...\t\244k"};
+-
+-static char *sizeMList[]   = { "Normal\tn",
+-			       "Max Size\tm",
+-			       "Maxpect\tM",
+-			       "Double Size\t>",
+-			       "Half Size\t<",
+-			       "10% Larger\t.",
+-			       "10% Smaller\t,",
+-			       MBSEP,
+-			       "Set Size\tS",
+-			       "Re-Aspect\ta",
+-			       "4x3\t4",
+-			       "Int. Expand\tI" };
+-
+-static char *windowMList[] = { "Visual Schnauzer\t^v",
+-			       "Color Editor\te",
+-			       "Image Info\ti",
+-			       "Image Comments\t^c",
+-			       "Text View\t^t",
+-			       MBSEP,
+-			       "About XV\t^a",
+-			       "XV Keyboard Help"};
++static const char *dispMList[] = { "Raw\tr",
++				   "Dithered\td",
++				   "Smooth\ts",
++				   MBSEP,
++				   "Read/Write Colors",
++				   MBSEP,
++				   "Normal Colors",
++				   "Perfect Colors",
++				   "Use Own Colormap",
++				   "Use Std. Colormap" };
++
++static const char *rootMList[] = { "Window",
++				   "Root: tiled",
++				   "Root: integer tiled",
++				   "Root: mirrored",
++				   "Root: integer mirrored",
++				   "Root: center tiled",
++				   "Root: centered",
++				   "Root: centered, warp",
++				   "Root: centered, brick",
++				   "Root: symmetrical tiled",
++				   "Root: symmetrical mirrored",
++				   "Root: upper left corner" };
++
++static const char *conv24MList[] = { "8-bit mode\t\2448",
++				     "24-bit mode\t\2448",
++				     MBSEP,
++				     "Lock current mode",
++				     MBSEP,
++				     "Quick 24->8",
++				     "Slow 24->8",
++				     "Best 24->8" };
++
++static const char *algMList[] = { "Undo All\t\244u",
++				  MBSEP,
++				  "Blur...\t\244b",
++				  "Sharpen...\t\244s",
++				  "Edge Detect\t\244e",
++				  "Emboss\t\244m",
++				  "Oil Painting\t\244o",
++				  "Blend\t\244B",
++				  "Copy Rotate...\t\244t",
++				  "Clear Rotate...\t\244T",
++				  "Pixelize...\t\244p",
++				  "Spread...\t\244S",
++				  "DeSpeckle...\t\244k"};
++
++static const char *sizeMList[] = { "Normal\tn",
++				   "Max Size\tm",
++				   "Maxpect\tM",
++				   "Double Size\t>",
++				   "Half Size\t<",
++				   "10% Larger\t.",
++				   "10% Smaller\t,",
++				   MBSEP,
++				   "Set Size\tS",
++				   "Re-Aspect\ta",
++				   "4x3\t4",
++				   "Int. Expand\tI" };
++
++static const char *windowMList[] = { "Visual Schnauzer\t^v",
++				     "Color Editor\te",
++				     "Image Info\ti",
++				     "Image Comments\t^c",
++				     "Text View\t^t",
++				     MBSEP,
++				     "About XV\t^a",
++				     "XV Keyboard Help"};
+ 
+ 
+ 
+@@ -157,14 +161,14 @@
+ 
+ /***************************************************/
+ void CreateCtrl(geom)
+-     char *geom;
++     const char *geom;
+ {
+-  int i, listh, topskip;
++  int listh, topskip;
+   double skip;
+   XSetWindowAttributes xswa;
+   Pixmap oicon1Pix, oicon2Pix;
+ 
+-  ctrlW = CreateWindow("xv controls", "XVcontrols", geom, 
++  ctrlW = CreateWindow("xv controls", "XVcontrols", geom,
+ 		       CTRLWIDE, CTRLHIGH, infofg, infobg, 0);
+   if (!ctrlW) FatalError("can't create controls window!");
+ 
+@@ -205,10 +209,10 @@
+   oicon2Pix = MakePix1(ctrlW, oicon2_bits,  oicon2_width,  oicon2_height);
+ 
+   if (!grayTile  || !dimStip  || !fifoPix   || !chrPix    || !dirPix    ||
+-      !blkPix    || !lnkPix   || !regPix    || !rotlPix   || !fliphPix  || 
++      !blkPix    || !lnkPix   || !regPix    || !rotlPix   || !fliphPix  ||
+       !flipvPix  || !p10Pix   || !m10Pix    || !cutPix    || !copyPix   ||
+       !pastePix  || !clearPix || !uiconPix  || !oiconPix  || !oicon1Pix ||
+-      !oicon2Pix || !padPix   || !annotPix) 
++      !oicon2Pix || !padPix   || !annotPix)
+     FatalError("unable to create all pixmaps in CreateCtrl()\n");
+ 
+ 
+@@ -226,7 +230,7 @@
+   XFreePixmap(theDisp, oicon1Pix);
+   XFreePixmap(theDisp, oicon2Pix);
+ 
+-  
++
+ 
+   if (ctrlColor) XSetWindowBackground(theDisp, ctrlW, locol);
+             else XSetWindowBackgroundPixmap(theDisp, ctrlW, grayTile);
+@@ -234,7 +238,7 @@
+   listh = LINEHIGH * NLINES;
+ 
+   LSCreate(&nList, ctrlW, 5, 52, (CTRLWIDE-BUTTW-18),
+-	   LINEHIGH*NLINES, NLINES, dispnames, numnames, 
++	   LINEHIGH*NLINES, NLINES, dispnames, numnames,
+ 	   infofg, infobg, hicol, locol, RedrawNList, 0, 0);
+   nList.selected = 0;  /* default to first name selected */
+ 
+@@ -245,8 +249,8 @@
+ 
+   topskip = nList.y;
+   skip =  ((double) (nList.h - (CHIGH+5))) / 6.0;
+-  if (skip > SBUTTH+8) {  
+-    skip = SBUTTH + 7;  
++  if (skip > SBUTTH+8) {
++    skip = SBUTTH + 7;
+     topskip = nList.y + (nList.h - (6*skip + (CHIGH+5))) / 2;
+   }
+ 
+@@ -258,7 +262,7 @@
+ #define R_BY3 (topskip + (int)(3*skip))
+ #define R_BY4 (topskip + (int)(4*skip))
+ #define R_BY5 (topskip + (int)(5*skip))
+-  
++
+   BTCreate(&but[BNEXT],    ctrlW, R_BX0, R_BY0, R_BW1, SBUTTH, "Next",   BCLS);
+   BTCreate(&but[BPREV],    ctrlW, R_BX0, R_BY1, R_BW1, SBUTTH, "Prev",   BCLS);
+   BTCreate(&but[BLOAD],    ctrlW, R_BX0, R_BY2, R_BW1, SBUTTH, "Load",   BCLS);
+@@ -309,7 +313,7 @@
+   BTCreate(&but[BABOUT],  ctrlW,BX4,  BY1,BUTTW,BUTTH,"About XV",BCLS);
+   BTCreate(&but[BQUIT],   ctrlW,BX5,  BY1,BUTTW,BUTTH,"Quit",    BCLS);
+ 
+-  BTCreate(&but[BXV],     ctrlW,5,5, 100, (u_int) nList.y - 5 - 2 - 5, 
++  BTCreate(&but[BXV],     ctrlW,5,5, 100, (u_int) nList.y - 5 - 2 - 5,
+ 	   "", BCLS);
+ 
+   SetButtPix(&but[BCOPY],  copyPix,  copy_width,   copy_height);
+@@ -329,7 +333,7 @@
+   if (ctrlColor) {
+     SetButtPix(&but[BXV], oiconPix, oicon1_width,  oicon1_height);
+     but[BXV].colorpix = 1;
+-  } 
++  }
+   else SetButtPix(&but[BXV], iconPix, icon_width,  icon_height);
+ #else
+   SetButtPix(&but[BXV], uiconPix, uicon_width,  uicon_height);
+@@ -338,21 +342,21 @@
+   XMapSubwindows(theDisp, ctrlW);
+ 
+ 
+-  /* have to create menu buttons after XMapSubWindows, as we *don't* want 
++  /* have to create menu buttons after XMapSubWindows, as we *don't* want
+      the popup menus mapped */
+ 
+-  MBCreate(&dispMB,   ctrlW, CTRLWIDE - 8 - 112 - 2*(112+2), 5,112,19, 
++  MBCreate(&dispMB,   ctrlW, CTRLWIDE - 8 - 112 - 2*(112+2), 5,112,19,
+ 	   "Display",    dispMList,   DMB_MAX,    BCLS);
+-  MBCreate(&conv24MB, ctrlW, CTRLWIDE - 8 - 112 - (112+2),   5,112,19, 
++  MBCreate(&conv24MB, ctrlW, CTRLWIDE - 8 - 112 - (112+2),   5,112,19,
+ 	   "24/8 Bit",   conv24MList, CONV24_MAX, BCLS);
+-  MBCreate(&algMB,    ctrlW, CTRLWIDE - 8 - 112,             5,112,19, 
++  MBCreate(&algMB,    ctrlW, CTRLWIDE - 8 - 112,             5,112,19,
+ 	   "Algorithms", algMList,    ALG_MAX,    BCLS);
+ 
+-  MBCreate(&rootMB,   ctrlW, CTRLWIDE - 8 - 112 - 2*(112+2), 5+21,112,19, 
++  MBCreate(&rootMB,   ctrlW, CTRLWIDE - 8 - 112 - 2*(112+2), 5+21,112,19,
+ 	   "Root",       rootMList,   RMB_MAX,    BCLS);
+-  MBCreate(&windowMB, ctrlW, CTRLWIDE - 8 - 112 - (112+2),   5+21,112,19, 
++  MBCreate(&windowMB, ctrlW, CTRLWIDE - 8 - 112 - (112+2),   5+21,112,19,
+ 	   "Windows",    windowMList, WMB_MAX,    BCLS);
+-  MBCreate(&sizeMB,   ctrlW, CTRLWIDE - 8 - 112,             5+21,112,19, 
++  MBCreate(&sizeMB,   ctrlW, CTRLWIDE - 8 - 112,             5+21,112,19,
+ 	   "Image Size", sizeMList,   SZMB_MAX,   BCLS);
+ 
+ 
+@@ -395,7 +399,7 @@
+      byte *bits;
+      int   w,h;
+ {
+-  return XCreatePixmapFromBitmapData(theDisp, win, (char *) bits, 
++  return XCreatePixmapFromBitmapData(theDisp, win, (char *) bits,
+ 				     (u_int) w, (u_int) h, 1L,0L,1);
+ }
+ 
+@@ -404,7 +408,7 @@
+ void CtrlBox(vis)
+ int vis;
+ {
+-  if (vis) XMapRaised(theDisp, ctrlW);  
++  if (vis) XMapRaised(theDisp, ctrlW);
+   else     XUnmapWindow(theDisp, ctrlW);
+ 
+   ctrlUp = vis;
+@@ -416,7 +420,6 @@
+ int x,y,w,h;
+ {
+   int i;
+-  XRectangle xr;
+ 
+   RANGE(w, 0, CTRLWIDE);
+   RANGE(h, 0, CTRLHIGH);
+@@ -452,7 +455,7 @@
+ /***************************************************/
+ void DrawCtrlNumFiles()
+ {
+-  int x,y,w,h;
++  int x,y,w;
+   char foo[40];
+ 
+   x  = but[BNEXT].x;
+@@ -463,14 +466,14 @@
+   XSetBackground(theDisp, theGC, infobg);
+ 
+   sprintf(foo, "%d file%s", numnames, (numnames==1) ? "" : "s");
+-    
++
+   XSetForeground(theDisp, theGC, infobg);
+   XFillRectangle(theDisp,ctrlW, theGC, x+1,y+1, (u_int) w-1, (u_int) CHIGH+5);
+ 
+   XSetForeground(theDisp,theGC,infofg);
+   XDrawRectangle(theDisp,ctrlW, theGC, x,y,     (u_int) w,   (u_int) CHIGH+6);
+ 
+-  Draw3dRect(ctrlW, x+1,y+1,                    (u_int) w-2, (u_int) CHIGH+4, 
++  Draw3dRect(ctrlW, x+1,y+1,                    (u_int) w-2, (u_int) CHIGH+4,
+ 	     R3D_IN, 2, hicol, locol, infobg);
+ 
+   XSetForeground(theDisp,theGC,infofg);
+@@ -489,7 +492,7 @@
+   st1 = GetISTR(ISTR_WARNING);
+ 
+   XSetForeground(theDisp, theGC, infobg);
+-  XFillRectangle(theDisp, ctrlW, theGC, 0, y+1, 
++  XFillRectangle(theDisp, ctrlW, theGC, 0, y+1,
+ 		 CTRLWIDE, (u_int)((CHIGH+4)*2+1));
+ 
+   XSetForeground(theDisp, theGC, infofg);
+@@ -501,7 +504,7 @@
+     XSetForeground(theDisp, theGC, locol);
+     XDrawLine(theDisp, ctrlW, theGC, 0, y+1,   CTRLWIDE, y+1);
+     XDrawLine(theDisp, ctrlW, theGC, 0, y+CHIGH+5, CTRLWIDE, y+CHIGH+5);
+-    XDrawLine(theDisp, ctrlW, theGC, 0, y+(CHIGH+4)*2+1, 
++    XDrawLine(theDisp, ctrlW, theGC, 0, y+(CHIGH+4)*2+1,
+ 	      CTRLWIDE, y+(CHIGH+4)*2+1);
+   }
+ 
+@@ -542,16 +545,16 @@
+ void ScrollToCurrent(lst)
+ LIST *lst;
+ {
+-  /* called when selected item on list is changed.  Makes the selected 
++  /* called when selected item on list is changed.  Makes the selected
+      item visible.  If it already is, nothing happens.  Otherwise, it
+-     attempts to scroll so that the selection appears in the middle of 
++     attempts to scroll so that the selection appears in the middle of
+      the list window */
+ 
+   int halfway;
+ 
+   if (lst->selected < 0) return;  /* no selection, do nothing */
+ 
+-  if (lst->selected > lst->scrl.val && 
++  if (lst->selected > lst->scrl.val &&
+       lst->selected <  lst->scrl.val + lst->nlines-1) LSRedraw(lst, 0);
+   else {
+     halfway = (lst->nlines)/2;   /* offset to the halfway pt. of the list */
+@@ -590,7 +593,7 @@
+   lp->win = XCreateSimpleWindow(theDisp,win,x,y,(u_int) w, (u_int) h,1,fg,bg);
+   if (!lp->win) FatalError("can't create list window!");
+ 
+-  lp->x = x;    lp->y = y;   
++  lp->x = x;    lp->y = y;
+   lp->w = w;    lp->h = h;
+   lp->fg = fg;  lp->bg = bg;
+   lp->hi = hi;  lp->lo = lo;
+@@ -603,7 +606,7 @@
+ 
+   XSelectInput(theDisp, lp->win, ExposureMask | ButtonPressMask);
+ 
+-  SCCreate(&lp->scrl, lp->win, w-20, -1, 1, h, 0, 
++  SCCreate(&lp->scrl, lp->win, w-20, -1, 1, h, 0,
+ 	   nstr-nlines, 0, nlines-1, fg, bg, hi, lo, fptr);
+ 
+   XMapSubwindows(theDisp, lp->win);
+@@ -646,7 +649,7 @@
+ LIST *lp;
+ {
+   /* redraws lists 3d-effect, which can be trounced by drawSel() */
+-  Draw3dRect(lp->win, 0, 0, lp->w-1, lp->h-1, R3D_IN, 2, 
++  Draw3dRect(lp->win, 0, 0, lp->w-1, lp->h-1, R3D_IN, 2,
+ 	     lp->hi, lp->lo, lp->bg);
+ }
+ 
+@@ -675,43 +678,43 @@
+   else { fg = lp->fg;  bg = lp->bg; }
+ 
+   XSetForeground(theDisp, theGC, bg);
+-  XFillRectangle(theDisp, lp->win, theGC, x0, y0+i*LINEHIGH, 
++  XFillRectangle(theDisp, lp->win, theGC, x0, y0+i*LINEHIGH,
+ 		 (u_int) wide+1, (u_int) LINEHIGH);
+ 
+   if (j>=0 && j<lp->nstr) {   /* only draw string if valid */
+     XSetForeground(theDisp, theGC, fg);
+     XSetBackground(theDisp, theGC, bg);
+ 
+-    if (!lp->filetypes) 
++    if (!lp->filetypes)
+       DrawString(lp->win, x0+3, y0+i*LINEHIGH + ASCENT + 1, lp->str[j]);
+     else {
+       int ypos = y0 + i*LINEHIGH + (LINEHIGH - i_fifo_height)/2;
+ 
+-      if (lp->str[j][0] == C_FIFO) 
++      if (lp->str[j][0] == C_FIFO)
+ 	XCopyPlane(theDisp, fifoPix, lp->win, theGC, 0, 0,
+ 		   i_fifo_width, i_fifo_height, x0+3, ypos, 1L);
+ 
+-      else if (lp->str[j][0] == C_CHR) 
++      else if (lp->str[j][0] == C_CHR)
+ 	XCopyPlane(theDisp, chrPix, lp->win, theGC, 0, 0,
+ 		   i_chr_width, i_chr_height, x0+3, ypos, 1L);
+ 
+-      else if (lp->str[j][0] == C_DIR) 
++      else if (lp->str[j][0] == C_DIR)
+ 	XCopyPlane(theDisp, dirPix, lp->win, theGC, 0, 0,
+ 		   i_dir_width, i_dir_height, x0+3, ypos, 1L);
+ 
+-      else if (lp->str[j][0] == C_BLK) 
++      else if (lp->str[j][0] == C_BLK)
+ 	XCopyPlane(theDisp, blkPix, lp->win, theGC, 0, 0,
+ 		   i_blk_width, i_blk_height, x0+3, ypos, 1L);
+ 
+-      else if (lp->str[j][0] == C_LNK) 
++      else if (lp->str[j][0] == C_LNK)
+ 	XCopyPlane(theDisp, lnkPix, lp->win, theGC, 0, 0,
+ 		   i_lnk_width, i_lnk_height, x0+3, ypos, 1L);
+ 
+-      else if (lp->str[j][0] == C_SOCK) 
++      else if (lp->str[j][0] == C_SOCK)
+ 	XCopyPlane(theDisp, sockPix, lp->win, theGC, 0, 0,
+ 		   i_sock_width, i_sock_height, x0+3, ypos, 1L);
+ 
+-      else if (lp->str[j][0] == C_EXE) 
++      else if (lp->str[j][0] == C_EXE)
+ 	XCopyPlane(theDisp, exePix, lp->win, theGC, 0, 0,
+ 		   i_exe_width, i_exe_height, x0+3, ypos, 1L);
+ 
+@@ -720,8 +723,8 @@
+ 		   i_reg_width, i_reg_height, x0+3, ypos, 1L);
+ 
+ 
+-      DrawString(lp->win, x0+3 + i_fifo_width + 3, 
+-		  y0+i*LINEHIGH + ASCENT + 1, 
++      DrawString(lp->win, x0+3 + i_fifo_width + 3,
++		  y0+i*LINEHIGH + ASCENT + 1,
+ 		  lp->str[j]+1);
+     }
+   }
+@@ -735,7 +738,7 @@
+ {
+   int  i;
+ 
+-  for (i = lp->scrl.val; i < lp->scrl.val + lp->nlines; i++) 
++  for (i = lp->scrl.val; i < lp->scrl.val + lp->nlines; i++)
+     drawSel(lp,i);
+   ls3d(lp);
+ }
+@@ -762,7 +765,7 @@
+   if (sel >= lp->nstr) sel = lp->selected;
+ 
+   /* see if it's a double click */
+-  if (ev->time - lasttime < DBLCLKTIME && sel==lastsel 
++  if (ev->time - lasttime < DBLCLKTIME && sel==lastsel
+       && (lp->scrl.val + (y-y0)/LINEHIGH) < lp->nstr
+       && !INACTIVE(lp,sel)) {
+     return (sel);
+@@ -782,7 +785,7 @@
+   while (XQueryPointer(theDisp,lp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
+     if (!(mask & Button1Mask)) break;    /* button released */
+ 
+-    if (y<y0) { /* scroll up in list */ 
++    if (y<y0) { /* scroll up in list */
+       if (lp->scrl.val > lp->scrl.min) {
+ 	lp->selected = lp->scrl.val - 1;
+ 	SCSetVal(&lp->scrl, lp->scrl.val - 1);
+@@ -804,7 +807,7 @@
+       if (sel >= lp->nstr) sel = lp->nstr - 1;
+ 
+       if (sel != lp->selected && sel >= lp->scrl.val &&
+-	  sel < lp->scrl.val + lp->nlines) {  
++	  sel < lp->scrl.val + lp->nlines) {
+ 	/* dragged to another on current page */
+ 	oldsel = lp->selected;
+ 	lp->selected = sel;
+@@ -829,17 +832,17 @@
+   else if (key==LS_PAGEDOWN) SCSetVal(&lp->scrl,lp->scrl.val + (lp->nlines-1));
+   else if (key==LS_HOME)     SCSetVal(&lp->scrl,lp->scrl.min);
+   else if (key==LS_END)      SCSetVal(&lp->scrl,lp->scrl.max);
+-  
++
+   else if (key==LS_LINEUP)   {
+     /* if the selected item visible, but not the top line */
+-    if (lp->selected > lp->scrl.val && 
++    if (lp->selected > lp->scrl.val &&
+ 	lp->selected <= lp->scrl.val + lp->nlines - 1) {
+       /* then just move it */
+       lp->selected--;
+       drawSel(lp, lp->selected);  drawSel(lp, lp->selected+1);
+       ls3d(lp);
+     }
+-    
++
+     /* if it's the top line... */
+     else if (lp->selected == lp->scrl.val) {
+       if (lp->selected > 0) {
+@@ -847,7 +850,7 @@
+ 	SCSetVal(&lp->scrl, lp->selected);
+       }
+     }
+-    
++
+     /* if it's not visible, put it on the bottom line */
+     else {
+       lp->selected = lp->scrl.val + lp->nlines - 1;
+@@ -856,10 +859,10 @@
+       ls3d(lp);
+     }
+   }
+-  
++
+   else if (key==LS_LINEDOWN)   {
+     /* if the selected item visible, but not the bottom line */
+-    if (lp->selected >= lp->scrl.val && 
++    if (lp->selected >= lp->scrl.val &&
+ 	lp->selected < lp->scrl.val + lp->nlines - 1) {
+       if (lp->selected < lp->nstr-1) {
+ 	/* then just move it */
+@@ -868,7 +871,7 @@
+ 	ls3d(lp);
+       }
+     }
+-    
++
+     /* if it's the bottom line... */
+     else if (lp->selected == lp->scrl.val + lp->nlines - 1) {
+       if (lp->selected < lp->nstr-1) {
+@@ -876,7 +879,7 @@
+ 	SCSetVal(&lp->scrl, lp->scrl.val+1);
+       }
+     }
+-    
++
+     /* if it's not visible, put it on the top line */
+     else {
+       lp->selected = lp->scrl.val;
+diff -ru xv-3.10a/xvcut.c xv-3.10a-enhancements/xvcut.c
+--- xv-3.10a/xvcut.c	1995-01-13 11:55:48.000000000 -0800
++++ xv-3.10a-enhancements/xvcut.c	2007-04-15 15:02:32.000000000 -0700
+@@ -15,7 +15,7 @@
+  *      static void  clearSelectedArea();
+  *      static void  makeClipFName    ();
+  *      static int   countcols24      (byte *, int,int, int,int,int,int));
+- *      static int   countNewCols     (byte*, int, int, byte*, int, 
++ *      static int   countNewCols     (byte*, int, int, byte*, int,
+  *                                     int, int, int, int);
+  *
+  *             void  InitSelection  ();
+@@ -72,7 +72,7 @@
+ static void clearSelectedArea  PARM((void));
+ static void makeClipFName      PARM((void));
+ static int  countcols24        PARM((byte *, int, int, int, int, int, int));
+-static int  countNewCols       PARM((byte *, int, int, byte *, int, 
++static int  countNewCols       PARM((byte *, int, int, byte *, int,
+ 				     int, int, int, int));
+ static int  dragHandle         PARM((XButtonEvent *));
+ static void dragSelection      PARM((XButtonEvent *, u_int, int));
+@@ -210,7 +210,7 @@
+   if (!PasteAllowed()) { XBell(theDisp, 0);  return; }
+ 
+   cimg = getFromClip();
+-  if (!cimg) return;  
++  if (!cimg) return;
+ 
+   /* if there's no selection, make one! */
+   if (!HaveSelection()) makePasteSel(cimg);
+@@ -231,7 +231,7 @@
+ 
+   byte *dp, *dpic, *clippic, *clipcmap;
+   int   clipw, cliph, clipis24, len, istran, trval;
+-  int   i, j, sx,sy,sw,sh, cx,cy,cw,ch, dx,dy,dw,dh,dx2,dy2;
++  int   i, j, sx,sy,sw,sh, cx,cy,cw,ch, dx,dy,dw,dh;
+ 
+ 
+   /*
+@@ -245,7 +245,7 @@
+ 	((int) (cimg[CIMG_LEN + 2]<<16)) |
+ 	((int) (cimg[CIMG_LEN + 3]<<24));
+ 
+-  if (len < CIMG_PIC24) return;        
++  if (len < CIMG_PIC24) return;
+ 
+   istran    = cimg[CIMG_TRANS];
+   trval     = cimg[CIMG_TRVAL];
+@@ -268,7 +268,7 @@
+    * already, because if we *are*, we'd prefer to do any clipboard rescaling
+    * in 24-bit space for the obvious reasons.
+    *
+-   * possibilities:  
++   * possibilities:
+    *   PIC24  -  easy, do clipboard rescale in 24-bit space
+    *   PIC8, and clipboard is 8 bits, (or 24-bits, but with <=256 colors)
+    *      and total unique colors < 256:
+@@ -283,7 +283,7 @@
+ 
+   /* dx,dy,dw,dh is the rectangle (in PIC coords) where the paste will occur
+      (cropped to be entirely within PIC */
+-  
++
+   dx = sx;  dy = sy;  dw = sw;  dh = sh;
+   CropRect2Rect(&dx, &dy, &dw, &dh, 0, 0, pWIDE, pHIGH);
+ 
+@@ -291,7 +291,7 @@
+   /* cx,cy,cw,ch is the rectangle of the clipboard data (in clipboard coords)
+      that will actually be used in the paste operation */
+ 
+-  cx = (sx>=0) ? 0 : ((-sx) * clipw) / sw;  
++  cx = (sx>=0) ? 0 : ((-sx) * clipw) / sw;
+   cy = (sy>=0) ? 0 : ((-sy) * cliph) / sh;
+   cw = (dw * clipw) / sw;
+   ch = (dh * cliph) / sh;
+@@ -302,27 +302,29 @@
+   if (picType == PIC8) {
+     int ncc, keep8;
+     char buf[512];
+-    
++
+     if (clipis24) { /* pasting in a 24-bit image that *requires* promotion */
+-      static char *bnames[] = { "\nOkay", "\033Cancel" };
++      static const char *labels[] = { "\nOkay", "\033Cancel" };
++
+       strcpy(buf, "Warning:  Pasting this 24-bit image will require ");
+       strcat(buf, "promoting the current image to 24 bits.");
+-      
+-      if (PopUp(buf, bnames, 2)) goto exit;   /* Cancelled */
++
++      if (PopUp(buf, labels, 2)) goto exit;   /* Cancelled */
+       else Change824Mode(PIC24);              /* promote pic to 24 bits */
+     }
+ 
+     else {   /* clip is 8 bits */
+       ncc = countNewCols(clippic,clipw,cliph,clipcmap,clipis24,cx,cy,cw,ch);
+-      
++
+       if (ncc + numcols > 256) {
+-	static char *bnames[] = { "\nPromote", "8Keep 8-bit", "\033Cancel" };
++	static const char *labels[] = { "\nPromote", "8Keep 8-bit", "\033Cancel" };
++
+ 	strcpy(buf,"Warning:  The image and the clipboard combine to have ");
+ 	strcat(buf,"more than 256 unique colors.  Promoting the ");
+ 	strcat(buf,"image to 24 bits is recommended, otherwise the contents ");
+ 	strcat(buf,"of the clipboard will probably lose some colors.");
+-	
+-	keep8 = PopUp(buf, bnames, 3);
++
++	keep8 = PopUp(buf, labels, 3);
+ 	if      (keep8==2) goto exit;              /* Cancel */
+ 	else if (keep8==0) Change824Mode(PIC24);   /* promote pic to 24 bits */
+       }
+@@ -331,8 +333,8 @@
+ 
+ 
+ 
+-  
+-  
++
++
+   /* legal possibilities at this point:
+    *   pic is PIC24:  clip is 8 or 24
+    *   pic is PIC8:   clip is 8, or clip is 24 but has 256 or fewer colors
+@@ -342,18 +344,18 @@
+ 
+   if (picType == PIC8) {
+     int   clx, cly, r,g,b,k,mind,close,newcols;
+-    byte *cp, *clp, *pp, *ccp, newr[256], newg[256], newb[256], remap[256];
++    byte *cp, *clp, *pp, newr[256], newg[256], newb[256], remap[256];
+     byte  order[256], trans[256];
+     int   bperpix, dpncols;
+-    
++
+     dpic = (byte *) malloc((size_t) dw * dh);
+     if (!dpic) FatalError("Out of memory in DoImgPaste()\n");
+-    
++
+     bperpix = (clipis24) ? 3 : 1;
+     newcols = 0;
+-    
++
+     /* dpic = a scaled, 8-bit representation of clippic[cx,cy,cw,ch] */
+-    
++
+     if (!clipis24) {   /* copy colormap from clip data into newr,g,b[] */
+       for (i=0; i<256; i++) {
+ 	newr[i] = clipcmap[i*3];
+@@ -366,22 +368,22 @@
+       dp = dpic + i*dw;
+       cly = cy + (i * ch) / dh;
+       clp = clippic + (cly*clipw * bperpix);
+-      
++
+       for (j=0; j<dw; j++, dp++) {
+ 	/* get appropriate pixel from clippic */
+ 	clx = cx + (j * cw) / dw;
+ 	cp = clp + (clx * bperpix);
+-	
++
+ 	if (!clipis24) *dp = *cp;
+ 	else {                            /* build colormap as we go... */
+ 	  r = *cp++;  g = *cp++;  b = *cp++;
+-	  
++
+ 	  /* look it up in new colormap, add if not there */
+ 	  for (k=0; k<newcols && (r!=newr[k] || g!=newg[k] ||b!=newb[k]); k++);
+ 	  if (k==newcols && k<256) {
+ 	    newr[k]=r;  newg[k]=g;  newb[k]=b;  newcols++;
+ 	  }
+-	  
++
+ 	  *dp = (byte) (k & 0xff);
+ 	}
+       }
+@@ -401,23 +403,23 @@
+ 	}
+       }
+     }
+-    
+-    
+-    
++
++
++
+     /* COLORMAP MERGING */
+-    
++
+     newcols = 0;
+-    
++
+     for (i=0; i<dpncols; i++) {
+       if (istran && i==trval) continue;
+-      
++
+       for (j=0; j<numcols; j++) {              /* look for an exact match */
+ 	if (rMap[j]==newr[i] && gMap[j]==newg[i] && bMap[j]==newb[i]) break;
+       }
+       if (j<numcols) remap[i] = j;
+       else {                                   /* no exact match */
+ 	newcols++;
+-	
++
+ 	if (numcols < 256) {
+ 	  rMap[numcols] = newr[i];
+ 	  gMap[numcols] = newg[i];
+@@ -429,7 +431,7 @@
+ 	  r = newr[i];  g=newg[i];  b=newb[i];
+ 	  mind = 256*256 + 256*256 + 256*256;
+ 	  for (j=close=0; j<numcols; j++) {
+-	    k = ((rMap[j]-r) * (rMap[j]-r)) + 
++	    k = ((rMap[j]-r) * (rMap[j]-r)) +
+ 	      ((gMap[j]-g) * (gMap[j]-g)) +
+ 		((bMap[j]-b) * (bMap[j]-b));
+ 	    if (k<mind) { mind = k;  close = j; }
+@@ -438,10 +440,10 @@
+ 	}
+       }
+     }
+-    
+-    
++
++
+     /* copy the data into PIC */
+-    
++
+     dp = dpic;
+     for (i=dy; i<dy+dh; i++) {
+       pp = pic + (i*pWIDE) + dx;
+@@ -451,7 +453,7 @@
+       }
+     }
+     free(dpic);
+-    
++
+     if (newcols) InstallNewPic();      /* does color reallocation, etc. */
+     else {
+       GenerateCpic();
+@@ -459,16 +461,16 @@
+       DrawEpic();
+     }
+   }
+-  
++
+ 
+   /******************** PIC24 handling **********************/
+-  
+-  
++
++
+   else {
+     byte *tmppic, *cp, *pp, *clp;
+     int   bperpix;
+     int   trr, trg, trb, clx, cly;
+-    
++
+     trr = trg = trb = 0;
+     if (istran) {
+       if (clipis24) {
+@@ -482,24 +484,24 @@
+ 	trb = clipcmap[trval*3+2];
+       }
+     }
+-    
++
+     bperpix = (clipis24) ? 3 : 1;
+ 
+     if (!istran && (cw != dw || ch != dh)) {  /* need to resize, can smooth */
+       byte rmap[256], gmap[256], bmap[256];
+-      
++
+       tmppic = (byte *) malloc((size_t) cw * ch * bperpix);
+       if (!tmppic) FatalError("Out of memory in DoImgPaste()\n");
+-      
+-      /* copy relevant hunk of clippic into tmppic (Smooth24 only works on 
++
++      /* copy relevant hunk of clippic into tmppic (Smooth24 only works on
+ 	 complete images */
+-      
++
+       for (i=0; i<ch; i++) {
+ 	dp = tmppic + i*cw*bperpix;
+ 	cp = clippic + ((i+cy)*clipw + cx) * bperpix;
+ 	for (j=0; j<cw*bperpix; j++) *dp++ = *cp++;
+       }
+-      
++
+       if (!clipis24) {
+ 	for (i=0; i<256; i++) {
+ 	  rmap[i] = clipcmap[i*3];
+@@ -507,15 +509,15 @@
+ 	  bmap[i] = clipcmap[i*3+2];
+ 	}
+       }
+-      
++
+       dpic = Smooth24(tmppic, clipis24, cw,ch, dw,dh, rmap,gmap,bmap);
+       if (!dpic) FatalError("Out of memory (2) in DoImgPaste()\n");
+       free(tmppic);
+-      
++
+       /* copy the resized, smoothed, 24-bit data into 'pic' */
+-      
++
+       /* XXX: (deal with smooth-resized transparent imgs) */
+-      
++
+       dp = dpic;
+       for (i=dy; i<dy+dh; i++) {
+ 	pp = pic + (i*pWIDE + dx) * 3;
+@@ -536,11 +538,11 @@
+ 	pp = pic + ((i+dy)*pWIDE + dx) * 3;
+ 	cly = cy + (i * ch) / dh;
+ 	clp = clippic + (cly*clipw * bperpix);
+-	
++
+ 	for (j=0; j<dw; j++, pp+=3) {
+ 	  clx = cx + (j * cw) / dw;
+ 	  cp = clp + (clx * bperpix);
+-	  
++
+ 	  if (clipis24) {
+ 	    if (!istran || cp[0]!=trr || cp[1]!=trg || cp[2]==trb) {
+ 	      pp[0] = *cp++;  pp[1] = *cp++;  pp[2] = *cp++;
+@@ -557,14 +559,14 @@
+       }
+     }
+ 
+-    
++
+     GenerateCpic();
+     GenerateEpic(eWIDE, eHIGH);
+     DrawEpic();
+   }
+-  
+-    
+- exit:  
++
++
++ exit:
+   SetCursors(-1);
+ }
+ 
+@@ -577,20 +579,20 @@
+   XColor cfg, cbg;
+ 
+   dragcurs = XCreateFontCursor(theDisp, XC_fleur);
+-  p1 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) cut_bits, 
++  p1 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) cut_bits,
+ 				   cut_width,  cut_height, 1L, 0L, 1);
+-  p2 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) cutm_bits, 
++  p2 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) cutm_bits,
+ 				   cutm_width, cutm_height, 1L, 0L, 1);
+-  p3 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) copy_bits, 
++  p3 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) copy_bits,
+ 				   copy_width,  copy_height, 1L, 0L, 1);
+-  p4 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) copym_bits, 
++  p4 = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) copym_bits,
+ 				   copym_width, copym_height, 1L, 0L, 1);
+   if (p1 && p2 && p3 && p4) {
+     cfg.red = cfg.green = cfg.blue = 0;
+     cbg.red = cbg.green = cbg.blue = 0xffff;
+-    cutcurs = XCreatePixmapCursor(theDisp, p1,p2, &cfg, &cbg, 
++    cutcurs = XCreatePixmapCursor(theDisp, p1,p2, &cfg, &cbg,
+ 				  cut_x_hot, cut_y_hot);
+-    copycurs = XCreatePixmapCursor(theDisp, p3,p4, &cfg, &cbg, 
++    copycurs = XCreatePixmapCursor(theDisp, p3,p4, &cfg, &cbg,
+ 				  copy_x_hot, copy_y_hot);
+     if (!cutcurs || !copycurs) FatalError("can't create cut/copy cursors...");
+   }
+@@ -619,7 +621,7 @@
+ 
+   if (!CutAllowed()) {  XBell(theDisp, 0);  return (byte *) NULL; }
+   if (!HaveSelection()) return (byte *) NULL;
+-  
++
+   GetSelRCoords(&x,&y,&w,&h);
+   CropRect2Rect(&x,&y,&w,&h, 0,0,pWIDE,pHIGH);
+ 
+@@ -663,15 +665,15 @@
+   if (picType == PIC24 && !do24) {                  /* 24-bit data as 8-bit */
+     int nc,pr,pg,pb;
+     byte *cm;
+-    
++
+     nc = 0;
+     dp = cimg + CIMG_PIC8;
+-    
++
+     for (i=y; i<y+h; i++) {
+       pp = pic + i*pWIDE*3 + x*3;
+       for (j=x; j<x+w; j++, pp+=3) {
+ 	pr = pp[0];  pg = pp[1];  pb = pp[2];
+-	
++
+ 	cm = cimg + CIMG_CMAP;
+ 	for (k=0; k<nc; k++,cm+=3) {
+ 	  if (pr==cm[0] && pg==cm[1] && pb==cm[2]) break;
+@@ -682,12 +684,12 @@
+ 	  cimg[CIMG_CMAP + nc*3 + 1] = pg;
+ 	  cimg[CIMG_CMAP + nc*3 + 2] = pb;
+ 	}
+-	
++
+ 	*dp++ = (byte) k;
+       }
+     }
+   }
+-  
++
+ 
+   else if (picType == PIC24) {                     /* 24-bit data as 24-bit */
+     dp = cimg + CIMG_PIC24;
+@@ -705,26 +707,26 @@
+   else if (picType == PIC8) {                       /* 8-bit selection */
+     byte *cm = cimg + CIMG_CMAP;
+     for (i=0; i<256; i++) {                         /* copy colormap */
+-      if (i<numcols) { 
++      if (i<numcols) {
+ 	*cm++ = rMap[i];
+ 	*cm++ = gMap[i];
+ 	*cm++ = bMap[i];
+       }
+     }
+-    
++
+     dp = cimg + CIMG_PIC8;
+     for (i=y; i<y+h; i++) {                         /* copy image */
+       pp = pic + i*pWIDE + x;
+       for (j=x; j<x+w; j++) *dp++ = *pp++;
+     }
+   }
+-    
++
+   return cimg;
+ }
+ 
+ 
+ 
+-  
++
+ /********************************************/
+ static byte *getFromClip()
+ {
+@@ -743,14 +745,14 @@
+     clipAtom = XInternAtom(theDisp, CLIPPROP, True);
+     if (clipAtom != None) XDeleteProperty(theDisp, rootW, clipAtom);
+   }
+-  
+-  
++
++
+   clipAtom = XInternAtom(theDisp, CLIPPROP, True);             /* find prop */
+   if (clipAtom != None) {
+ 
+     /* try to retrieve the length of the data in the property */
+-    i = XGetWindowProperty(theDisp, rootW, clipAtom, 0L, 1L, False, XA_STRING, 
+-		       &actType, &actFormat, &nitems, &nleft, 
++    i = XGetWindowProperty(theDisp, rootW, clipAtom, 0L, 1L, False, XA_STRING,
++		       &actType, &actFormat, &nitems, &nleft,
+ 		       (unsigned char **) &data);
+ 
+     if (i==Success && actType==XA_STRING && actFormat==8 && nleft>0) {
+@@ -763,9 +765,9 @@
+       XFree((void *) data);
+ 
+       /* read the rest of the data (len bytes) */
+-      i = XGetWindowProperty(theDisp, rootW, clipAtom, 1L, 
+-			     (long) ((len-4)+3)/4, 
+-			     False, XA_STRING, &actType, &actFormat, &nitems, 
++      i = XGetWindowProperty(theDisp, rootW, clipAtom, 1L,
++			     (long) ((len-4)+3)/4,
++			     False, XA_STRING, &actType, &actFormat, &nitems,
+ 			     &nleft, (unsigned char **) &data);
+ 
+       if (i==Success) {
+@@ -791,8 +793,8 @@
+     }
+   }
+ 
+-  
+-  /* if we're still here, then the prop method was less than successful. 
++
++  /* if we're still here, then the prop method was less than successful.
+      use the file method, instead */
+ 
+   if (!clipfname) makeClipFName();
+@@ -800,7 +802,7 @@
+   fp = fopen(clipfname, "r");
+   if (!fp) {
+     unlink(clipfname);
+-    sprintf(str, "Can't read clipboard file '%s'\n\n  %s.", 
++    sprintf(str, "Can't read clipboard file '%s'\n\n  %s.",
+ 	    clipfname, ERRSTR(errno));
+     ErrPopUp(str,"\nBletch!");
+     return (byte *) NULL;
+@@ -877,19 +879,19 @@
+     clipAtom = XInternAtom(theDisp, CLIPPROP, True);
+     if (clipAtom != None) XDeleteProperty(theDisp, rootW, clipAtom);
+   }
+-  
+-  
++
++
+   if (!forceClipFile) {
+     clipAtom = XInternAtom(theDisp, CLIPPROP, False);  /* find or make prop */
+     if (clipAtom != None) {
+       /* try to store the data in the property */
+-      
++
+       xerrcode = 0;
+       XChangeProperty(theDisp, rootW, clipAtom, XA_STRING, 8, PropModeReplace,
+ 		      cimg, len);
+       XSync(theDisp, False);                         /* make it happen *now* */
+       if (!xerrcode) return;                         /* success! */
+-      
++
+       /* failed, use file method */
+       XDeleteProperty(theDisp, rootW, clipAtom);
+     }
+@@ -903,7 +905,7 @@
+   fp = fopen(clipfname, "w");
+   if (!fp) {
+     unlink(clipfname);
+-    sprintf(str, "Can't write clipboard file '%s'\n\n  %s.", 
++    sprintf(str, "Can't write clipboard file '%s'\n\n  %s.",
+ 	    clipfname, ERRSTR(errno));
+     ErrPopUp(str,"\nBletch!");
+     return;
+@@ -964,7 +966,7 @@
+ /********************************************/
+ static void makeClipFName()
+ {
+-  char *homedir;
++  const char *homedir;
+ 
+   if (clipfname) return;
+ 
+@@ -996,7 +998,7 @@
+   byte *pp;
+ 
+   nc = 0;
+-  
++
+   for (i=y; nc<257 && i<y+h; i++) {
+     pp = pic + i*pwide*3 + x*3;
+     for (j=x; nc<257 && j<x+w; j++, pp+=3) {
+@@ -1022,7 +1024,7 @@
+    */
+ 
+   int   i, j, k, nc, r,g,b;
+-  byte *pp, *cp;
++  byte *pp;
+   byte  newr[257], newg[257], newb[257];
+ 
+   if (picType != PIC8) return 0;           /* shouldn't happen */
+@@ -1034,7 +1036,7 @@
+       pp = newpic + i*w*3 + cx*3;
+       for (j=cx; j<cx+cw; j++) {
+ 	r = *pp++;  g = *pp++;  b = *pp++;
+-	
++
+ 	/* lookup r,g,b in 'pic's colormap and the newcolors colormap */
+ 	for (k=0; k<nc && (r!=newr[k] || g!=newg[k] || b!=newb[k]); k++);
+ 	if (k==nc) {
+@@ -1062,11 +1064,11 @@
+     /* now see which of the used colors are new */
+     for (i=0, nc=0; i<256; i++) {
+       if (!coluse[i]) continue;
+-      
+-      r = newcmap[i*3];  
+-      g = newcmap[i*3+1];  
++
++      r = newcmap[i*3];
++      g = newcmap[i*3+1];
+       b = newcmap[i*3+2];
+-      
++
+       /* lookup r,g,b in pic's colormap */
+       for (k=0; k<numcols && (r!=rMap[k] || g!=gMap[k] || b!=bMap[k]);k++);
+       if (k==numcols) {  /* it's a new color, alright */
+@@ -1075,7 +1077,7 @@
+       }
+     }
+   }
+-  
++
+   return nc;
+ }
+ 
+@@ -1143,7 +1145,7 @@
+   /* NOTE:  SELECTION IS *NOT* GUARANTEED to be within the bounds of 'pic'.
+      It is only guaranteed to *intersect* pic. */
+ 
+-  *xp = selrx;  *yp = selry;  
++  *xp = selrx;  *yp = selry;
+   *wp = selrw;  *hp = selrh;
+ }
+ 
+@@ -1200,7 +1202,7 @@
+     if (lastClickButton==Button1 && (ev->time - lastClickTime) < DBLCLKTIME) {
+       lastClickButton=Button3;
+       if (HaveSelection() && PTINRECT(px, py, selrx, selry, selrw, selrh)) {
+-	EnableSelection(0); 
++	EnableSelection(0);
+ 	rv = 1;
+       }
+       else {
+@@ -1225,7 +1227,7 @@
+   else if (ev->button == Button2) {      /* do a drag & drop operation */
+     if (HaveSelection() && PTINRECT(px,py,selrx,selry,selrw,selrh)) {
+       /* clip selection rect to pic */
+-      EnableSelection(0);  
++      EnableSelection(0);
+       CropRect2Rect(&selrx, &selry, &selrw, &selrh, 0, 0, pWIDE, pHIGH);
+ 
+       if (selrw<1 || selrh<1) rv = 0;
+@@ -1253,8 +1255,8 @@
+    * holding SHIFT constrains selection to be square,
+    * holding CTRL  constrains selection to keep original aspect ratio
+    */
+-  
+-  int          i, mex, mey, mpx, mpy, offx,offy;
++
++  int          mex, mey, mpx, mpy, offx,offy;
+   int          sex, sey, sex2, sey2, sew, seh, sew2, seh2, hs, h2;
+   int          istp, isbt, islf, isrt, isvm, ishm;
+   int          cnstsq, cnstasp;
+@@ -1272,7 +1274,7 @@
+   sew2 = sew/2;
+   seh2 = seh/2;
+   sex2--;  sey2--;
+-  
++
+   if      (sew>=35 && seh>=35) hs=7;
+   else if (sew>=20 && seh>=20) hs=5;
+   else if (sew>= 9 && seh>= 9) hs=3;
+@@ -1307,7 +1309,7 @@
+ 
+ 
+   /* it's definitely in a handle...  track 'til released */
+-  
++
+   DrawSelection(0);
+   selFilled   = 1;
+   selTracking = 1;
+@@ -1366,12 +1368,12 @@
+                        else { chwide=1;  newwide = (int) (seh*orgaspect); }
+ 	}
+       }
+-      
++
+       if (chwide) {
+ 	if (islf) { sex = (sex+sew) - newwide; }
+ 	sew = newwide;
+       }
+-      
++
+       if (chhigh) {
+ 	if (istp) { sey = (sey+seh) - newhigh; }
+ 	seh = newhigh;
+@@ -1380,7 +1382,7 @@
+ 
+     if (sew<1) sew=1;
+     if (seh<1) seh=1;
+-    
++
+     if (sex!=selrx || sey!=selry || sew!=selrw || seh!=selrh) {
+       DrawSelection(0);
+       selrx = sex;  selry = sey;  selrw = sew;  selrh = seh;
+@@ -1395,14 +1397,14 @@
+       Timer(100);
+     }
+   }
+-  
++
+   EnableSelection(0);
+ 
+   selFilled   = 0;
+   selTracking = 0;
+ 
+   /* only 'enable' the selection if it intersects CPIC */
+-  if (selrx < cXOFF+cWIDE && selrx+selrw > cXOFF && 
++  if (selrx < cXOFF+cWIDE && selrx+selrw > cXOFF &&
+       selry < cYOFF+cHIGH && selry+selrh > cYOFF) EnableSelection(1);
+ 
+   return 1;
+@@ -1422,7 +1424,7 @@
+    *
+    * if 'dragndrop', changes cursor, monitors CTRL status
+    */
+-  
++
+   int          mpx, mpy, offx, offy;
+   int          newsx, newsy, orgsx, orgsy, cnstrain, docopy, lastdocopy;
+   Window       rW, cW;
+@@ -1436,9 +1438,9 @@
+ 
+   CoordE2P(ev->x, ev->y, &mpx, &mpy);
+   offx = mpx - selrx;  offy = mpy - selry;
+-  
++
+   /* track rectangle until we get a release */
+-  
++
+   DrawSelection(0);
+   selFilled   = 1;
+   selTracking = 1;
+@@ -1467,7 +1469,7 @@
+       dx = newsx - orgsx;  dy = newsy - orgsy;
+       if      (abs(dx) > abs(dy)) dy = 0;
+       else if (abs(dy) > abs(dx)) dx = 0;
+-      
++
+       newsx = orgsx + dx;  newsy = orgsy + dy;
+     }
+ 
+@@ -1485,7 +1487,7 @@
+       Timer(100);
+     }
+   }
+-  
++
+   EnableSelection(0);
+ 
+   selFilled   = 0;
+@@ -1495,7 +1497,7 @@
+ 
+   /* only do <whatever> if the selection intersects CPIC */
+ 
+- if (selrx < cXOFF+cWIDE && selrx+selrw > cXOFF && 
++ if (selrx < cXOFF+cWIDE && selrx+selrw > cXOFF &&
+       selry < cYOFF+cHIGH && selry+selrh > cYOFF) {
+ 
+     EnableSelection(1);
+@@ -1503,10 +1505,10 @@
+     if (dragndrop) {
+       int   tmpsx, tmpsy;
+       byte *data;
+-      
++
+       tmpsx = selrx;  tmpsy = selry;
+       selrx = orgsx;  selry = orgsy;
+-      
++
+       data = getSelection();         /* copy old data */
+       if (data) {
+ 	if (!docopy) clearSelectedArea();
+@@ -1531,29 +1533,29 @@
+   int          rx,ry,ox,oy,x,y,active, x1, y1, x2, y2, cnstrain;
+   int          i, px,py,px2,py2,pw,ph;
+   unsigned int mask;
+-  
++
+   /* called on a B1 press in mainW to draw a new rectangular selection.
+    * any former selection has already been removed.  holding shift down
+-   * while tracking constrains selection to a square 
++   * while tracking constrains selection to a square
+    */
+-  
++
+   active = 0;
+-  
++
+   x1 = ox = ev->x;  y1 = oy = ev->y;               /* nail down one corner */
+   selrx = selry = selrw = selrh = 0;
+   selTracking = 1;
+-  
++
+   while (1) {
+     if (!XQueryPointer(theDisp,mainW,&rW,&cW,&rx,&ry,&x,&y,&mask)) continue;
+     if (!(mask & Button1Mask)) break;      /* button released */
+     cnstrain = (mask & ShiftMask);
+-    
++
+     if (x!=ox || y!=oy) {                  /* moved.  erase and redraw (?) */
+       x2 = x;  y2 = y;
+-      
++
+       /* x1,y1,x2,y2 are in epic coords.  sort, convert to pic coords,
+ 	 and if changed, erase+redraw */
+-      
++
+       CoordE2P(x1, y1, &px,  &py);
+       CoordE2P(x2, y2, &px2, &py2);
+       if (px>px2) { i=px; px=px2; px2=i; }
+@@ -1561,17 +1563,17 @@
+       pw = px2-px+1;  ph=py2-py+1;
+ 
+       /* keep px,py,pw,ph inside 'pic' */
+-      
++
+       if (px<0) { pw+=px;  px=0; }
+       if (py<0) { ph+=py;  py=0; }
+       if (px>pWIDE-1) px = pWIDE-1;
+       if (py>pHIGH-1) py = pHIGH-1;
+-      
++
+       if (pw<0) pw=0;
+       if (ph<0) ph=0;
+       if (px+pw>pWIDE) pw = pWIDE - px;
+       if (py+ph>pHIGH) ph = pHIGH - py;
+-      
++
+       if (cnstrain) {          /* make a square at smaller of w,h */
+ 	if      (ph>pw) { if (y2<y1) py += (ph-pw);  ph=pw; }
+ 	else if (pw>ph) { if (x2<x1) px += (pw-ph);  pw=ph; }
+@@ -1579,12 +1581,12 @@
+ 
+       /* put x,y,w,h -> selr{x,y,w,h}
+ 	 if the rectangle has changed, erase old and draw new */
+-      
++
+       if (px!=selrx || py!=selry || pw!=selrw || ph!=selrh) {
+ 	DrawSelection(0);
+ 	selrx = px;  selry = py;  selrw = pw;  selrh = ph;
+ 	DrawSelection(1);
+-	
++
+ 	haveSel = active = (pw>0 && ph>0);
+ 	if (infoUp) SetSelectionString();
+ 	XFlush(theDisp);
+@@ -1615,7 +1617,7 @@
+      set, pick a new 'color' to invert the selection with */
+ 
+   int   x,y,x1,y1,w,h;
+-  
++
+   if (newcol) selColor = (selColor+1) & 0x7;
+ 
+   /* convert selr{x,y,w,h} into epic coords */
+@@ -1650,7 +1652,7 @@
+   if (y<0 && y+h>eHIGH && selFilled!=1)
+     XDrawLine(theDisp, mainW, theGC, x, eHIGH/2, x+w, eHIGH/2);
+ 
+-  
++
+   if (selFilled==0 || selFilled == 1) {
+     /* one little kludge:  if w or h == eWIDE or eHIGH, make it one smaller */
+     if (x+w == eWIDE) w--;
+@@ -1664,17 +1666,17 @@
+       else if (w>=20 && h>=20) { hs=5;  h1=4; h2=2; }
+       else if (w>= 9 && h>= 9) { hs=3;  h1=2; h2=1; }
+       else hs=h1=h2=0;
+-      
++
+       if (hs) {
+ 	XFillRectangle(theDisp,mainW,theGC,x+1,     y+1,  (u_int)h1,(u_int)h1);
+ 	XFillRectangle(theDisp,mainW,theGC,x+w/2-h2,y+1,  (u_int)hs,(u_int)h1);
+ 	XFillRectangle(theDisp,mainW,theGC,x+w-h1,  y+1,  (u_int)h1,(u_int)h1);
+-	
++
+ 	XFillRectangle(theDisp,mainW,theGC,x+1,   y+h/2-h2,
+ 		       (u_int)h1, (u_int)hs);
+ 	XFillRectangle(theDisp,mainW,theGC,x+w-h1,y+h/2-h2,
+ 		       (u_int)h1, (u_int)hs);
+-	
++
+ 	XFillRectangle(theDisp,mainW,theGC,x+1,     y+h-h1,
+ 		       (u_int)h1,(u_int)h1);
+ 	XFillRectangle(theDisp,mainW,theGC,x+w/2-h2,y+h-h1,
+@@ -1683,7 +1685,7 @@
+ 		       (u_int)h1,(u_int)h1);
+       }
+     }
+-	
++
+     if (selFilled==1) {
+       XDrawLine(theDisp, mainW, theGC, x+1, y+1,   x+w-1, y+h-1);
+       XDrawLine(theDisp, mainW, theGC, x+1, y+h-1, x+w-1, y+1);
+@@ -1692,8 +1694,8 @@
+   else if (selFilled==2) {
+     XFillRectangle(theDisp, mainW, theGC, x,y,(u_int) w, (u_int) h);
+   }
+-  
+-  
++
++
+   XSetFunction(theDisp,theGC,GXcopy);
+   XSetPlaneMask(theDisp, theGC, AllPlanes);
+ }
+@@ -1703,7 +1705,7 @@
+ void MoveGrowSelection(dx,dy,dw,dh)
+      int dx,dy,dw,dh;
+ {
+-  /* moves and/or grows the selection by the specified amount 
++  /* moves and/or grows the selection by the specified amount
+      (in pic coords).  keeps the selection entirely within 'pic'.
+      (called by 'CropKey()') */
+ 
+@@ -1729,7 +1731,7 @@
+   }
+ }
+ 
+-  
++
+ /***********************************/
+ void BlinkSelection(cnt)
+      int cnt;
+diff -ru xv-3.10a/xvdflt.c xv-3.10a-enhancements/xvdflt.c
+--- xv-3.10a/xvdflt.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvdflt.c	2007-05-12 14:07:36.000000000 -0700
+@@ -16,12 +16,12 @@
+ #include "bits/xv_rev"
+ #include "bits/xv_ver"
+ #include "bits/xf_left"
+-#include "bits/xf_right"
++/* #include "bits/xf_right"	not used */
+ #include "bits/font5x9.h"
+ 
+ 
+ #ifndef USEOLDPIC
+-#  include "xvdflt.h"  
++#  include "xvdflt.h"
+ #endif
+ 
+ 
+@@ -62,7 +62,7 @@
+   for (i=0; i<XVDFLT_HIGH; i++) {
+     nbytes = 0;
+     while (nbytes < XVDFLT_WIDE) {
+-      char *sp;
++      const char *sp;
+       byte *dp;
+ 
+       j = XVDFLT_WIDE - nbytes;
+@@ -100,21 +100,21 @@
+   setcolor(pinfo, 252,   0,  0,  0);   /* black background for text */
+ 
+ 
+-  xbm2pic((byte *) xv_cpyrt_bits, xv_cpyrt_width, xv_cpyrt_height, 
++  xbm2pic((byte *) xv_cpyrt_bits, xv_cpyrt_width, xv_cpyrt_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2+1, 203+1, 252);
+-  xbm2pic((byte *) xv_cpyrt_bits, xv_cpyrt_width, xv_cpyrt_height, 
++  xbm2pic((byte *) xv_cpyrt_bits, xv_cpyrt_width, xv_cpyrt_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2,   203, 250);
+ 
+   i = xv_ver_width + xv_rev_width + 30;
+ 
+-  xbm2pic((byte *) xv_ver_bits, xv_ver_width, xv_ver_height, 
++  xbm2pic((byte *) xv_ver_bits, xv_ver_width, xv_ver_height,
+        dfltpic, DWIDE, DHIGH, DWIDE/2 - (i/2) + xv_ver_width/2+1, 220+1,252);
+-  xbm2pic((byte *) xv_rev_bits, xv_rev_width, xv_rev_height, 
++  xbm2pic((byte *) xv_rev_bits, xv_rev_width, xv_rev_height,
+        dfltpic, DWIDE, DHIGH, DWIDE/2 + (i/2) - xv_rev_width/2+1, 220+1,252);
+ 
+-  xbm2pic((byte *) xv_ver_bits, xv_ver_width, xv_ver_height, 
++  xbm2pic((byte *) xv_ver_bits, xv_ver_width, xv_ver_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2 - (i/2) + xv_ver_width/2, 220, 250);
+-  xbm2pic((byte *) xv_rev_bits, xv_rev_width, xv_rev_height, 
++  xbm2pic((byte *) xv_rev_bits, xv_rev_width, xv_rev_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2 + (i/2) - xv_rev_width/2, 220, 250);
+ 
+   strcpy(str,"Press <right> mouse button for menu.");
+@@ -136,7 +136,11 @@
+   pinfo->w       = XVDFLT_WIDE;
+   pinfo->h       = XVDFLT_HIGH;
+   pinfo->type    = PIC8;
++#ifdef HAVE_PNG
++  pinfo->frmType = F_PNG;
++#else
+   pinfo->frmType = F_GIF;
++#endif
+   pinfo->colType = F_FULLCOLOR;
+ 
+   pinfo->normw   = pinfo->w;
+@@ -169,7 +173,7 @@
+     for (i=k=0; i<DHIGH; i+=xf_left_height) {
+       for (j=0; j<DWIDE; j+=xf_left_width) {
+ 	k++;
+-	if (k&1) 
++	if (k&1)
+ 	  xbm2pic((byte *) xf_left_bits, xf_left_width, xf_left_height,
+ 		  dfltpic, DWIDE, DHIGH, j + xf_left_width/2,
+ 		  i + xf_left_height/2, 1);
+@@ -179,29 +183,29 @@
+ 
+ 
+ 
+-  xbm2pic((byte *) xvpic_logo_out_bits, xvpic_logo_out_width, 
++  xbm2pic((byte *) xvpic_logo_out_bits, xvpic_logo_out_width,
+ 	  xvpic_logo_out_height, dfltpic, DWIDE, DHIGH, DWIDE/2 + 10, 80, 103);
+ 
+-  xbm2pic((byte *) xvpic_logo_top_bits, xvpic_logo_top_width, 
++  xbm2pic((byte *) xvpic_logo_top_bits, xvpic_logo_top_width,
+ 	  xvpic_logo_top_height, dfltpic, DWIDE, DHIGH, DWIDE/2 + 10, 80, 100);
+ 
+-  xbm2pic((byte *) xvpic_logo_bot_bits, xvpic_logo_bot_width, 
++  xbm2pic((byte *) xvpic_logo_bot_bits, xvpic_logo_bot_width,
+ 	  xvpic_logo_bot_height, dfltpic, DWIDE, DHIGH, DWIDE/2 + 10, 80, 101);
+ 
+ 
+ 
+-  xbm2pic((byte *) xv_jhb_bits, xv_jhb_width, xv_jhb_height, 
++  xbm2pic((byte *) xv_jhb_bits, xv_jhb_width, xv_jhb_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2, 160, 102);
+ 
+-  xbm2pic((byte *) xv_cpyrt_bits, xv_cpyrt_width, xv_cpyrt_height, 
++  xbm2pic((byte *) xv_cpyrt_bits, xv_cpyrt_width, xv_cpyrt_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2, 203, 102);
+ 
+   i = xv_ver_width + xv_rev_width + 30;
+ 
+-  xbm2pic((byte *) xv_ver_bits, xv_ver_width, xv_ver_height, 
++  xbm2pic((byte *) xv_ver_bits, xv_ver_width, xv_ver_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2 - (i/2) + xv_ver_width/2, 220, 102);
+ 
+-  xbm2pic((byte *) xv_rev_bits, xv_rev_width, xv_rev_height, 
++  xbm2pic((byte *) xv_rev_bits, xv_rev_width, xv_rev_height,
+ 	   dfltpic, DWIDE, DHIGH, DWIDE/2 + (i/2) - xv_rev_width/2, 220, 102);
+ 
+   strcpy(str,"Press <right> mouse button for menu.");
+@@ -240,7 +244,11 @@
+   pinfo->w       = DWIDE;
+   pinfo->h       = DHIGH;
+   pinfo->type    = PIC8;
++#ifdef HAVE_PNG
++  pinfo->frmType = F_PNG;
++#else
+   pinfo->frmType = F_GIF;
++#endif
+   pinfo->colType = F_FULLCOLOR;
+ 
+   sprintf(pinfo->fullInfo, "<8-bit internal>");
+@@ -272,7 +280,7 @@
+       x = cx - bwide/2;
+ 
+       k = *bptr;
+-      for (j=0,bit=0; j<bwide; j++, bit = (++bit)&7, x++) {
++      for (j=0,bit=0; j<bwide; j++, bit = (bit+1)&7, x++) {
+ 	if (!bit) k = *bptr++;
+ 	if ( (k&1) && (x>=0) && (x<pwide))
+ 	  pptr[x] = col;
+@@ -281,7 +289,7 @@
+       }
+     }
+   }
+-}  
++}
+ 
+ 
+ /*******************************************/
+@@ -300,7 +308,7 @@
+      byte    *dfltpic;
+      PICINFO *pinfo;
+ {
+-  int i,j,k, dr, dg, db;
++  int i,j, dr, dg, db;
+   byte *pp;
+ 
+   pp = dfltpic;
+@@ -357,7 +365,7 @@
+ 
+   for ( ; *str; str++, cx+=6) {
+     i = (byte) *str;
+-    if (i >= 32 && i < 128) 
++    if (i >= 32 && i < 128)
+       xbm2pic(font5x9[i - 32], 5, 9, pic, pw, ph, cx, cy, col);
+   }
+ }
+diff -ru xv-3.10a/xvdflt.h xv-3.10a-enhancements/xvdflt.h
+--- xv-3.10a/xvdflt.h	1994-12-22 14:34:56.000000000 -0800
++++ xv-3.10a-enhancements/xvdflt.h	2007-04-15 20:45:08.000000000 -0700
+@@ -2,7 +2,7 @@
+ #define XVDFLT_HIGH    270
+ #define XVDFLT_NPARTS    5
+ #define XVDFLT_PARTLEN 100
+-char *xvdflt_pic[1350] = {
++const char *xvdflt_pic[1350] = {
+ /*   0a */ "00000000000000000000000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101000000000000000000000000000002020202020202020303030303030303030404040404040505050505060708",
+ /*   0b */ "0809090a0b0c0d0e0e0f101111121213131313141414141515151515151515151616161616161616161616161616161616161616161616161616161616171717171717171717171717171717161616161616161616161616161616161616161616161617",
+ /*   0c */ "171717181818181818181818181818181818181919181818181818191919191919191a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1b1b1b1b1b1b1b1b1b1c1c1c1c1c1c1c1c1d1d1d1d1d1d1d1d1d1c1c1c1c1c1c1c1c1c1c1c1c1c1c1b1b1b1b1b1b1b1b1b1a1a",
+@@ -1356,9 +1356,9 @@
+ };
+ 
+ 
+-byte xvdflt_r[256] = { 83,83,84,84,84,85,92,94,100,109,119,124,133,137,145,157,163,168,175,183,191,202,203,255,254,253,252,251,250,249,145,114,83,106,129,249,250,251,250,243,216,226,241,222,222,132,61,82,244,249,243,248,173,59,247,102,252,241,244,244,57,241,216,239,6,17,157,244,139,236,250,246,84,213,121,240,70,30,99,91,38,73,105,123,82,40,30,38,114,81,44,35,37,35,30,33,1,0,5,1,1,4,3,0,0,11,0,0,6,15,7,3,8,0,0,4,8,11,15,0,10,11,14,11,0,14,0,28,6,1,22,17,8,1,8,7,7,13,0,9,10,6,7,10,11,11,18,7,2,8,7,9,5,10,8,16,6,6,5,8,8,6,10,8,4,30,22,5,33,33,11,6,10,15,19,13,28,21,35,28,10,25,26,27,29,3,27,14,21,30,31,27,31,35,6,33,37,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,};
++const byte xvdflt_r[256] = { 83,83,84,84,84,85,92,94,100,109,119,124,133,137,145,157,163,168,175,183,191,202,203,255,254,253,252,251,250,249,145,114,83,106,129,249,250,251,250,243,216,226,241,222,222,132,61,82,244,249,243,248,173,59,247,102,252,241,244,244,57,241,216,239,6,17,157,244,139,236,250,246,84,213,121,240,70,30,99,91,38,73,105,123,82,40,30,38,114,81,44,35,37,35,30,33,1,0,5,1,1,4,3,0,0,11,0,0,6,15,7,3,8,0,0,4,8,11,15,0,10,11,14,11,0,14,0,28,6,1,22,17,8,1,8,7,7,13,0,9,10,6,7,10,11,11,18,7,2,8,7,9,5,10,8,16,6,6,5,8,8,6,10,8,4,30,22,5,33,33,11,6,10,15,19,13,28,21,35,28,10,25,26,27,29,3,27,14,21,30,31,27,31,35,6,33,37,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,};
+ 
+-byte xvdflt_g[256] = { 83,83,84,84,84,85,92,94,100,109,119,124,133,137,145,157,162,168,174,184,191,196,205,255,254,253,252,251,250,249,146,114,83,106,130,211,185,176,173,230,211,157,161,170,144,31,52,82,168,168,162,248,116,42,247,68,171,164,245,244,35,159,133,161,18,26,151,163,138,65,67,51,68,49,111,159,88,30,100,87,38,74,92,124,82,38,22,38,114,81,22,35,37,35,30,33,1,0,4,0,1,4,2,0,0,11,0,0,6,15,7,3,8,0,0,4,9,10,14,0,10,10,13,11,0,7,0,18,6,0,22,18,8,1,8,7,7,13,0,9,9,6,7,10,11,11,18,7,2,9,7,9,5,10,8,16,6,6,5,8,8,7,9,8,4,30,22,5,33,32,11,6,10,15,19,13,28,21,35,25,9,22,26,27,29,3,27,14,21,30,31,11,31,35,6,18,31,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,};
++const byte xvdflt_g[256] = { 83,83,84,84,84,85,92,94,100,109,119,124,133,137,145,157,162,168,174,184,191,196,205,255,254,253,252,251,250,249,146,114,83,106,130,211,185,176,173,230,211,157,161,170,144,31,52,82,168,168,162,248,116,42,247,68,171,164,245,244,35,159,133,161,18,26,151,163,138,65,67,51,68,49,111,159,88,30,100,87,38,74,92,124,82,38,22,38,114,81,22,35,37,35,30,33,1,0,4,0,1,4,2,0,0,11,0,0,6,15,7,3,8,0,0,4,9,10,14,0,10,10,13,11,0,7,0,18,6,0,22,18,8,1,8,7,7,13,0,9,9,6,7,10,11,11,18,7,2,9,7,9,5,10,8,16,6,6,5,8,8,7,9,8,4,30,22,5,33,32,11,6,10,15,19,13,28,21,35,25,9,22,26,27,29,3,27,14,21,30,31,11,31,35,6,18,31,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,};
+ 
+-byte xvdflt_b[256] = { 251,250,252,253,254,255,254,255,254,253,254,254,252,255,255,253,251,253,253,253,254,249,252,255,254,253,252,251,250,249,252,255,249,253,250,162,99,79,81,225,239,113,92,147,72,43,37,248,84,88,91,248,83,34,247,80,84,86,245,244,30,90,74,92,10,55,239,85,250,90,88,72,125,68,206,92,190,87,245,230,133,216,199,248,247,105,73,108,252,244,62,97,119,143,150,134,57,49,64,64,72,78,72,40,75,98,66,59,110,110,80,89,95,86,34,87,80,88,77,48,100,80,98,89,33,60,29,75,91,73,111,87,120,89,103,103,126,111,23,121,108,147,111,142,105,111,111,140,107,107,118,113,112,110,114,123,140,120,141,132,124,130,98,127,151,102,124,132,108,119,123,159,124,135,123,124,114,135,126,100,122,126,132,140,126,164,119,149,149,137,113,75,127,114,131,78,107,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,};
++const byte xvdflt_b[256] = { 251,250,252,253,254,255,254,255,254,253,254,254,252,255,255,253,251,253,253,253,254,249,252,255,254,253,252,251,250,249,252,255,249,253,250,162,99,79,81,225,239,113,92,147,72,43,37,248,84,88,91,248,83,34,247,80,84,86,245,244,30,90,74,92,10,55,239,85,250,90,88,72,125,68,206,92,190,87,245,230,133,216,199,248,247,105,73,108,252,244,62,97,119,143,150,134,57,49,64,64,72,78,72,40,75,98,66,59,110,110,80,89,95,86,34,87,80,88,77,48,100,80,98,89,33,60,29,75,91,73,111,87,120,89,103,103,126,111,23,121,108,147,111,142,105,111,111,140,107,107,118,113,112,110,114,123,140,120,141,132,124,130,98,127,151,102,124,132,108,119,123,159,124,135,123,124,114,135,126,100,122,126,132,140,126,164,119,149,149,137,113,75,127,114,131,78,107,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,};
+ 
+diff -ru xv-3.10a/xvdial.c xv-3.10a-enhancements/xvdial.c
+--- xv-3.10a/xvdial.c	1995-01-03 13:20:31.000000000 -0800
++++ xv-3.10a-enhancements/xvdial.c	2007-04-15 17:55:50.000000000 -0700
+@@ -1,11 +1,11 @@
+-/* 
++/*
+  * xvdial.c - DIAL handling functions
+  *
+  * callable functions:
+  *
+  *   DCreate()   -  creates a dial
+  *   DSetRange() -  sets min/max/current values of control
+- *   DSetVal()   -  sets value of control 
++ *   DSetVal()   -  sets value of control
+  *   DSetActive() - turns dial '.active' on and off
+  *   DRedraw()   -  redraws the dial
+  *   DTrack()    -  called when clicked.  Operates control 'til mouseup
+@@ -41,51 +41,53 @@
+ 
+ 
+ /* local functions */
+-static int  whereInDial     PARM((DIAL *, int, int));
+-static void drawArrow       PARM((DIAL *));
+-static void drawValStr      PARM((DIAL *));
+-static void drawButt        PARM((DIAL *, int, int));
+-static int  computeDialVal  PARM((DIAL *, int, int));
+-static void dimDial         PARM((DIAL *));
++static int    whereInDial     PARM((DIAL *, int, int));
++static void   drawArrow       PARM((DIAL *));
++static void   drawValStr      PARM((DIAL *));
++static void   drawButt        PARM((DIAL *, int, int));
++static double computeDialVal  PARM((DIAL *, int, int));
++static void   dimDial         PARM((DIAL *));
+ 
+ 
+ /***************************************************/
+-void DCreate(dp, parent, x, y, w, h, minv, maxv, curv, page, 
++void DCreate(dp, parent, x, y, w, h, minv, maxv, curv, inc, page,
+ 	          fg, bg, hi, lo, title, units)
+-DIAL         *dp;
+-Window        parent;
+-int           x,y,w,h,minv,maxv,curv,page;
+-unsigned long fg,bg,hi,lo;
+-char         *title, *units;
++DIAL          *dp;
++Window         parent;
++int            x, y, w, h;
++double         minv, maxv, curv, inc, page;
++unsigned long  fg, bg, hi, lo;
++const char    *title, *units;
+ {
+ 
+   if (!pixmaps_built) {
+-    cw1Pix   = XCreatePixmapFromBitmapData(theDisp, parent, 
++    cw1Pix   = XCreatePixmapFromBitmapData(theDisp, parent,
+ 		(char *) dial_cw1_bits, PW, PH, fg, bg, dispDEEP);
+-    ccw1Pix  = XCreatePixmapFromBitmapData(theDisp, parent, 
++    ccw1Pix  = XCreatePixmapFromBitmapData(theDisp, parent,
+ 	        (char *) dial_ccw1_bits, PW, PH, fg, bg, dispDEEP);
+-    cw2Pix   = XCreatePixmapFromBitmapData(theDisp, parent, 
++    cw2Pix   = XCreatePixmapFromBitmapData(theDisp, parent,
+                 (char *) dial_cw2_bits, PW, PH, fg, bg, dispDEEP);
+-    ccw2Pix  = XCreatePixmapFromBitmapData(theDisp, parent, 
++    ccw2Pix  = XCreatePixmapFromBitmapData(theDisp, parent,
+ 	        (char *) dial_ccw2_bits, PW, PH, fg, bg, dispDEEP);
+   }
+ 
+-  dp->x     = x;
+-  dp->y     = y;
+-
+-  dp->w     = w;
+-  dp->h     = h;
+-  dp->fg    = fg;
+-  dp->bg    = bg;
+-  dp->hi    = hi;
+-  dp->lo    = lo;
+-  dp->title = title;
+-  dp->units = units;
+-  dp->active = 1;
++  dp->x       = x;
++  dp->y       = y;
++  dp->w       = w;
++  dp->h       = h;
++  dp->fg      = fg;
++  dp->bg      = bg;
++  dp->hi      = hi;
++  dp->lo      = lo;
++  dp->title   = title;
++  dp->units   = units;
++  dp->active  = 1;
+   dp->drawobj = NULL;
+ 
+-  if (w < h-24-16) dp->rad = (w - 8) / 2;
+-           else dp->rad = (h - 24 - 16 - 8) / 2;
++  if (w < h-24-16)
++    dp->rad = (w - 8) / 2;
++  else
++    dp->rad = (h - 24 - 16 - 8) / 2;
+   dp->cx = w / 2;
+   dp->cy = dp->rad + 4 + 16;
+ 
+@@ -94,22 +96,22 @@
+   dp->bx[INCW1]  = w-14-4;  dp->by[INCW1]  = h - 4 - 20;
+   dp->bx[INCW2]  = w-14-4;  dp->by[INCW2]  = h - 4 - 10;
+ 
+-  dp->win = XCreateSimpleWindow(theDisp, parent,x,y,(u_int) w,(u_int) h,
+-				1,fg,bg);
++  dp->win = XCreateSimpleWindow(theDisp, parent, x, y, (u_int) w, (u_int) h,
++				1, fg, bg);
+   if (!dp->win) FatalError("can't create dial window");
+ 
+-  DSetRange(dp, minv, maxv, curv, page);
++  DSetRange(dp, minv, maxv, curv, inc, page);
+   XSelectInput(theDisp, dp->win, ExposureMask | ButtonPressMask);
+ }
+ 
+ 
+ /***************************************************/
+-void DSetRange(dp, minv, maxv, curv, page)
+-DIAL *dp;
+-int   minv, maxv, curv, page;
++void DSetRange(dp, minv, maxv, curv, inc, page)
++DIAL   *dp;
++double  minv, maxv, curv, inc, page;
+ {
+   if (maxv<minv) maxv=minv;
+-  dp->min = minv;    dp->max = maxv;    dp->page = page;
++  dp->min = minv; dp->max = maxv; dp->inc = inc; dp->page = page;
+   dp->active =  (minv < maxv);
+ 
+   DSetVal(dp, curv);
+@@ -118,22 +120,22 @@
+ 
+ /***************************************************/
+ void DSetVal(dp, curv)
+-DIAL *dp;
+-int   curv;
++DIAL  *dp;
++double curv;
+ {
+   RANGE(curv, dp->min, dp->max);   /* make sure curv is in-range */
+ 
+   if (curv == dp->val) return;
+ 
+   /* erase old arrow */
+-  XSetForeground(theDisp, theGC, dp->bg); 
++  XSetForeground(theDisp, theGC, dp->bg);
+   drawArrow(dp);
+ 
+-  dp->val = curv;
++  dp->val = (double)((int)(curv / dp->inc + (curv > 0 ? 0.5 : -0.5))) * dp->inc;
+ 
+   /* draw new arrow and string */
+   XSetForeground(theDisp, theGC, dp->fg);
+-  XSetBackground(theDisp, theGC, dp->bg); 
++  XSetBackground(theDisp, theGC, dp->bg);
+   drawArrow(dp);
+   drawValStr(dp);
+   if (!dp->active) dimDial(dp);
+@@ -202,7 +204,8 @@
+ int mx,my;
+ {
+   Window       rW,cW;
+-  int          rx,ry, x,y, ipos, pos, lit, i, origval;
++  int          rx, ry, x, y, ipos, pos, lit;
++  double       origval;
+   unsigned int mask;
+ 
+   lit = 0;
+@@ -224,35 +227,36 @@
+   if (ipos != INDIAL) {
+     drawButt(dp, ipos, 1);
+     switch (ipos) {
+-    case INCW1:  if (dp->val < dp->max) DSetVal(dp, dp->val+1); break;
++    case INCW1:  if (dp->val < dp->max) DSetVal(dp, dp->val+dp->inc);  break;
+     case INCW2:  if (dp->val < dp->max) DSetVal(dp, dp->val+dp->page); break;
+-    case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-1); break;
++    case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->inc);  break;
+     case INCCW2: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->page); break;
+     }
+-    if (dp->drawobj != NULL) (dp->drawobj)();  
++    if (dp->drawobj != NULL) (dp->drawobj)();
+     Timer(INC1WAIT);
+     lit = 1;
+   }
+ 
+-  else { 
+-    i = computeDialVal(dp, mx, my);
+-    DSetVal(dp, i);
+-    if (dp->drawobj != NULL) (dp->drawobj)();  
++  else {
++    double v;
++    v = computeDialVal(dp, mx, my);
++    DSetVal(dp, v);
++    if (dp->drawobj != NULL) (dp->drawobj)();
+   }
+ 
+-  
++
+   /* loop until mouse is released */
+   while (XQueryPointer(theDisp,dp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
+     if (!(mask & Button1Mask)) break;    /* button released */
+ 
+     if (ipos == INDIAL) {
+-      int j;
+-      i = computeDialVal(dp, x, y);
+-      j = dp->val;
+-      DSetVal(dp, i);
+-      if (j != dp->val) {
++      double v, w;
++      v = computeDialVal(dp, x, y);
++      w = dp->val;
++      DSetVal(dp, v);
++      if (w != dp->val) {
+ 	/* track whatever dial controls */
+-	if (dp->drawobj != NULL) (dp->drawobj)();  
++	if (dp->drawobj != NULL) (dp->drawobj)();
+       }
+     }
+ 
+@@ -266,18 +270,18 @@
+ 
+       if (lit) {
+ 	switch (ipos) {
+-	case INCW1:  if (dp->val < dp->max) DSetVal(dp, dp->val+1); 
++	case INCW1:  if (dp->val < dp->max) DSetVal(dp, dp->val+dp->inc);
+ 	             break;
+ 	case INCW2:  if (dp->val < dp->max) DSetVal(dp, dp->val+dp->page);
+                      break;
+-	case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-1);
++	case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->inc);
+                      break;
+ 	case INCCW2: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->page);
+                      break;
+ 	}
+ 
+ 	/* track whatever dial controls */
+-	if (dp->drawobj != NULL) (dp->drawobj)();  
++	if (dp->drawobj != NULL) (dp->drawobj)();
+ 
+ 	Timer(INC2WAIT);
+       }
+@@ -305,34 +309,35 @@
+ 
+   /* returns region * that x,y is in.  returns -1 if none */
+ 
+-  for (i=0; i<4; i++) 
++  for (i=0; i<4; i++)
+     if (PTINRECT(x,y, dp->bx[i], dp->by[i], 14, 10)) return i;
+ 
+-  if (PTINRECT(x,y, dp->cx - dp->rad, dp->cy - dp->rad, 
++  if (PTINRECT(x,y, dp->cx - dp->rad, dp->cy - dp->rad,
+ 	       2*dp->rad, 2*dp->rad))
+     return INDIAL;
+ 
+   return -1;
+ }
+ 
+-	  
++
+ /***************************************************/
+ static void drawArrow(dp)
+ DIAL *dp;
+ {
+-  int i, rad, cx, cy;
++  int rad, cx, cy;
++  double v;
+   XPoint arrow[4];
+ 
+   rad = dp->rad;  cx = dp->cx;  cy = dp->cy;
+ 
+   /* map pos (range minv..maxv) into degrees (range 240..-60) */
+-  i = 240 + (-300 * (dp->val - dp->min)) / (dp->max - dp->min);
+-  arrow[0].x = cx + (int) ((double) rad * .80 * cos(i * DEG2RAD));
+-  arrow[0].y = cy - (int) ((double) rad * .80 * sin(i * DEG2RAD));
+-  arrow[1].x = cx + (int) ((double) rad * .33 * cos((i+160) * DEG2RAD));
+-  arrow[1].y = cy - (int) ((double) rad * .33 * sin((i+160) * DEG2RAD));
+-  arrow[2].x = cx + (int) ((double) rad * .33 * cos((i-160) * DEG2RAD));
+-  arrow[2].y = cy - (int) ((double) rad * .33 * sin((i-160) * DEG2RAD));
++  v = 240 + (-300 * (dp->val - dp->min)) / (dp->max - dp->min);
++  arrow[0].x = cx + (int) ((double) rad * .80 * cos(v * DEG2RAD));
++  arrow[0].y = cy - (int) ((double) rad * .80 * sin(v * DEG2RAD));
++  arrow[1].x = cx + (int) ((double) rad * .33 * cos((v+160) * DEG2RAD));
++  arrow[1].y = cy - (int) ((double) rad * .33 * sin((v+160) * DEG2RAD));
++  arrow[2].x = cx + (int) ((double) rad * .33 * cos((v-160) * DEG2RAD));
++  arrow[2].y = cy - (int) ((double) rad * .33 * sin((v-160) * DEG2RAD));
+   arrow[3].x = arrow[0].x;
+   arrow[3].y = arrow[0].y;
+   XDrawLines(theDisp, dp->win, theGC, arrow, 4, CoordModeOrigin);
+@@ -343,33 +348,47 @@
+ static void drawValStr(dp)
+ DIAL *dp;
+ {
+-  int  i, x1, x2;
++  int  tot, i, x1, x2;
+   char foo[60], foo1[60];
+ 
+   /* compute longest string necessary so we can right-align this thing */
+-  sprintf(foo,"%d",dp->min);    x1 = strlen(foo);
+-  sprintf(foo,"%d",dp->max);    x2 = strlen(foo);
++  sprintf(foo,"%d",(int)dp->min);    x1 = strlen(foo);
++  sprintf(foo,"%d",(int)dp->max);    x2 = strlen(foo);
+   if (dp->min < 0 && dp->max > 0) x2++;   /* put '+' at beginning */
+   i = x1;  if (x2>x1) i = x2;
+   if (dp->units) i += strlen(dp->units);
+ 
+-  if (dp->min < 0 && dp->max > 0) sprintf(foo,"%+d", dp->val);
+-  else sprintf(foo,"%d", dp->val);
++  sprintf(foo,"%g",dp->inc);   /* space for decimal values */
++  tot = i + strlen(foo) - 1;   /* Take away the 0 from the beginning */
++
++  if (dp->min < 0.0 && dp->max > 0.0) sprintf(foo,"%+g", dp->val);
++  else sprintf(foo,"%g", dp->val);
++
++  if (dp->inc < 1.0)
++  {
++    int j;
++
++    if (dp->val == (double)((int)dp->val))
++      strcat(foo,".");
++
++    for (j = strlen(foo); j < tot; j++)
++      strcat(foo,"0");
++  }
+ 
+   if (dp->units) strcat(foo,dp->units);
+   foo1[0] = '\0';
+   if (strlen(foo) < (size_t) i) {
+-    for (i = i - strlen(foo); i>0; i--) strcat(foo1," ");
++    for (i-=strlen(foo);i>0;i--) strcat(foo1," ");
+   }
+   strcat(foo1, foo);
+ 
+   XSetForeground(theDisp, theGC, dp->fg);
+   XSetBackground(theDisp, theGC, dp->bg);
+   XSetFont(theDisp, theGC, monofont);
+-  XDrawImageString(theDisp, dp->win, theGC, 
++  XDrawImageString(theDisp, dp->win, theGC,
+ 		   dp->w/2 - XTextWidth(monofinfo, foo1, (int) strlen(foo1))/2,
+ 		   dp->h-14 - (monofinfo->ascent + monofinfo->descent)/2
+-		                                 + monofinfo->ascent, 
++		                                 + monofinfo->ascent,
+ 		   foo1, (int) strlen(foo1));
+   XSetFont(theDisp, theGC, mfont);
+ }
+@@ -411,12 +430,13 @@
+ 
+ 
+ /***************************************************/
+-static int computeDialVal(dp, x, y)
++static double computeDialVal(dp, x, y)
+ DIAL *dp;
+ int x, y;
+ {
+-  int dx, dy, val;
+-  double angle;
++  int dx, dy;
++
++  double angle, val;
+ 
+   /* compute dx, dy (distance from cx, cy).  Note: +dy is *up* */
+   dx = x - dp->cx;  dy = dp->cy - y;
+@@ -431,13 +451,15 @@
+   }
+   else if (dx>0) angle = atan((double)  dy / (double)  dx) * RAD2DEG;
+   else           angle = atan((double) -dy / (double) -dx) * RAD2DEG + 180.0;
+-    
++
+   /* map angle into range: -90..270, then into to value */
+   if (angle > 270.0) angle -= 360.0;
+   if (angle < -90.0) angle += 360.0;
+ 
+-  val = (int) ((dp->max - dp->min) * (240.0 - angle) / 300.0) + dp->min;
++  val = ((dp->max - dp->min) * (240.0 - angle) / 300.0) + dp->min;
+ 
++  /* round value to be an even multiple of dp->inc */
++  val = (double)((int)(val / dp->inc + 0.5)) * dp->inc;
+   return val;
+ }
+ 
+diff -ru xv-3.10a/xvdir.c xv-3.10a-enhancements/xvdir.c
+--- xv-3.10a/xvdir.c	1995-01-03 13:21:39.000000000 -0800
++++ xv-3.10a-enhancements/xvdir.c	2007-05-13 18:47:51.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvdir.c - Directory changin', file i/o dialog box
+  *
+  * callable functions:
+@@ -50,32 +50,63 @@
+ #define COLWIDE  150               /* width of colMB */
+ 
+ /* NOTE: make sure these match up with F_* definitions in xv.h */
+-static char *saveColors[] = { "Full Color", 
+-			      "Greyscale",
+-			      "B/W Dithered",
+-			      "Reduced Color" };
+-
+-static char *saveFormats[] = { "GIF",
++static const char *saveColors[] = { "Full Color",
++				    "Greyscale",
++				    "B/W Dithered",
++				    "Reduced Color" };
++
++static const char *saveFormats[] = {
++#ifdef HAVE_PNG
++					"PNG",
++#endif
+ #ifdef HAVE_JPEG
+-			       "JPEG",
++					"JPEG",
+ #endif
++#ifdef HAVE_JP2K
++					"JPEG 2000",
++					"JP2",
++#endif 
++					"GIF",
+ #ifdef HAVE_TIFF
+-			       "TIFF",
++					"TIFF",
++#endif
++					"PostScript",
++					"PBM/PGM/PPM (raw)",
++					"PBM/PGM/PPM (ascii)",
++					"X11 Bitmap",
++					"XPM",
++					"BMP",
++					"Sun Rasterfile",
++					"IRIS RGB",
++					"Targa (24-bit)",
++					"FITS",
++					"PM",
++					"Spectrum SCREEN$",	/* [JCE] */
++					"WBMP",
++#ifdef HAVE_MAG
++					"MAG",
++#endif
++#ifdef HAVE_PIC
++					"PIC",
++#endif
++#ifdef HAVE_MAKI
++					"MAKI (640x400 only)",
++#endif
++#ifdef HAVE_PI
++					"PI",
++#endif
++#ifdef HAVE_PIC2
++					"PIC2",
++#endif
++#ifdef HAVE_MGCSFX
++					"MgcSfx",
+ #endif
+-			       "PostScript",
+-			       "PBM/PGM/PPM (raw)",
+-			       "PBM/PGM/PPM (ascii)",
+-			       "X11 Bitmap",
+-			       "XPM",
+-			       "BMP",
+-			       "Sun Rasterfile",
+-			       "IRIS RGB",
+-			       "Targa (24-bit)",
+-			       "FITS",
+-			       "PM",
+-			       MBSEP,
+-			       "Filename List"};
++					MBSEP,
++					"Filename List" };
+ 
++#ifdef HAVE_PIC2
++extern int PIC2SaveParams    PARM((char *, int));
++#endif
+ 
+ static void arrangeButts     PARM((int));
+ static void RedrawDList      PARM((int, SCRL *));
+@@ -83,34 +114,37 @@
+ static int  dnamcmp          PARM((const void *, const void *));
+ static int  FNameCdable      PARM((void));
+ static void loadCWD          PARM((void));
++#ifdef FOO
+ static int  cd_able          PARM((char *));
++#endif
+ static void scrollToFileName PARM((void));
+-static void setFName         PARM((char *));
++static void setFName         PARM((const char *));
+ static void showFName        PARM((void));
+ static void changeSuffix     PARM((void));
+ static int  autoComplete     PARM((void));
+ 
+-static byte *handleBWandReduced   PARM((byte *, int,int,int, int, int *, 
++static byte *handleBWandReduced   PARM((byte *, int,int,int, int, int *,
+ 					byte **, byte **, byte **));
+ static byte *handleNormSel        PARM((int *, int *, int *, int *));
+ 
+ 
+-static char  *fnames[MAXNAMES];
+-static int    numfnames = 0, ndirs = 0;
+-static char   path[MAXPATHLEN+1];       /* '/' terminated */
+-static char   loadpath[MAXPATHLEN+1];   /* '/' terminated */
+-static char   savepath[MAXPATHLEN+1];   /* '/' terminated */
+-static char  *dirs[MAXDEEP];            /* list of directory names */
+-static char  *dirMBlist[MAXDEEP];       /* list of dir names in right order */
+-static char  *lastdir;                  /* name of the directory we're in */
+-static char   filename[MAXFNLEN+100];   /* filename being entered */
+-static char   deffname[MAXFNLEN+100];   /* default filename */
+-
+-static int    savemode;                 /* if 0 'load box', if 1 'save box' */
+-static int    curPos, stPos, enPos;     /* filename textedit stuff */
+-static MBUTT  dirMB;                    /* popup path menu */
+-static MBUTT  fmtMB;                    /* 'format' menu button (Save only) */
+-static MBUTT  colMB;                    /* 'colors' menu button (Save only) */
++static char       *fnames[MAXNAMES];
++static int         numfnames = 0, ndirs = 0;
++static char        path[MAXPATHLEN+1];       /* '/' terminated */
++static char        loadpath[MAXPATHLEN+1];   /* '/' terminated */
++static char        savepath[MAXPATHLEN+1];   /* '/' terminated */
++static char       *dirs[MAXDEEP];            /* list of directory names */
++static const char *dirMBlist[MAXDEEP];       /* list of dir names in right order */
++static char       *lastdir;                  /* name of the directory we're in */
++static char        filename[MAXFNLEN+100];   /* filename being entered */
++static char        deffname[MAXFNLEN+100];   /* default filename */
++
++static int   savemode;                 /* if 0 'load box', if 1 'save box' */
++static int   curPos;                   /* insertion point in textedit filename */
++static int   stPos, enPos;             /* start and end of visible textedit filename */
++static MBUTT dirMB;                    /* popup path menu */
++static MBUTT fmtMB;                    /* 'format' menu button (Save only) */
++static MBUTT colMB;                    /* 'colors' menu button (Save only) */
+ 
+ static Pixmap d_loadPix, d_savePix;
+ 
+@@ -119,7 +153,7 @@
+ static char oldfname[MAXFNLEN+100];
+ 
+ /* the name of the file actually opened.  (the temp file if we are piping) */
+-static char outFName[256];  
++static char outFName[256];
+ static int  dopipe;
+ 
+ 
+@@ -127,48 +161,46 @@
+ void CreateDirW(geom)
+      char *geom;
+ {
+-  int w, y;
+-  
+   path[0] = '\0';
+ 
+   xv_getwd(loadpath, sizeof(loadpath));
+   xv_getwd(savepath, sizeof(savepath));
+ 
+-  
++
+   dirW = CreateWindow("","XVdir", geom, DIRWIDE, DIRHIGH, infofg, infobg, 0);
+   if (!dirW) FatalError("couldn't create 'directory' window!");
+ 
+-  LSCreate(&dList, dirW, 10, 5 + 3*(6+LINEHIGH) + 6, LISTWIDE, 
+-	   LINEHIGH*NLINES, NLINES, fnames, numfnames, infofg, infobg, 
++  LSCreate(&dList, dirW, 10, 5 + 3*(6+LINEHIGH) + 6, LISTWIDE,
++	   LINEHIGH*NLINES, NLINES, fnames, numfnames, infofg, infobg,
+ 	   hicol, locol, RedrawDList, 1, 0);
+ 
+-  dnamW = XCreateSimpleWindow(theDisp, dirW, 80, dList.y + (int) dList.h + 30, 
+-			      (u_int) DNAMWIDE+6, (u_int) LINEHIGH+5, 
++  dnamW = XCreateSimpleWindow(theDisp, dirW, 80, dList.y + (int) dList.h + 30,
++			      (u_int) DNAMWIDE+6, (u_int) LINEHIGH+5,
+ 			      1, infofg, infobg);
+   if (!dnamW) FatalError("can't create name window");
+   XSelectInput(theDisp, dnamW, ExposureMask);
+ 
+ 
+-  CBCreate(&browseCB,   dirW, DIRWIDE/2, dList.y + (int) dList.h + 6, 
++  CBCreate(&browseCB,   dirW, DIRWIDE/2, dList.y + (int) dList.h + 6,
+ 	   "Browse", infofg, infobg, hicol,locol);
+ 
+-  CBCreate(&savenormCB, dirW, 220, dList.y + (int) dList.h + 6, 
++  CBCreate(&savenormCB, dirW, 220, dList.y + (int) dList.h + 6,
+ 	   "Normal Size", infofg, infobg,hicol,locol);
+ 
+-  CBCreate(&saveselCB,  dirW, 80,        dList.y + (int) dList.h + 6, 
++  CBCreate(&saveselCB,  dirW, 80,        dList.y + (int) dList.h + 6,
+            "Selected Area", infofg, infobg,hicol,locol);
+ 
+ 
+   /* y-coordinates get filled in when window is opened */
+-  BTCreate(&dbut[S_BOK],     dirW, 259, 0, 80, BUTTH, 
++  BTCreate(&dbut[S_BOK],     dirW, 259, 0, 80, BUTTH,
+ 	   "Ok",        infofg, infobg,hicol,locol);
+-  BTCreate(&dbut[S_BCANC],   dirW, 259, 0, 80, BUTTH, 
++  BTCreate(&dbut[S_BCANC],   dirW, 259, 0, 80, BUTTH,
+ 	   "Cancel",    infofg,infobg,hicol,locol);
+-  BTCreate(&dbut[S_BRESCAN], dirW, 259, 0, 80, BUTTH, 
++  BTCreate(&dbut[S_BRESCAN], dirW, 259, 0, 80, BUTTH,
+ 	   "Rescan",    infofg,infobg,hicol,locol);
+-  BTCreate(&dbut[S_BOLDSET], dirW, 259, 0, 80, BUTTH, 
++  BTCreate(&dbut[S_BOLDSET], dirW, 259, 0, 80, BUTTH,
+ 	   "Prev Set",  infofg,infobg,hicol,locol);
+-  BTCreate(&dbut[S_BOLDNAM], dirW, 259, 0, 80, BUTTH, 
++  BTCreate(&dbut[S_BOLDNAM], dirW, 259, 0, 80, BUTTH,
+ 	   "Prev Name", infofg,infobg,hicol,locol);
+ 
+   SetDirFName("");
+@@ -180,33 +212,33 @@
+    * create MBUTTs *after* calling XMapSubWindows() to keep popup unmapped
+    */
+ 
+-  MBCreate(&dirMB, dirW, 50, dList.y -(LINEHIGH+6), 
++  MBCreate(&dirMB, dirW, 50, dList.y -(LINEHIGH+6),
+ 	   (u_int) DDWIDE, (u_int) LINEHIGH, NULL, NULL, 0,
+ 	   infofg,infobg,hicol,locol);
+ 
+-  MBCreate(&fmtMB, dirW, DIRWIDE-FMTWIDE-10, 5,            
+-	   (u_int) FMTWIDE, (u_int) LINEHIGH, NULL, saveFormats, F_MAXFMTS, 
++  MBCreate(&fmtMB, dirW, DIRWIDE-FMTWIDE-10, 5,
++	   (u_int) FMTWIDE, (u_int) LINEHIGH, NULL, saveFormats, F_MAXFMTS,
+ 	   infofg,infobg,hicol,locol);
+   fmtMB.hascheck = 1;
+   MBSelect(&fmtMB, 0);
+ 
+-  MBCreate(&colMB, dirW, DIRWIDE-COLWIDE-10, 5+LINEHIGH+6, 
+-	   (u_int) COLWIDE, (u_int) LINEHIGH, NULL, saveColors, F_MAXCOLORS, 
++  MBCreate(&colMB, dirW, DIRWIDE-COLWIDE-10, 5+LINEHIGH+6,
++	   (u_int) COLWIDE, (u_int) LINEHIGH, NULL, saveColors, F_MAXCOLORS,
+ 	   infofg,infobg,hicol,locol);
+   colMB.hascheck = 1;
+   MBSelect(&colMB, 0);
+ 
+ 
+-  d_loadPix = XCreatePixmapFromBitmapData(theDisp, dirW, 
+-                 (char *) d_load_bits, d_load_width, d_load_height, 
++  d_loadPix = XCreatePixmapFromBitmapData(theDisp, dirW,
++                 (char *) d_load_bits, d_load_width, d_load_height,
+ 					  infofg, infobg, dispDEEP);
+ 
+-  d_savePix = XCreatePixmapFromBitmapData(theDisp, dirW, 
+-                 (char *) d_save_bits, d_save_width, d_save_height, 
++  d_savePix = XCreatePixmapFromBitmapData(theDisp, dirW,
++                 (char *) d_save_bits, d_save_width, d_save_height,
+ 					  infofg, infobg, dispDEEP);
+ 
+ }
+-  
++
+ 
+ /***************************************************/
+ void DirBox(mode)
+@@ -261,7 +293,7 @@
+ 
+     BTSetActive(&dbut[S_BOLDSET], haveoldinfo);
+     BTSetActive(&dbut[S_BOLDNAM], haveoldinfo);
+-    
++
+     CBSetActive(&saveselCB, HaveSelection());
+ 
+     MBSetActive(&fmtMB, 1);
+@@ -303,15 +335,15 @@
+   if (gap>16) {
+     gap = 16;
+     top = dList.y + (dList.h - (nbts*BUTTH) - (ngaps*gap))/2;
+-    
++
+     for (i=0; i<nbts; i++) dbut[i].y = top + i*(BUTTH+gap);
+   }
+   else {
+-    for (i=0; i<nbts; i++) 
++    for (i=0; i<nbts; i++)
+       dbut[i].y = dList.y + ((dList.h-BUTTH)*i) / ngaps;
+   }
+ }
+-    
++
+ 
+ 
+ /***************************************************/
+@@ -319,24 +351,24 @@
+      int x,y,w,h;
+ {
+   int        i, ypos, txtw;
+-  char       foo[30], *str;
+-  XRectangle xr;
++  char       foo[30];
++  const char *str;
+ 
+   if (dList.nstr==1) strcpy(foo,"1 file");
+                 else sprintf(foo,"%d files",dList.nstr);
+ 
+   ypos = dList.y + dList.h + 8 + ASCENT;
+   XSetForeground(theDisp, theGC, infobg);
+-  XFillRectangle(theDisp, dirW, theGC, 10, ypos-ASCENT, 
++  XFillRectangle(theDisp, dirW, theGC, 10, ypos-ASCENT,
+ 		 (u_int) DIRWIDE, (u_int) CHIGH);
+   XSetForeground(theDisp, theGC, infofg);
+   DrawString(dirW, 10, ypos, foo);
+ 
+ 
+-  if (dirUp == BLOAD) str = "Load file:";  
++  if (dirUp == BLOAD) str = "Load file:";
+                  else str = "Save file:";
+   DrawString(dirW, 10, dList.y + (int) dList.h + 30 + 4 + ASCENT, str);
+-  
++
+   /* draw dividing line */
+   XSetForeground(theDisp,    theGC, infofg);
+   XDrawLine(theDisp, dirW,   theGC, 0, dirMB.y-6, DIRWIDE, dirMB.y-6);
+@@ -346,11 +378,11 @@
+     XSetForeground(theDisp,  theGC, hicol);
+   }
+   XDrawLine(theDisp, dirW,   theGC, 0, dirMB.y-4, DIRWIDE, dirMB.y-4);
+-  
+-  
+-  
++
++
++
+   for (i=0; i<(savemode ? S_NBUTTS : S_LOAD_NBUTTS); i++) BTRedraw(&dbut[i]);
+-  
++
+   MBRedraw(&dirMB);
+   MBRedraw(&fmtMB);
+   MBRedraw(&colMB);
+@@ -362,7 +394,7 @@
+   if (StringWidth(COLLABEL) > txtw) txtw = StringWidth(COLLABEL);
+ 
+   if (!savemode) {
+-    XCopyArea(theDisp, d_loadPix, dirW, theGC, 0,0,d_load_width,d_load_height, 
++    XCopyArea(theDisp, d_loadPix, dirW, theGC, 0,0,d_load_width,d_load_height,
+ 	      10, (dirMB.y-6)/2 - d_load_height/2);
+ 
+     XSetFillStyle(theDisp, theGC, FillStippled);
+@@ -399,18 +431,18 @@
+     i = v = 0;
+     if      (MBClick(&fmtMB, x,y) && (v=MBTrack(&fmtMB))>=0) i=1;
+     else if (MBClick(&colMB, x,y) && (v=MBTrack(&colMB))>=0) i=2;
+-    
++
+     if (i) {  /* changed one of them */
+       if (i==1) SetDirSaveMode(F_FORMAT, v);
+            else SetDirSaveMode(F_COLORS, v);
+       changeSuffix();
+     }
+   }
+-  
+-  
++
++
+   if (!savemode) {  /* LOAD */
+     if (CBClick(&browseCB,x,y)) CBTrack(&browseCB);
+-  } 
++  }
+   else {            /* SAVE */
+     if      (CBClick(&savenormCB,x,y)) CBTrack(&savenormCB);
+     else if (CBClick(&saveselCB,x,y))  CBTrack(&saveselCB);
+@@ -482,7 +514,7 @@
+       }
+ 
+       if (oldnumnames != numnames) {  /* added some */
+-	if (numnames>0) BTSetActive(&but[BDELETE],1); 
++	if (numnames>0) BTSetActive(&but[BDELETE],1);
+ 	windowMB.dim[WMB_TEXTVIEW] = (numnames==0);
+ 
+ 	LSNewData(&nList, dispnames, numnames);
+@@ -501,10 +533,35 @@
+   }
+ 
+ 
+-
+   if (MBClick(&dirMB, x, y)) {
+     i = MBTrack(&dirMB);
+     if (i >= 0) changedDirMB(i);
++    return -1;
++  }
++
++  /* handle clicks inside the filename box */
++  if (x > 80 &&
++      y > dList.y + (int) dList.h + 30 &&
++      x < 80 + DNAMWIDE+6 &&
++      y < dList.y + (int) dList.h + 30 + LINEHIGH+5) {
++    int tx;
++    int dx;
++    int pos;
++
++    /* make coordinates relative to dnamW */
++    tx = x - (80 + 1 + 3); /* left side plus the border plus the space for the "more stuff" sign */
++
++    for (pos=stPos; pos+1 < enPos; pos++) {
++      if (XTextWidth(mfinfo, &filename[stPos], 1+pos-stPos) > tx)
++        break;
++    }
++    /* if we are more than halfway past this char, put the insertion point after it */
++    dx = tx - XTextWidth(mfinfo, &filename[stPos], pos-stPos);
++    if (dx > XTextWidth(mfinfo, &filename[pos], 1)/2)
++      pos++;
++
++    curPos = pos;
++    showFName();
+   }
+ 
+   return -1;
+@@ -564,14 +621,18 @@
+      *  a special concealed device setup to provide a list of available
+      *  disks).
+      */
+-    if ( ((ndirs-sel) == 2) && (strlen(tmppath) > 1) ) 
++    if ( ((ndirs-sel) == 2) && (strlen(tmppath) > 1) )
+       strcat ( tmppath, "/000000" ); /* add root dir for device */
+     else if  ((ndirs-sel) == 1 ) {
+       strcpy ( tmppath, "/XV_Root_Device/000000" );  /* fake top level */
+     }
+ #endif
+ 
++#ifdef AUTO_EXPAND
++    if (Chvdir(tmppath)) {
++#else
+     if (chdir(tmppath)) {
++#endif
+       char str[512];
+       sprintf(str,"Unable to cd to '%s'\n", tmppath);
+       *trunc_point = '/';  /* restore the path */
+@@ -602,7 +663,7 @@
+   xv_getwd(path, sizeof(path));
+   LoadCurrentDirectory();
+ }
+-  
++
+ 
+ 
+ /***************************************************/
+@@ -621,14 +682,14 @@
+ #else
+   struct dirent *dp;
+ #endif
+-  
++
+ 
+   /* get rid of previous file names */
+   for (i=0; i<numfnames; i++) free(fnames[i]);
+   numfnames = 0;
+ 
+   /* get rid of old dirMBlist */
+-  for (i=0; i<ndirs; i++) free(dirMBlist[i]);
++  for (i=0; i<ndirs; i++) free((char *) dirMBlist[i]);
+ 
+ #ifndef VMS
+   if (strlen(path) == 0) xv_getwd(path, sizeof(path));  /* no dir, use cwd */
+@@ -636,7 +697,11 @@
+   xv_getwd(path, sizeof(path));
+ #endif
+ 
++#ifdef AUTO_EXPAND
++  if (Chvdir(path)) {
++#else
+   if (chdir(path)) {
++#endif
+     ErrPopUp("Current load/save directory seems to have gone away!",
+ 	     "\nYikes!");
+ #ifdef apollo
+@@ -644,7 +709,11 @@
+ #else
+     strcpy(path,"/");
+ #endif
++#ifdef AUTO_EXPAND
++    Chvdir(path);
++#else
+     chdir(path);
++#endif
+   }
+ 
+   changedDir = strcmp(path, oldpath);
+@@ -673,19 +742,22 @@
+ 
+   /* build dirMBlist */
+   for (i=ndirs-1,j=0; i>=0; i--,j++) {
+-    size_t stlen = (i<(ndirs-1)) ? dirs[i+1] - dirs[i] : strlen(dirs[i]);
+-    dirMBlist[j] = (char *) malloc(stlen+1);
+-    if (!dirMBlist[j]) FatalError("unable to malloc dirMBlist[]");
++    size_t  stlen = (i<(ndirs-1)) ? dirs[i+1] - dirs[i] : strlen(dirs[i]);
++    char   *copy;
++
++    copy = malloc(stlen+1);
++    if (!copy) FatalError("unable to malloc dirMBlist[]");
+ 
+-    strncpy(dirMBlist[j], dirs[i], stlen);
+-    dirMBlist[j][stlen] = '\0';
++    strncpy(copy, dirs[i], stlen);
++    copy[stlen] = '\0';
++    dirMBlist[j] = copy;
+   }
+-    
++
+ 
+   lastdir = dirs[ndirs-1];
+   dirMB.list = dirMBlist;
+   dirMB.nlist = ndirs;
+-  XClearArea(theDisp, dirMB.win, dirMB.x, dirMB.y, 
++  XClearArea(theDisp, dirMB.win, dirMB.x, dirMB.y,
+ 	     (u_int) dirMB.w+3, (u_int) dirMB.h+3, False);
+   i = StringWidth(dirMBlist[0]) + 10;
+   dirMB.x = dirMB.x + dirMB.w/2 - i/2;
+@@ -704,8 +776,8 @@
+ 
+   i=0;
+   while ( (dp = readdir(dirp)) != NULL) {
+-    if (strcmp(dp->d_name, ".")==0   || 
+-	(strcmp(dp->d_name, "..")==0 && 
++    if (strcmp(dp->d_name, ".")==0   ||
++	(strcmp(dp->d_name, "..")==0 &&
+ 	 (strcmp(path,"/")==0 || strcmp(path,"//")==0)) ||
+ 	strcmp(dp->d_name, THUMBDIR)==0) {
+       /* skip over '.' and '..' and THUMBDIR */
+@@ -714,7 +786,7 @@
+ 
+       if (i == MAXNAMES) {
+ 	fprintf(stderr,
+-		"%s: too many directory entries.  Only using first %d.\n",
++		"%s: too many directory entries.  Using only first %d.\n",
+ 		cmd, MAXNAMES);
+ 	break;
+       }
+@@ -733,7 +805,7 @@
+       /* For VMS we will default all files EXCEPT directories to avoid
+ 	 the high cost of the VAX C implementation of the stat function.
+ 	 Suggested by Kevin Oberman (OBERMAN at icdc.llnl.gov) */
+- 
++
+       if (xv_strstr (fnames[i]+1, ".DIR") != NULL) fnames[i][0] = C_DIR;
+       if (xv_strstr (fnames[i]+1, ".EXE") != NULL) fnames[i][0] = C_EXE;
+       if (xv_strstr (fnames[i]+1, ".OBJ") != NULL) fnames[i][0] = C_BLK;
+@@ -749,6 +821,9 @@
+ 	else if (S_ISFIFO(ftype)) fnames[i][0] = C_FIFO;
+ 	else if (S_ISSOCK(ftype)) fnames[i][0] = C_SOCK;
+         else if (fnames[i][0] == C_REG && (mode&0111)) fnames[i][0] = C_EXE;
++#ifdef AUTO_EXPAND
++	else if (Isarchive(fnames[i]+1)) fnames[i][0] = C_DIR;
++#endif
+       }
+       else {
+ 	/* fprintf(stderr,"problems 'stat-ing' files\n");*/
+@@ -784,11 +859,13 @@
+ 
+ 
+ /***************************************************/
++#ifdef FOO
+ static int cd_able(str)
+ char *str;
+ {
+   return ((str[0] == C_DIR || str[0] == C_LNK));
+ }
++#endif /* FOO */
+ 
+ 
+ /***************************************************/
+@@ -829,24 +906,28 @@
+   int len;
+ 
+   len = strlen(filename);
+-  
++
+   if (c>=' ' && c<'\177') {             /* printable characters */
+     /* note: only allow 'piped commands' in savemode... */
+ 
++#undef PREVENT_SPACES /* Spaces are fine in filenames. */
++#ifdef PREVENT_SPACES
+     /* only allow spaces in 'piped commands', not filenames */
+     if (c==' ' && (!ISPIPE(filename[0]) || curPos==0)) return (-1);
++#endif
+ 
+     /* only allow vertbars in 'piped commands', not filenames */
+     if (c=='|' && curPos!=0 && !ISPIPE(filename[0])) return(-1);
+ 
+     if (len >= MAXFNLEN-1) return(-1);  /* max length of string */
++
+     xvbcopy(&filename[curPos], &filename[curPos+1], (size_t) (len-curPos+1));
+     filename[curPos]=c;  curPos++;
+ 
+     scrollToFileName();
+   }
+ 
+-  else if (c=='\010' || c=='\177') {    /* BS or DEL */
++  else if (c=='\010') {                 /* BS */
+     if (curPos==0) return(-1);          /* at beginning of str */
+     xvbcopy(&filename[curPos], &filename[curPos-1], (size_t) (len-curPos+1));
+     curPos--;
+@@ -871,7 +952,7 @@
+     curPos = len;
+   }
+ 
+-  else if (c=='\004') {                 /* ^D: delete character at curPos */
++  else if (c=='\004' || c=='\177') {    /* ^D or DEL: delete character at curPos */
+     if (curPos==len) return(-1);
+     xvbcopy(&filename[curPos+1], &filename[curPos], (size_t) (len-curPos));
+   }
+@@ -918,19 +999,19 @@
+ {
+   /* called to 'auto complete' a filename being entered.  If the name that
+      has been entered so far is anything but a simple filename (ie, has
+-     spaces, pipe char, '/', etc) fails.  If it is a simple filename, 
++     spaces, pipe char, '/', etc) fails.  If it is a simple filename,
+      looks through the name list to find something that matches what's already
+      been typed.  If nothing matches, it fails.  If more than one thing
+      matches, it sets the name to the longest string that the multiple
+-     matches have in common, and succeeds (and beeps).  
++     matches have in common, and succeeds (and beeps).
+      If only one matches, sets the string to the match and succeeds.
+-     
++
+      returns zero on failure, non-zero on success */
+-  
++
+   int i, firstmatch, slen, nummatch, cnt;
+ 
+   /* is filename a simple filename? */
+-  if (strlen(filename)==0  || 
++  if (strlen(filename)==0  ||
+       ISPIPE(filename[0])  ||
+       index(filename, '/') ||
+       filename[0]=='~'   ) return 0;
+@@ -946,7 +1027,7 @@
+   firstmatch = i;
+ 
+   /* count # of matches */
+-  for (i=firstmatch, nummatch=0; 
++  for (i=firstmatch, nummatch=0;
+        i<dList.nstr && strncmp(filename, dList.str[i]+1, (size_t) slen)==0;
+        i++, nummatch++);
+ 
+@@ -960,14 +1041,14 @@
+   while (dList.str[firstmatch][slen+1]!='\0') {
+     filename[slen] = dList.str[firstmatch][slen+1];
+     slen++;  filename[slen] = '\0';
+-    
++
+     for (i=firstmatch, cnt=0;
+ 	 i<dList.nstr && strncmp(filename, dList.str[i]+1, (size_t) slen)==0;
+ 	 i++, cnt++);
+ 
+     if (cnt != nummatch) {  slen--;  filename[slen] = '\0';  break; }
+-  }  
+-  
++  }
++
+   XBell(theDisp, 0);
+ 
+   return 1;
+@@ -1003,7 +1084,7 @@
+   i = pos - (NLINES/2);
+   SCSetVal(&dList.scrl, i);
+ }
+-  
++
+ 
+ /***************************************************/
+ void RedrawDNamW()
+@@ -1012,7 +1093,7 @@
+ 
+   /* draw substring filename[stPos:enPos] and cursor */
+ 
+-  Draw3dRect(dnamW, 0, 0, (u_int) DNAMWIDE+5, (u_int) LINEHIGH+4, R3D_IN, 2, 
++  Draw3dRect(dnamW, 0, 0, (u_int) DNAMWIDE+5, (u_int) LINEHIGH+4, R3D_IN, 2,
+ 	     hicol, locol, infobg);
+ 
+   XSetForeground(theDisp, theGC, infofg);
+@@ -1023,7 +1104,7 @@
+     XDrawLine(theDisp, dnamW, theGC, 2,0,2,LINEHIGH+5);
+   }
+ 
+-  if ((size_t) enPos < strlen(filename)) { 
++  if ((size_t) enPos < strlen(filename)) {
+     /* draw a "there's more over here" doowah */
+     XDrawLine(theDisp, dnamW, theGC, DNAMWIDE+5,0,DNAMWIDE+5,LINEHIGH+5);
+     XDrawLine(theDisp, dnamW, theGC, DNAMWIDE+4,0,DNAMWIDE+4,LINEHIGH+5);
+@@ -1032,6 +1113,7 @@
+ 
+   XDrawString(theDisp, dnamW, theGC,3,ASCENT+3,filename+stPos, enPos-stPos);
+ 
++  /* draw insertion point */
+   cpos = XTextWidth(mfinfo, &filename[stPos], curPos-stPos);
+   XDrawLine(theDisp, dnamW, theGC, 3+cpos, 2, 3+cpos, 2+CHIGH+1);
+   XDrawLine(theDisp, dnamW, theGC, 3+cpos, 2+CHIGH+1, 5+cpos, 2+CHIGH+3);
+@@ -1054,10 +1136,29 @@
+ 
+   fullname = GetDirFullName();
+ 
++#ifdef AUTO_EXPAND
++  {
++      char path[MAXPATHLEN];
++
++      GetDirPath(path);
++      Mkvdir(path);
++      if ((i = Isvdir(fullname)) & 01) {
++	  char buf[128];
++	  sprintf(buf,
++		  "Sorry, you can't save file in the virtual directory, '%s'",
++		  path);
++	  ErrPopUp(buf, "\nBummer!");
++	  return -1;
++      }
++      if (i & 06)
++	  Rmvdir(fullname);
++  }
++#endif
++
+   fmt = MBWhich(&fmtMB);
+   col = MBWhich(&colMB);
+ 
+-  if (fmt<0 || col<0) 
++  if (fmt<0 || col<0)
+     FatalError("xv: no 'checked' format or color.  shouldn't happen!\n");
+ 
+ 
+@@ -1068,19 +1169,19 @@
+       dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
+       return -1;
+     }
+-    
++
+     for (i=0; i<numnames; i++) {
+       if ((i&0x3f)==0) WaitCursor();
+       if (namelist[i][0] != '/') fprintf(fp, "%s/%s\n", initdir, namelist[i]);
+                             else fprintf(fp, "%s\n", namelist[i]);
+     }
+-    
++
+     i = (ferror(fp)) ? 1 : 0;
+     if (CloseOutFile(fp, fullname, i) == 0) {
+       DirBox(0);
+       XVCreatedFile(fullname);
+     }
+-    
++
+     SetCursors(-1);
+     dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
+     return i;
+@@ -1100,7 +1201,16 @@
+ #ifdef HAVE_JPEG
+   else if (fmt == F_JPEG) {   /* JPEG */
+     JPEGSaveParams(fullname, col);
+-    JPEGDialog(1);                   /* open JPEGDialog box */
++    JPEGDialog(1);                 /* open JPEGDialog box */
++    dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
++    return 0;                      /* always 'succeeds' */
++  }
++#endif
++
++#ifdef HAVE_JP2K
++  else if (fmt == F_JPC || fmt == F_JP2) {   /* JPEG 2000 */
++    JP2KSaveParams(fmt, fullname, col);
++    JP2KDialog(1);                 /* open JP2KDialog box */
+     dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
+     return 0;                      /* always 'succeeds' */
+   }
+@@ -1109,13 +1219,40 @@
+ #ifdef HAVE_TIFF
+   else if (fmt == F_TIFF) {   /* TIFF */
+     TIFFSaveParams(fullname, col);
+-    TIFFDialog(1);                   /* open TIFF Dialog box */
++    TIFFDialog(1);                 /* open TIFF Dialog box */
++    dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
++    return 0;                      /* always 'succeeds' */
++  }
++#endif
++
++#ifdef HAVE_PNG
++  else if (fmt == F_PNG) {   /* PNG */
++    PNGSaveParams(fullname, col);
++    PNGDialog(1);                  /* open PNG Dialog box */
+     dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
+     return 0;                      /* always 'succeeds' */
+   }
+ #endif
+ 
++#ifdef HAVE_PIC2
++  else if (fmt == F_PIC2) {   /* PIC2 */
++    if (PIC2SaveParams(fullname, col) < 0)
++	return 0;
++    PIC2Dialog(1);                   /* open PIC2 Dialog box */
++    dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
++    return 0;                      /* always 'succeeds' */
++  }
++#endif /* HAVE_PIC2 */
+ 
++#ifdef HAVE_MGCSFX
++  else if (fmt == F_MGCSFX) {   /* MGCSFX */
++    if (MGCSFXSaveParams(fullname, col) < 0)
++	return 0;
++    MGCSFXDialog(1);                   /* open MGCSFX Dialog box */
++    dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
++    return 0;                      /* always 'succeeds' */
++  }
++#endif /* HAVE_MGCSFX */
+ 
+ 
+   WaitCursor();
+@@ -1147,34 +1284,74 @@
+     rv = WritePBM   (fp, thepic, ptype, w, h, rp,gp,bp, nc,col,1,picComments);
+     break;
+ 
+-  case F_PBMASCII: 
++  case F_PBMASCII:
+     rv = WritePBM   (fp, thepic, ptype, w, h, rp,gp,bp, nc,col,0,picComments);
+     break;
+ 
+   case F_XBM:
+-    rv = WriteXBM   (fp, thepic, w, h, rp, gp, bp, fullname);          break;
++    rv = WriteXBM   (fp, thepic, w, h, rp, gp, bp, fullname);
++    break;
+ 
+   case F_SUNRAS:
+-    rv = WriteSunRas(fp, thepic, ptype, w, h, rp, gp, bp, nc, col,0);  break;
++    rv = WriteSunRas(fp, thepic, ptype, w, h, rp, gp, bp, nc, col,0);
++    break;
+ 
+   case F_BMP:
+-    rv = WriteBMP   (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);    break;
++    rv = WriteBMP   (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);
++    break;
++
++  case F_WBMP:
++    rv = WriteWBMP  (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);
++    break;
+ 
+   case F_IRIS:
+-    rv = WriteIRIS  (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);    break;
+-    
++    rv = WriteIRIS  (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);
++    break;
++
+   case F_TARGA:
+-    rv = WriteTarga (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);    break;
+-    
++    rv = WriteTarga (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);
++    break;
++
+   case F_XPM:
+-    rv = WriteXPM   (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, 
+-		     fullname, picComments);    
++    rv = WriteXPM   (fp, thepic, ptype, w, h, rp, gp, bp, nc, col,
++		     fullname, picComments);
++    break;
++
+   case F_FITS:
+-    rv = WriteFITS  (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, 
+-		     picComments);    
++    rv = WriteFITS  (fp, thepic, ptype, w, h, rp, gp, bp, nc, col,
++		     picComments);
++    break;
++
++  case F_ZX:		/* [JCE] Spectrum SCREEN$ */
++    rv = WriteZX    (fp, thepic, ptype, w, h, rp, gp, bp, nc, col,
++		     picComments);
++    break;
++#ifdef HAVE_MAG
++  case F_MAG:
++    rv = WriteMAG   (fp, thepic, ptype, w, h, rp, gp, bp, nc, col,
++		     picComments);
++    break;
++#endif /* HAVE_MAG */
++#ifdef HAVE_PIC
++  case F_PIC:
++    rv = WritePIC   (fp, thepic, ptype, w, h, rp, gp, bp, nc, col,
++		     picComments);
+     break;
++#endif /* HAVE_PIC */
++#ifdef HAVE_MAKI
++  case F_MAKI:
++    rv = WriteMAKI  (fp, thepic, ptype, w, h, rp, gp, bp, nc, col);
++    break;
++#endif /* HAVE_MAKI */
++
++#ifdef HAVE_PI
++  case F_PI:
++    rv = WritePi    (fp, thepic, ptype, w, h, rp, gp, bp, nc, col,
++		     picComments);
++    break;
++#endif /* HAVE_PI */
+   }
+-  
++
+ 
+   if (CloseOutFile(fp, fullname, rv) == 0) {
+     DirBox(0);
+@@ -1184,12 +1361,12 @@
+     }
+   }
+ 
+-  
++
+   if (pfree) free(thepic);
+-  
++
+   SetCursors(-1);
+   dbut[S_BOK].lit = 0;  BTRedraw(&dbut[S_BOK]);
+-  
++
+   return rv;
+ }
+ 
+@@ -1197,22 +1374,23 @@
+ 
+ /***************************************************/
+ void SetDirFName(st)
+-     char *st;
++     const char *st;
+ {
+   strncpy(deffname, st, (size_t) MAXFNLEN-1);
++  deffname[MAXFNLEN-1] = '\0';
+   setFName(st);
+ }
+ 
+ 
+ /***************************************************/
+ static void setFName(st)
+-     char *st;
++     const char *st;
+ {
+   strncpy(filename, st, (size_t) MAXFNLEN-1);
+   filename[MAXFNLEN-1] = '\0';  /* make sure it's terminated */
+   curPos = strlen(st);
+   stPos = 0;  enPos = curPos;
+-  
++
+   showFName();
+ }
+ 
+@@ -1221,17 +1399,17 @@
+ static void showFName()
+ {
+   int len;
+-  
++
+   len = strlen(filename);
+-  
++
+   if (curPos<stPos) stPos = curPos;
+   if (curPos>enPos) enPos = curPos;
+-  
++
+   if (stPos>len) stPos = (len>0) ? len-1 : 0;
+   if (enPos>len) enPos = (len>0) ? len-1 : 0;
+-  
++
+   /* while substring is shorter than window, inc enPos */
+-  
++
+   while (XTextWidth(mfinfo, &filename[stPos], enPos-stPos) < DNAMWIDE
+ 	 && enPos<len) { enPos++; }
+ 
+@@ -1244,7 +1422,7 @@
+   }
+ 
+ 
+-  if (ctrlColor) XClearArea(theDisp, dnamW, 2,2, (u_int) DNAMWIDE+5-3, 
++  if (ctrlColor) XClearArea(theDisp, dnamW, 2,2, (u_int) DNAMWIDE+5-3,
+ 			    (u_int) LINEHIGH+4-3, False);
+   else XClearWindow(theDisp, dnamW);
+ 
+@@ -1270,7 +1448,7 @@
+   else {
+     strcpy(globname, filename);
+     if (globname[0] == '~') Globify(globname);
+-    
++
+     if (globname[0] != '/') sprintf(fullname, "%s%s", path, globname);
+     else strcpy(fullname, globname);
+   }
+@@ -1294,14 +1472,15 @@
+ 	MBRedraw(&fmtMB);
+       }
+     }
+-    
++
+     if (bnum>=0) MBSelect(&colMB, bnum);
+   }
+-  
++
+ 
+   else if (group == F_FORMAT) {
+     MBSelect(&fmtMB, bnum);
+-    if (MBWhich(&fmtMB) == F_XBM) { /* turn off all but B/W */
++    if (MBWhich(&fmtMB) == F_XBM ||
++	MBWhich(&fmtMB) == F_WBMP) { /* turn off all but B/W */
+       colMB.dim[F_FULLCOLOR] = 1;
+       colMB.dim[F_GREYSCALE] = 1;
+       colMB.dim[F_BWDITHER]  = 0;
+@@ -1322,10 +1501,10 @@
+       colMB.dim[F_GREYSCALE] = 0;
+       colMB.dim[F_BWDITHER]  = 0;
+       colMB.dim[F_REDUCED]   = (picType==PIC8) ? 0 : 1;
+-      if (picType!=PIC8 && MBWhich(&colMB)==F_REDUCED) 
++      if (picType!=PIC8 && MBWhich(&colMB)==F_REDUCED)
+ 	MBSelect(&colMB, F_FULLCOLOR);
+     }
+-    
++
+     if (MBWhich(&fmtMB) == F_FILELIST) {
+       MBSetActive(&colMB,      0);
+       CBSetActive(&savenormCB, 0);
+@@ -1337,12 +1516,12 @@
+   }
+ }
+ 
+-  
++
+ 
+ /***************************************/
+ static void changeSuffix()
+ {
+-  /* see if there's a common suffix at the end of the filename.  
++  /* see if there's a common suffix at the end of the filename.
+      if there is, remember what case it was (all caps or all lower), lop
+      it off, and replace it with a new appropriate suffix, in the
+      same case */
+@@ -1356,7 +1535,7 @@
+   suffix++;  /* point to first letter of the suffix */
+ 
+   /* check for all-caposity */
+-  for (sp = suffix, allcaps=1; *sp; sp++) 
++  for (sp = suffix, allcaps=1; *sp; sp++)
+     if (islower(*sp)) allcaps = 0;
+ 
+   /* copy the suffix into an all-lower-case buffer */
+@@ -1380,14 +1559,33 @@
+       (strcmp(lowsuf,"eps" )==0) ||
+       (strcmp(lowsuf,"rgb" )==0) ||
+       (strcmp(lowsuf,"tga" )==0) ||
+-      (strcmp(lowsuf,"xpm" )==0) ||
+       (strcmp(lowsuf,"fits")==0) ||
+       (strcmp(lowsuf,"fts" )==0) ||
++#ifdef HAVE_JPEG
+       (strcmp(lowsuf,"jpg" )==0) ||
+       (strcmp(lowsuf,"jpeg")==0) ||
+       (strcmp(lowsuf,"jfif")==0) ||
++#endif
++#ifdef HAVE_JP2K
++      (strcmp(lowsuf,"jpc" )==0) ||
++      (strcmp(lowsuf,"jp2" )==0) ||
++#endif
++#ifdef HAVE_TIFF
+       (strcmp(lowsuf,"tif" )==0) ||
+-      (strcmp(lowsuf,"tiff")==0)) {
++      (strcmp(lowsuf,"tiff")==0) ||
++#endif
++#ifdef HAVE_PNG
++      (strcmp(lowsuf,"png" )==0) ||
++#endif
++      (strcmp(lowsuf,"wbmp")==0) ||
++      (strcmp(lowsuf,"xpm" )==0) ||
++      (strcmp(lowsuf,"tiff")==0) ||
++      (strcmp(lowsuf,"mag" )==0) ||
++      (strcmp(lowsuf,"pic" )==0) ||
++      (strcmp(lowsuf,"mki" )==0) ||
++      (strcmp(lowsuf,"pi"  )==0) ||
++      (strcmp(lowsuf,"p2"  )==0) ||
++      (strcmp(lowsuf,"pcd" )==0)) {
+ 
+     /* found one.  set lowsuf = to the new suffix, and tack on to filename */
+ 
+@@ -1401,7 +1599,7 @@
+     case F_GIF:      strcpy(lowsuf,"gif");  break;
+     case F_PM:       strcpy(lowsuf,"pm");   break;
+     case F_PBMRAW:
+-    case F_PBMASCII: if (col == F_FULLCOLOR || col == F_REDUCED) 
++    case F_PBMASCII: if (col == F_FULLCOLOR || col == F_REDUCED)
+                                                   strcpy(lowsuf,"ppm");
+                      else if (col == F_GREYSCALE) strcpy(lowsuf,"pgm");
+                      else if (col == F_BWDITHER)  strcpy(lowsuf,"pbm");
+@@ -1410,6 +1608,7 @@
+     case F_XBM:      strcpy(lowsuf,"xbm");  break;
+     case F_SUNRAS:   strcpy(lowsuf,"ras");  break;
+     case F_BMP:      strcpy(lowsuf,"bmp");  break;
++    case F_WBMP:     strcpy(lowsuf,"wbmp"); break;
+     case F_PS:       strcpy(lowsuf,"ps");   break;
+     case F_IRIS:     strcpy(lowsuf,"rgb");  break;
+     case F_TARGA:    strcpy(lowsuf,"tga");  break;
+@@ -1420,16 +1619,46 @@
+     case F_JPEG:     strcpy(lowsuf,"jpg");  break;
+ #endif
+ 
++#ifdef HAVE_JP2K
++    case F_JPC:      strcpy(lowsuf,"jpc");  break;
++    case F_JP2:      strcpy(lowsuf,"jp2");  break;
++#endif
++
+ #ifdef HAVE_TIFF
+     case F_TIFF:     strcpy(lowsuf,"tif");  break;
+ #endif
++
++#ifdef HAVE_PNG
++    case F_PNG:      strcpy(lowsuf,"png");  break;
++#endif
++
++#ifdef HAVE_MAG
++    case F_MAG:      strcpy(lowsuf,"mag");  break;
++#endif
++
++#ifdef HAVE_PIC
++    case F_PIC:      strcpy(lowsuf,"pic");  break;
++#endif
++
++#ifdef HAVE_MAKI
++    case F_MAKI:     strcpy(lowsuf,"mki");  break;
++#endif
++
++#ifdef HAVE_PI
++    case F_PI:       strcpy(lowsuf,"pi");   break;
++#endif
++
++#ifdef HAVE_PIC2
++    case F_PIC2:     strcpy(lowsuf,"p2");   break;
++#endif
+     }
+ 
++
+     if (allcaps) {  /* upper-caseify lowsuf */
+-      for (sp=lowsuf; *sp; sp++) 
++      for (sp=lowsuf; *sp; sp++)
+ 	*sp = (islower(*sp)) ? toupper(*sp) : *sp;
+     }
+-    
++
+     /* one other case:  if the original suffix started with a single
+        capital letter, make the new suffix start with a single cap */
+     if (isupper(suffix[0])) lowsuf[0] = toupper(lowsuf[0]);
+@@ -1439,7 +1668,7 @@
+   }
+ 
+ }
+-  
++
+ 
+ /***************************************************/
+ int DirCheckCD()
+@@ -1462,7 +1691,7 @@
+ static int FNameCdable()
+ {
+   /* returns '1' if filename is a directory, and goes there */
+-  
++
+   char newpath[1024];
+   struct stat st;
+   int retval = 0;
+@@ -1490,6 +1719,11 @@
+   }
+ #endif
+ 
++#ifdef AUTO_EXPAND
++  Mkvdir(newpath);
++  Dirtovd(newpath);
++#endif
++
+   if (stat(newpath, &st)==0) {
+     int isdir;
+ 
+@@ -1518,7 +1752,7 @@
+       retval = 1;
+     }
+   }
+-  
++
+   return retval;
+ }
+ 
+@@ -1549,8 +1783,8 @@
+   *up='\0';
+ 
+   if (*uname=='\0') { /* no name.  substitute ~ with $HOME */
+-    char *homedir;
+-    homedir = (char *) getenv("HOME");  
++    const char *homedir;
++    homedir = (const char *) getenv("HOME");
+     if (homedir == NULL) homedir = ".";
+     strcpy(tmp,homedir);
+     strcat(tmp,sp);
+@@ -1574,12 +1808,12 @@
+ 
+ /***************************************/
+ FILE *OpenOutFile(filename)
+-     char *filename;
++     const char *filename;
+ {
+   /* opens file for output.  does various error handling bits.  Returns
+      an open file pointer if success, NULL if failure */
+ 
+-  FILE *fp;
++  FILE *fp = NULL;
+   struct stat st;
+ 
+   if (!filename || filename[0] == '\0') return NULL;
+@@ -1587,7 +1821,11 @@
+   dopipe = 0;
+ 
+   /* make sure we're in the correct directory */
++#ifdef AUTO_EXPAND
++  if (strlen(path)) Chvdir(path);
++#else
+   if (strlen(path)) chdir(path);
++#endif
+ 
+   if (ISPIPE(filename[0])) {   /* do piping */
+     /* make up some bogus temp file to put this in */
+@@ -1596,23 +1834,34 @@
+ #else
+     strcpy(outFName, "[]xvXXXXXX.lis");
+ #endif
++#ifdef USE_MKSTEMP
++    fp = fdopen(mkstemp(outFName), "w");
++#else
+     mktemp(outFName);
++#endif
+     dopipe = 1;
+   }
+ 
+ 
+-  /* see if file exists (ie, we're overwriting) */
+-  if (stat(outFName, &st)==0) {   /* stat succeeded, file must exist */
+-    static char *foo[] = { "\nOk", "\033Cancel" };
+-    char str[512];
++#ifdef USE_MKSTEMP  /* (prior) nonexistence of file is already guaranteed by */
++  if (!dopipe)      /*  mkstemp(), but now mkstemp() itself has created it */
++#endif
++    /* see if file exists (i.e., we're overwriting) */
++    if (stat(outFName, &st)==0) {   /* stat succeeded, file must exist */
++      static const char *labels[] = { "\nOk", "\033Cancel" };
++      char               str[512];
+ 
+-    sprintf(str,"Overwrite existing file '%s'?", outFName);
+-    if (PopUp(str, foo, 2)) return NULL;
+-  }
+-    
++      sprintf(str,"Overwrite existing file '%s'?", outFName);
++      if (PopUp(str, labels, 2)) return NULL;
++    }
++
++
++  /* Open file (if not already open via mkstemp()) */
++#ifdef USE_MKSTEMP
++  if (!dopipe)
++#endif
++    fp = fopen(outFName, "w");
+ 
+-  /* Open file */
+-  fp = fopen(outFName, "w");
+   if (!fp) {
+     char  str[512];
+     sprintf(str,"Can't write file '%s'\n\n  %s.",outFName, ERRSTR(errno));
+@@ -1622,12 +1871,12 @@
+ 
+   return fp;
+ }
+-  
++
+ 
+ /***************************************/
+ int CloseOutFile(fp, filename, failed)
+      FILE *fp;
+-     char *filename;
++     const char *filename;
+      int   failed;
+ {
+   char buf[64];
+@@ -1642,9 +1891,8 @@
+     return 1;
+   }
+ 
+-    
++
+   if (fclose(fp) == EOF) {
+-    static char *foo[] = { "\nWeird!" };
+     char  str[512];
+     sprintf(str,"Can't close file '%s'\n\n  %s.",outFName, ERRSTR(errno));
+     ErrPopUp(str, "\nWeird!");
+@@ -1666,7 +1914,7 @@
+   }
+ 
+   SetISTR(ISTR_INFO,"Successfully wrote '%s'%s", outFName, buf);
+-  
++
+   if (dopipe) {
+     char cmd[512], str[1024];
+     int  i;
+@@ -1709,7 +1957,7 @@
+   return 0;
+ }
+ 
+-      
++
+ 
+ 
+ static byte rBW[2], gBW[2], bBW[2];
+@@ -1732,7 +1980,7 @@
+   bwpic = (byte *) NULL;
+   *nc = numcols;  *rpp = rMap;  *gpp = gMap;  *bpp = bMap;
+ 
+-  /* quick check:  if we're saving a 24-bit image, then none of this 
++  /* quick check:  if we're saving a 24-bit image, then none of this
+      complicated 'reduced'/dithered/smoothed business comes into play.
+      'reduced' is disabled, for semi-obvious reasons, in 24-bit mode,
+      as is 'dithered'.  If 'smoothed', and we're saving at current
+@@ -1744,32 +1992,32 @@
+      if we're saving B/W DITHERED, and deal accordingly */
+ 
+ 
+-  if (ptype == PIC24) {  
++  if (ptype == PIC24) {
+     if (color != F_BWDITHER) return NULL;
+     else {                                /* generate a bw-dithered version */
+       byte *p24, *thepic;
+-      
++
+       thepic = pic;
+       p24 = GammifyPic24(thepic, pw, ph);
+       if (p24) thepic = p24;
+-      
++
+       /* generate a FSDithered 1-byte per pixel image */
+       bwpic = FSDither(thepic, PIC24, pw, ph, NULL,NULL,NULL, 0, 1);
+       if (!bwpic) FatalError("unable to malloc dithered picture (DoSave)");
+-      
++
+       if (p24) free(p24);  /* won't need it any more */
+-      
++
+       /* build a BW colormap */
+       rBW[0] = gBW[0] = bBW[0] = 0;
+       rBW[1] = gBW[1] = bBW[1] = 255;
+-      
++
+       *rpp = rBW;  *gpp = gBW;  *bpp = bBW;
+       *nc = 2;
+-      
++
+       return bwpic;
+     }
+   }
+-    
++
+ 
+ 
+   /* ptype == PIC8 ... */
+@@ -1777,7 +2025,7 @@
+   *nc = numcols;  *rpp = rMap;  *gpp = gMap;  *bpp = bMap;
+   if (color==F_REDUCED) { *rpp = rdisp;  *gpp = gdisp;  *bpp = bdisp; }
+ 
+-  /* if DITHER or SMOOTH, and color==FULLCOLOR or GREY, 
++  /* if DITHER or SMOOTH, and color==FULLCOLOR or GREY,
+      make color=REDUCED, so it will be written with the correct colortable  */
+ 
+   if ((epicMode == EM_DITH || epicMode == EM_SMOOTH) && color != F_REDUCED) {
+@@ -1789,7 +2037,7 @@
+       *rpp = gray;  *gpp = gray;  *bpp = gray;
+     }
+   }
+-  
++
+ 
+ 
+ 
+@@ -1823,8 +2071,8 @@
+    * and whether or not it should be freed when we're done with it.  The 'pic'
+    * returned is the desired portion of 'cpic' or 'epic' if there is a
+    * selection, and the saveselCB is enabled, or alternately, it's the
+-   * whole cpic or epic.  
+-   * 
++   * whole cpic or epic.
++   *
+    * if selection does not intersect cpic/epic, returns cpic/epic
+    * NEVER RETURNS NULL
+    */
+@@ -1837,7 +2085,7 @@
+   if (savenormCB.val) { thepic = cpic;  pw = cWIDE;  ph = cHIGH; }
+                  else { thepic = epic;  pw = eWIDE;  ph = eHIGH; }
+ 
+-  *pwide = pw;  *phigh = ph;  
++  *pwide = pw;  *phigh = ph;
+ 
+ 
+   if (saveselCB.active && saveselCB.val && HaveSelection()) {
+@@ -1862,7 +2110,7 @@
+       CoordP2E(x2,y2, &x2, &y2);
+       slx = x1;  sly = y1;  slw = x2-x1;  slh = y2-y1;
+       CropRect2Rect(&slx, &sly, &slw, &slh, 0,0,pw,ph);
+-      
++
+       if (slw<1 || slh<1) { slx = sly = 0;  slw=pw;  slh=ph; }
+ 
+       if (slx!=0 || sly!=0 || slw!=pw || slh!=ph) {
+@@ -1871,7 +2119,7 @@
+       }
+     }
+ 
+-    *pwide = slw;  *phigh = slh;  
++    *pwide = slw;  *phigh = slh;
+   }
+ 
+   return thepic;
+@@ -1884,11 +2132,11 @@
+      byte **rmapP, **gmapP, **bmapP;
+ {
+   /* handles the whole ugly mess of the various save options.
+-   * returns an image, of type 'ptypeP', size 'wP,hP'.  
++   * returns an image, of type 'ptypeP', size 'wP,hP'.
+    * if (*ptypeP == PIC8), also returns numcols 'ncP', and the r,g,b map
+    * to use rmapP, gmapP, bmapP.
+    *
+-   * if freeP is set, image can safely be freed after it is saved 
++   * if freeP is set, image can safely be freed after it is saved
+    */
+ 
+   byte *pic1, *pic2;
+@@ -1896,9 +2144,9 @@
+ 
+   pic1 = handleNormSel(&ptype, &w, &h, &pfree);
+ 
+-  pic2 = handleBWandReduced(pic1, ptype, w,h, MBWhich(&colMB), 
++  pic2 = handleBWandReduced(pic1, ptype, w,h, MBWhich(&colMB),
+ 			      ncP, rmapP, gmapP, bmapP);
+-  if (pic2) { 
++  if (pic2) {
+     if (pfree) free(pic1);
+     pic1  = pic2;
+     pfree = 1;
+@@ -1906,7 +2154,7 @@
+   }
+ 
+ 
+-  if (ptype == PIC24) {       
++  if (ptype == PIC24) {
+     pic2 = GammifyPic24(pic1, w, h);
+     if (pic2) {
+       if (pfree) free(pic1);
+@@ -1920,7 +2168,7 @@
+   return pic1;
+ }
+ 
+-     
++
+ /***************************************/
+ void GetSaveSize(wP, hP)
+      int *wP, *hP;
+@@ -1947,7 +2195,7 @@
+       CoordP2E(x2,y2, &x2, &y2);
+       slx = x1;  sly = y1;  slw = x2-x1;  slh = y2-y1;
+       CropRect2Rect(&slx, &sly, &slw, &slh, 0,0,eWIDE,eHIGH);
+-      
++
+       if (slw<1 || slh<1) { slx = sly = 0;  slw=eWIDE;  slh=eHIGH; }
+     }
+   }
+@@ -1982,8 +2230,8 @@
+ 
+     if (stat(namelist[curname], &origStat)==0) {
+       haveStat = 1;
+-      if (DEBUG) fprintf(stderr," origStat.size=%ld,  origStat.mtime=%d\n", 
+-			 origStat.st_size, origStat.st_mtime);
++      if (DEBUG) fprintf(stderr," origStat.size=%ld,  origStat.mtime=%ld\n",
++			 (long)origStat.st_size, (long)origStat.st_mtime);
+     }
+   }
+ }
+@@ -1993,7 +2241,7 @@
+ int CheckPoll(del)
+      int del;
+ {
+-  /* returns '1' if the file has been modified, and either 
++  /* returns '1' if the file has been modified, and either
+       A) the file has stabilized (st = lastStat), or
+       B) 'del' seconds have gone by since the file last changed size
+    */
+@@ -2007,14 +2255,14 @@
+       (strcmp(namelist[curname], STDINSTR)!=0)) {
+ 
+     if (stat(namelist[curname], &st)==0) {
+-      if (DEBUG) fprintf(stderr," st.size=%ld,  st.mtime=%d\n", 
+-			 st.st_size, st.st_mtime);
++      if (DEBUG) fprintf(stderr," st.size=%ld,  st.mtime=%ld\n",
++			 (long)st.st_size, (long)st.st_mtime);
+ 
+       if ((st.st_size  == origStat.st_size) &&
+ 	  (st.st_mtime == origStat.st_mtime)) return 0;  /* no change */
+ 
+       /* if it's changed since last looked ... */
+-      if (!haveLastStat || 
++      if (!haveLastStat ||
+ 	  st.st_size  != lastStat.st_size  ||
+ 	  st.st_mtime != lastStat.st_mtime)   {
+ 	xvbcopy((char *) &st, (char *) &lastStat, sizeof(struct stat));
+@@ -2031,7 +2279,7 @@
+       }
+     }
+   }
+-  
++
+   return 0;
+ }
+ 
+@@ -2042,14 +2290,13 @@
+ {
+   /* called when file 'name' has been deleted.  If any of the browsers
+      were showing the directory that the file was in, does a rescan() */
+-  
+-  int  i;
++
+   char buf[MAXPATHLEN + 2], *tmp;
+ 
+   strcpy(buf, name);
+-  tmp = BaseName(buf);
++  tmp = (char *) BaseName(buf);  /* intentionally losing constness */
+   *tmp = '\0';     /* truncate after last '/' */
+-  
++
+   if (strcmp(path, buf)==0) LoadCurrentDirectory();
+ }
+ 
+@@ -2062,3 +2309,164 @@
+ }
+ 
+ 
++#ifdef HAVE_PIC2
++/**** Stuff for PIC2Dialog box ****/
++FILE *pic2_OpenOutFile(filename, append)
++char *filename;
++int *append;
++{
++    /* opens file for output.  does various error handling bits.  Returns
++       an open file pointer if success, NULL if failure */
++
++    FILE *fp = NULL;
++    struct stat st;
++
++    if (!filename || filename[0] == '\0')
++	return (NULL);
++    strcpy(outFName, filename);
++    dopipe = 0;
++
++    /* make sure we're in the correct directory */
++#ifdef AUTO_EXPAND
++    if (strlen(path)) Chvdir(path);
++#else
++    if (strlen(path)) chdir(path);
++#endif
++
++    if (ISPIPE(filename[0])) {   /* do piping */
++	/* make up some bogus temp file to put this in */
++#ifndef VMS
++	sprintf(outFName, "%s/xvXXXXXX", tmpdir);
++#else
++	strcpy(outFName, "[]xvXXXXXX.lis");
++#endif
++#ifdef USE_MKSTEMP
++	fp = fdopen(mkstemp(outFName), "w");
++#else
++	mktemp(outFName);
++#endif
++	dopipe = 1;
++    }
++
++
++    /* see if file exists (i.e., we're overwriting) */
++    *append = 0;
++#ifdef USE_MKSTEMP
++    if (!dopipe)
++#endif
++    if (stat(outFName, &st)==0) {    /* stat succeeded, file must exist */
++	if (ReadFileType(outFName) != RFT_PIC2) {
++	    static const char *labels[] = { "\nOk", "\033Cancel" };
++	    char               str[512];
++
++	    sprintf(str,"Overwrite existing file '%s'?", outFName);
++	    if (PopUp(str, labels, 2))
++		return (NULL);
++	} else {
++	    static const char *labels[] = { "\nOk", "\033Cancel" };
++	    char               str[512];
++
++	    sprintf(str,"Append to existing file '%s'?", outFName);
++	    if (PopUp(str, labels, 2)) {
++		sprintf(str,"Overwrite existing file '%s'?", outFName);
++		if (PopUp(str, labels, 2))
++		    return (NULL);
++	    } else
++		*append = 1;
++	}
++    }
++
++    /* Open file */
++#ifdef USE_MKSTEMP
++    if (!dopipe)
++#endif
++    fp = *append ? fopen(outFName, "r+") : fopen(outFName, "w");
++    if (!fp) {
++	char  str[512];
++	sprintf(str,"Can't write file '%s'\n\n  %s.",outFName, ERRSTR(errno));
++	ErrPopUp(str, "\nBummer");
++	return (NULL);
++    }
++
++    return (fp);
++}
++
++
++/***************************************/
++void pic2_KillNullFile(fp)
++FILE *fp;
++{
++    fseek(fp, (size_t) 0, SEEK_END);
++    if (ftell(fp) > 0) {
++	fclose(fp);
++	return;
++    } else {
++	fclose(fp);
++	unlink(outFName);
++	return;
++    }
++}
++#endif /* HAVE_PIC2 */
++
++
++#ifdef HAVE_MGCSFX
++/**** Stuff for MGCSFX Dialog box ****/
++/***************************************/
++int OpenOutFileDesc(filename)
++     char *filename;
++{
++  /* opens file for output.  does various error handling bits.  Returns
++     an open file pointer if success, NULL if failure */
++
++  int         fd;
++  struct stat st;
++
++  if (!filename || filename[0] == '\0') return -1;
++  strcpy(outFName, filename);
++  dopipe = 0;
++
++  /* make sure we're in the correct directory */
++#ifdef AUTO_EXPAND
++  if (strlen(path)) Chvdir(path);
++#else
++  if (strlen(path)) chdir(path);
++#endif
++
++  if (ISPIPE(filename[0])) {   /* do piping */
++    /* make up some bogus temp file to put this in */
++#ifndef VMS
++    sprintf(outFName, "%s/xvXXXXXX", tmpdir);
++#else
++    strcpy(outFName, "[]xvXXXXXX.lis");
++#endif
++#ifdef USE_MKSTEMP
++    close(mkstemp(outFName));
++#else
++    mktemp(outFName);
++#endif
++    dopipe = 1;
++  }
++
++
++  /* if didn't just create it, see if file exists (i.e., we're overwriting) */
++  if (!dopipe && stat(outFName, &st)==0) {   /* stat succeeded, file exists */
++    static const char *labels[] = { "\nOk", "\033Cancel" };
++    char               str[512];
++
++    sprintf(str,"Overwrite existing file '%s'?", outFName);
++    if (PopUp(str, labels, 2)) return -1;
++  }
++
++
++  /* Open file */
++  fd = open(outFName, O_WRONLY | O_CREAT | O_TRUNC, (0644));
++  if (fd < 0) {
++    char  str[512];
++    sprintf(str,"Can't write file '%s'\n\n  %s.", outFName, ERRSTR(errno));
++    ErrPopUp(str, "\nBummer");
++    return -1;
++  }
++
++  return fd;
++}
++#endif /* HAVE_MGCSFX */
+diff -ru xv-3.10a/xvevent.c xv-3.10a-enhancements/xvevent.c
+--- xv-3.10a/xvevent.c	1995-01-23 15:20:24.000000000 -0800
++++ xv-3.10a-enhancements/xvevent.c	2007-05-12 15:27:11.000000000 -0700
+@@ -39,8 +39,15 @@
+ static Cursor dropper = 0, pen = 0, blur = 0;
+ 
+ 
++static void SelectDispMB       PARM((int));
++static void Select24to8MB      PARM((int));
++static void SelectRootMB       PARM((int));
++static void SelectWindowMB     PARM((int));
++static void SelectSizeMB       PARM((int));
++
++static void DoPrint            PARM((void));
+ static void debugEvent         PARM((XEvent *));
+-static char *win2name          PARM((Window));
++static const char *win2name    PARM((Window));
+ static void handleButtonEvent  PARM((XEvent *, int *, int *));
+ static void handleKeyEvent     PARM((XEvent *, int *, int *));
+ static void zoomCurs           PARM((u_int));
+@@ -64,6 +71,8 @@
+ 
+ static void   annotatePic      PARM((void));
+ 
++static int    debkludge_offx;
++static int    debkludge_offy;
+ 
+ /****************/
+ int EventLoop()
+@@ -71,13 +80,25 @@
+ {
+   XEvent event;
+   int    retval,done,waiting;
+-  time_t orgtime, curtime;
++#ifdef USE_TICKS
++  clock_t waitsec_ticks=0L, orgtime_ticks=0L, curtime_ticks;
++  clock_t elapsed_ticks=0L, remaining_interval;
++#else
++  time_t orgtime=0L, curtime;
++#endif
+ 
+ 
+ #ifndef NOSIGNAL
+   signal(SIGQUIT, onInterrupt);
+ #endif
+ 
++  if (startGrab == 1) {
++     startGrab = 2;
++     FakeButtonPress(&but[BGRAB]);
++     FakeKeyPress(ctrlW, XK_Return);
++     return(1);
++  }
++
+   /* note: there's no special event handling if we're using the root window.
+      if we're using the root window, we will recieve NO events for mainW */
+ 
+@@ -100,18 +121,24 @@
+ 
+   while (!done) {
+ 
+-    if (waitsec > -1 && canstartwait && !waiting && XPending(theDisp)==0) {
+-      /* we wanna wait, we can wait, we haven't started waiting yet, and 
+-	 all pending events (ie, drawing the image the first time) 
++    if (waitsec >= 0.0 && canstartwait && !waiting && XPending(theDisp)==0) {
++      /* we wanna wait, we can wait, we haven't started waiting yet, and
++	 all pending events (ie, drawing the image the first time)
+ 	 have been dealt with:  START WAITING */
+-      time((time_t *) &orgtime);
++#ifdef USE_TICKS
++      waitsec_ticks = (clock_t)(waitsec * CLK_TCK);
++      orgtime_ticks = times(NULL);  /* unclear if NULL valid, but OK on Linux */
++#else
++      orgtime = time(NULL);
++#endif
+       waiting = 1;
+     }
+ 
+ 
+-    /* if there's an XEvent pending *or* we're not doing anything 
++    /* if there's an XEvent pending *or* we're not doing anything
+        in real-time (polling, flashing the selection, etc.) get next event */
+-    if ((waitsec==-1 && !polling && !HaveSelection()) || XPending(theDisp)>0) {
++    if ((waitsec<0.0 && !polling && !HaveSelection()) || XPending(theDisp)>0)
++    {
+       XNextEvent(theDisp, &event);
+       retval = HandleEvent(&event,&done);
+     }
+@@ -121,7 +148,7 @@
+ 	DrawSelection(0);
+ 	DrawSelection(1);
+ 	XFlush(theDisp);
+-	Timer(200);
++	Timer(200);             /* milliseconds */
+       }
+ 
+       if (polling) {
+@@ -129,13 +156,32 @@
+ 	else if (!XPending(theDisp)) sleep(1);
+       }
+ 
+-      if (waitsec>-1 && waiting) {
+-	time((time_t *) &curtime);
+-	if (curtime - orgtime < waitsec) sleep(1);
+-	else {
+-	  if (waitloop) return NEXTLOOP;
+-	  else return NEXTQUIT;
+-	}
++      if (waitsec>=0.0 && waiting) {
++#ifdef USE_TICKS
++        curtime_ticks = times(NULL);   /* value in ticks */
++        if (curtime_ticks < orgtime_ticks) {
++          /* clock ticks rolled over:  need to correct for that (i.e.,
++           *  curtime_ticks is presumably quite small, while orgtime_ticks
++           *  should be close to LONG_MAX, so do math accordingly--any way
++           *  to check whether clock_t is *not* a signed long?) */
++          elapsed_ticks = curtime_ticks + (LONG_MAX - orgtime_ticks);
++        } else
++          elapsed_ticks = curtime_ticks - orgtime_ticks;
++        remaining_interval = waitsec_ticks - elapsed_ticks;
++        if (remaining_interval >= (clock_t)(1 * CLK_TCK))
++          sleep(1);
++        else {
++          /* less than one second remaining:  do delay in msec, then return */
++          Timer((remaining_interval * 1000L) / CLK_TCK);  /* can't overflow */
++          return waitloop? NEXTLOOP : NEXTQUIT;
++        }
++#else
++        curtime = time(NULL);          /* value in seconds */
++	if (curtime - orgtime < (time_t)waitsec)
++          sleep(1);
++	else
++          return waitloop? NEXTLOOP : NEXTQUIT;
++#endif
+       }
+     }
+   }  /* while (!done) */
+@@ -154,7 +200,27 @@
+      int    *donep;
+ {
+   static int wasInfoUp=0, wasCtrlUp=0, wasDirUp=0, wasGamUp=0, wasPsUp=0;
+-  static int wasJpegUp=0, wasTiffUp=0;
++#ifdef HAVE_JPEG
++  static int wasJpegUp=0;
++#endif
++#ifdef HAVE_JP2K
++  static int wasJp2kUp=0;
++#endif
++#ifdef HAVE_TIFF
++  static int wasTiffUp=0;
++#endif
++#ifdef HAVE_PNG
++  static int wasPngUp=0;
++#endif
++#ifdef HAVE_PCD
++  static int wasPcdUp=0;
++#endif
++#ifdef HAVE_PIC2
++  static int wasPic2Up=0;
++#endif
++#ifdef HAVE_MGCSFX
++  static int wasMgcSfxUp=0;
++#endif
+ 
+   static int mainWKludge=0;  /* force first mainW expose after a mainW config
+ 				to redraw all of mainW */
+@@ -187,7 +253,7 @@
+ 
+ #ifdef VMS
+     static int borders_sized = 0;
+-  
++
+     if (!borders_sized  && !useroot && exp_event->window == mainW) {
+       /*
+        * Initial expose of main window, find the size of the ancestor
+@@ -198,13 +264,13 @@
+       int status, count, mwid, mhgt, x, y, w, h, b, d, mbrd;
+       Window root, parent, *children, crw = exp_event->window;
+       borders_sized = 1;
+-      status = XGetGeometry(theDisp, crw, 
++      status = XGetGeometry(theDisp, crw,
+ 			    &root, &x, &y, &mwid, &mhgt, &mbrd, &d);
+-      
++
+       for ( parent = crw, w=mwid, h=mhgt;
+ 	   status && (parent != root) && (parent != vrootW); ) {
+ 	crw = parent;
+-	status = XQueryTree ( theDisp, crw, &root, &parent, 
++	status = XQueryTree ( theDisp, crw, &root, &parent,
+ 			     &children, &count );
+ 	if ( children != NULL ) XFree ( children );
+       }
+@@ -221,7 +287,7 @@
+     win = exp_event->window;
+     x = exp_event->x;      y = exp_event->y;
+     w = exp_event->width;  h = exp_event->height;
+-    
++
+     if (PUCheckEvent  (event)) break;   /* event has been processed */
+     if (PSCheckEvent  (event)) break;   /* event has been processed */
+ 
+@@ -229,16 +295,42 @@
+     if (JPEGCheckEvent(event)) break;   /* event has been processed */
+ #endif
+ 
++#ifdef HAVE_JP2K
++    if (JP2KCheckEvent(event)) break;   /* event has been processed */
++#endif
++
+ #ifdef HAVE_TIFF
+     if (TIFFCheckEvent(event)) break;   /* event has been processed */
+ #endif
+ 
++#ifdef HAVE_PNG
++    if (PNGCheckEvent (event)) break;   /* event has been processed */
++#endif
++
++    if (PCDCheckEvent(event)) break;    /* event has been processed */
++
++#ifdef HAVE_PIC2
++    if (PIC2CheckEvent(event)) break;   /* event has been processed */
++#endif
++
++#ifdef HAVE_PCD
++    if (PCDCheckEvent (event)) break;   /* event has been processed */
++#endif
++
++#ifdef HAVE_MGCSFX
++    if (MGCSFXCheckEvent(event)) break; /* event has been processed */
++#endif
++
++#ifdef TV_MULTILINGUAL
++    if (CharsetCheckEvent(event)) break; /* event has been processed */
++#endif
++
+     if (GamCheckEvent (event)) break;   /* event has been processed */
+     if (BrowseCheckEvent (event, &retval, &done)) break;   /* event eaten */
+     if (TextCheckEvent   (event, &retval, &done)) break;   /* event eaten */
+ 
+     /* if the window doesn't do intelligent redraw, drop but last expose */
+-    if (exp_event->count>0 && 
++    if (exp_event->count>0 &&
+ 	win != mainW && win != ctrlW &&	win != dirW && win != infoW) break;
+ 
+ 
+@@ -301,7 +393,7 @@
+ 	  if (DEBUG) fprintf(stderr,"No configs pending.\n");
+ 	  /* if (DEBUG) XClearArea(theDisp, mainW, x,y,w,h, False); */
+ 	  DrawWindow(x,y,w,h);
+-	    
++
+ 	  if (HaveSelection()) DrawSelection(0);
+ 
+ 	  canstartwait = 1;  /* finished drawing */
+@@ -314,7 +406,7 @@
+       else if (win == infoW)          RedrawInfo(x,y,w,h);
+       else if (win == ctrlW)          RedrawCtrl(x,y,w,h);
+       else if (win == dirW)           RedrawDirW(x,y,w,h);
+-      
++
+       XSetClipMask(theDisp, theGC, None);
+       XDestroyRegion(reg);
+     }
+@@ -324,10 +416,10 @@
+     else if (win == dList.win)      LSRedraw(&dList,0);
+     else if (win == dList.scrl.win) SCRedraw(&dList.scrl);
+     else if (win == dnamW)          RedrawDNamW();
+-  }      
++  }
+     break;
+ 
+-    
++
+ 
+   case ClientMessage: {
+     Atom proto, delwin;
+@@ -344,6 +436,9 @@
+ 
+       if (BrowseDelWin(client_event->window)) break;
+       if (TextDelWin(client_event->window)) break;
++#ifdef TV_MULTILINGUAL
++      if (CharsetDelWin(client_event->window)) break;
++#endif
+ 
+       if      (client_event->window == infoW) InfoBox(0);
+       else if (client_event->window == gamW)  GamBox(0);
+@@ -355,10 +450,32 @@
+       else if (client_event->window == jpegW) JPEGDialog(0);
+ #endif
+ 
++#ifdef HAVE_JP2K
++      else if (client_event->window == jp2kW) JP2KDialog(0);
++#endif
++
+ #ifdef HAVE_TIFF
+       else if (client_event->window == tiffW) TIFFDialog(0);
+ #endif
+ 
++#ifdef HAVE_PNG
++      else if (client_event->window == pngW)  PNGDialog(0);
++#endif
++
++      else if (client_event->window == pcdW)  PCDDialog(0);
++
++#ifdef HAVE_PIC2
++      else if (client_event->window == pic2W) PIC2Dialog(0);
++#endif
++
++#ifdef HAVE_PCD
++      else if (client_event->window == pcdW)  PCDDialog(0);
++#endif
++
++#ifdef HAVE_MGCSFX
++      else if (client_event->window == mgcsfxW) MGCSFXDialog(0);
++#endif
++
+       else if (client_event->window == mainW) Quit(0);
+     }
+   }
+@@ -381,31 +498,35 @@
+     if (win==ctrlW || win==gamW || win==infoW || win==mainW || win==dirW) {
+       XSizeHints hints;
+ 
++#define BAD_IDEA
++#ifdef BAD_IDEA
+       /*
+-       * if there's a virtual window manager running (e.g. tvtwm / olvwm), 
+-       * we're going to get 'cevt' values in terms of the 
++       * if there is a virtual window manager running (e.g., tvtwm / olvwm),
++       * we're going to get 'cevt' values in terms of the
+        * 'real' root window (the one that is the size of the screen).
+        * We'll want to translate them into values that are in terms of
+        * the 'virtual' root window (the 'big' one)
+        */
+ 
+       if (vrootW != rootW) {
+-	int x1,y1;  Window child;
++	int x1,y1;
++	Window child;
+ 
+-	XTranslateCoordinates(theDisp, rootW, vrootW, cevt->x, cevt->y, 
++	XTranslateCoordinates(theDisp, rootW, vrootW, cevt->x, cevt->y,
+ 			      &x1, &y1, &child);
+ 	if (DEBUG) fprintf(stderr,"  CONFIG trans %d,%d root -> %d,%d vroot\n",
+ 			   cevt->x, cevt->y, x1, y1);
+ 	cevt->x = x1;  cevt->y = y1;
+       }
++#endif
+ 
+ #ifndef VMS
+       /* read hints for this window and adjust any position hints, but
+-         only if this is a 'synthetic' event sent to us by the WM 
++         only if this is a 'synthetic' event sent to us by the WM
+ 	 ('real' events from the server have useless x,y info, since the
+ 	 mainW has been reparented by the WM) */
+ 
+-      if (cevt->send_event && 
++      if (cevt->send_event &&
+ 	  XGetNormalHints(theDisp, cevt->window, &hints)) {
+ 
+ 	if (DEBUG) fprintf(stderr,"  CONFIG got hints (0x%x  %d,%d)\n",
+@@ -439,11 +560,11 @@
+        * This sucks!
+        *
+        * So, if we have just loaded an image, and we get a Synthetic conf
+-       * that is not the desired size (eWIDExeHIGH), ignore it, as it's 
++       * that is not the desired size (eWIDExeHIGH), ignore it, as it's
+        * just the conf generated by moving the old window.  And stop
+        * ignoring further config events
+        *
+-       * EVIL KLUDGE:  do *not* ignore configs that are <100x100.  Not 
++       * EVIL KLUDGE:  do *not* ignore configs that are <100x100.  Not
+        * ignoring them won't be a big performance problem, and it'll get
+        * around the 'I only got one config in the wrong size' problem when
+        * initially displaying small images
+@@ -453,7 +574,7 @@
+ 
+ /* fprintf(stderr,"***mainw, ignore=%d, send_event=%d, evtSize=%d,%d, size=%d,%d\n", ignoreConfigs, cevt->send_event, cevt->width, cevt->height, eWIDE, eHIGH); */
+ 
+-      if (ignoreConfigs==1 && cevt->send_event && 
++      if (ignoreConfigs==1 && cevt->send_event &&
+ 	  (cevt->width != eWIDE || cevt->height != eHIGH)) {
+ 	ignoreConfigs=0;        /* ignore this one only */
+ 	break;
+@@ -470,7 +591,7 @@
+ 	else {
+ 	  XEvent xev;
+ 	  if (DEBUG) fprintf(stderr,"No configs pend.");
+-	  
++
+ 	  if (cevt->width == eWIDE && cevt->height == eHIGH) {
+ 	    if (DEBUG) fprintf(stderr,"No redraw\n");
+ 	  }
+@@ -478,12 +599,12 @@
+ 	    if (DEBUG) fprintf(stderr,"Do full redraw\n");
+ 
+ 	    Resize(cevt->width, cevt->height);
+-	    
++
+ 	    /* eat any pending expose events and do a full redraw */
+ 	    while (XCheckTypedWindowEvent(theDisp, mainW, Expose, &xev)) {
+ 	      XExposeEvent *exp = (XExposeEvent *) &xev;
+ 
+-	      if (DEBUG) 
++	      if (DEBUG)
+ 		fprintf(stderr,"  ate expose (%s) (count=%d) %d,%d %dx%d\n",
+ 			exp->send_event ? "synth" : "real", exp->count,
+ 			exp->x, exp->y, exp->width, exp->height);
+@@ -508,9 +629,9 @@
+ 
+   }
+     break;
+-	
+ 
+-	
++
++
+   case CirculateNotify:
+   case DestroyNotify:
+   case GravityNotify:       break;
+@@ -534,10 +655,24 @@
+ #ifdef HAVE_JPEG
+ 	if (wasJpegUp) { JPEGDialog(wasJpegUp);  wasJpegUp=0; }
+ #endif
+-
++#ifdef HAVE_JP2K
++	if (wasJp2kUp) { JP2KDialog(wasJpegUp);  wasJp2kUp=0; }
++#endif
+ #ifdef HAVE_TIFF
+ 	if (wasTiffUp) { TIFFDialog(wasTiffUp);  wasTiffUp=0; }
+ #endif
++#ifdef HAVE_PNG
++	if (wasPngUp)  { PNGDialog(wasPngUp);    wasPngUp=0; }
++#endif
++#ifdef HAVE_PCD
++	if (wasPcdUp)  { PCDDialog(wasPcdUp);    wasPcdUp=0; }
++#endif
++#ifdef HAVE_PIC2
++	if (wasPic2Up) { PIC2Dialog(wasPic2Up);  wasPic2Up=0; }
++#endif
++#ifdef HAVE_MGCSFX
++	if (wasMgcSfxUp) { MGCSFXDialog(wasMgcSfxUp);  wasMgcSfxUp=0; }
++#endif
+       }
+     }
+   }
+@@ -554,7 +689,7 @@
+ 
+       /* don't do it if we've just switched to a root mode */
+       if ((unmap_event->window == mainW && dispMode == 0) ||
+-	  (unmap_event->window == ctrlW && dispMode != 0)) {  
++	  (unmap_event->window == ctrlW && dispMode != 0)) {
+ 
+ 	if (autoclose) {
+ 	  if (autoclose>1) autoclose -= 2;  /* grab kludge */
+@@ -572,10 +707,24 @@
+ #ifdef HAVE_JPEG
+ 	  if (jpegUp) { wasJpegUp = jpegUp;  JPEGDialog(0); }
+ #endif
+-
++#ifdef HAVE_JP2K
++	  if (jp2kUp) { wasJp2kUp = jp2kUp;  JP2KDialog(0); }
++#endif
+ #ifdef HAVE_TIFF
+ 	  if (tiffUp) { wasTiffUp = tiffUp;  TIFFDialog(0); }
+ #endif
++#ifdef HAVE_PNG
++	  if (pngUp)  { wasPngUp  = pngUp;   PNGDialog(0); }
++#endif
++#ifdef HAVE_PCD
++	  if (pcdUp)  { wasPcdUp = pcdUp;    PCDDialog(0); }
++#endif
++#ifdef HAVE_PIC2
++	  if (pic2Up) { wasPic2Up = pic2Up;  PIC2Dialog(0); }
++#endif
++#ifdef HAVE_MGCSFX
++	  if (mgcsfxUp) { wasMgcSfxUp = mgcsfxUp;  MGCSFXDialog(0); }
++#endif
+ 	}
+       }
+     }
+@@ -586,8 +735,8 @@
+     XReparentEvent *reparent_event = (XReparentEvent *) event;
+ 
+     if (DEBUG) {
+-      fprintf(stderr,"Reparent: mainW=%x ->win=%x ->ev=%x  ->parent=%x  ", 
+-	      (u_int) mainW,                 (u_int) reparent_event->window, 
++      fprintf(stderr,"Reparent: mainW=%x ->win=%x ->ev=%x  ->parent=%x  ",
++	      (u_int) mainW,                 (u_int) reparent_event->window,
+ 	      (u_int) reparent_event->event, (u_int) reparent_event->parent);
+       fprintf(stderr,"%d,%d\n", reparent_event->x, reparent_event->y);
+     }
+@@ -598,7 +747,7 @@
+ 
+       p_offx = p_offy = 0;          /* topleft correction for WMs titlebar */
+ 
+-      if (ch_offx == 0 && ch_offy == 0) {  
++      if (ch_offx == 0 && ch_offy == 0) {
+ 	/* looks like the user is running MWM or OLWM */
+ 
+ 	XWindowAttributes xwa;
+@@ -609,8 +758,8 @@
+ 
+ 	XSync(theDisp, False);
+ 	XGetWindowAttributes(theDisp, mainW, &xwa);
+-	
+-	if (DEBUG) 
++
++	if (DEBUG)
+ 	  fprintf(stderr,"XGetAttr: mainW %d,%d %dx%d\n", xwa.x, xwa.y,
+ 		  xwa.width, xwa.height);
+ 
+@@ -620,8 +769,8 @@
+ 
+ 	  XSync(theDisp, False);
+ 	  XGetWindowAttributes(theDisp, reparent_event->parent, &xwa);
+-	
+-	  if (DEBUG) 
++
++	  if (DEBUG)
+ 	    fprintf(stderr,"XGetAttr: parent %d,%d %dx%d\n", xwa.x, xwa.y,
+ 		    xwa.width, xwa.height);
+ 	}
+@@ -641,42 +790,75 @@
+ 	p_offy = xwa.y;
+       }
+ 
+-      
++      /* Gather info to keep right border inside */
++      {
++	Window current;
++	Window root_r;
++	Window parent_r;
++	Window *children_r;
++	unsigned int nchildren_r;
++	XWindowAttributes xwa;
++
++	parent_r=mainW;
++	current=mainW;
++	do {
++	  current=parent_r;
++	  XQueryTree(theDisp, current, &root_r, &parent_r,
++		     &children_r, &nchildren_r);
++	  if (children_r!=NULL) {
++	    XFree(children_r);
++	  }
++	} while (parent_r!=root_r && parent_r!=vrootW);
++	XGetWindowAttributes(theDisp, current, &xwa);
++	debkludge_offx = eWIDE-xwa.width+p_offx;
++	debkludge_offy = eHIGH-xwa.height+p_offy;
++      }
++
++#if 0
++      /* FIXME: if we want to do this, we first have to wait for a configure
++       * notify to avoid a race condition because the location might be in-
++       * correct if the window manager does placement after managing the window.
++       */
+       /* move window around a bit... */
+       {
+ 	XWindowAttributes xwa;
++
+ 	GetWindowPos(&xwa);
++	//fprintf(stderr, "RAC: orig window pos %d,%d\n", xwa.x, xwa.y);
++
+ 	xwa.width = eWIDE;  xwa.height = eHIGH;
+-	
++	//fprintf(stderr, "RAC: image size now %d,%d\n", xwa.width, xwa.height);
++
+ 	/* try to keep the damned thing on-screen, if possible */
+-	if (xwa.x + xwa.width  > dispWIDE) xwa.x = dispWIDE - xwa.width;
+-	if (xwa.y + xwa.height > dispHIGH) xwa.y = dispHIGH - xwa.height;
++	if (xwa.x + xwa.width  > vrWIDE) xwa.x = vrWIDE - xwa.width;
++	if (xwa.y + xwa.height > vrHIGH) xwa.y = vrHIGH - xwa.height;
+ 	if (xwa.x < 0) xwa.x = 0;
+ 	if (xwa.y < 0) xwa.y = 0;
+-	
++
++	//fprintf(stderr, "RAC: moving window to %d,%d\n", xwa.x, xwa.y);
+ 	SetWindowPos(&xwa);
+       }
+-
++#endif
+     }
+   }
+     break;
+-    
++
+ 
+   case EnterNotify:
+   case LeaveNotify: {
+     XCrossingEvent *cross_event = (XCrossingEvent *) event;
+     if (cross_event->window == mainW || 0
+ 	/* (cross_event->window == gamW && cmapInGam) */ ) {
+-      
++
+       if (cross_event->type == EnterNotify && cross_event->window == mainW) {
+ 	zoomCurs(cross_event->state);
+       }
+ 
+ 
+-      if (cross_event->type == EnterNotify && LocalCmap && !ninstall) 
++      if (cross_event->type == EnterNotify && LocalCmap && !ninstall)
+ 	XInstallColormap(theDisp,LocalCmap);
+ 
+-      if (cross_event->type == LeaveNotify && LocalCmap && !ninstall) 
++      if (cross_event->type == LeaveNotify && LocalCmap && !ninstall)
+ 	XUninstallColormap(theDisp,LocalCmap);
+     }
+   }
+@@ -685,12 +867,12 @@
+ 
+   case SelectionClear:  break;
+ 
+-  case SelectionRequest: 
++  case SelectionRequest:
+     {
+       XSelectionRequestEvent *xsrevt = (XSelectionRequestEvent *) event;
+       XSelectionEvent  xse;
+ 
+-      if (xsrevt->owner     != ctrlW      || 
++      if (xsrevt->owner     != ctrlW      ||
+ 	  xsrevt->selection != XA_PRIMARY ||
+ 	  xsrevt->target    != XA_STRING) {  /* can't do it. */
+ 	xse.property = None;
+@@ -702,7 +884,7 @@
+ 	if (xse.property != None) {
+           xerrcode = 0;
+ 	  XChangeProperty(theDisp, xsrevt->requestor, xse.property,
+-			  XA_STRING, 8, PropModeReplace, 
++			  XA_STRING, 8, PropModeReplace,
+ 			  (byte *) ((xevPriSel) ? xevPriSel           : "\0"),
+ 			  (int)    ((xevPriSel) ? strlen(xevPriSel)+1 : 1));
+           XSync(theDisp, False);
+@@ -721,9 +903,9 @@
+       XSync(theDisp, False);
+     }
+     break;
+-	
+-      
+-	
++
++
++
+   default: break;		/* ignore unexpected events */
+   }  /* switch */
+ 
+@@ -734,11 +916,11 @@
+ 
+ 
+ /***********************************/
+-void SelectDispMB(i)
++static void SelectDispMB(i)
+      int i;
+ {
+   /* called to handle selection of a dispMB item */
+-  
++
+   if (i<0 || i>=DMB_MAX) return;
+ 
+   if (dispMB.dim[i]) return;    /* disabled */
+@@ -747,36 +929,36 @@
+     if      (i==DMB_RAW)  epicMode = EM_RAW;
+     else if (i==DMB_DITH) epicMode = EM_DITH;
+     else                  epicMode = EM_SMOOTH;
+-    
+-    SetEpicMode();	              
++
++    SetEpicMode();
+     GenerateEpic(eWIDE, eHIGH);
+     DrawEpic();
+     SetCursors(-1);
+   }
+-  
++
+   else if (i==DMB_COLRW) {   /* toggle rw on/off */
+     dispMB.flags[i] = !dispMB.flags[i];
+     allocMode = (dispMB.flags[i]) ? AM_READWRITE : AM_READONLY;
+     ChangeCmapMode(colorMapMode, 1, 0);
+   }
+-  
++
+   else if (i>=DMB_COLNORM && i<=DMB_COLSTDC && !dispMB.flags[i]) {
+     switch (i) {
+-    case DMB_COLNORM:  
+-      ChangeCmapMode(CM_NORMAL, 1, 0);   
+-      defaultCmapMode = CM_NORMAL;    
++    case DMB_COLNORM:
++      ChangeCmapMode(CM_NORMAL, 1, 0);
++      defaultCmapMode = CM_NORMAL;
+       break;
+-    case DMB_COLPERF:  
++    case DMB_COLPERF:
+       ChangeCmapMode(CM_PERFECT,1, 0);
+-      defaultCmapMode = CM_PERFECT;   
++      defaultCmapMode = CM_PERFECT;
+       break;
+-    case DMB_COLOWNC:  
++    case DMB_COLOWNC:
+       ChangeCmapMode(CM_OWNCMAP,1, 0);
+-      defaultCmapMode = CM_OWNCMAP;   
++      defaultCmapMode = CM_OWNCMAP;
+       break;
+-    case DMB_COLSTDC:  
++    case DMB_COLSTDC:
+       ChangeCmapMode(CM_STDCMAP,1, 0);
+-      defaultCmapMode = CM_STDCMAP;   
++      defaultCmapMode = CM_STDCMAP;
+       break;
+     }
+   }
+@@ -784,27 +966,27 @@
+ 
+ 
+ /***********************************/
+-void SelectRootMB(i)
++static void SelectRootMB(i)
+      int i;
+ {
+   /* called to handle selection of a rootMB item */
+-  
++
+   if (i<0 || i>=RMB_MAX) return;
+   if (rootMB.flags[i])   return;
+   if (rootMB.dim[i])     return;
+ 
+   dispMode = i;
+-  
++
+   /* move checkmark */
+   for (i=RMB_WINDOW; i<RMB_MAX; i++) rootMB.flags[i] = 0;
+   rootMB.flags[dispMode] = 1;
+-  
++
+   HandleDispMode();
+ }
+ 
+ 
+ /***********************************/
+-void Select24to8MB(i)
++static void Select24to8MB(i)
+      int i;
+ {
+   if (i<0 || i>=CONV24_MAX) return;
+@@ -818,25 +1000,25 @@
+       else if (i==CONV24_24BIT && state824==1) {
+ 	/* went 24->8->24 */
+ 	char buf[512];
+-	
++
+ 	sprintf(buf,"Warning:  You appear to have taken a 24-bit ");
+ 	strcat(buf, "image, turned it to an 8-bit image, and turned ");
+ 	strcat(buf, "it back into a 24-bit image.  Understand that ");
+ 	strcat(buf, "image data has probably been lost in this ");
+ 	strcat(buf, "transformation.  You *may* want to reload the ");
+ 	strcat(buf, "original image to avoid this problem.");
+-	
++
+ 	ErrPopUp(buf, "\nI Know!");
+-	
++
+ 	state824 = 2;   /* shut up until next image is loaded */
+       }
+     }
+   }
+-  
++
+   else if (i==CONV24_LOCK) {
+     conv24MB.flags[i] = !conv24MB.flags[i];
+   }
+-  
++
+   else if (i>=CONV24_FAST && i<=CONV24_BEST) {
+     conv24 = i;
+     for (i=CONV24_FAST; i<=CONV24_BEST; i++) {
+@@ -847,7 +1029,7 @@
+ 
+ 
+ /***********************************/
+-void SelectWindowMB(i)
++static void SelectWindowMB(i)
+      int i;
+ {
+   if (i<0 || i>=WMB_MAX) return;
+@@ -859,15 +1041,15 @@
+     else chdir(initdir);
+     OpenBrowse();
+     break;
+-    
++
+   case WMB_COLEDIT:  GamBox (!gamUp);   break;
+   case WMB_INFO:     InfoBox(!infoUp);  break;
+-    
+-  case WMB_COMMENT:  
++
++  case WMB_COMMENT:
+     if (!commentUp) OpenCommentText();
+     else CloseCommentText();
+     break;
+-    
++
+   case WMB_TEXTVIEW:  textViewCmd();  break;
+   case WMB_ABOUTXV:   ShowLicense();  break;
+   case WMB_KEYHELP:   ShowKeyHelp();  break;
+@@ -878,7 +1060,7 @@
+ 
+ 
+ /***********************************/
+-void SelectSizeMB(i)
++static void SelectSizeMB(i)
+      int i;
+ {
+   int w,h;
+@@ -892,19 +1074,19 @@
+       double r,wr,hr;
+       wr = ((double) cWIDE) / maxWIDE;
+       hr = ((double) cHIGH) / maxHIGH;
+-      
++
+       r = (wr>hr) ? wr : hr;   /* r is the max(wr,hr) */
+       w = (int) ((cWIDE / r) + 0.5);
+       h = (int) ((cHIGH / r) + 0.5);
+     }
+     else { w = cWIDE;  h = cHIGH; }
+-    
++
+     WResize(w, h);
+     break;
+ 
+   case SZMB_MAXPIC:   WMaximize();  break;
+ 
+-  case SZMB_MAXPECT: 
++  case SZMB_MAXPECT:
+     {
+       int w1,h1;
+       w1 = eWIDE;  h1 = eHIGH;
+@@ -925,24 +1107,24 @@
+     if (h==eHIGH) h++;
+     WResize(w,h);
+     break;
+-    
+-    
++
++
+   case SZMB_SETSIZE:  setSizeCmd();  break;
+   case SZMB_ASPECT:   FixAspect(1, &w, &h);  WResize(w,h);  break;
+ 
+-  case SZMB_4BY3:   
++  case SZMB_4BY3:
+     w = eWIDE;  h = (w * 3) / 4;
+     if (h>maxHIGH) { h = eHIGH;  w = (h*4)/3; }
+     WResize(w,h);
+     break;
+ 
+-  case SZMB_INTEXP:  
++  case SZMB_INTEXP:
+     {
+       /* round  (eWIDE/cWIDE),(eHIGH/cHIGH) to nearest
+ 	 integer expansion/compression values */
+-      
++
+       double w,h;
+-      
++
+       if (eWIDE >= cWIDE) {
+ 	w = ((double) eWIDE) / cWIDE;
+ 	w = floor(w + 0.5);
+@@ -961,7 +1143,7 @@
+ 	}
+ 	w = pick;
+       }
+-      
++
+       if (eHIGH >= cHIGH) {
+ 	h = ((double) eHIGH) / cHIGH;
+ 	h = floor(h + 0.5);
+@@ -980,25 +1162,26 @@
+ 	}
+ 	h = pick;
+       }
+-      
++
+       WResize((int) (w*cWIDE), (int) (h*cHIGH));
+     }
+     break;
+-    
++
+   default: break;
+   }
+ }
+ 
+ 
+ /***********************************/
+-void DoPrint()
++static void DoPrint()
+ {
+   /* pops open appropriate dialog boxes, issues print command */
+ 
+-  int          i;
+-  char         txt[512], str[PRINTCMDLEN + 10];
+-  static char *labels[] = { " Color", " Grayscale", " B/W", "\033Cancel" };
+-  
++  int                i;
++  char               txt[512], str[PRINTCMDLEN + 10];
++  static const char *labels[] = { "\03Color", "\07Grayscale", " B/W", "\033Cancel" };
++                          /* ^B ("\02") already used for moving cursor back */
++
+   strcpy(txt, "Print:  Enter a command that will read a PostScript file ");
+   strcat(txt, "from stdin and print it to the desired printer.\n\n");
+ #ifndef VMS
+@@ -1011,11 +1194,11 @@
+   if (i == 3 || strlen(printCmd)==0) return;   /* CANCEL */
+ 
+   if (dirUp == BLOAD) DirBox(0);
+-  
++
+   SetDirSaveMode(F_FORMAT, F_PS);
+   SetDirSaveMode(F_COLORS, i);
+ 
+-  if (printCmd[0] != '|' && printCmd[0] != '!') 
++  if (printCmd[0] != '|' && printCmd[0] != '!')
+     sprintf(str, "| %s", printCmd);
+   else strcpy(str, printCmd);
+ 
+@@ -1086,11 +1269,11 @@
+   }
+ }
+ 
+-static char *win2name(win)
++static const char *win2name(win)
+      Window win;
+ {
+   static char foo[16];
+-  
++
+   if      (win == mainW)  return "mainW";
+   else if (win == rootW)  return "rootW";
+   else if (win == vrootW) return "vrootW";
+@@ -1106,7 +1289,7 @@
+   }
+ }
+ 
+-	    
++
+ /***********************************/
+ static void handleButtonEvent(event, donep, retvalp)
+   XEvent *event;
+@@ -1127,38 +1310,60 @@
+   case ButtonPress:
+     /* *always* check for pop-up events, as errors can happen... */
+     if (PUCheckEvent  (event)) break;
+-    
++
+     if (autoquit && win == mainW) Quit(0);
+-    
++
+     if (viewonly) break;     /* ignore all other button presses */
+-    
++
+     if (win == mainW && !useroot && showzoomcursor) {
+       DoZoom(x, y, but_event->button);
+       break;
+     }
+-    
++
+     if (PSCheckEvent  (event)) break;
+-    
++
+ #ifdef HAVE_JPEG
+     if (JPEGCheckEvent(event)) break;
+ #endif
+-    
++
++#ifdef HAVE_JP2K
++    if (JP2KCheckEvent(event)) break;
++#endif
++
+ #ifdef HAVE_TIFF
+     if (TIFFCheckEvent(event)) break;
+ #endif
+-    
++
++#ifdef HAVE_PNG
++    if (PNGCheckEvent (event)) break;
++#endif
++
++#ifdef HAVE_PCD
++    if (PCDCheckEvent (event)) break;	/* event has been processed */
++#endif
++
++#ifdef HAVE_PIC2
++    if (PIC2CheckEvent(event)) break;
++#endif
++
++#ifdef HAVE_MGCSFX
++    if (MGCSFXCheckEvent(event)) break;
++#endif
++
++#ifdef TV_MULTILINGUAL
++    if (CharsetCheckEvent(event)) break;
++#endif
++
+     if (GamCheckEvent (event)) break;
+     if (BrowseCheckEvent (event, &retval, &done)) break;
+     if (TextCheckEvent   (event, &retval, &done)) break;
+-    
++
+     switch (but_event->button) {
+-      
+-    case Button1:  
++
++    case Button1:
+       if      (win == mainW) DoSelection(but_event);
+-      
++
+       else if (win == ctrlW) {
+-	int   w,h;
+-	
+ 	if      (MBClick(&dispMB,   x,y)) SelectDispMB  (MBTrack(&dispMB)  );
+ 	else if (MBClick(&conv24MB, x,y)) Select24to8MB (MBTrack(&conv24MB));
+ 	else if (MBClick(&rootMB,   x,y)) SelectRootMB  (MBTrack(&rootMB)  );
+@@ -1170,9 +1375,9 @@
+ 	  if (i>=0) DoAlg(i);
+ 	  break;
+ 	}
+-	
++
+ 	i=ClickCtrl(x,y);
+-	
++
+ 	switch (i) {
+ 	case BNEXT:   retval= NEXTPIC;  done=1;     break;
+ 	case BPREV:   retval= PREVPIC;  done=1;     break;
+@@ -1192,21 +1397,21 @@
+ 	case BROTR:   Rotate(0);                    break;
+ 	case BFLIPH:  Flip(0);                      break;
+ 	case BFLIPV:  Flip(1);                      break;
+-	  
++
+ 	case BCROP:   Crop();                       break;
+ 	case BUNCROP: UnCrop();                     break;
+ 	case BACROP:  AutoCrop();                   break;
+-	  
++
+ 	case BPAD:
+ 	  {
+ 	    int mode, wide, high, opaque, omode;  char *str;
+-	    
++
+ 	    while (PadPopUp(&mode, &str, &wide, &high, &opaque, &omode)==0) {
+-	      if (DoPad(mode, str, wide, high, opaque, omode)) { 
++	      if (DoPad(mode, str, wide, high, opaque, omode)) {
+ 		done = 1;  retval = PADDED;  break;
+ 	      }
+-	    }     
+-	  }  
++	    }
++	  }
+ 	  break;
+ 
+ 	case BANNOT:  annotatePic();                break;
+@@ -1214,85 +1419,127 @@
+ 	case BABOUT:  SelectWindowMB(WMB_ABOUTXV);  break;
+ 	case BXV:     retval = DFLTPIC;  done=1;    break;
+ 	case BQUIT:   retval = QUIT;     done=1;    break;
+-	  
++
+ 	default:      break;
+ 	}
+-	
++
+ 	if (i==BFLIPH || i==BFLIPV) {
+ 	  DrawEpic();
+ 	  SetCursors(-1);
+ 	}
+       }
+-      
++
+       else if (win == nList.win) {
+ 	i=LSClick(&nList,but_event);
+ 	if (curname<0) ActivePrevNext();
+ 	if (i>=0) { done = 1;  retval = i; }
+       }
+-      
++
+       else if (win == nList.scrl.win) SCTrack(&nList.scrl, x, y);
+-      
++
+       else if (win == dirW) {
+ 	i=ClickDirW(x,y);
+-	
++
+ 	switch (i) {
+ 	case S_BOK:   if (dirUp == BLOAD) {
+-	  if (!DirCheckCD()) {
+-	    retval = LOADPIC;
+-	    done=1;
++	    if (!DirCheckCD()) {
++	      retval = LOADPIC;
++	      done=1;
++	    }
++	  }
++	  else if (dirUp == BSAVE) {
++	    DoSave();
+ 	  }
+-	}
+-	else if (dirUp == BSAVE) {
+-	  DoSave();
+-	}
+ 	  break;
+-	  
++
+ 	case S_BCANC: DirBox(0);  break;
+-	  
++
+ 	case S_BRESCAN:
+ 	  WaitCursor();  LoadCurrentDirectory();  SetCursors(-1);
+ 	  break;
+ 	}
+       }
+-      
++
+       else if (win == dList.win) {
+ 	i=LSClick(&dList,but_event);
+ 	SelectDir(i);
+       }
+-      
++
+       else if (win == dList.scrl.win) SCTrack(&dList.scrl, x,y);
+       else if (win == infoW)          InfoBox(0);  /* close info */
+-      
++
+       break;
+-      
+-      
+-    case Button2:  
++
++
++    case Button2:
+       if (win == mainW && !useroot) {
+ 	if (!shift && !DoSelection(but_event)) TrackPicValues(x,y);
+ 	else if (shift) Paint();
+       }
+       break;
+-      
++
+     case Button3:  /* if using root, MUST NOT get rid of ctrlbox. */
+-      if (!shift && !useroot) CtrlBox(!ctrlUp); 
++      if (!shift && !useroot) CtrlBox(!ctrlUp);
+       else if (shift) BlurPaint();
+       break;
+-      
++
++    case Button4:   /* note min vs. max, + vs. - */
++      if (win == ctrlW || win == nList.win || win == nList.scrl.win) {
++	SCRL *sp=&nList.scrl;
++	int  halfpage=sp->page/2;
++
++	if (sp->val > sp->min+halfpage)
++	  SCSetVal(sp,sp->val-halfpage);
++	else
++	  SCSetVal(sp,sp->min);
++      }
++      else if (win ==  dirW || win == dList.win || win == dList.scrl.win) {
++	SCRL *sp=&dList.scrl;
++	int  halfpage=sp->page/2;
++
++	if (sp->val > sp->min+halfpage)
++	  SCSetVal(sp,sp->val-halfpage);
++	else
++	  SCSetVal(sp,sp->min);
++      }
++      break;
++
++    case Button5:   /* note max vs. min, - vs. + */
++      if (win == ctrlW || win == nList.win || win == nList.scrl.win) {
++	SCRL *sp=&nList.scrl;
++	int  halfpage=sp->page/2;
++
++	if (sp->val < sp->max-halfpage)
++	  SCSetVal(sp,sp->val+halfpage);
++	else
++	  SCSetVal(sp,sp->max);
++      }
++      else if (win ==  dirW || win == dList.win || win == dList.scrl.win) {
++	SCRL *sp=&dList.scrl;
++	int  halfpage=sp->page/2;
++
++	if (sp->val < sp->max-halfpage)
++	  SCSetVal(sp,sp->val+halfpage);
++	else
++	  SCSetVal(sp,sp->max);
++      }
++      break;
++
+     default:       break;
+     }
+   }
+-  
++
+   *donep = done;  *retvalp = retval;
+ }
+ 
+-	
++
+ /***********************************/
+ static void handleKeyEvent(event, donep, retvalp)
+   XEvent *event;
+   int    *donep, *retvalp;
+ {
+   /* handles KeyPress and KeyRelease events, called from HandleEvent */
+-  
++
+   XKeyEvent *key_event;
+   KeySym     ks;
+   char       buf[128];
+@@ -1306,26 +1553,26 @@
+   switch (event->type) {
+   case KeyRelease:
+     if (viewonly) break;     /* ignore all user input */
+-    
++
+     stlen = XLookupString(key_event,buf,128,&ks,(XComposeStatus *) NULL);
+     dealt = 0;
+-    
++
+     if (key_event->window == mainW) {
+       u_int foo = key_event->state;
+ 
+-      if (ks == XK_Shift_L   || ks == XK_Shift_R)   
++      if (ks == XK_Shift_L   || ks == XK_Shift_R)
+ 	foo = foo & (u_int) (~ShiftMask);
+-      if (ks == XK_Control_L || ks == XK_Control_R) 
++      if (ks == XK_Control_L || ks == XK_Control_R)
+ 	foo = foo & (u_int) (~ControlMask);
+-      if (ks == XK_Meta_L    || ks == XK_Meta_R)    
++      if (ks == XK_Meta_L    || ks == XK_Meta_R)
+ 	foo = foo & (u_int) (~Mod1Mask);
+-      if (ks == XK_Alt_L     || ks == XK_Alt_R)     
++      if (ks == XK_Alt_L     || ks == XK_Alt_R)
+ 	foo = foo & (u_int) (~Mod1Mask);
+ 
+       zoomCurs(foo);
+     }
+     break;
+-    
++
+ 
+   case KeyPress:
+     svkeystate = key_event->state;
+@@ -1343,11 +1590,11 @@
+     if (PUCheckEvent  (event)) break;          /* always check popups */
+ 
+     if (autoquit && key_event->window == mainW) Quit(0);
+-    
++
+     if (viewonly && !frominterrupt) break;     /* ignore all user input */
+-    
++
+     if (PSCheckEvent  (event)) break;
+-    
++
+     if (key_event->window == mainW) {
+       u_int foo = key_event->state;
+ 
+@@ -1362,20 +1609,43 @@
+     if (JPEGCheckEvent(event)) break;
+ #endif
+ 
++#ifdef HAVE_JP2K
++    if (JP2KCheckEvent(event)) break;
++#endif
++
+ #ifdef HAVE_TIFF
+     if (TIFFCheckEvent(event)) break;
+ #endif
+ 
++#ifdef HAVE_PNG
++    if (PNGCheckEvent (event)) break;
++#endif
++
++    if (PCDCheckEvent (event)) break;
++
++#ifdef HAVE_PIC2
++    if (PIC2CheckEvent(event)) break;
++#endif
++
++#ifdef HAVE_PCD
++    if (PCDCheckEvent (event)) break;
++#endif
++
++#ifdef HAVE_MGCSFX
++    if (MGCSFXCheckEvent(event)) break;
++#endif
++
+     if (GamCheckEvent (event)) break;
+     if (BrowseCheckEvent (event, &retval, &done)) break;
+     if (TextCheckEvent   (event, &retval, &done)) break;
+ 
+ 
+-    /* check for pageup/pagedown, 'p' in main window 
+-       (you can use shift-up or shift-down if no crop rectangle drawn)
+-       (for viewing multipage docs) */
++    /* Support for multi-image files ("multipage docs").  Check for PgUp/PgDn
++       or 'p' in any window but control or directory; PgUp/PgDn are already
++       used to page through the file list in those windows.  If no cropping
++       rectangle is active, shift-Up and shift-Down also work. */
+ 
+-    if (key_event->window == mainW) {
++    if (key_event->window != ctrlW && key_event->window != dirW) {
+       dealt = 1;
+ 
+       ck = CursorKey(ks, shift, 0);
+@@ -1386,7 +1656,7 @@
+ 	else XBell(theDisp,0);
+       }
+ 
+-      else if (ck==CK_PAGEDOWN || 
++      else if (ck==CK_PAGEDOWN ||
+ 	       (ck==CK_DOWN && shift && !but[BCROP].active)) {
+ 	if (strlen(pageBaseName) && numPages>1) {
+ 	  done = 1;  retval = OP_PAGEDN;
+@@ -1396,9 +1666,9 @@
+ 
+       else if (buf[0] == 'p' && stlen>0) {
+ 	if (strlen(pageBaseName) && numPages>1) {
+-	  int  i,j, okay;
+-	  char buf[64], txt[512];
+-	  static char *labels[] = { "\nOk", "\033Cancel" };
++	  int                i,j, okay;
++	  char               buf[64], txt[512];
++	  static const char *labels[] = { "\nOk", "\033Cancel" };
+ 
+ 	  /* ask what page to go to */
+ 	  sprintf(txt, "Go to page number...   (1-%d)", numPages);
+@@ -1429,7 +1699,7 @@
+ 
+       if (dealt) break;
+     }
+-	
++
+ 
+ 
+     /* check for crop rect keys */
+@@ -1468,15 +1738,17 @@
+       if (theList == &dList && dealt) {  /* changed dir selection */
+ 	SelectDir(-1);  /* nothing was double-clicked */
+       }
+-      
++
+       if (dealt) break;
+     }
+ 
+ 
+     /* check dir filename arrows */
+-    ck = CursorKey(ks, shift, 1);
+-    if (key_event->window == dirW && ck==CK_LEFT)  { DirKey('\002'); break; }
+-    if (key_event->window == dirW && ck==CK_RIGHT) { DirKey('\006'); break; }
++    if (key_event->window == dirW) {
++      ck = CursorKey(ks, shift, 1);
++      if (ck==CK_LEFT)  { DirKey('\002'); break; }
++      if (ck==CK_RIGHT) { DirKey('\006'); break; }
++    }
+ 
+ 
+     /* check for preset keys     (meta-1, meta-2, meta-3, meta-4, meta-0)
+@@ -1491,7 +1763,7 @@
+       else if (ks==XK_2) FakeButtonPress(&gbut[G_B2]);
+       else if (ks==XK_3) FakeButtonPress(&gbut[G_B3]);
+       else if (ks==XK_4) FakeButtonPress(&gbut[G_B4]);
+-      else if (ks==XK_r || ks==XK_0) 
++      else if (ks==XK_r || ks==XK_0)
+ 	                 FakeButtonPress(&gbut[G_BRESET]);
+ 
+       else if (ks==XK_x) FakeButtonPress(&but[BCUT]);
+@@ -1521,7 +1793,7 @@
+ 
+       else if (ks==XK_a) FakeButtonPress(&gbut[G_BAPPLY]);
+ 
+-      else if (ks==XK_8) { 
++      else if (ks==XK_8) {
+ 	if (picType==PIC8) Select24to8MB(CONV24_24BIT);
+ 	              else Select24to8MB(CONV24_8BIT);
+       }
+@@ -1530,20 +1802,47 @@
+ 
+       if (dealt) break;
+     }
+-    
++
++    /* Check for function keys */
++    if (key_event->window == ctrlW || key_event->window == mainW) {
++      if (ks >= XK_F1 && ks <= XK_F1 + FSTRMAX - 1) {
++        int fkey = ks - XK_F1;
++        if (fkeycmds[fkey] && fullfname[0]) {
++#define CMDLEN 4096
++          char cmd[CMDLEN];
++          /* If a command begins with '@', we do not reload the current file */
++          int noreload = (fkeycmds[fkey][0] == '@');
++          int x = 0, y = 0, w = 0, h = 0;
++          if (HaveSelection())
++            GetSelRCoords(&x, &y, &w, &h);
++          snprintf(cmd, CMDLEN, fkeycmds[fkey] + noreload, fullfname, x, y, w, h);
++#undef CMDLEN
++          if (DEBUG) fprintf(stderr, "Executing '%s'\n", cmd);
++          WaitCursor();
++          system(cmd);
++          SetCursors(-1);
++          if (!noreload) {
++            retval = RELOAD;
++            done = 1;
++          }
++          break;
++        }
++      }
++    }
++
+     if (!stlen) break;
+-    
++
+     if (key_event->window == dirW) {
+       if (DirKey(buf[0])) XBell(theDisp,0);
+     }
+     else {                               /* commands valid in any window */
+       switch (buf[0]) {
+-	
++
+ 	/* things in dispMB */
+       case 'r':    SelectDispMB(DMB_RAW);           break;
+       case 'd':    SelectDispMB(DMB_DITH);          break;
+       case 's':    SelectDispMB(DMB_SMOOTH);        break;
+-	
++
+ 	/* things in sizeMB */
+       case 'n':    SelectSizeMB(SZMB_NORM);         break;
+       case 'm':    SelectSizeMB(SZMB_MAXPIC);       break;
+@@ -1556,7 +1855,7 @@
+       case 'a':    SelectSizeMB(SZMB_ASPECT);       break;
+       case '4':    SelectSizeMB(SZMB_4BY3);         break;
+       case 'I':    SelectSizeMB(SZMB_INTEXP);       break;
+-	
++
+ 	/* things in windowMB */
+       case '\026':
+       case 'V':    SelectWindowMB(WMB_BROWSE);      break;  /* ^V or V */
+@@ -1565,36 +1864,36 @@
+       case '\003': SelectWindowMB(WMB_COMMENT);     break;  /* ^C */
+       case '\024': SelectWindowMB(WMB_TEXTVIEW);    break;  /* ^T */
+       case '\001': SelectWindowMB(WMB_ABOUTXV);     break;  /* ^A */
+-	
+-	
+-	
++
++
++
+ 	/* buttons in ctrlW */
+       case '\t':
+       case ' ':    FakeButtonPress(&but[BNEXT]);    break;
+-	
++
+       case '\r':
+       case '\n':
+ 	if (nList.selected >= 0 && nList.selected < nList.nstr) {
+-	  done = 1;  retval = nList.selected; 
++	  done = 1;  retval = nList.selected;
+ 	  if (frominterrupt) retval = RELOAD;
+ 	}
+ 	break;
+-	
+-      case '\010':
+-      case '\177': FakeButtonPress(&but[BPREV]);    break;
+-	
+-	
++
++      case '\010': FakeButtonPress(&but[BPREV]);    break;
++
++
+       case '\014': FakeButtonPress(&but[BLOAD]);    break;  /* ^L */
+       case '\023': FakeButtonPress(&but[BSAVE]);    break;  /* ^S */
+       case '\020': FakeButtonPress(&but[BPRINT]);   break;  /* ^P */
++      case '\177':
+       case '\004': FakeButtonPress(&but[BDELETE]);  break;  /* ^D */
+-	
++
+ 	/* BCOPY, BCUT, BPASTE, BCLEAR handled in 'meta' case */
+-	
++
+       case '\007': FakeButtonPress(&but[BGRAB]);    break;  /* ^G */
+-	
++
+ 	/* BUP10, BDN10 handled in sizeMB case */
+-	
++
+       case 'T':    FakeButtonPress(&but[BROTL]);    break;
+       case 't':    FakeButtonPress(&but[BROTR]);    break;
+       case 'h':    FakeButtonPress(&but[BFLIPH]);   break;
+@@ -1604,24 +1903,24 @@
+       case 'C':    FakeButtonPress(&but[BACROP]);   break;
+       case 'P':    FakeButtonPress(&but[BPAD]);     break;
+       case 'A':    FakeButtonPress(&but[BANNOT]);   break;
+-	
++
+ 	/* BABOUT handled in windowMB case */
+-	
++
+       case '\021': /* ^Q */
+       case 'q':    FakeButtonPress(&but[BQUIT]);    break;
+-	
++
+       case '?':    if (!useroot) CtrlBox(!ctrlUp);  break;
+-	
++
+ 	/* things in color editor */
+       case 'R':    FakeButtonPress(&gbut[G_BRESET]);   break;
+       case 'H':    FakeButtonPress(&gbut[G_BHISTEQ]);  break;
+       case 'N':    FakeButtonPress(&gbut[G_BMAXCONT]); break;
+-	
++
+       default:     break;
+       }
+     }
+   }
+-  
++
+   *donep = done;  *retvalp = retval;
+ }
+ 
+@@ -1657,7 +1956,7 @@
+   else name = namelist[i];
+ 
+   TextView(name);
+-  
++
+   if (name != namelist[i]) free(name);
+ }
+ 
+@@ -1668,10 +1967,10 @@
+   /* open 'set size' prompt window, get a string, parse it, and try to
+      set the window size accordingly */
+ 
+-  int   i, arg1, arg2, numargs, pct1, pct2, state, neww, newh;
+-  char  txt[512], buf[64], *sp, ch;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
+-  
++  int                i, arg1, arg2, numargs, pct1, pct2, state, neww, newh;
++  char               txt[512], buf[64], *sp, ch;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++
+   sprintf(txt, "Enter new image display size (ex. '400 x 300'),\n");
+   strcat (txt, "expansion ratio (ex. '75%'),\n");
+   strcat (txt, "or expansion ratios (ex. '200% x 125%'):");
+@@ -1685,7 +1984,7 @@
+ 
+ 
+   /* attempt to parse the string accordingly...
+-   * parses strings of the type: <num> [%] [ x <num> [%] ] 
++   * parses strings of the type: <num> [%] [ x <num> [%] ]
+    * (-ish.  <num> all by itself isn't legal)
+    * there may be any # of spaces between items, including zero
+    */
+@@ -1825,7 +2124,7 @@
+ 
+   if (theImage)
+     XPutImage(theDisp,mainW,theGC,theImage,x,y,x,y, (u_int) w, (u_int) h);
+-  else 
++  else
+     if (DEBUG) fprintf(stderr,"Tried to DrawWindow when theImage was NULL\n");
+ }
+ 
+@@ -1845,12 +2144,14 @@
+     return;
+   }
+ 
++  GetWindowPos(&xwa);
++
+   /* determine if new size goes off edge of screen.  if so move window so it
+      doesn't go off screen */
+-
+-  GetWindowPos(&xwa);
+   if (xwa.x + w > vrWIDE) xwa.x = vrWIDE - w;
+   if (xwa.y + h > vrHIGH) xwa.y = vrHIGH - h;
++  if (xwa.x < 0) xwa.x = 0;
++  if (xwa.y < 0) xwa.y = 0;
+ 
+   if (DEBUG) fprintf(stderr,"%s: resizing window to %d,%d at %d,%d\n",
+ 		     cmd,w,h,xwa.x,xwa.y);
+@@ -1872,7 +2173,7 @@
+     XWindowAttributes xwa;
+     xvbzero((char *) &xwa, sizeof(XWindowAttributes));
+     xwa.x = xwa.y = 0;
+-    xwa.width  = dispWIDE;  
++    xwa.width  = dispWIDE;
+     xwa.height = dispHIGH;
+     SetWindowPos(&xwa);
+   }
+@@ -1898,14 +2199,14 @@
+     rotatesLeft++;
+     XClearWindow(theDisp, mainW);  /* get rid of old bits */
+     GenExpose(mainW, 0, 0, (u_int) eWIDE, (u_int) eHIGH);
+-    { int ew, eh; 
++    { int ew, eh;
+       ew = eWIDE;  eh = eHIGH;
+       WResize(eWIDE, eHIGH);
+       if (ew>maxWIDE || eh>maxHIGH) {   /* rotated pic too big, scale down */
+ 	double r,wr,hr;
+ 	wr = ((double) ew) / maxWIDE;
+ 	hr = ((double) eh) / maxHIGH;
+-	
++
+ 	r = (wr>hr) ? wr : hr;   /* r is the max(wr,hr) */
+ 	ew = (int) ((ew / r) + 0.5);
+ 	eh = (int) ((eh / r) + 0.5);
+@@ -1920,7 +2221,7 @@
+ void WCrop(w,h,dx,dy)
+      int w,h,dx,dy;
+ {
+-  int cx, cy, cw, ch, ex, ey;
++  int ex, ey;
+   XWindowAttributes xwa;
+ 
+   if (useroot) {
+@@ -1931,7 +2232,7 @@
+   else {
+     /* we want to move window to old x,y + dx,dy (in pic coords) */
+     GetWindowPos(&xwa);
+-  
++
+     if (!origcropvalid) {  /* first crop.  remember win pos */
+       origcropvalid = 1;
+       origcropx = xwa.x;
+@@ -1939,7 +2240,7 @@
+     }
+ 
+     CoordC2E(dx, dy, &ex, &ey);
+-    
++
+     xwa.x += ex;  xwa.y += ey;
+     xwa.width = w;  xwa.height = h;
+     GenExpose(mainW, 0, 0, (u_int) eWIDE, (u_int) eHIGH);
+@@ -1974,13 +2275,14 @@
+       xwa.y = origcropy;
+     }
+ 
+-    if (xwa.x + w > vrWIDE) xwa.x = vrWIDE - w;   /* keep on screen */
++    /* keep on screen */
++    if (xwa.x + w > vrWIDE) xwa.x = vrWIDE - w;
+     if (xwa.y + h > vrHIGH) xwa.y = vrHIGH - h;
++    if (xwa.x < 0) xwa.x = 0;
++    if (xwa.y < 0) xwa.y = 0;
+ 
+-    if (xwa.x<0) xwa.x = 0;
+-    if (xwa.y<0) xwa.y = 0;
+     xwa.width = w;  xwa.height = h;
+-    
++
+     if (!useroot) {
+       SetWindowPos(&xwa);
+       GenExpose(mainW, 0, 0, (u_int) eWIDE, (u_int) eHIGH);
+@@ -1995,8 +2297,8 @@
+ XWindowAttributes *xwa;
+ {
+   Window child;
+-  
+-  /* returns the x,y,w,h coords of mainW.  x,y are relative to rootW 
++
++  /* returns the x,y,w,h coords of mainW.  x,y are relative to rootW
+      the border is not included (x,y map to top-left pixel in window) */
+ 
+   /* Get the window width/height */
+@@ -2023,36 +2325,58 @@
+ 
+   /* if we're less than max size in one axis, allow window manager doohickeys
+      on the screen */
+-  
++
+   if (xwa->width  < dispWIDE && xwc.x < p_offx) xwc.x = p_offx;
+   if (xwa->height < dispHIGH && xwc.y < p_offy) xwc.y = p_offy;
+ 
++  /* Try to keep bottom right decorations inside */
++#ifdef CRAP
++  if (xwc.x+eWIDE-debkludge_offx>dispWIDE) {
++    xwc.x=dispWIDE-eWIDE+debkludge_offx;
++    if (xwc.x<0) xwc.x=0;
++  }
++  if (xwc.y+eHIGH-debkludge_offy>dispHIGH) {
++    xwc.y=dispHIGH-eHIGH+debkludge_offy;
++    if (xwc.y<0) xwc.y=0;
++  }
++#else
++  if (xwc.x+eWIDE+p_offx>dispWIDE) {
++    xwc.x=dispWIDE-(eWIDE+debkludge_offx);
++    if (xwc.x<0) xwc.x=0;
++  }
++  if (xwc.y+eHIGH+p_offy>dispHIGH) {
++    xwc.y=dispHIGH-(eHIGH+debkludge_offy);
++    if (xwc.y<0) xwc.y=0;
++  }
++#endif
++
+   xwc.width  = xwa->width;
+   xwc.height = xwa->height;
+ 
+-
++#define BAD_IDEA
+ #ifdef BAD_IDEA
+   /* if there is a virtual window manager running, then we should translate
+      the coordinates that are in terms of 'real' screen into coordinates
+-     that are in terms of the 'virtual' root window 
++     that are in terms of the 'virtual' root window
+      from: Daren W. Latham <dwl at mentat.udev.cdc.com> */
+-  
++
+   if (vrootW != rootW) { /* virtual window manager running */
+     int x1,y1;
+     Window child;
+-    XTranslateCoordinates(theDisp, rootW, vrootW,xwc.x,xwc.y,&x1,&y1,&child);
++
++    XTranslateCoordinates(theDisp, rootW, vrootW, xwc.x, xwc.y, &x1, &y1, &child);
+     if (DEBUG) fprintf(stderr,"SWP: translate: %d,%d -> %d,%d\n",
+-		       xwc.x,xwc.y,x1,y1);
++		       xwc.x, xwc.y, x1, y1);
+     xwc.x = x1;  xwc.y = y1;
+   }
+-#endif  
++#endif
+ 
+ 
+   if (DEBUG) {
+     fprintf(stderr,
+ 	    "SWP: xwa=%d,%d %dx%d xwc=%d,%d %dx%d off=%d,%d bw=%d klg=%d,%d\n",
+ 	    xwa->x, xwa->y, xwa->width, xwa->height,
+-	    xwc.x, xwc.y, xwc.width, xwc.height, p_offx, p_offy, 
++	    xwc.x, xwc.y, xwc.width, xwc.height, p_offx, p_offy,
+ 	    xwa->border_width, kludge_offx, kludge_offy);
+   }
+ 
+@@ -2080,7 +2404,7 @@
+ 
+   /* all non-DXWM window managers (?) */
+   /* Move/Resize the window. */
+-  XConfigureWindow(theDisp, mainW, 
++  XConfigureWindow(theDisp, mainW,
+ 		   CWX | CWY | CWWidth | CWHeight /*| CWBorderWidth*/, &xwc);
+ }
+ 
+@@ -2090,7 +2414,7 @@
+ static void CropKey(dx,dy,grow,crop)
+      int dx,dy,grow,crop;
+ {
+-  int x1,x2,y1,y2,active, ocx, ocy;
++  int ocx, ocy;
+ 
+   if (crop) { /* chop off a pixel from the appropriate edge */
+     int dealt=1;
+@@ -2112,7 +2436,7 @@
+     }
+     return;
+   }
+-      
++
+   if (grow) MoveGrowSelection(0,  0,  dx, dy);
+        else MoveGrowSelection(dx, dy, 0,  0);
+ }
+@@ -2128,7 +2452,7 @@
+   u_long       wh, bl;
+   int          ty, w, ecol, done1;
+   char         foo[128];
+-  char         *str  = 
++  const char   *str  =
+    "8888,8888 = 123,123,123  #123456  (123,123,123 HSV)  [-2345,-2345]";
+ 
+   ecol = 0;  wh = infobg;  bl = infofg;
+@@ -2136,14 +2460,14 @@
+   if (!dropper) {
+     Pixmap      pix, mask;
+     XColor      cfg, cbg;
+-    
++
+     cfg.red = cfg.green = cfg.blue = 0x0000;
+     cbg.red = cbg.green = cbg.blue = 0xffff;
+-    
++
+     pix = MakePix1(rootW, dropper_bits,  dropper_width,  dropper_height);
+     mask= MakePix1(rootW, dropperm_bits, dropperm_width, dropperm_height);
+-    if (pix && mask) 
+-      dropper = XCreatePixmapCursor(theDisp, pix, mask, &cfg, &cbg, 
++    if (pix && mask)
++      dropper = XCreatePixmapCursor(theDisp, pix, mask, &cfg, &cbg,
+ 				    dropper_x_hot, dropper_y_hot);
+     if (pix)  XFreePixmap(theDisp, pix);
+     if (mask) XFreePixmap(theDisp, mask);
+@@ -2151,7 +2475,7 @@
+ 
+   if (dropper) XDefineCursor(theDisp, mainW, dropper);
+ 
+-  /* do a colormap search for black and white if LocalCmap 
++  /* do a colormap search for black and white if LocalCmap
+      and use those colors instead of infobg and infofg */
+ 
+   if (LocalCmap) {
+@@ -2159,7 +2483,7 @@
+ 
+     for (i=0; i<nfcols; i++) ctab[i].pixel = freecols[i];
+     XQueryColors(theDisp,LocalCmap,ctab,nfcols);
+-    
++
+     /* find 'blackest' pixel */
+     cval = 0x10000 * 3;
+     for (i=0; i<nfcols; i++)
+@@ -2176,7 +2500,7 @@
+ 	wh = ctab[i].pixel;
+       }
+   }
+-  
++
+ 
+   XSetFont(theDisp, theGC, monofont);
+   w = XTextWidth(monofinfo, str, (int) strlen(str));
+@@ -2185,7 +2509,7 @@
+                else ty = eHIGH-(monofinfo->ascent + mfinfo->descent)-4;
+ 
+   XSetForeground(theDisp, theGC, bl);
+-  XFillRectangle(theDisp, mainW, theGC, 0, ty, (u_int) w + 8, 
++  XFillRectangle(theDisp, mainW, theGC, 0, ty, (u_int) w + 8,
+ 		 (u_int) (monofinfo->ascent+monofinfo->descent) + 4);
+   XSetForeground(theDisp, theGC, wh);
+   XSetBackground(theDisp, theGC, bl);
+@@ -2198,15 +2522,15 @@
+ 
+     if (!XQueryPointer(theDisp,mainW,&rW,&cW,&rx,&ry,&x,&y,&mask)) continue;
+     if (done1 && !(mask & Button2Mask)) break;    /* button released */
+-    
++
+     CoordE2P(x,y, &px, &py);
+-    RANGE(px,0,pWIDE-1);  
++    RANGE(px,0,pWIDE-1);
+     RANGE(py,0,pHIGH-1);
+-    
++
+     if (px!=ox || py!=oy || !done1) {  /* moved, or firsttime.  erase & draw */
+       double h1, s1, v1;
+       int    rval, gval, bval;
+-      
++
+       if (picType == PIC8) {
+ 	ecol = pix = pic[py * pWIDE + px];
+ 	rval = rcmap[pix];  gval = gcmap[pix];  bval = bcmap[pix];
+@@ -2216,7 +2540,7 @@
+ 	gval = pic[py * pWIDE * 3 + px * 3 + 1];
+ 	bval = pic[py * pWIDE * 3 + px * 3 + 2];
+       }
+-      
++
+       clearR = rval;  clearG = gval;  clearB = bval;
+ 
+       rgb2hsv(rval, gval, bval, &h1, &s1, &v1);
+@@ -2229,8 +2553,8 @@
+ 	      px, py, rval, gval, bval, rval, gval, bval,
+ 	      (int) h1, (int) (s1 * 100), (int) (v1 * 100),
+ 	      px-orgx, py-orgy);
+-      
+-      XDrawImageString(theDisp,mainW,theGC, 4, ty + 2 + monofinfo->ascent, 
++
++      XDrawImageString(theDisp,mainW,theGC, 4, ty + 2 + monofinfo->ascent,
+ 		       foo, (int) strlen(foo));
+       ox = px;  oy = py;
+       done1 = 1;
+@@ -2275,7 +2599,7 @@
+ 
+   /* returns true if there's a config event in which mainW changes size
+      in the event queue */
+-  
++
+   XSync(theDisp, False);
+   foo = 0;
+   XCheckIfEvent(theDisp, &ev, IsConfig, &foo);
+@@ -2328,7 +2652,7 @@
+    *    BadMatch  errors on XGetImage
+    */
+ 
+-  if ((xerrcode == BadAlloc)                                               || 
++  if ((xerrcode == BadAlloc)                                               ||
+       (xerrcode == BadAccess && err->request_code==88 /* X_FreeColors */ ) ||
+       (err->request_code == 113                       /* X_KillClient */ ) ||
+       (xerrcode == BadLength && err->request_code==18 /* X_ChangeProp */ ) ||
+@@ -2361,17 +2685,39 @@
+ {
+   /* but first, if any input-grabbing popups are active, we have to 'cancel'
+      them. */
+-  
++
+   if (psUp) PSDialog(0);      /* close PS window */
+ 
+ #ifdef HAVE_JPEG
+   if (jpegUp) JPEGDialog(0);  /* close jpeg window */
+ #endif
+ 
++#ifdef HAVE_JP2K
++  if (jp2kUp) JP2KDialog(0);  /* close jpeg 2000 window */
++#endif
++
+ #ifdef HAVE_TIFF
+   if (tiffUp) TIFFDialog(0);  /* close tiff window */
+ #endif
+ 
++#ifdef HAVE_PNG
++  if (pngUp) PNGDialog(0);    /* close png window */
++#endif
++
++  if (pcdUp) PCDDialog(0);    /* close pcd window */
++
++#ifdef HAVE_PIC2
++  if (pic2Up) PIC2Dialog(0);  /* close pic2 window */
++#endif
++
++#ifdef HAVE_PCD
++  if (pcdUp)  PCDDialog(0);   /* close pcd window */
++#endif
++
++#ifdef HAVE_MGCSFX
++  if (mgcsfxUp) MGCSFXDialog(0);  /* close mgcsfx window */
++#endif
++
+   ClosePopUp();
+ 
+   /* make the interrupt signal look like a '\n' keypress in ctrlW */
+@@ -2400,14 +2746,14 @@
+   if (!pen) {
+     Pixmap      pix, pmask;
+     XColor      cfg, cbg;
+-    
++
+     cfg.red = cfg.green = cfg.blue = 0x0000;
+     cbg.red = cbg.green = cbg.blue = 0xffff;
+-    
++
+     pix = MakePix1(rootW, pen_bits,  pen_width,  pen_height);
+     pmask= MakePix1(rootW, penm_bits, penm_width, penm_height);
+-    if (pix && pmask) 
+-      pen = XCreatePixmapCursor(theDisp, pix, pmask, &cfg, &cbg, 
++    if (pix && pmask)
++      pen = XCreatePixmapCursor(theDisp, pix, pmask, &cfg, &cbg,
+ 				    pen_x_hot, pen_y_hot);
+     if (pix)   XFreePixmap(theDisp, pix);
+     if (pmask) XFreePixmap(theDisp, pmask);
+@@ -2416,7 +2762,7 @@
+   if (pen) XDefineCursor(theDisp, mainW, pen);
+ 
+ 
+-  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 	       | StructureNotifyMask /* | ButtonPressMask */
+ 	       | KeyReleaseMask | ColormapChangeMask
+ 	       | EnterWindowMask | LeaveWindowMask );
+@@ -2435,7 +2781,7 @@
+ 
+     switch (state) {
+     case 0:               /* initial state:  make sure we do one pixel */
+-      px1 = lx = px;  py1 = ly = py;  
++      px1 = lx = px;  py1 = ly = py;
+       paintPixel(px, py);
+ 
+       if      (nmask & ShiftMask  ) state = 99;
+@@ -2444,7 +2790,7 @@
+       else                          state = 10;
+       break;
+ 
+-      
++
+     case 1:               /* waiting for click */
+       if      (nmask & ShiftMask) state = 99;
+       else if ( mask & Button2Mask) {
+@@ -2459,7 +2805,7 @@
+       }
+       break;
+ 
+-      
++
+     case 10:               /* in freehand drawing mode */
+       if      (nmask & ShiftMask  ) state = 99;
+       else if (nmask & Button2Mask) state = 1;
+@@ -2507,11 +2853,11 @@
+ 	  XSync(theDisp, False);
+ 	  Timer(100);
+ 	}
+-	  
++
+ 	if (nmask & Button2Mask) seenRelease = 1;
+       }
+       break;
+-      
++
+     case 99:              /* EXIT loop:  cleanup */
+       if (line) { /* erase old xor-line */
+ 	paintXLine(lx, ly, px1, py1, 0);
+@@ -2521,11 +2867,11 @@
+       break;
+     }
+   }
+-    
+-  
++
++
+   WaitCursor();
+-  
+-  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++
++  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 	       | StructureNotifyMask | ButtonPressMask
+ 	       | KeyReleaseMask | ColormapChangeMask
+ 	       | EnterWindowMask | LeaveWindowMask );
+@@ -2557,17 +2903,17 @@
+     byte *pp = pic + (y * pWIDE + x) * 3;
+     pp[0] = clearR;  pp[1] = clearG;  pp[2] = clearB;
+   }
+-  
++
+   /* visual feedback */
+   CoordP2E(x,   y,   &ex,  &ey);
+   CoordP2E(x+1, y+1, &ex1, &ey1);
+-  
++
+   ew = ex1-ex;  eh = ey1-ey;
+-  
++
+   if (picType == PIC8) XSetForeground(theDisp, theGC, cols[editColor]);
+   else XSetForeground(theDisp, theGC, RGBToXColor(clearR, clearG, clearB));
+-  
+-  if (ew>0 && eh>0) 
++
++  if (ew>0 && eh>0)
+     XFillRectangle(theDisp,mainW,theGC, ex,ey, (u_int) ew, (u_int) eh);
+ }
+ 
+@@ -2576,29 +2922,46 @@
+ static void paintLine(x,y,x1,y1)
+   int x,y,x1,y1;
+ {
+-  int dx,dy,i,lx,ly,adx,ady;
+-  
+-  dx = x1-x;  dy = y1-y;
+-  adx = abs(dx);  ady = abs(dy);
+-
+-  if (dx == 0 && dy == 0) paintPixel(x,y);
+-
+-  else if (adx > ady) {           /* X is major axis */
+-    for (i=0; i<=adx; i++) {
+-      lx = x + (i * dx + (adx/2)) / abs(dx);
+-      ly = y + (i * dy + (adx/2)) / abs(dx);
+-      paintPixel(lx,ly);
++  int t,dx,dy,d,dd;
++
++  dx = abs(x1-x);  dy = abs(y1-y);
++
++  if (dx >= dy) {                       /* X is major axis */
++    if (x > x1) {
++       t = x; x = x1; x1 = t;
++       t = y; y = y1; y1 = t;
++     }
++    d = dy + dy - dx;
++    dd = y < y1 ? 1 : -1;
++    while (x <= x1) {
++      paintPixel(x,y);
++      if (d > 0) {
++        y += dd;
++        d -= dx + dx;
++      }
++      ++x;
++      d += dy + dy;
+     }
+   }
+ 
+   else {                                /* Y is major axis */
+-    for (i=0; i<=ady; i++) {
+-      lx = x + (i * dx + (ady/2)) / ady;
+-      ly = y + (i * dy + (ady/2)) / ady;
+-      paintPixel(lx,ly);
++    if (y > y1) {
++       t = x; x = x1; x1 = t;
++       t = y; y = y1; y1 = t;
++     }
++    d = dx + dx - dy;
++    dd = x < x1 ? 1 : -1;
++    while (y <= y1) {
++      paintPixel(x,y);
++      if (d > 0) {
++        x += dd;
++        d -= dy + dy;
++      }
++      ++y;
++      d += dx + dx;
+     }
+   }
+-  
++
+ 
+ }
+ 
+@@ -2618,14 +2981,14 @@
+   CoordP2E(x+1,y+1,&tx1,&ty1);
+   ex = tx + (tx1 - tx)/2;
+   ey = ty + (ty1 - ty)/2;
+-  
++
+   CoordP2E(x1,  y1,  &tx, &ty);
+   CoordP2E(x1+1,y1+1,&tx1,&ty1);
+   ex1 = tx + (tx1 - tx)/2;
+   ey1 = ty + (ty1 - ty)/2;
+-  
++
+   if (ex==ex1 && ey==ey1) return;
+-  
++
+   XSetPlaneMask(theDisp, theGC, xorMasks[pntxlcol]);
+   XSetFunction(theDisp, theGC, GXinvert);
+   XDrawLine(theDisp, mainW, theGC, ex, ey, ex1, ey1);
+@@ -2638,10 +3001,8 @@
+ static void BlurPaint()
+ {
+   Window  rW,cW;
+-  int     rx,ry,ox,oy,x,y, px,py, ex,ey, ex1,ey1, ew, eh, done1, dragging;
+-  int     uppedpic;
++  int     rx,ry,ox,oy,x,y, px,py, done1, dragging;
+   u_int   mask;
+-  byte   *pp;
+ 
+   /* blurs pixels in either editCol (PIC8) or clear{R,G,B} (PIC24) until
+      'shift' key is released.  */
+@@ -2653,14 +3014,14 @@
+   if (!blur) {
+     Pixmap      pix, mask;
+     XColor      cfg, cbg;
+-    
++
+     cfg.red = cfg.green = cfg.blue = 0x0000;
+     cbg.red = cbg.green = cbg.blue = 0xffff;
+-    
++
+     pix = MakePix1(rootW, blur_bits,  blur_width,  blur_height);
+     mask= MakePix1(rootW, blurm_bits, blurm_width, blurm_height);
+-    if (pix && mask) 
+-      blur = XCreatePixmapCursor(theDisp, pix, mask, &cfg, &cbg, 
++    if (pix && mask)
++      blur = XCreatePixmapCursor(theDisp, pix, mask, &cfg, &cbg,
+ 				    blur_x_hot, blur_y_hot);
+     if (pix)  XFreePixmap(theDisp, pix);
+     if (mask) XFreePixmap(theDisp, mask);
+@@ -2669,7 +3030,7 @@
+   if (blur) XDefineCursor(theDisp, mainW, blur);
+ 
+ 
+-  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 	       | StructureNotifyMask /* | ButtonPressMask */
+ 	       | KeyReleaseMask | ColormapChangeMask
+ 	       | EnterWindowMask | LeaveWindowMask );
+@@ -2682,12 +3043,12 @@
+     if (!(mask & Button3Mask)) { dragging = 0;  continue; }
+ 
+     CoordE2P(x,y, &px, &py);
+-    
++
+     if (!dragging || (dragging && (px!=ox || py!=oy))) {  /* click or drag */
+       if (!dragging) blurPixel(px,py);
+       else {
+ 	int dx,dy,i,lx,ly;
+-	
++
+ 	dx = px-ox;  dy = py-oy;   /* at least one will be non-zero */
+ 	if (abs(dx) > abs(dy)) {   /* X is major axis */
+ 	  for (i=0; i<=abs(dx); i++) {
+@@ -2707,10 +3068,10 @@
+       done1 = 1;  dragging = 1;  ox = px;  oy = py;
+     }
+   }
+-  
++
+   WaitCursor();
+-  
+-  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask 
++
++  XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
+ 	       | StructureNotifyMask | ButtonPressMask
+ 	       | KeyReleaseMask | ColormapChangeMask
+ 	       | EnterWindowMask | LeaveWindowMask );
+@@ -2731,9 +3092,9 @@
+ {
+   /* returns position of highest set bit in 'ul' as an integer (0-31),
+      or -1 if none */
+-  
++
+   int i;  unsigned long hb;
+-  
++
+   hb = 0x80;  hb = hb << 24;   /* hb = 0x80000000UL */
+   for (i=31; ((ul & hb) == 0) && i>=0;  i--, ul<<=1);
+   return i;
+@@ -2757,7 +3118,7 @@
+ 
+     d = 3*(256*256);  j=0;
+     for (i=0; i<numcols; i++) {
+-      di = ((r-rMap[i]) * (r-rMap[i])) + 
++      di = ((r-rMap[i]) * (r-rMap[i])) +
+ 	   ((g-gMap[i]) + (g-gMap[i])) +
+            ((b-bMap[i]) * (b-bMap[i]));
+       if (i==0 || di<d) { j=i;  d=di; }
+@@ -2771,45 +3132,45 @@
+     if (theVisual->class==TrueColor || theVisual->class==DirectColor) {
+       unsigned long rmask, gmask, bmask;
+       int           rshift, gshift, bshift, cshift, maplen;
+-      
++
+       /* compute various shifting constants that we'll need... */
+-      
++
+       rmask = theVisual->red_mask;
+       gmask = theVisual->green_mask;
+       bmask = theVisual->blue_mask;
+-      
++
+       rshift = 7 - highbit(rmask);
+       gshift = 7 - highbit(gmask);
+       bshift = 7 - highbit(bmask);
+-      
++
+       if (theVisual->class == DirectColor) {
+ 	maplen = theVisual->map_entries;
+ 	if (maplen>256) maplen=256;
+ 	cshift = 7 - highbit((u_long) (maplen-1));
+-	
++
+ 	r = (u_long) directConv[(r>>cshift) & 0xff] << cshift;
+ 	g = (u_long) directConv[(g>>cshift) & 0xff] << cshift;
+ 	b = (u_long) directConv[(b>>cshift) & 0xff] << cshift;
+       }
+-      
+-      
++
++
+       /* shift the bits around */
+       if (rshift<0) r = r << (-rshift);
+       else r = r >> rshift;
+-      
++
+       if (gshift<0) g = g << (-gshift);
+       else g = g >> gshift;
+-      
++
+       if (bshift<0) b = b << (-bshift);
+       else b = b >> bshift;
+-      
++
+       r = r & rmask;
+       g = g & gmask;
+       b = b & bmask;
+-      
++
+       rv =r | g | b;
+     }
+-    
++
+     else {                          /* non-TrueColor/DirectColor visual */
+       if (!ncols)
+ 	rv = ((r + g + b >= 128*3) ? white : black);
+@@ -2820,14 +3181,14 @@
+ 
+   return rv;
+ }
+-      
+-    
++
++
+ /***********************/
+ static void blurPixel(x,y)
+      int x,y;
+ {
+   /* blurs pixel x,y (pic coords) into pic in editColor (PIC8) or clearR,G,B
+-     (PIC24) and does appropriate screen feedback.  Does a 3x3 average 
++     (PIC24) and does appropriate screen feedback.  Does a 3x3 average
+      around the pixel, and replaces it with the average value (PIC24), or
+      the closest existing color to the average value (PIC8) */
+ 
+@@ -2861,7 +3222,7 @@
+   if (picType == PIC8) {  /* find nearest actual color */
+     d = 3*(256*256);  j=0;
+     for (i=0; i<numcols; i++) {
+-      di = ((ar-rMap[i]) * (ar-rMap[i])) + 
++      di = ((ar-rMap[i]) * (ar-rMap[i])) +
+ 	   ((ag-gMap[i]) + (ag-gMap[i])) +
+            ((ab-bMap[i]) * (ab-bMap[i]));
+       if (i==0 || di<d) { j=i;  d=di; }
+@@ -2874,17 +3235,17 @@
+     pp = pic + (y * pWIDE + x) * 3;
+     pp[0] = ar;  pp[1] = ag;  pp[2] = ab;
+   }
+-  
++
+   /* visual feedback */
+   CoordP2E(x,   y,   &ex,  &ey);
+   CoordP2E(x+1, y+1, &ex1, &ey1);
+-  
++
+   ew = ex1-ex;  eh = ey1-ey;
+-  
++
+   if (picType == PIC8) XSetForeground(theDisp, theGC, cols[ac]);
+   else XSetForeground(theDisp, theGC, RGBToXColor(ar, ag, ab));
+-  
+-  if (ew>0 && eh>0) 
++
++  if (ew>0 && eh>0)
+     XFillRectangle(theDisp,mainW,theGC, ex,ey, (u_int) ew, (u_int) eh);
+ }
+ 
+@@ -2895,19 +3256,19 @@
+ /***********************/
+ static void annotatePic()
+ {
+-  int          i, w,h, len;
+-  byte        *cimg;
+-  char         txt[256];
+-  static char  buf[256] = {'\0'};
+-  static char *labels[] = {"\nOk", "\033Cancel" };
++  int                i, w,h, len;
++  byte              *cimg;
++  char               txt[256];
++  static char        buf[256] = {'\0'};
++  static const char *labels[] = {"\nOk", "\033Cancel" };
+ 
+-  sprintf(txt, "Image Annotation:\n\n%s", 
++  sprintf(txt, "Image Annotation:\n\n%s",
+ 	  "Enter string to be placed on image.");
+-  
++
+   i = GetStrPopUp(txt, labels, 2, buf, 256, "", 0);
+   if (i==1 || strlen(buf)==0) return;
+-  
+-  
++
++
+   /* build a 'cimg' array to be pasted on clipboard */
+   w = strlen(buf) * 6 - 1;  h = 9;
+   len = CIMG_PIC8 + w*h;
+diff -ru xv-3.10a/xvfits.c xv-3.10a-enhancements/xvfits.c
+--- xv-3.10a/xvfits.c	1994-12-27 23:43:29.000000000 -0800
++++ xv-3.10a-enhancements/xvfits.c	2007-05-12 15:46:55.000000000 -0700
+@@ -14,7 +14,7 @@
+  * provided "as is" without express or implied warranty.
+  */
+ 
+-
++#define  NEEDSDIR /* for S_IRUSR|S_IWUSR */
+ #include "xv.h"
+ 
+ #define NCARDS    (36)
+@@ -39,17 +39,17 @@
+ static char *fits_block=NULL;
+ 
+ 
+-static int   splitfits  PARM((byte *, char *, int, int, int, char *));
+-static char *ftopen3d   PARM((FITS *, char *, int *, int *, int *, int *));
+-static void  ftclose    PARM((FITS *));
+-static int   ftgbyte    PARM((FITS *, byte *, int));
+-static char *rdheader   PARM((FITS *));
+-static char *wrheader   PARM((FILE *, int, int, char *));
+-static char *rdcard     PARM((char *, char *, DATTYPE, long int *));
+-static void  wrcard     PARM((char *, char *, DATTYPE, int, char *));
+-static int   ftgdata    PARM((FITS *, void *, int));
+-static void  ftfixdata  PARM((FITS *, void *, int));
+-static void  flip       PARM((byte *, int, int));
++static       int   splitfits PARM((byte *, char *, int, int, int, char *));
++static const char *ftopen3d  PARM((FITS *, char *, int *, int *, int *, int *));
++static       void  ftclose   PARM((FITS *));
++static       int   ftgbyte   PARM((FITS *, byte *, int));
++static const char *rdheader  PARM((FITS *));
++static const char *wrheader  PARM((FILE *, int, int, char *));
++static const char *rdcard    PARM((char *, const char *, DATTYPE, long int *));
++static       void  wrcard    PARM((char *, const char *, DATTYPE, int, char *));
++static       int   ftgdata   PARM((FITS *, void *, int));
++static       void  ftfixdata PARM((FITS *, void *, int));
++static       void  flip      PARM((byte *, int, int));
+ 
+ 
+ 
+@@ -63,16 +63,16 @@
+   /* returns '1' on success */
+ 
+   FITS  fs;
+-  int   i, nx, ny, nz, bitpix, np, nrd, ioerror;
++  int   i, nx, ny, nz, bitpix, nrd, ioerror, npixels, bufsize;
+   byte *image;
+-  char *error;
++  const char *error;
+   char  basename[64];
+ 
+   if (fits_block == NULL) {
+     fits_block = (char *) malloc((size_t) BLOCKSIZE);
+     if (!fits_block) FatalError("Insufficient memory for FITS block buffer");
+   }
+-  
++
+   error = ftopen3d(&fs, fname, &nx, &ny, &nz, &bitpix);
+   if (error) {
+     SetISTR(ISTR_WARNING, "%s", error);
+@@ -80,9 +80,15 @@
+   }
+ 
+   if (quick) nz = 1;             /* only load first plane */
+-  np = nx * ny * nz;
++  npixels = nx * ny;
++  bufsize = nz * npixels;
++  if (nx <= 0 || ny <= 0 || npixels/nx != ny || bufsize/nz != npixels) {
++    SetISTR(ISTR_WARNING, "FITS image dimensions out of range (%dx%dx%d)",
++      nx, ny, nz);
++    return 0;
++  }
+ 
+-  image = (byte *) malloc((size_t) np);
++  image = (byte *) malloc((size_t) bufsize);
+   if (!image) FatalError("Insufficient memory for image");
+ 
+   /*
+@@ -90,7 +96,7 @@
+    * to ensure that we get that same scaling for all planes.
+    */
+ 
+-  nrd     = ftgbyte(&fs, image, np);
++  nrd     = ftgbyte(&fs, image, bufsize);
+   ioerror = ferror(fs.fp);
+   ftclose(&fs);
+ 
+@@ -104,33 +110,32 @@
+     return 0;
+   }
+ 
+-  else if (nrd < np) {       /* read partial image */
++  else if (nrd < bufsize) {       /* read partial image */
+     if (ioerror)
+       SetISTR(ISTR_WARNING, "%s", "Truncated FITS file due to I/O error");
+     else
+       SetISTR(ISTR_WARNING, "%s", "Truncated FITS file");
+-    
++
+     { byte *foo;
+-      for (foo=image+nrd; foo<image+np; foo++) *foo=0x80;  /* pad with grey */
++      for (foo=image+nrd; foo<image+bufsize; foo++) *foo=0x80;  /* pad with grey */
+     }
+   }
+ 
+   if (nz > 1) {
+     /* how many planes do we actually have? */
+-    nz = (nrd-1)/(nx*ny) + 1;
++    nz = (nrd-1)/(npixels) + 1;
+ 
+     /* returns how many sub-files created */
+     nz = splitfits(image, fs.comment, nx, ny, nz, basename);
+-    np = nx * ny;
+-    image = (byte *)realloc(image, (size_t) np);  /* toss all but first */
++    image = (byte *)realloc(image, (size_t) npixels);  /* toss all but first */
+   }
+-  
++
+   /* There seems to be a convention that fits files be displayed using
+    * a cartesian coordinate system. Thus the first pixel is in the lower left
+    * corner. Fix this by reflecting in the line y=ny/2.
+    */
+   flip(image, nx, ny);
+-  
++
+   /* Success! */
+   pinfo->pic  = image;
+   pinfo->type = PIC8;
+@@ -149,12 +154,12 @@
+     pinfo->numpages = nz;
+     strcpy(pinfo->pagebname, basename);
+   }
+-  
++
+   return 1;
+-}  
++}
++
+ 
+ 
+-	  
+ /*******************************************/
+ int WriteFITS(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,comment)
+      FILE *fp;
+@@ -164,16 +169,16 @@
+      int   numcols, colorstyle;
+      char *comment;
+ {
+-  int   i, j, np, nend;
++  int   i, j, npixels, nend;
+   byte *ptr;
+-  char *error;
++  const char *error;
+   byte  rgb[256];
+-  
++
+   if (!fits_block) {
+     fits_block = (char *) malloc((size_t) BLOCKSIZE);
+     if (!fits_block) FatalError("Insufficient memory for FITS block buffer");
+   }
+-  
++
+   error = wrheader(fp, w, h, comment);
+   if (error) {
+     SetISTR(ISTR_WARNING, "%s", error);
+@@ -197,12 +202,12 @@
+     }
+   }
+ 
+-  np = w*h;
++  npixels = w*h;
+ 
+   /* nend is the number of padding characters at the end of the last block */
+-  nend = ((np+BLOCKSIZE-1)/BLOCKSIZE)*BLOCKSIZE - np;
++  nend = ((npixels+BLOCKSIZE-1)/BLOCKSIZE)*BLOCKSIZE - npixels;
+   if (nend) for (i=0; i<nend; i++) putc('\0', fp);
+-  
++
+   return 0;
+ }
+ 
+@@ -216,17 +221,16 @@
+      char *basename;
+ {
+   /*
+-   * Given a 3 dimensional FITS image, this splits it up into nz 2-d files.
++   * Given a 3-dimensional FITS image, this splits it up into nz 2-d files.
+    * It returns the number of files actually stored.
+    * If only one file could be written, then no split files are created.
+    * It returns the basename of the split files in bname.
+    * If there was a problem writing files, then a error message will be set.
+    */
+-  
+-  int   i, np=nx * ny, ioerror, nwrt;
++
++  int   i, npixels=nx * ny, nwrt, tmpfd;
+   FILE *fp;
+-  char *error;
+-  byte *work;
++  const char *error;
+   char  filename[70];
+ 
+ #ifndef VMS
+@@ -234,8 +238,12 @@
+ #else
+   sprintf(basename, "Sys$Disk:[]xvpgXXXXXX");
+ #endif
+-  
++
++#ifdef USE_MKSTEMP
++  close(mkstemp(basename));
++#else
+   mktemp(basename);
++#endif
+   if (basename[0] == '\0') {
+     SetISTR(ISTR_WARNING, "%s", "Unable to build temporary filename");
+     return 1;
+@@ -246,28 +254,37 @@
+ 
+   for (i=0; i < nz && !error; i++) {
+     sprintf(filename, "%s%d", basename, i+1);
+-    fp = xv_fopen(filename, "w");
++    tmpfd = open(filename,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR);
++    if (tmpfd < 0) {
++      error = "Unable to open temporary file";
++      break;
++    }
++    fp = fdopen(tmpfd, "w");
+     if (!fp) {
+       error = "Unable to open temporary file";
+       break;
+     }
+-    
++
+     if (wrheader(fp, nx, ny, comment)) {
+       error = "I/O error writing temporary file";
++      fflush(fp);
+       fclose(fp);
+       unlink(filename);
++      close(tmpfd);
+       break;
+     }
+ 
+-    nwrt = fwrite(image+i*np, sizeof(byte), (size_t) np, fp);
++    nwrt = fwrite(image+i*npixels, sizeof(byte), (size_t) npixels, fp);
++    fflush(fp);
+     fclose(fp);
++    close(tmpfd);
+ 
+     if (nwrt == 0) {  /* failed to write any data */
+       error = "I/O error writing temporary file";
+       unlink(filename);
+       break;
+-    } 
+-    else if (nwrt < np)
++    }
++    else if (nwrt < npixels)
+       error = "I/O error writing temporary file";
+   }
+ 
+@@ -285,19 +302,19 @@
+ 
+ 
+ /************************************/
+-static char *wrheader(fp, nx, ny, comment)
++static const char *wrheader(fp, nx, ny, comment)
+      FILE *fp;
+      int nx, ny;
+      char *comment;
+ {
+   /* Writes a minimalist FITS file header */
+-  
++
+   char *block = fits_block, *bp;
+-  int   i, j, wrotehist, lenhist;
++  int   i, j, lenhist;
+   char  history[80];
+ 
+   for (i=0, bp=block; i<BLOCKSIZE; i++, bp++) *bp = ' ';
+-  
++
+   sprintf(history, "Written by XV %s", VERSTR);
+   lenhist = strlen(history);
+ 
+@@ -309,7 +326,7 @@
+   wrcard(&block[80*i++], "NAXIS2", T_INT, ny, NULL);  /* write NAXIS2 card */
+ 
+   /* Write HISTORY keyword */
+-  wrcard(&block[80*i++], "HISTORY", T_STR, lenhist, history); 
++  wrcard(&block[80*i++], "HISTORY", T_STR, lenhist, history);
+ 
+   if (comment && *comment != '\0') {
+     while (*comment == '\n') comment++;  /* Skip any blank lines */
+@@ -317,7 +334,7 @@
+       for (j=0; j<72; j++)
+ 	if (comment[j] == '\0' || comment[j] == '\n') break;
+ 
+-      /* 
++      /*
+        * Check to see if it is an xv history record; if so, then avoid
+        * duplicating it.
+        */
+@@ -330,7 +347,7 @@
+ 	for (i=0, bp=block; i<BLOCKSIZE; i++, bp++) *bp = ' ';
+ 	i = 0;
+       }
+-      
++
+       comment += j;
+       while (*comment == '\n') comment++;  /* Skip any blank lines */
+     }
+@@ -346,7 +363,7 @@
+ 
+ 
+ /************************************/
+-static char *ftopen3d(fs, file, nx, ny, nz, bitpix)
++static const char *ftopen3d(fs, file, nx, ny, nz, bitpix)
+      FITS *fs;
+      char *file;
+      int  *nx, *ny, *nz, *bitpix;
+@@ -358,40 +375,40 @@
+    * Will return an error message if the primary data unit is not a
+    * 2 or 3-dimensional array.
+    */
+-  
++
+   FILE *fp;
+   int naxis, i;
+-  char *error;
+-  
++  const char *error;
++
+   fp = xv_fopen(file, "r");
+   if (!fp) return "Unable to open FITS file";
+-  
++
+   fs->fp     = fp;
+   fs->bitpix = 0;
+   fs->naxis  = 0;
+   fs->cpos   = 0;
+-  
++
+   /* read header */
+   error = rdheader(fs);
+   if (error) {
+     ftclose(fs);
+     return error;
+   }
+-  
++
+   naxis = fs->naxis;
+-  
++
+   /* get number of data */
+   fs->ndata = 1;
+-  for (i=0; i<naxis; i++) 
++  for (i=0; i<naxis; i++)
+     fs->ndata = fs->ndata * fs->axes[i];
+-  
++
+   *nx = fs->axes[0];
+   *ny = fs->axes[1];
+   if (naxis == 2) *nz = 1;
+              else *nz = fs->axes[2];
+-  
++
+   *bitpix = fs->bitpix;
+-  
++
+   return NULL;
+ }
+ 
+@@ -406,7 +423,7 @@
+ 
+ 
+ /************************************/
+-static char *rdheader(fs)
++static const char *rdheader(fs)
+      FITS *fs;
+ {
+   /* reads the fits header, and updates the FITS structure fs.
+@@ -416,13 +433,13 @@
+   int i, j, res, commlen, commsize;
+   char name[9];
+   char *block=fits_block, *p;
+-  char *error;
++  const char *error;
+   long int val;         /* the value */
+-  
++
+   fs->comment = NULL;
+   commlen     = 0;
+   commsize    = 256;
+-  
++
+   res = fread(block, sizeof(char), (size_t) BLOCKSIZE, fs->fp);
+   if (res != BLOCKSIZE) return "Error reading FITS file";
+   i = 0;
+@@ -464,13 +481,13 @@
+       if (res != BLOCKSIZE) return "Error reading FITS file";
+       i = 0;
+     }
+-    
++
+     sprintf(name, "NAXIS%d", j+1);
+     error = rdcard(&block[i*80], name, T_INT, &val);
+     if (error)    return error;
+     if (val < 0)  return "Bad NAXISn value in FITS file";
+     if (val == 0) return "FITS file does not contain an image";
+-    
++
+     if (j < 3)    fs->axes[j] = val;
+     else if (val != 1) return "FITS file has more than three dimensions";
+     i++;
+@@ -488,21 +505,21 @@
+       if (res != BLOCKSIZE) return "Unexpected eof in FITS file";
+       i = 0;
+     }
+-    
++
+     p = &block[i*80];
+     if (strncmp(p, "END     ", (size_t) 8) == 0) break;
+-    if (strncmp(p, "HISTORY ", (size_t) 8) == 0 || 
++    if (strncmp(p, "HISTORY ", (size_t) 8) == 0 ||
+ 	strncmp(p, "COMMENT ", (size_t) 8) == 0) {
+       p += 8;                       /* skip keyword */
+       for (j=71; j >= 0; j--) if (p[j] != ' ') break;
+       j++;                          /* make j length of comment */
+       if (j > 0) {                  /* skip blank comment cards */
+ 	if (fs->comment == NULL) {
+-	  fs->comment = (char *) malloc((size_t) commsize);
++	  fs->comment = (char *) malloc((size_t) commsize);  /* initially 256 */
+ 	  if (fs->comment == NULL)
+ 	    FatalError("Insufficient memory for comment buffer");
+ 	}
+-	
++
+ 	if (commlen + j + 2 > commsize) { /* if too small */
+ 	  char *new;
+ 	  commsize += commsize;      /* double size of array */
+@@ -515,7 +532,7 @@
+ 	  free(fs->comment);
+ 	  fs->comment = new;
+ 	}
+-	
++
+ 	xvbcopy(p, &fs->comment[commlen], (size_t) j);  /* add string */
+ 	commlen += j;
+ 	fs->comment[commlen++] = '\n';       /* with trailing cr */
+@@ -531,7 +548,8 @@
+ 
+ /************************************/
+ static void wrcard(card, name, dtype, kvalue, svalue)
+-     char *card, *name;
++     char *card;
++     const char *name;
+      DATTYPE dtype;   /* type of value */
+      int kvalue;
+      char *svalue;
+@@ -556,9 +574,9 @@
+ 
+   l = strlen(name);
+   if (l) xvbcopy(name, card, (size_t) l);   /* copy name */
+-  
++
+   if (dtype == T_NOVAL) return;
+-  
++
+   if (dtype == T_STR) {
+     l = kvalue;
+     if (l <= 0) return;
+@@ -566,9 +584,9 @@
+     xvbcopy(svalue, &card[8], (size_t) l);
+     return;
+   }
+-  
++
+   card[8] = '=';
+-  
++
+   if (dtype == T_LOG)
+     card[29] = kvalue ? 'T' : 'F';
+   else { /* T_INT */
+@@ -579,8 +597,9 @@
+ 
+ 
+ /************************************/
+-static char *rdcard(card, name, dtype, kvalue)
+-     char *card, *name;
++static const char *rdcard(card, name, dtype, kvalue)
++     char *card;
++     const char *name;
+      DATTYPE dtype;   /* type of value */
+      long int *kvalue;
+ {
+@@ -599,7 +618,7 @@
+   int         i, ptr;
+   char        namestr[9];
+   static char error[45];
+-  
++
+   xvbcopy(card, namestr, (size_t) 8);
+ 
+   for (i=7; i>=0 && namestr[i] == ' '; i--);
+@@ -609,24 +628,24 @@
+     sprintf(error, "Keyword %s not found in FITS file", name);
+     return error;
+   }
+-  
++
+ 
+   /* get start of value */
+   ptr = 10;
+   while (ptr < 80 && card[ptr] == ' ') ptr++;
+   if (ptr == 80) return "FITS file has missing keyword value"; /* no value */
+-  
++
+   if (dtype == T_LOG) {
+     if (ptr != 29 || (card[29] != 'T' && card[29] != 'F'))
+       return "Keyword has bad logical value in FITS file";
+     *kvalue = (card[29] == 'T');
+-  } 
++  }
+ 
+   else {  /* an integer */
+     int j;
+     long int ival;
+     char num[21];
+-    
++
+     if (ptr > 29) return "Keyword has bad integer value in FITS file";
+     xvbcopy(&card[ptr], num, (size_t) (30-ptr));
+     num[30-ptr] = '\0';
+@@ -634,7 +653,7 @@
+     if (j != 1) return "Keyword has bad integer value in FITS file";
+     *kvalue = ival;
+   }
+-  
++
+   return NULL;
+ }
+ 
+@@ -660,13 +679,13 @@
+    */
+ 
+   int res;
+-  
++
+   if (nelem == 0) return 0;
+-  
++
+   res = fread(buffer, (size_t) fs->size, (size_t) nelem, fs->fp);
+   /* if failed to read all the data because at end of file */
+   if (res != nelem && feof(fs->fp)) {
+-    /* nblock is the number of elements in a record. 
++    /* nblock is the number of elements in a record.
+        size is always a factor of BLOCKSIZE */
+ 
+     int loffs, nblock=BLOCKSIZE/fs->size;
+@@ -714,7 +733,7 @@
+   byte *ptr=buffer;
+ 
+   /*
+-   * conversions. Although the data may be signed, reverse using unsigned 
++   * conversions. Although the data may be signed, reverse using unsigned
+    * variables.
+    * Because the native int types may be larger than the types in the file,
+    * we start from the end and work backwards to avoid overwriting data
+@@ -741,12 +760,12 @@
+ 	      ((unsigned int)ptr[2] << 8)  |
+ 	      ((unsigned int)ptr[3]);
+   }
+-  
++
+   /* convert from IEE 754 single precision to native form */
+   else if (fs->bitpix == -32) {
+     int j, k, expo;
+     static float *exps=NULL;
+-    
++
+     if (exps == NULL) {
+       exps = (float *)malloc(256 * sizeof(float));
+       if (exps == NULL) FatalError("Insufficient memory for exps store");
+@@ -754,7 +773,7 @@
+       for (i=151; i < 256; i++) exps[i] = 2.*exps[i-1];
+       for (i=149; i >= 0; i--) exps[i] = 0.5*exps[i+1];
+     }
+-	      
++
+     for (i=0; i < n; i++, ptr+=4) {
+       k = (int)*ptr;
+       j = ((int)ptr[1] << 16) | ((int)ptr[2] << 8) | (int)ptr[3];
+@@ -765,13 +784,13 @@
+     }
+ 
+   }
+-  
++
+   /* convert from IEE 754 double precision to native form */
+   else if (fs->bitpix == -64) {
+     int expo, k, l;
+     unsigned int j;
+     static double *exps=NULL;
+-    
++
+     if (exps == NULL) {
+       exps = (double *)malloc(2048 * sizeof(double));
+       if (exps == NULL) FatalError("Insufficient memory for exps store");
+@@ -779,7 +798,7 @@
+       for (i=1076; i < 2048; i++) exps[i] = 2.*exps[i-1];
+       for (i=1074; i >= 0; i--) exps[i] = 0.5*exps[i+1];
+     }
+-	      
++
+     for (i=0; i < n; i++, ptr+=8) {
+       k = (int)*ptr;
+       j = ((unsigned int)ptr[1] << 24) | ((unsigned int)ptr[2] << 16) |
+@@ -813,23 +832,36 @@
+    */
+ 
+   void *voidbuff;
+-  int i, n, nrd;
++  int i, n, nrd, bufsize, overflow=0;
+ 
+   /* if the data is byte, then read it directly */
+   if (fs->bitpix == 8)
+     return ftgdata(fs, cbuff, nelem);
+-  
++
+   /* allocate a buffer to store the image */
+-  if (fs->bitpix == 16)
+-    voidbuff = (void *)malloc(nelem * sizeof(short int));
+-  else if (fs->bitpix == 32)
+-    voidbuff = (void *)malloc(nelem * sizeof(int));
+-  else
+-    voidbuff = (void *)malloc(nelem * (size_t) fs->size);  /* float, double */
++  if (fs->bitpix == 16) {
++    bufsize = nelem * sizeof(short int);
++    if (bufsize/nelem != (int)sizeof(short int))
++      overflow = 1;
++  } else if (fs->bitpix == 32) {
++    bufsize = nelem * sizeof(int);
++    if (bufsize/nelem != (int)sizeof(short int))
++      overflow = 1;
++  } else {
++    bufsize = nelem * fs->size;  /* float, double */
++    if (bufsize/nelem != fs->size)
++      overflow = 1;
++  }
+ 
++  if (overflow) {
++    SetISTR(ISTR_WARNING, "FITS image dimensions out of range");
++    return 0;
++  }
++
++  voidbuff = (void *)malloc((size_t) bufsize);
+   if (voidbuff == NULL) {
+     char emess[60];
+-    sprintf(emess, "Insufficient memory for raw image of %d bytes", 
++    sprintf(emess, "Insufficient memory for raw image of %d bytes",
+ 	    nelem*fs->size);
+     FatalError(emess);
+   }
+@@ -843,28 +875,28 @@
+     short int *buffer=voidbuff;
+     int max, min, maxmin_t;
+     float scale;
+-    
++
+     min = max = buffer[0];
+     for (i=1; i < n; i++, buffer++) maxmin(*buffer, max, min);
+     scale = (max == min) ? 0. : 255./(float)(max-min);
+-    
++
+     /* rescale and convert */
+     for (i=0, buffer=voidbuff; i < n; i++)
+       cbuff[i] = (byte)(scale*(float)((int)buffer[i]-min));
+-    
++
+     /* convert long int to byte */
+-  } 
++  }
+ 
+   else if (fs->bitpix == 32) {
+     int *buffer=voidbuff;
+     int max, min, maxmin_t;
+     float scale, fmin;
+-    
++
+     min = max = buffer[0];
+     for (i=1; i < n; i++, buffer++) maxmin(*buffer, max, min);
+     scale = (max == min) ? 1. : 255./((double)max-(double)min);
+     fmin = (float)min;
+-    
++
+     /* rescale and convert */
+     if (scale < 255./2.1e9) /* is max-min too big for an int ? */
+       for (i=0, buffer=voidbuff; i < n; i++)
+@@ -872,34 +904,34 @@
+     else /* use integer subtraction */
+       for (i=0, buffer=voidbuff; i < n; i++)
+ 	cbuff[i] = (byte)(scale*(float)(buffer[i]-min));
+-    
+-   
+-  } 
++
++
++  }
+ 
+   /* convert float to byte */
+   else if (fs->bitpix == -32) {
+     float *buffer=voidbuff;
+     float max, min, maxmin_t, scale;
+-    
++
+     min = max = buffer[0];
+     for (i=1; i < n; i++, buffer++) maxmin(*buffer, max, min);
+     scale = (max == min) ? 0. : 255./(max-min);
+-    
++
+     /* rescale and convert */
+     for (i=0, buffer=voidbuff; i < n; i++)
+       cbuff[i] = (byte)(scale*(buffer[i]-min));
+-    
+-  } 
++
++  }
+ 
+   /* convert double to byte */
+   else if (fs->bitpix == -64) {
+     double *buffer=voidbuff;
+     double max, min, maxmin_t, scale;
+-    
++
+     min = max = buffer[0];
+     for (i=1; i < n; i++, buffer++) maxmin(*buffer, max, min);
+     scale = (max == min) ? 0. : 255./(max-min);
+-    
++
+     /* rescale and convert */
+     for (i=0, buffer=voidbuff; i < n; i++)
+       cbuff[i] = (byte)(scale*(buffer[i]-min));
+@@ -923,7 +955,7 @@
+   int i;
+   int j, v;
+   byte *buff1, *buff2;
+-  
++
+   for (i=0; i < ny/2; i++) {
+     buff1 = &buffer[i*nx];
+     buff2 = &buffer[(ny-1-i)*nx];
+diff -ru xv-3.10a/xvgam.c xv-3.10a-enhancements/xvgam.c
+--- xv-3.10a/xvgam.c	1995-01-13 11:51:14.000000000 -0800
++++ xv-3.10a-enhancements/xvgam.c	2007-05-13 14:12:04.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvgam.c
+  *
+  * callable functions:
+@@ -87,7 +87,7 @@
+ 		  GRAF_STATE istate, rstate, gstate, bstate;
+ 		};
+ 
+-static struct gamstate undo[MAXUNDO], preset[4], defstate; 
++static struct gamstate undo[MAXUNDO], preset[4], defstate;
+ static struct gamstate *defLoadState;
+ 
+ static int uptr, uhead, utail;
+@@ -99,7 +99,7 @@
+ 		 int    stval;    /* start of range (ONLY val ifnot range) */
+ 		 int    enval;    /* end of range */
+ 		 int    ccwise;   /* 1 if range goes ccwise, 0 if cwise */
+-		 char  *str;      /* title string */
++		 const char *str; /* title string */
+ 		 u_long fg,bg;    /* colors */
+ 		 int    satval;   /* saturation value on non-range dial */
+ 		 BUTT   hdbutt[N_HDBUTT];
+@@ -122,7 +122,7 @@
+ static int    defAutoApply;
+ static int    hsvnonlinear = 0;
+ 
+-static void printUTime       PARM((char *));
++static void printUTime       PARM((const char *));
+ 
+ static void computeHSVlinear PARM((void));
+ static void changedGam       PARM((void));
+@@ -153,8 +153,8 @@
+ static void dragHueDial      PARM((void));
+ static void dragEditColor    PARM((void));
+ 
+-static void HDCreate         PARM((HDIAL *, Window, int, int, int, int, 
+-				   int, int, char *, u_long, u_long));
++static void HDCreate         PARM((HDIAL *, Window, int, int, int, int,
++				   int, int, const char *, u_long, u_long));
+ 
+ static void HDRedraw         PARM((HDIAL *, int));
+ static int  HDClick          PARM((HDIAL *, int, int));
+@@ -191,10 +191,11 @@
+ 
+ /***************************/
+ static void printUTime(str)
+-     char *str;
++     const char *str;
+ {
+ #ifdef TIMING_TEST
+-  int i;  struct rusage ru;
++  int i;
++  struct rusage ru;
+ 
+   i = getrusage(RUSAGE_SELF, &ru);
+   fprintf(stderr,"%s: utime = %ld.%ld seconds\n",
+@@ -206,19 +207,19 @@
+ 
+ /***************************************************/
+ void CreateGam(geom, gam, rgam, ggam, bgam, defpreset)
+-     char   *geom;
+-     double  gam, rgam, ggam, bgam;
+-     int     defpreset;
++     const char *geom;
++     double      gam, rgam, ggam, bgam;
++     int         defpreset;
+ {
+   XSetWindowAttributes xswa;
+ 
+-  gamW = CreateWindow("xv color editor", "XVcedit", geom, 
++  gamW = CreateWindow("xv color editor", "XVcedit", geom,
+ 		      GAMW, GAMH, infofg,infobg, 0);
+   if (!gamW) FatalError("can't create cedit window!");
+-  
++
+   cmapF = XCreateSimpleWindow(theDisp,gamW, 10,   8,CMAPF_WIDE,CMAPF_HIGH,
+ 			      1,infofg,infobg);
+-  butF  = XCreateSimpleWindow(theDisp,gamW, 10, 336,BUTF_WIDE,BUTF_HIGH, 
++  butF  = XCreateSimpleWindow(theDisp,gamW, 10, 336,BUTF_WIDE,BUTF_HIGH,
+ 			      1,infofg,infobg);
+   modF  = XCreateSimpleWindow(theDisp,gamW, 10, 438,MODF_WIDE,MODF_HIGH,
+ 			      1,infofg,infobg);
+@@ -227,7 +228,7 @@
+   rgbF  = XCreateSimpleWindow(theDisp,gamW, 467,  8,RGBF_WIDE,RGBF_HIGH,
+ 			      1,infofg,infobg);
+ 
+-  if (!cmapF || !butF || !modF || !hsvF || !rgbF) 
++  if (!cmapF || !butF || !modF || !hsvF || !rgbF)
+     FatalError("couldn't create frame windows");
+ 
+ #ifdef BACKING_STORE
+@@ -251,25 +252,25 @@
+   /********** COLORMAP editing doo-wahs ***********/
+ 
+ 
+-  BTCreate(&gbut[G_BCOLUNDO], cmapF, 5, 165, 66, BUTTH, 
++  BTCreate(&gbut[G_BCOLUNDO], cmapF, 5, 165, 66, BUTTH,
+ 	   "ColUndo", infofg, infobg, hicol, locol);
+-  BTCreate(&gbut[G_BCOLREV], cmapF,  5 + 66 + 1, 165, 67, BUTTH, 
++  BTCreate(&gbut[G_BCOLREV], cmapF,  5 + 66 + 1, 165, 67, BUTTH,
+ 	   "Revert", infofg, infobg, hicol, locol);
+-  BTCreate(&gbut[G_BHSVRGB], cmapF,  5+66+67+2,  165, 66, BUTTH, 
++  BTCreate(&gbut[G_BHSVRGB], cmapF,  5+66+67+2,  165, 66, BUTTH,
+ 	   "RGB/HSV", infofg, infobg, hicol, locol);
+ 
+-  BTCreate(&gbut[G_BMONO], cmapF,    5, 189, 66, BUTTH, 
++  BTCreate(&gbut[G_BMONO], cmapF,    5, 189, 66, BUTTH,
+ 	   "Grey", infofg, infobg, hicol, locol);
+-  BTCreate(&gbut[G_BRV],   cmapF,    5 + 66 + 1, 189, 67, BUTTH, 
++  BTCreate(&gbut[G_BRV],   cmapF,    5 + 66 + 1, 189, 67, BUTTH,
+ 	   "RevVid", infofg, infobg, hicol, locol);
+-  BTCreate(&gbut[G_BRNDCOL], cmapF,  5 + 66 + 67 + 2, 189, 66, BUTTH, 
++  BTCreate(&gbut[G_BRNDCOL], cmapF,  5 + 66 + 67 + 2, 189, 66, BUTTH,
+ 	   "Random", infofg, infobg, hicol, locol);
+ 
+-  DCreate(&rhDial, cmapF, 5, 215, 66, 100,   0,360,180, 5, 
++  DCreate(&rhDial, cmapF, 5, 215, 66, 100,   0.0, 360.0, 180.0, 1.0, 5.0,
+ 	  infofg, infobg, hicol, locol, "Hue", NULL);
+-  DCreate(&gsDial, cmapF, 72, 215, 66, 100,  0,360,180, 5, 
++  DCreate(&gsDial, cmapF, 72, 215, 66, 100,  0.0, 360.0, 180.0, 1.0, 5.0,
+ 	  infofg, infobg, hicol, locol, "Sat.", NULL);
+-  DCreate(&bvDial, cmapF, 139, 215, 66, 100,   0,360,180, 5, 
++  DCreate(&bvDial, cmapF, 139, 215, 66, 100, 0.0, 360.0, 180.0, 1.0, 5.0,
+ 	  infofg, infobg, hicol, locol, "Value", NULL);
+ 
+   rhDial.drawobj = gsDial.drawobj = bvDial.drawobj = dragEditColor;
+@@ -291,44 +292,44 @@
+ #define BY2 (BY0 + BYSPACE*2)
+ #define BY3 (BY0 + BYSPACE*3)
+ 
+-  BTCreate(&gbut[G_BAPPLY],  butF, BX0,BY0, 52,BUTTH,"Apply", 
++  BTCreate(&gbut[G_BAPPLY],  butF, BX0,BY0, 52,BUTTH,"Apply",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BNOGAM],  butF, BX0,BY1, 52,BUTTH,"NoMod", 
++  BTCreate(&gbut[G_BNOGAM],  butF, BX0,BY1, 52,BUTTH,"NoMod",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BMAXCONT],butF, BX0,BY2, 52,BUTTH,"Norm",  
++  BTCreate(&gbut[G_BMAXCONT],butF, BX0,BY2, 52,BUTTH,"Norm",
+ 	   infofg,infobg,hicol,locol);
+   BTCreate(&gbut[G_BHISTEQ], butF, BX0,BY3, 52,BUTTH,"HistEq",
+ 	   infofg,infobg,hicol,locol);
+ 
+   BTCreate(&gbut[G_BUP_BR],butF, BX1,BY0, 52,BUTTH,"Brite",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BDN_BR],butF, BX1,BY1, 52,BUTTH,"Dim",  
++  BTCreate(&gbut[G_BDN_BR],butF, BX1,BY1, 52,BUTTH,"Dim",
+ 	   infofg,infobg,hicol,locol);
+   BTCreate(&gbut[G_BUP_CN],butF, BX1,BY2, 52,BUTTH,"Sharp",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BDN_CN],butF, BX1,BY3, 52,BUTTH,"Dull", 
++  BTCreate(&gbut[G_BDN_CN],butF, BX1,BY3, 52,BUTTH,"Dull",
+ 	   infofg,infobg,hicol,locol);
+ 
+-  BTCreate(&gbut[G_BRESET],butF, BX2,   BY0, 52,BUTTH,"Reset", 
++  BTCreate(&gbut[G_BRESET],butF, BX2,   BY0, 52,BUTTH,"Reset",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_B1],    butF, BX2,   BY1, 25,BUTTH,"1",    
++  BTCreate(&gbut[G_B1],    butF, BX2,   BY1, 25,BUTTH,"1",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_B2],    butF, BX2+26,BY1, 26,BUTTH,"2",    
++  BTCreate(&gbut[G_B2],    butF, BX2+26,BY1, 26,BUTTH,"2",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_B3],    butF, BX2,   BY2, 25,BUTTH,"3",    
++  BTCreate(&gbut[G_B3],    butF, BX2,   BY2, 25,BUTTH,"3",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_B4],    butF, BX2+26,BY2, 26,BUTTH,"4",    
++  BTCreate(&gbut[G_B4],    butF, BX2+26,BY2, 26,BUTTH,"4",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BSET],  butF, BX2,   BY3, 52,BUTTH,"Set",  
++  BTCreate(&gbut[G_BSET],  butF, BX2,   BY3, 52,BUTTH,"Set",
+ 	   infofg,infobg,hicol,locol);
+ 
+-  BTCreate(&gbut[G_BUNDO], butF, BX3, BY0, 52,BUTTH,"Undo",   
++  BTCreate(&gbut[G_BUNDO], butF, BX3, BY0, 52,BUTTH,"Undo",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BREDO], butF, BX3, BY1, 52,BUTTH,"Redo",   
++  BTCreate(&gbut[G_BREDO], butF, BX3, BY1, 52,BUTTH,"Redo",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BGETRES],butF,BX3, BY2, 52,BUTTH,"CutRes", 
++  BTCreate(&gbut[G_BGETRES],butF,BX3, BY2, 52,BUTTH,"CutRes",
+ 	   infofg,infobg,hicol,locol);
+-  BTCreate(&gbut[G_BCLOSE],butF, BX3, BY3, 52,BUTTH,"Close",  
++  BTCreate(&gbut[G_BCLOSE],butF, BX3, BY3, 52,BUTTH,"Close",
+ 	   infofg,infobg,hicol,locol);
+ 
+ 
+@@ -338,11 +339,11 @@
+ 
+   CBCreate(&enabCB, modF,2,2,     "Display with HSV/RGB mods.",
+ 	   infofg,infobg,hicol,locol);
+-  CBCreate(&autoCB, modF,2,2+17,  "Auto-apply HSV/RGB mods.",  
++  CBCreate(&autoCB, modF,2,2+17,  "Auto-apply HSV/RGB mods.",
+ 	   infofg,infobg,hicol,locol);
+   CBCreate(&dragCB, modF,2,2+17*2,"Auto-apply while dragging.",
+ 	   infofg,infobg,hicol,locol);
+-  CBCreate(&resetCB,modF,2,2+17*3,"Auto-reset on new image.",  
++  CBCreate(&resetCB,modF,2,2+17*3,"Auto-reset on new image.",
+ 	   infofg,infobg,hicol,locol);
+ 
+   enabCB.val = autoCB.val = resetCB.val = dragCB.val = 1;
+@@ -359,23 +360,23 @@
+ 
+   srcHD.drawobj = dstHD.drawobj = whtHD.drawobj = dragHueDial;
+ 
+-  DCreate(&satDial, hsvF, 100, 199, 100, 121, -100, 100, 0, 5, 
++  DCreate(&satDial, hsvF, 100, 199, 100, 121, -100.0, 100.0, 0.0, 1.0, 5.0,
+ 	   infofg, infobg,hicol,locol, "Saturation", "%");
+ 
+-  hueRB = RBCreate(NULL, hsvF,  7, 153, "1", 
++  hueRB = RBCreate(NULL, hsvF,  7, 153, "1",
+ 		   infofg, infobg,hicol,locol);
+-  RBCreate        (hueRB,hsvF, 47, 153, "2", 
++  RBCreate        (hueRB,hsvF, 47, 153, "2",
+ 		   infofg, infobg,hicol,locol);
+-  RBCreate        (hueRB,hsvF, 87, 153, "3", 
++  RBCreate        (hueRB,hsvF, 87, 153, "3",
+ 		   infofg, infobg,hicol,locol);
+-  RBCreate        (hueRB,hsvF,  7, 170, "4", 
++  RBCreate        (hueRB,hsvF,  7, 170, "4",
+ 		   infofg, infobg,hicol,locol);
+-  RBCreate        (hueRB,hsvF, 47, 170, "5", 
++  RBCreate        (hueRB,hsvF, 47, 170, "5",
+ 		   infofg, infobg,hicol,locol);
+-  RBCreate        (hueRB,hsvF, 87, 170, "6", 
++  RBCreate        (hueRB,hsvF, 87, 170, "6",
+ 		   infofg, infobg,hicol,locol);
+ 
+-  BTCreate(&hueclrB, hsvF, 127, 158, 70, BUTTH, "Reset", 
++  BTCreate(&hueclrB, hsvF, 127, 158, 70, BUTTH, "Reset",
+ 	   infofg, infobg,hicol,locol);
+ 
+   initHmap();
+@@ -394,13 +395,13 @@
+ 
+   InitGraf(&gGraf);
+   CreateGraf(&gGraf, rgbF, 10, 179, infofg, infobg, "Green");
+-  
++
+   InitGraf(&bGraf);
+   CreateGraf(&bGraf, rgbF, 10, 338, infofg, infobg, "Blue");
+ 
+   satDial.drawobj = dragGamma;
+   intGraf.drawobj = rGraf.drawobj = gGraf.drawobj = bGraf.drawobj = dragGamma;
+-  
++
+   SetHSVmode();
+ 
+   ctrls2gamstate(&defstate);
+@@ -415,14 +416,14 @@
+   Str2Graf(&preset[1].rstate,"L 4 : 0,0 : 127,0 : 128,255 : 255,255");
+   Str2Graf(&preset[1].gstate,"L 4 : 0,0 : 127,0 : 128,255 : 255,255");
+   Str2Graf(&preset[1].bstate,"L 4 : 0,0 : 127,0 : 128,255 : 255,255");
+-  
++
+ 
+   /* set up preset2 as a 'temperature' pseudo-color preset */
+   ctrls2gamstate(&preset[2]);
+   Str2Graf(&preset[2].rstate,"S 4 : 0,0 : 105,0 : 155,140 : 255,255");
+   Str2Graf(&preset[2].gstate,"S 5 : 0,0 : 57,135 : 127,255 : 198,135 : 255,0");
+   Str2Graf(&preset[2].bstate,"S 4 : 0,255 : 100,140 : 150,0 : 255,0");
+-  
++
+ 
+   /* set up preset3 as a 'map' pseudo-color preset */
+   ctrls2gamstate(&preset[3]);
+@@ -480,7 +481,7 @@
+ 
+   computeHSVlinear();
+ }
+-  
++
+ 
+ /***************************************************/
+ int GamCheckEvent(xev)
+@@ -492,14 +493,14 @@
+   int rv;
+ 
+   rv = 1;
+-  
++
+   if (xev->type == Expose) {
+     int x,y,w,h;
+     XExposeEvent *e = (XExposeEvent *) xev;
+     x = e->x;  y = e->y;  w = e->width;  h = e->height;
+ 
+     /* throw away excess redraws for 'dumb' windows */
+-    if (e->count > 0 && 
++    if (e->count > 0 &&
+ 	(e->window == satDial.win || e->window == rhDial.win ||
+ 	 e->window == gsDial.win  || e->window == bvDial.win ||
+ 	 e->window == cmapF       || e->window == modF       ||
+@@ -600,7 +601,7 @@
+ 
+ 
+       else if (e->window == hsvF) {
+-	if (HDClick(&srcHD, x,y) || HDClick(&dstHD, x,y)) { 
++	if (HDClick(&srcHD, x,y) || HDClick(&dstHD, x,y)) {
+ 	  dials2hmap();
+ 	  build_hremap();
+ 	  changedGam();
+@@ -654,7 +655,7 @@
+ 	       e->window == gsDial.win ||
+ 	       e->window == bvDial.win) {
+ 
+-	if ((e->window == rhDial.win && DTrack(&rhDial, x,y)) || 
++	if ((e->window == rhDial.win && DTrack(&rhDial, x,y)) ||
+ 	    (e->window == gsDial.win && DTrack(&gsDial, x,y)) ||
+ 	    (e->window == bvDial.win && DTrack(&bvDial, x,y))) {
+ 	  saveCMap(&prevcmap);
+@@ -683,7 +684,7 @@
+     XKeyEvent *e = (XKeyEvent *) xev;
+     char buf[128];  KeySym ks;
+     int stlen;
+-	
++
+     stlen = XLookupString(e,buf,128,&ks,(XComposeStatus *) NULL);
+     buf[stlen] = '\0';
+ 
+@@ -722,7 +723,7 @@
+ 
+   if (whtHD.enabCB.val && whtHD.satval) hsvnonlinear++;
+ 
+-  if (satDial.val != 0) hsvnonlinear++;
++  if (satDial.val != 0.0) hsvnonlinear++;
+ 
+   /* check intensity graf */
+   for (i=0; i<256 && intGraf.func[i]==i; i++);
+@@ -792,7 +793,7 @@
+ int x,y;
+ {
+   XPoint pts[8];
+-  
++
+   pts[0].x = x+10;     pts[0].y = y;
+   pts[1].x = x-4;      pts[1].y = y-100;
+   pts[2].x = x-4;      pts[2].y = y-40;
+@@ -873,11 +874,11 @@
+   XSetForeground(theDisp, theGC, infofg);
+ 
+   if (picType != PIC8) {
+-    CenterString(cmapF, CMAPX + CMAPW/2, CMAPY + CMAPH/2, 
++    CenterString(cmapF, CMAPX + CMAPW/2, CMAPY + CMAPH/2,
+ 		 "No colormap in 24-bit mode.");
+     return;
+   }
+-      
++
+ 
+ 
+   for (i=0; i<numcols; i++) {
+@@ -941,14 +942,14 @@
+     if (bp->win == butF && PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
+   }
+ 
+-  /* if 'Set' is lit, and we didn't click 'set' or 'Reset' or '1'..'4', 
++  /* if 'Set' is lit, and we didn't click 'set' or 'Reset' or '1'..'4',
+      turn it off */
+   if (i!=G_BSET && i!=G_B1 && i!=G_B2 && i!=G_B3 && i!=G_B4 && i!=G_BRESET
+       && gbut[G_BSET].lit) {
+-    gbut[G_BSET].lit = 0;  
++    gbut[G_BSET].lit = 0;
+     BTRedraw(&gbut[G_BSET]);
+   }
+-  
++
+ 
+   if (i<G_NBUTTS) {  /* found one */
+     if (BTTrack(bp)) doCmd(i);
+@@ -1003,7 +1004,7 @@
+       } /* if i<numcols */
+     } /* if but==1 */
+ 
+-    
++
+     else if (but==2) {   /* color smooth */
+       int cellnum, delc, col1, j, delr, delg, delb;
+ 
+@@ -1025,9 +1026,9 @@
+ 	    gcmap[col1 + i] = gcmap[col1] + (delg * i) / delc;
+ 	    bcmap[col1 + i] = bcmap[col1] + (delb * i) / delc;
+ 
+-	    if (cellgroup[col1 + i]) { 
++	    if (cellgroup[col1 + i]) {
+ 	      /* propogate new color to all members of this group */
+-	      for (j=0; j<numcols; j++) 
++	      for (j=0; j<numcols; j++)
+ 		if (cellgroup[j] == cellgroup[col1 + i]) {
+ 		  rcmap[j] = rcmap[col1 + i];
+ 		  gcmap[j] = gcmap[col1 + i];
+@@ -1043,7 +1044,7 @@
+ 	  }
+ 
+ 	  if (i<numcols) {  /* something changed */
+-	    xvbcopy((char *) &tmpcmap, (char *) &prevcmap, 
++	    xvbcopy((char *) &tmpcmap, (char *) &prevcmap,
+ 		    sizeof(struct cmapstate));
+ 	    BTSetActive(&gbut[G_BCOLUNDO],1);
+ 	    applyGamma(1);
+@@ -1067,7 +1068,7 @@
+ 
+ 	lastcell = curcell;
+ 
+-	j = XGrabPointer(theDisp, cmapF, False, 0, GrabModeAsync, 
++	j = XGrabPointer(theDisp, cmapF, False, 0, GrabModeAsync,
+ 			 GrabModeAsync, None, None, (Time) CurrentTime);
+ 	while (1) {
+ 	  Window       rW,cW;
+@@ -1076,7 +1077,7 @@
+ 
+ 	  if (XQueryPointer(theDisp,cmapF,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
+ 	    /* if button3 and shift released */
+-	    if (!(mask & (Button3Mask | ShiftMask))) break;  
++	    if (!(mask & (Button3Mask | ShiftMask))) break;
+ 
+ 	    /* if user lets go of B3, reset addonly/delonly flag & lastcell */
+ 	    if (!(mask & Button3Mask) && (mask & ShiftMask)) {
+@@ -1112,7 +1113,7 @@
+ 
+ 	if (recolor) {
+ 	  /* colors changed.  save to color undo area */
+-	  xvbcopy((char *) &tmpcmap, (char *) &prevcmap, 
++	  xvbcopy((char *) &tmpcmap, (char *) &prevcmap,
+ 		  sizeof(struct cmapstate));
+ 	  BTSetActive(&gbut[G_BCOLUNDO],1);
+ 	  applyGamma(1);   /* have to regen entire image when groupings chg */
+@@ -1146,12 +1147,12 @@
+   /* cases:  curgroup>0, clicked on something in same group
+                          remove target from group
+ 	     curgroup>0, clicked on something in different group
+-	                 merge groups.  (target group gets 
++	                 merge groups.  (target group gets
+ 			 set equal to current values)
+              curgroup>0, clicked on something in no group
+ 	                 add target to curgroup
+              curgroup=0, clicked on something in a group
+-	                 add editColor to target group, 
++	                 add editColor to target group,
+ 			 set curgroup = target group
+ 			 target group gets current values
+ 	     curgroup=0, clicked on something in no group
+@@ -1185,7 +1186,7 @@
+       }
+     }
+ 
+-    else if ((mode!=DELONLY) && cellgroup[cnum] != curgroup && 
++    else if ((mode!=DELONLY) && cellgroup[cnum] != curgroup &&
+ 	     cellgroup[cnum]>0) {
+       /* merge clicked-on group into curgroup */
+       mode = ADDONLY;
+@@ -1196,11 +1197,11 @@
+ 	  selectCell(i,1);
+ 	  rcmap[i] = rcmap[editColor];
+ 	  gcmap[i] = gcmap[editColor];
+-	  bcmap[i] = bcmap[editColor]; 
++	  bcmap[i] = bcmap[editColor];
+ 	}
+       }
+     }
+-	    
++
+     else if ((mode!=DELONLY) && cellgroup[cnum] == 0) {
+       /* merge clicked-on cell into curgroup */
+       mode = ADDONLY;
+@@ -1209,7 +1210,7 @@
+       selectCell(cnum,1);
+       rcmap[cnum] = rcmap[editColor];
+       gcmap[cnum] = gcmap[editColor];
+-      bcmap[cnum] = bcmap[editColor]; 
++      bcmap[cnum] = bcmap[editColor];
+     }
+   }
+ 
+@@ -1224,14 +1225,14 @@
+ 	  selectCell(i,1);
+ 	  rcmap[i] = rcmap[editColor];
+ 	  gcmap[i] = gcmap[editColor];
+-	  bcmap[i] = bcmap[editColor]; 
++	  bcmap[i] = bcmap[editColor];
+ 	}
+       }
+       curgroup = cellgroup[cnum];
+       cellgroup[editColor] = curgroup;
+     }
+-	    
+-    else if ((mode!=DELONLY) && (cellgroup[cnum] == 0) 
++
++    else if ((mode!=DELONLY) && (cellgroup[cnum] == 0)
+ 	     && (cnum != editColor)) {
+       /* create new group for these two cells (cnum and editColor) */
+       mode = ADDONLY;
+@@ -1247,14 +1248,14 @@
+   }
+ 
+   return rv;
+-}	    
+-	    
++}
++
+ 
+ /*********************/
+ void ChangeEC(num)
+ int num;
+ {
+-  /* given a color # that is to become the new editColor, do all 
++  /* given a color # that is to become the new editColor, do all
+      highlighting/unhighlighting, copy editColor's rgb values to
+      the rgb/hsv dials */
+ 
+@@ -1291,18 +1292,18 @@
+     rgb2hsv(rcmap[editColor], gcmap[editColor], bcmap[editColor], &h, &s, &v);
+     if (h<0) h = 0;
+ 
+-    DSetVal(&rhDial, (int) h);
+-    DSetVal(&gsDial, (int) (s*100));
+-    DSetVal(&bvDial, (int) (v*100));
++    DSetVal(&rhDial, h);
++    DSetVal(&gsDial, s*100);
++    DSetVal(&bvDial, v*100);
+   }
+   else {
+-    DSetVal(&rhDial, rcmap[editColor]);
+-    DSetVal(&gsDial, gcmap[editColor]);
+-    DSetVal(&bvDial, bcmap[editColor]);
++    DSetVal(&rhDial, (double)rcmap[editColor]);
++    DSetVal(&gsDial, (double)gcmap[editColor]);
++    DSetVal(&bvDial, (double)bcmap[editColor]);
+   }
+ }
+-  
+-    
++
++
+ /*********************/
+ void ApplyECctrls()
+ {
+@@ -1310,16 +1311,15 @@
+ 
+   if (hsvmode) {
+     int rv, gv, bv;
+-    hsv2rgb((double) rhDial.val, ((double) gsDial.val) / 100.0, 
+-	    ((double) bvDial.val) / 100.0, &rv, &gv, &bv);
++    hsv2rgb(rhDial.val, gsDial.val / 100.0, bvDial.val / 100.0, &rv, &gv, &bv);
+     rcmap[editColor] = rv;
+     gcmap[editColor] = gv;
+     bcmap[editColor] = bv;
+   }
+   else {
+-    rcmap[editColor] = rhDial.val;
+-    gcmap[editColor] = gsDial.val;
+-    bcmap[editColor] = bvDial.val;
++    rcmap[editColor] = (int)rhDial.val;
++    gcmap[editColor] = (int)gsDial.val;
++    bcmap[editColor] = (int)bvDial.val;
+   }
+ }
+ 
+@@ -1330,7 +1330,7 @@
+ {
+   /* this function generates the Floyd-Steinberg gamma curve (fsgamcr)
+ 
+-     This function generates a 4 point spline curve to be used as a 
++     This function generates a 4 point spline curve to be used as a
+      non-linear grey 'colormap'.  Two of the points are nailed down at 0,0
+      and 255,255, and can't be changed.  You specify the other two.  If
+      you specify points on the line (0,0 - 255,255), you'll get the normal
+@@ -1345,7 +1345,7 @@
+   double yf[4];
+ 
+   InitSpline(x, y, 4, yf);
+-  
++
+   for (i=0; i<256; i++) {
+     j = (int) EvalSpline(x, y, yf, 4, (double) i);
+     if (j<0) j=0;
+@@ -1364,14 +1364,14 @@
+ 
+   switch (cmd) {
+ 
+-  case G_BAPPLY: 
++  case G_BAPPLY:
+     if (enabCB.val != 1) { enabCB.val = 1;  CBRedraw(&enabCB); }
+-    applyGamma(0);           
++    applyGamma(0);
+     break;
+ 
+   case G_BNOGAM:
+     if (enabCB.val != 0) { enabCB.val = 0;  CBRedraw(&enabCB); }
+-    applyGamma(0);           
++    applyGamma(0);
+     break;
+ 
+   case G_BUNDO:  gamUndo();  break;
+@@ -1383,7 +1383,7 @@
+ 
+ 
+ 
+-  case G_BDN_BR: 
++  case G_BDN_BR:
+   case G_BUP_BR: GetGrafState(&intGraf, &gs);
+                  for (i=0; i < gs.nhands; i++) {
+ 		   if (cmd==G_BUP_BR) gs.hands[i].y += 10;
+@@ -1434,7 +1434,7 @@
+ 	       else if (cmd==G_B3)     ptr = &preset[2];
+ 	       else if (cmd==G_B4)     ptr = &preset[3];
+ 	       else if (cmd==G_BRESET) ptr = &defstate;
+-                
++
+ 	       if (gbut[G_BSET].lit) {
+ 		 ctrls2gamstate(ptr);
+ 		 gbut[G_BSET].lit = 0;
+@@ -1454,7 +1454,7 @@
+     break;
+ 
+ 
+-  case G_BCOLREV: 
++  case G_BCOLREV:
+     {
+       struct cmapstate tmp1cmap;
+       int gchg;
+@@ -1463,9 +1463,9 @@
+       gchg = (i!=numcols);
+ 
+       saveCMap(&tmpcmap);         /* buffer current cmapstate */
+-    
++
+       for (i=0; i<numcols; i++) { /* do reversion */
+-	rcmap[i] = rorg[i];  
++	rcmap[i] = rorg[i];
+ 	gcmap[i] = gorg[i];
+ 	bcmap[i] = borg[i];
+ 	cellgroup[i] = 0;
+@@ -1473,12 +1473,12 @@
+       curgroup = maxgroup = 0;
+ 
+       saveCMap(&tmp1cmap);        /* buffer current cmapstate */
+-    
++
+       /* prevent multiple 'Undo All's from filling Undo buffer */
+-      if (xvbcmp((char *) &tmpcmap, (char *) &tmp1cmap, 
++      if (xvbcmp((char *) &tmpcmap, (char *) &tmp1cmap,
+ 		 sizeof(struct cmapstate))) {
+ 	/* the reversion changed the cmapstate */
+-	xvbcopy((char *) &tmpcmap, (char *) &prevcmap, 
++	xvbcopy((char *) &tmpcmap, (char *) &prevcmap,
+ 		sizeof(struct cmapstate));
+ 	BTSetActive(&gbut[G_BCOLUNDO],1);
+ 
+@@ -1496,7 +1496,7 @@
+     BTSetActive(&gbut[G_BCOLUNDO],1);
+     rndCols();
+     break;
+-  
++
+   case G_BRV:
+     saveCMap(&prevcmap);
+     BTSetActive(&gbut[G_BCOLUNDO],1);
+@@ -1523,7 +1523,7 @@
+     ChangeEC(editColor);
+     applyGamma(1);
+     break;
+-  
++
+ 
+   case G_BMONO:
+     saveCMap(&prevcmap);
+@@ -1534,7 +1534,7 @@
+     ChangeEC(editColor);
+     applyGamma(1);
+     break;
+-  
++
+ 
+   case G_BCOLUNDO:
+     for (i=0; i<numcols && cellgroup[i]==prevcmap.cellgroup[i]; i++);
+@@ -1560,10 +1560,10 @@
+     rhDial.title = "Red";
+     gsDial.title = "Green";
+     bvDial.title = "Blue";
+-		   
+-    DSetRange(&rhDial, 0, 255, rcmap[editColor], 16);
+-    DSetRange(&gsDial, 0, 255, gcmap[editColor], 16);
+-    DSetRange(&bvDial, 0, 255, bcmap[editColor], 16);
++
++    DSetRange(&rhDial, 0.0, 255.0, (double)rcmap[editColor], 1.0, 16.0);
++    DSetRange(&gsDial, 0.0, 255.0, (double)gcmap[editColor], 1.0, 16.0);
++    DSetRange(&bvDial, 0.0, 255.0, (double)bcmap[editColor], 1.0, 16.0);
+ 
+     XClearWindow(theDisp, rhDial.win);    DRedraw(&rhDial);
+     XClearWindow(theDisp, gsDial.win);    DRedraw(&gsDial);
+@@ -1581,9 +1581,9 @@
+ 	    &h, &s, &v);
+ 
+     if (h<0.0) h = 0.0;
+-    DSetRange(&rhDial, 0, 360, (int) h, 5);
+-    DSetRange(&gsDial, 0, 100, (int) (s*100), 5);
+-    DSetRange(&bvDial, 0, 100, (int) (v*100), 5);
++    DSetRange(&rhDial, 0.0, 360.0,     h, 1.0, 5.0);
++    DSetRange(&gsDial, 0.0, 100.0, s*100, 1.0, 5.0);
++    DSetRange(&bvDial, 0.0, 100.0, v*100, 1.0, 5.0);
+ 
+     XClearWindow(theDisp, rhDial.win);    DRedraw(&rhDial);
+     XClearWindow(theDisp, gsDial.win);    DRedraw(&gsDial);
+@@ -1615,12 +1615,12 @@
+     GammifyColors();
+ 
+     /* if current 'desired' colormap hasn't changed, don't DO anything */
+-    if (!xvbcmp((char *) rMap, (char *) oldr, (size_t) numcols) && 
+-	!xvbcmp((char *) gMap, (char *) oldg, (size_t) numcols) && 
++    if (!xvbcmp((char *) rMap, (char *) oldr, (size_t) numcols) &&
++	!xvbcmp((char *) gMap, (char *) oldg, (size_t) numcols) &&
+ 	!xvbcmp((char *) bMap, (char *) oldb, (size_t) numcols)) return;
+ 
+     /* special case: if using R/W color, just modify the colors and leave */
+-    if (allocMode==AM_READWRITE && rwthistime && 
++    if (allocMode==AM_READWRITE && rwthistime &&
+ 	(!cmapchange || nfcols==numcols)) {
+       XColor ctab[256];
+ 
+@@ -1647,10 +1647,10 @@
+ 	gdisp[i] = gMap[rwpc2pc[i]];
+ 	bdisp[i] = bMap[rwpc2pc[i]];
+       }
+-      
++
+       return;
+     }
+-    
++
+     FreeColors();
+ 
+     {
+@@ -1663,10 +1663,10 @@
+     AllocColors();
+ 
+ 
+-    if (epicMode != EM_RAW) {  
++    if (epicMode != EM_RAW) {
+       /* regen image, as we'll probably want to dither differently, given
+ 	 new colors and such */
+-      
++
+       GenerateEpic(eWIDE, eHIGH);
+     }
+   }
+@@ -1701,7 +1701,7 @@
+     for (i=255; i>0 && !hist[i]; i--);
+     *rmaxv = i;
+   }
+-  
++
+   else {  /* PIC24 */
+     int v,minv,maxv;
+ 
+@@ -1724,7 +1724,7 @@
+ 	hist[v]++;
+       }
+     }
+-    
++
+     *rminv = minv;  *rmaxv = maxv;
+   }
+ 
+@@ -1764,13 +1764,13 @@
+   int i, histeq[256], minv, maxv;
+ 
+   calcHistEQ(histeq, &minv, &maxv);  /* ignore minv,maxv */
+-    
+-  for (i=0; i<256; i++) 
++
++  for (i=0; i<256; i++)
+     intGraf.func[i] = histeq[i];
+-    
++
+   for (i=0; i< intGraf.nhands; i++)
+     intGraf.hands[i].y = intGraf.func[intGraf.hands[i].x];
+-    
++
+   intGraf.entergamma = 0;
+ 
+   if (gamUp) {
+@@ -1797,7 +1797,7 @@
+       if (v>maxv) maxv = v;
+     }
+   }
+-  else { 
++  else {
+     int histeq[256];
+     calcHistEQ(histeq, &minv, &maxv);  /* ignore histeq */
+   }
+@@ -1833,11 +1833,11 @@
+     for (i=0; i<numcols; i++) Gammify1(i);
+   }
+   else {
+-    for (i=0; i<numcols; i++) { 
++    for (i=0; i<numcols; i++) {
+       rMap[i] = rcmap[i];
+       gMap[i] = gcmap[i];
+       bMap[i] = bcmap[i];
+-      if (!ncols) 
++      if (!ncols)
+ 	cols[i] = (((int)rMap[i]) + ((int)gMap[i]) + ((int)bMap[i]) >= 128*3)
+ 	  ? white : black;
+     }
+@@ -1875,7 +1875,7 @@
+     if (DEBUG>1) fprintf(stderr," (v=%f)",v);
+ 
+     if (h>=0) {
+-      hi = (int) h;  
++      hi = (int) h;
+       if (hi<0)    hi += 360;
+       if (hi>=360) hi -= 360;
+       h = (double) hremap[hi];
+@@ -1884,14 +1884,14 @@
+       if (whtHD.enabCB.val) {
+ 	h = (double) whtHD.stval;
+ 	s = (double) whtHD.satval / 100.0;
+-	
++
+ 	/* special case:  if stval = satval = 0, set hue = -1 */
+ 	if (whtHD.stval == 0 && whtHD.satval == 0) h = -1.0;
+       }
+     }
+ 
+     /* apply satDial value to s */
+-    s = s + ((double) satDial.val) / 100.0;
++    s = s + satDial.val / 100.0;
+     if (s<0.0) s = 0.0;
+     if (s>1.0) s = 1.0;
+ 
+@@ -1899,13 +1899,13 @@
+     if (DEBUG>1) fprintf(stderr," -> %d,%d,%d",rv,gv,bv);
+   }
+ 
+-  rMap[col] = rGraf.func[rv];  
++  rMap[col] = rGraf.func[rv];
+   gMap[col] = gGraf.func[gv];
+   bMap[col] = bGraf.func[bv];
+ 
+-  if (!ncols) 
+-    cols[col] = 
+-      (((int)rMap[col]) + ((int)gMap[col]) + ((int)bMap[col]) >= 128*3) 
++  if (!ncols)
++    cols[col] =
++      (((int)rMap[col]) + ((int)gMap[col]) + ((int)bMap[col]) >= 128*3)
+ 	? white : black;
+ 
+   if (DEBUG>1) fprintf(stderr," -> %d,%d,%d\n",rMap[col],gMap[col],bMap[col]);
+@@ -2001,13 +2001,13 @@
+ {
+   xvbcopy((char *) hmap, (char *) gs->hmap, sizeof(hmap));
+ 
+-  gs->wht_stval = whtHD.stval;  
+-  gs->wht_satval = whtHD.satval;  
++  gs->wht_stval = whtHD.stval;
++  gs->wht_satval = whtHD.satval;
+   gs->wht_enab = whtHD.enabCB.val;
+ 
+   gs->hueRBnum = RBWhich(hueRB);
+ 
+-  gs->satval = satDial.val;
++  gs->satval = (int)satDial.val;
+   GetGrafState(&intGraf,&gs->istate);
+   GetGrafState(&rGraf,  &gs->rstate);
+   GetGrafState(&gGraf,  &gs->gstate);
+@@ -2042,7 +2042,7 @@
+       srcHD.ccwise = hm->src_ccw;
+       HDRedraw(&srcHD, HD_ALL | HD_CLEAR);
+     }
+-    
++
+     if (dstHD.stval  != hm->dst_st ||
+ 	dstHD.enval  != hm->dst_en ||
+ 	dstHD.ccwise != hm->dst_ccw) {
+@@ -2051,7 +2051,7 @@
+       dstHD.ccwise = hm->dst_ccw;
+       HDRedraw(&dstHD, HD_ALL | HD_CLEAR);
+     }
+-  }    
++  }
+ 
+ 
+   if (whtHD.stval != gs->wht_stval || whtHD.satval != gs->wht_satval ||
+@@ -2063,9 +2063,9 @@
+     HDRedraw(&whtHD, HD_ALL | HD_CLEAR);
+     changed++;
+   }
+-    
+-  if (gs->satval != satDial.val) {
+-    DSetVal(&satDial,gs->satval);
++
++  if (gs->satval != (int)satDial.val) {
++    DSetVal(&satDial,(double)gs->satval);
+     changed++;
+   }
+ 
+@@ -2203,7 +2203,7 @@
+ }
+ 
+ 
+-    
++
+ 
+ /*********************/
+ static void parseResources()
+@@ -2226,7 +2226,7 @@
+     if (i) { sprintf(gname,"preset%d",i);  gsp = &preset[i-1]; }
+       else { sprintf(gname,"default");     gsp = &defstate; }
+ 
+-    xvbcopy((char *) gsp, (char *) &gs, 
++    xvbcopy((char *) gsp, (char *) &gs,
+ 	    sizeof(struct gamstate));   /* load 'gs' with defaults */
+ 
+     for (j=0; j<6; j++) {                       /* xv.*.huemap resources */
+@@ -2239,7 +2239,7 @@
+ 	lower_str(def_str);
+ 	if (sscanf(def_str,"%d %d %s %d %d %s",
+ 		   &fst, &fen, fcw, &tst, &ten, tcw) != 6) {
+-	  fprintf(stderr,"%s: unable to parse resource 'xv.%s: %s'\n", 
++	  fprintf(stderr,"%s: unable to parse resource 'xv.%s: %s'\n",
+ 		  cmd, tmp, def_str);
+ 	}
+ 	else {
+@@ -2260,7 +2260,7 @@
+       int wst, wsat, enab;
+       if (DEBUG) fprintf(stderr,"parseResource 'xv.%s: %s'\n",tmp, def_str);
+       if (sscanf(def_str,"%d %d %d", &wst, &wsat, &enab) != 3) {
+-	fprintf(stderr,"%s: unable to parse resource 'xv.%s: %s'\n", 
++	fprintf(stderr,"%s: unable to parse resource 'xv.%s: %s'\n",
+ 		cmd, tmp, def_str);
+       }
+       else {                                    /* successful parse */
+@@ -2276,7 +2276,7 @@
+       int sat;
+       if (DEBUG) fprintf(stderr,"parseResource 'xv.%s: %s'\n",tmp, def_str);
+       if (sscanf(def_str,"%d", &sat) != 1) {
+-	fprintf(stderr,"%s: unable to parse resource 'xv.%s: %s'\n", 
++	fprintf(stderr,"%s: unable to parse resource 'xv.%s: %s'\n",
+ 		cmd, tmp, def_str);
+       }
+       else {                                    /* successful parse */
+@@ -2304,7 +2304,7 @@
+ 	}
+       }
+     }
+-    
++
+     /* copy (potentially) modified gs back to default/preset */
+     xvbcopy((char *) &gs, (char *) gsp, sizeof(struct gamstate));
+   }
+@@ -2324,16 +2324,16 @@
+   /* write out current state */
+   ctrls2gamstate(&gstate);
+   strcpy(gname, "xv.default");
+-  
++
+   /* write out huemap resources */
+   for (i=0; i<6; i++) {
+     if (1 || gstate.hmap[i].src_st  != gstate.hmap[i].dst_st ||
+ 	gstate.hmap[i].src_en  != gstate.hmap[i].dst_en ||
+ 	gstate.hmap[i].src_ccw != gstate.hmap[i].dst_ccw) {
+-      sprintf(tmp, "%s.huemap%d: %3d %3d %3s %3d %3d %3s\n", gname, i+1, 
+-	      gstate.hmap[i].src_st, gstate.hmap[i].src_en, 
++      sprintf(tmp, "%s.huemap%d: %3d %3d %3s %3d %3d %3s\n", gname, i+1,
++	      gstate.hmap[i].src_st, gstate.hmap[i].src_en,
+ 	      gstate.hmap[i].src_ccw ? "CCW" : "CW",
+-	      gstate.hmap[i].dst_st, gstate.hmap[i].dst_en, 
++	      gstate.hmap[i].dst_st, gstate.hmap[i].dst_en,
+ 	      gstate.hmap[i].dst_ccw ? "CCW" : "CW");
+       strcat(rsrc, tmp);
+     }
+@@ -2341,7 +2341,7 @@
+ 
+   /* write out whtmap resource */
+   if (1 || gstate.wht_stval || gstate.wht_satval || gstate.wht_enab != 1) {
+-    sprintf(tmp, "%s.whtmap:  %d %d %d\n", gname, gstate.wht_stval, 
++    sprintf(tmp, "%s.whtmap:  %d %d %d\n", gname, gstate.wht_stval,
+ 	    gstate.wht_satval, gstate.wht_enab);
+     strcat(rsrc, tmp);
+   }
+@@ -2372,7 +2372,7 @@
+ 
+   NewCutBuffer(rsrc);
+ }
+-    
++
+ 
+ /*****************************/
+ static void dragGamma ()
+@@ -2381,14 +2381,14 @@
+      while gamma ctrls are being dragged
+      applies change to image if dragCB.val is set
+      does NOT call saveGamState() (as changedGam does) */
+-  
++
+   if (dragCB.val && dragCB.active) {
+     hsvnonlinear = 1;   /* force HSV calculations during drag */
+     applyGamma(0);
+   }
+ }
+ 
+-  
++
+ /*****************************/
+ static void dragHueDial()
+ {
+@@ -2396,7 +2396,7 @@
+      while hue gamma ctrls are being dragged
+      applies change to image if dragCB.val is set
+      does NOT call saveGamState() (as changedGam does) */
+-  
++
+   if (dragCB.val && dragCB.active) {
+     dials2hmap();
+     build_hremap();
+@@ -2413,14 +2413,14 @@
+      while color editor ctrls are being dragged
+      applies change to image if dragCB.val is set
+      does NOT call saveCMap(&prevcmap); BTSetActive(&gbut[G_BCOLUNDO],1); */
+-  
++
+   if (dragCB.val && dragCB.active) ApplyEditColor(0);
+ }
+ 
+ 
+-    
+-    
+-        
++
++
++
+ 
+ /**********************************************/
+ /*************  HUE wheel functions ***********/
+@@ -2435,11 +2435,11 @@
+ 
+ /**************************************************/
+ static void HDCreate(hd, win, x, y, r, st, en, ccwise, str, fg, bg)
+-HDIAL *hd;
+-Window win;
+-int x,y,r,st,en,ccwise;
+-char *str;
+-u_long fg,bg;
++     HDIAL      *hd;
++     Window      win;
++     int         x, y, r, st, en, ccwise;
++     const char *str;
++     u_long      fg, bg;
+ {
+   int i;
+ 
+@@ -2470,7 +2470,7 @@
+     hdbpix2[HDB_ROTR]  = hdbpix1[HDB_ROTR];
+   }
+ 
+-    
++
+ #define BCOLS fg,bg,hicol,locol
+ 
+   if (hd->range) {
+@@ -2520,13 +2520,13 @@
+   }
+ 
+   if (flags & HD_FRAME) {
+-    static char *colstr = "RYGCBM";
++    static const char *colstr = "RYGCBM";
+     char tstr[2];
+ 
+     XSetForeground(theDisp, theGC, hd->fg);
+     XDrawArc(theDisp, hd->win, theGC, hd->x - HD_RADIUS, hd->y - HD_RADIUS,
+ 	     HD_RADIUS*2, HD_RADIUS*2, 0, 360*64);
+-    
++
+     for (i=0; i<6; i++) {
+       int kldg;
+ 
+@@ -2553,8 +2553,8 @@
+       a = hdg2xdg(hd->stval) * DEG2RAD;
+       pol2xy(hd->x, hd->y, a, HD_RADIUS - 4, &x, &y);
+       XDrawLine(theDisp, hd->win, theGC, hd->x, hd->y, x,y);
+-      
+-      if (flags & HD_CLHNDS) 
++
++      if (flags & HD_CLHNDS)
+ 	XFillRectangle(theDisp, hd->win, theGC, x-2,y-2, 5,5);
+       else {
+ 	XSetForeground(theDisp, theGC, hd->bg);
+@@ -2567,8 +2567,8 @@
+       a = hdg2xdg(hd->enval) * DEG2RAD;
+       pol2xy(hd->x, hd->y, a, HD_RADIUS - 4, &x, &y);
+       XDrawLine(theDisp, hd->win, theGC, hd->x, hd->y, x,y);
+-    
+-      if (flags & HD_CLHNDS) 
++
++      if (flags & HD_CLHNDS)
+ 	XFillRectangle(theDisp, hd->win, theGC, x-2,y-2, 5,5);
+       else {
+ 	XSetForeground(theDisp, theGC, hd->bg);
+@@ -2587,7 +2587,7 @@
+       r = ((HD_RADIUS - 4) * hd->satval) / 100;
+       pol2xy(hd->x, hd->y, a, r, &x, &y);
+ 
+-      if (flags & HD_CLHNDS) 
++      if (flags & HD_CLHNDS)
+ 	XFillRectangle(theDisp, hd->win, theGC, x-2,y-2, 5,5);
+       else {
+ 	XFillRectangle(theDisp, hd->win, theGC, hd->x-1, hd->y-1, 3,3);
+@@ -2600,7 +2600,7 @@
+       }
+     }
+   }
+-    
++
+ 
+ 
+ 
+@@ -2653,13 +2653,13 @@
+     XSetBackground(theDisp, theGC, hd->bg);
+ 
+     if (hd->range) {
+-      sprintf(vstr,"%3d\007,%3d\007 %s", hd->stval, hd->enval, 
++      sprintf(vstr,"%3d\007,%3d\007 %s", hd->stval, hd->enval,
+ 	      hd->ccwise ? "CCW" : " CW");
+     }
+     else {
+       sprintf(vstr,"%3d\007 %3d%%", hd->stval, hd->satval);
+     }
+-      
++
+     XDrawImageString(theDisp, hd->win, theGC,
+ 		     hd->x - XTextWidth(monofinfo, vstr, (int) strlen(vstr))/2,
+ 		     hd->y + HD_RADIUS + 24, vstr, (int) strlen(vstr));
+@@ -2669,7 +2669,7 @@
+ 
+   if (flags & HD_TITLE) {
+     XSetForeground(theDisp, theGC, hd->fg);
+-    ULineString(hd->win, hd->x - HD_RADIUS - 15, hd->y - HD_RADIUS - 4, 
++    ULineString(hd->win, hd->x - HD_RADIUS - 15, hd->y - HD_RADIUS - 4,
+ 		hd->str);
+   }
+ 
+@@ -2694,7 +2694,7 @@
+ }
+ 
+ 
+-    
++
+ /**************************************************/
+ static int HDClick(hd,mx,my)
+ HDIAL *hd;
+@@ -2716,7 +2716,7 @@
+   if (!hd->range && !hd->enabCB.val) return 0;    /* disabled */
+ 
+ 
+-  if ( ((mx - hd->x) * (mx - hd->x)  +  (my - hd->y) * (my - hd->y)) 
++  if ( ((mx - hd->x) * (mx - hd->x)  +  (my - hd->y) * (my - hd->y))
+       < (HD_RADIUS * HD_RADIUS)) {
+     return HDTrack(hd,mx,my);
+   }
+@@ -2816,14 +2816,14 @@
+ 	      hd->satval--;  if (hd->satval<0) hd->satval = 0;
+ 	      HDRedraw(hd, HD_HANDS | HD_VALS);
+ 	    }
+-	      
++
+ 	    else if (bnum == HDB_SAT && hd->satval<100) {
+ 	      HDRedraw(hd, HD_CLHNDS);
+ 	      hd->satval++;  if (hd->satval>100) hd->satval = 100;
+ 	      HDRedraw(hd, HD_HANDS | HD_VALS);
+ 	    }
+ 	  }
+-	      
++
+ 	  break;
+ 	}
+ 
+@@ -2836,7 +2836,7 @@
+   }
+ 
+   if (bp->lit) {  bp->lit = 0;  BTRedraw(bp); }
+-    
++
+   return 1;
+ }
+ 
+@@ -2872,7 +2872,7 @@
+ 
+       dx = x - hd->x;  dy = y - hd->y;
+       dist = sqrt(dx*dx + dy*dy);
+-      
++
+       newsat = (int) (dist / ((double) (HD_RADIUS - 4)) * 100);
+       RANGE(newsat,0,100);
+ 
+@@ -2899,7 +2899,7 @@
+     a = hdg2xdg(hd->enval) * DEG2RAD;
+     pol2xy(hd->x, hd->y, a, HD_RADIUS-4, &x,&y);
+     if (PTINRECT(mx,my,x-3,y-3,7,7)) handle = 2;
+-    
++
+ 
+ 
+     if (!handle) {  /* not in either, rotate both */
+@@ -2939,7 +2939,7 @@
+       }
+       rv = (origj != j);
+     }
+-	    
++
+ 
+     else {  /* in one of the handles */
+       if (handle==1) valp = &(hd->stval);  else valp = &(hd->enval);
+@@ -2958,22 +2958,22 @@
+ 
+ 	  if (!hd->ccwise) {
+ 	    ddist = (hd->enval - hd->stval + 360) % 360;
+-	    if (handle==1) 
++	    if (handle==1)
+ 	      ndist = (hd->enval - j + 360) % 360;
+ 	    else
+ 	      ndist = (j - hd->stval + 360) % 360;
+ 	  }
+ 	  else {
+ 	    ddist = (hd->stval - hd->enval + 360) % 360;
+-	    if (handle==1) 
++	    if (handle==1)
+ 	      ndist = (j - hd->enval + 360) % 360;
+ 	    else
+ 	      ndist = (hd->stval - j + 360) % 360;
+ 	  }
+ 
+-	  if (abs(ddist - ndist) >= 180 && ddist<180) 
++	  if (abs(ddist - ndist) >= 180 && ddist<180)
+ 	    hd->ccwise = !hd->ccwise;
+-	  
++
+ 	  *valp = j;
+ 	  HDRedraw(hd, HD_HANDS | HD_DIR | HD_VALS);
+ 
+@@ -2986,8 +2986,8 @@
+ 
+   return rv;
+ }
+-    
+-      
++
++
+ 
+ /**************************************************/
+ static int hdg2xdg(hdg)
+@@ -3012,7 +3012,7 @@
+   *yp = cy - (int) (sin(ang) * (double) rad);
+ }
+ 
+-  
++
+ /***************************************************/
+ static int computeHDval(hd, x, y)
+ HDIAL *hd;
+@@ -3044,7 +3044,7 @@
+ 
+ 
+ 
+-    
++
+ /****************************************************/
+ static void initHmap()
+ {
+@@ -3117,10 +3117,10 @@
+ 	(hmap[i].src_en  != hmap[i].dst_en) ||
+ 	(hmap[i].src_ccw != hmap[i].dst_ccw)) {   /* not a 1:1 mapping */
+ 
+-      st1  = hmap[i].src_st;  
++      st1  = hmap[i].src_st;
+       en1  = hmap[i].src_en;
+       if (hmap[i].src_ccw) {
+-	inc1 = -1; 
++	inc1 = -1;
+ 	len1 = (st1 - en1 + 360) % 360;
+       }
+       else {
+@@ -3131,7 +3131,7 @@
+       st2 = hmap[i].dst_st;
+       en2 = hmap[i].dst_en;
+       if (hmap[i].dst_ccw) {
+-	inc2 = -1; 
++	inc2 = -1;
+ 	len2 = (st2 - en2 + 360) % 360;
+       }
+       else {
+@@ -3179,7 +3179,7 @@
+ 
+   byte *pp, *op;
+   int   i,j;
+-  int   rv, gv, bv, vi, hi;
++  int   rv, gv, bv;
+   byte *outpic;
+   int   min, max, del, h, s, v;
+   int   f, p, q, t, vs100, vsf10000;
+@@ -3200,7 +3200,7 @@
+ 
+   if (whtHD.enabCB.val && whtHD.satval) hsvmod++;
+ 
+-  if (satDial.val != 0) hsvmod++;
++  if (satDial.val != 0.0) hsvmod++;
+ 
+   /* check intensity graf */
+   for (i=0; i<256; i++) {
+@@ -3270,7 +3270,7 @@
+ 
+       /* map near-black to black to avoid weird effects */
+       if (v <= 16) s = 0;
+-      
++
+       /* apply intGraf.func[] function to 'v' (the intensity) */
+       v = intGraf.func[v];
+ 
+@@ -3284,7 +3284,7 @@
+       }
+ 
+       /* apply satDial value to s */
+-      s = s + satDial.val;
++      s = s + (int)satDial.val;
+       if (s<  0) s =   0;
+       if (s>100) s = 100;
+ 
+@@ -3295,7 +3295,7 @@
+       if (h==NOHUE || !s) { rv = gv = bv = v; }
+       else {
+ 	if (h==360) h = 0;
+-	
++
+ 	h        = (h*100) / 60;    /* h is in range 000..599 (0.0 - 5.99) */
+ 	j        = h - (h%100);     /* j = 000, 100, 200, 300, 400, 500 */
+ 	f        = h - j;           /* 'fractional' part of h (00..99) */
+@@ -3305,7 +3305,7 @@
+ 	p = v - vs100;
+ 	q = v - vsf10000;
+ 	t = v - vs100 + vsf10000;
+-	
++
+ 	switch (j) {
+ 	case 000:  rv = v;  gv = t;  bv = p;  break;
+ 	case 100:  rv = q;  gv = v;  bv = p;  break;
+@@ -3319,7 +3319,7 @@
+     }   /* if hsvmod */
+ 
+ 
+-    *op++ = rGraf.func[rv];  
++    *op++ = rGraf.func[rv];
+     *op++ = gGraf.func[gv];
+     *op++ = bGraf.func[bv];
+   }
+diff -ru xv-3.10a/xvgif.c xv-3.10a-enhancements/xvgif.c
+--- xv-3.10a/xvgif.c	1995-01-10 11:54:41.000000000 -0800
++++ xv-3.10a-enhancements/xvgif.c	2007-05-13 17:33:51.000000000 -0700
+@@ -28,17 +28,19 @@
+ typedef int boolean;
+ 
+ #define NEXTBYTE (*dataptr++)
++#define SKIPBYTE (dataptr++)	/* quiet some compiler warnings */
+ #define EXTENSION     0x21
+-#define IMAGESEP      0x2c
++#define IMAGESEP      0x2c	/* a.k.a. Image Descriptor */
+ #define TRAILER       0x3b
+ #define INTERLACEMASK 0x40
+ #define COLORMAPMASK  0x80
+ 
+-  
+ 
+-FILE *fp;
+ 
+-int BitOffset = 0,		/* Bit Offset of next code */
++static FILE *fp;
++
++static int
++    BitOffset = 0,		/* Bit Offset of next code */
+     XC = 0, YC = 0,		/* Output X and Y coords of current pixel */
+     Pass = 0,			/* Used by output routine if interlaced pic */
+     OutCount = 0,		/* Decompressor output 'stack count' */
+@@ -46,9 +48,10 @@
+     Width, Height,		/* image dimensions */
+     LeftOfs, TopOfs,		/* image offset */
+     BitsPerPixel,		/* Bits per pixel, read from GIF header */
+-    BytesPerScanline,		/* bytes per scanline in output raster */
++/*  BytesPerScanline,	*/	/* bytes per scanline in output raster */
+     ColorMapSize,		/* number of colors */
+     Background,			/* background color */
++    Transparent,		/* transparent color (GRR 19980314) */
+     CodeSize,			/* Code size, read from GIF header */
+     InitCodeSize,		/* Starting code size, used during Clear */
+     Code,			/* Value returned by ReadCode */
+@@ -57,47 +60,49 @@
+     EOFCode,			/* GIF end-of-information code */
+     CurCode, OldCode, InCode,	/* Decompressor variables */
+     FirstFree,			/* First free code, generated per GIF spec */
+-    FreeCode,			/* Decompressor,next free slot in hash table */
++    FreeCode,			/* Decompressor, next free slot in hash table */
+     FinChar,			/* Decompressor variable */
+     BitMask,			/* AND mask for data size */
+     ReadMask,			/* Code AND mask for current code size */
+-    Misc;                       /* miscellaneous bits (interlace, local cmap)*/
++    Misc,                       /* miscellaneous bits (interlace, local cmap)*/
++    GlobalBitsPerPixel,		/* may have local colormap of different size */
++    GlobalColorMapSize,		/*   (ditto)  */
++    GlobalBitMask;		/*   (ditto)  */
+ 
+ 
+-boolean Interlace, HasColormap;
++static boolean Interlace, HasGlobalColormap;
+ 
+-byte *RawGIF;			/* The heap array to hold it, raw */
+-byte *Raster;			/* The raster data stream, unblocked */
+-byte *pic8;
++static byte *RawGIF;		/* The heap array to hold it, raw */
++static byte *Raster;		/* The raster data stream, unblocked */
++static byte *pic8;
+ 
+     /* The hash table used by the decompressor */
+-int Prefix[4096];
+-int Suffix[4096];
++static int Prefix[4096];
++static int Suffix[4096];
+ 
+     /* An output array used by the decompressor */
+-int OutCode[4097];
++static int OutCode[4097];
+ 
+-int   gif89 = 0;
+-char *id87 = "GIF87a";
+-char *id89 = "GIF89a";
++static int gif89 = 0;
++static const char *id87 = "GIF87a";
++static const char *id89 = "GIF89a";
+ 
+-static int EGApalette[16][3] = {
+-  {0,0,0},       {0,0,128},     {0,128,0},     {0,128,128}, 
++static int const EGApalette[16][3] = {
++  {0,0,0},       {0,0,128},     {0,128,0},     {0,128,128},
+   {128,0,0},     {128,0,128},   {128,128,0},   {200,200,200},
+   {100,100,100}, {100,100,255}, {100,255,100}, {100,255,255},
+   {255,100,100}, {255,100,255}, {255,255,100}, {255,255,255} };
+-  
++
+ 
+ static int   readImage   PARM((PICINFO *));
+ static int   readCode    PARM((void));
+ static void  doInterlace PARM((int));
+-static int   gifError    PARM((PICINFO *, char *));
+-static void  gifWarning  PARM((char *));
++static int   gifError    PARM((PICINFO *, const char *));
++static void  gifWarning  PARM((const char *));
+ 
+-int   filesize;
+-char *bname;
+-
+-byte *dataptr;
++static int         filesize;
++static const char *bname;
++static byte       *dataptr;
+ 
+ 
+ /*****************************/
+@@ -108,17 +113,22 @@
+ {
+   /* returns '1' if successful */
+ 
+-  register byte  ch, ch1, *origptr;
++  register byte  ch, *origptr;
+   register int   i, block;
+-  int            aspect, gotimage;
++  int            aspect;
++  char tmpname[256];
++  byte r[256], g[256], b[256];
+ 
+   /* initialize variables */
+-  BitOffset = XC = YC = Pass = OutCount = gotimage = 0;
++  BitOffset = XC = YC = OutCount = 0;
++  Pass = -1;
+   RawGIF = Raster = pic8 = NULL;
+   gif89 = 0;
++  Transparent = -1;
+ 
+   pinfo->pic     = (byte *) NULL;
+   pinfo->comment = (char *) NULL;
++  pinfo->numpages= 0;
+ 
+   bname = BaseName(fname);
+   fp = xv_fopen(fname,"r");
+@@ -129,67 +139,87 @@
+   fseek(fp, 0L, 2);
+   filesize = ftell(fp);
+   fseek(fp, 0L, 0);
+-  
+-  /* the +256's are so we can read truncated GIF files without fear of 
++
++  if (filesize + 256 < filesize)
++    return( gifError(pinfo, "GIF file size is too large") );
++
++  /* the +256's are so we can read truncated GIF files without fear of
+      segmentation violation */
+   if (!(dataptr = RawGIF = (byte *) calloc((size_t) filesize+256, (size_t) 1)))
+-    return( gifError(pinfo, "not enough memory to read gif file") );
+-  
+-  if (!(Raster = (byte *) calloc((size_t) filesize+256,(size_t) 1))) 
+-    return( gifError(pinfo, "not enough memory to read gif file") );
+-  
+-  if (fread(dataptr, (size_t) filesize, (size_t) 1, fp) != 1) 
+-    return( gifError(pinfo, "GIF data read failed") );
++    FatalError("LoadGIF: not enough memory to read GIF file");
+ 
++  if (!(Raster = (byte *) calloc((size_t) filesize+256,(size_t) 1)))
++    FatalError("LoadGIF: not enough memory to read GIF file");
++
++  if (fread(dataptr, (size_t) filesize, (size_t) 1, fp) != 1)
++    return( gifError(pinfo, "GIF data read failed") );
++  fclose(fp);
+ 
+   origptr = dataptr;
+ 
+   if      (strncmp((char *) dataptr, id87, (size_t) 6)==0) gif89 = 0;
+   else if (strncmp((char *) dataptr, id89, (size_t) 6)==0) gif89 = 1;
+   else    return( gifError(pinfo, "not a GIF file"));
+-  
++
+   dataptr += 6;
+-  
++
+   /* Get variables from the GIF screen descriptor */
+-  
++
+   ch = NEXTBYTE;
+   RWidth = ch + 0x100 * NEXTBYTE;	/* screen dimensions... not used. */
+   ch = NEXTBYTE;
+   RHeight = ch + 0x100 * NEXTBYTE;
+-  
++  if (DEBUG) fprintf(stderr,"GIF89 logical screen = %d x %d\n",RWidth,RHeight);
++
+   ch = NEXTBYTE;
+-  HasColormap = ((ch & COLORMAPMASK) ? True : False);
+-  
+-  BitsPerPixel = (ch & 7) + 1;
+-  numcols = ColorMapSize = 1 << BitsPerPixel;
+-  BitMask = ColorMapSize - 1;
+-  
++  HasGlobalColormap = ((ch & COLORMAPMASK) ? True : False);
++
++  /* GRR 20070318:  fix decoding bug when global and local color-table sizes
++   *                differ */
++  GlobalBitsPerPixel = BitsPerPixel = (ch & 7) + 1;
++  GlobalColorMapSize = ColorMapSize = numcols = 1 << BitsPerPixel;
++  GlobalBitMask = BitMask = ColorMapSize - 1;
++
+   Background = NEXTBYTE;		/* background color... not used. */
+-  
++
+   aspect = NEXTBYTE;
+   if (aspect) {
+     if (!gif89) return(gifError(pinfo,"corrupt GIF file (screen descriptor)"));
+     else normaspect = (float) (aspect + 15) / 64.0;   /* gif89 aspect ratio */
+     if (DEBUG) fprintf(stderr,"GIF89 aspect = %f\n", normaspect);
++    /* FIXME:  apparently this _should_ apply to all frames in a multi-image
++     *         GIF (i.e., PgUp/PgDn), but it doesn't */
+   }
+-  
+-  
++
++
+   /* Read in global colormap. */
+-  
+-  if (HasColormap)
++
++  if (HasGlobalColormap)
+     for (i=0; i<ColorMapSize; i++) {
+-      pinfo->r[i] = NEXTBYTE;
+-      pinfo->g[i] = NEXTBYTE;
+-      pinfo->b[i] = NEXTBYTE;
++      r[i] = NEXTBYTE;
++      g[i] = NEXTBYTE;
++      b[i] = NEXTBYTE;
+     }
+-  else {  /* no colormap in GIF file */
++  else {  /* no _global_ colormap in GIF file (but may have local one(s)) */
+     /* put std EGA palette (repeated 16 times) into colormap, for lack of
+-       anything better to do */
++       anything better to do at the moment */
+ 
+     for (i=0; i<256; i++) {
+-      pinfo->r[i] = EGApalette[i&15][0];
+-      pinfo->g[i] = EGApalette[i&15][1];
+-      pinfo->b[i] = EGApalette[i&15][2];
++      r[i] = EGApalette[i&15][0];
++      g[i] = EGApalette[i&15][1];
++      b[i] = EGApalette[i&15][2];
++    }
++  }
++  memcpy(pinfo->r, r, sizeof r);
++  memcpy(pinfo->g, g, sizeof g);
++  memcpy(pinfo->b, b, sizeof b);
++
++  if (DEBUG > 1) {
++    fprintf(stderr,"  global color table%s:\n",
++      HasGlobalColormap? "":" (repeated EGA palette)");
++    for (i=0; i<ColorMapSize; i++) {
++      fprintf(stderr,"    (%3d  %02x,%02x,%02x)\n", i, pinfo->r[i],
++        pinfo->g[i], pinfo->b[i]);
+     }
+   }
+ 
+@@ -221,19 +251,19 @@
+ 	if (blocksize == 2) {
+ 	  aspnum = NEXTBYTE;
+ 	  aspden = NEXTBYTE;
+-	  if (aspden>0 && aspnum>0) 
++	  if (aspden>0 && aspnum>0)
+ 	    normaspect = (float) aspnum / (float) aspden;
+ 	  else { normaspect = 1.0;  aspnum = aspden = 1; }
+ 
+-	  if (DEBUG) fprintf(stderr,"GIF87 aspect extension: %d:%d = %f\n\n", 
++	  if (DEBUG) fprintf(stderr,"GIF87 aspect extension: %d:%d = %f\n\n",
+ 			     aspnum, aspden,normaspect);
+ 	}
+ 	else {
+-	  for (i=0; i<blocksize; i++) NEXTBYTE;
++	  for (i=0; i<blocksize; i++) SKIPBYTE;
+ 	}
+ 
+ 	while ((sbsize=NEXTBYTE)>0) {  /* eat any following data subblocks */
+-	  for (i=0; i<sbsize; i++) NEXTBYTE;
++	  for (i=0; i<sbsize; i++) SKIPBYTE;
+ 	}
+       }
+ 
+@@ -254,9 +284,11 @@
+ 
+ 
+ 	if (cmtlen>0) {   /* build into one un-blocked comment */
++	  /* this can overflow iff cmtlen == 2G - 1, but then filesize
++	   * would have to be > 2GB, which was disallowed above */
+ 	  cmt = (byte *) malloc((size_t) (cmtlen + 1));
+-	  if (!cmt) gifWarning("couldn't malloc space for comments\n");
+-	  else {
++	  if (!cmt) FatalError("LoadGIF: couldn't malloc space for comments");
++	  /* else */ {
+ 	    sp = cmt;
+ 	    do {
+ 	      sbsize = (*ptr1++);
+@@ -267,10 +299,10 @@
+ 	    if (pinfo->comment) {    /* have to strcat onto old comments */
+ 	      cmt1 = (byte *) malloc(strlen(pinfo->comment) + cmtlen + 2);
+ 	      if (!cmt1) {
+-		gifWarning("couldn't malloc space for comments\n");
+ 		free(cmt);
++	        FatalError("LoadGIF: couldn't malloc space for comments");
+ 	      }
+-	      else {
++	      /* else */ {
+ 		strcpy((char *) cmt1, (char *) pinfo->comment);
+ 		strcat((char *) cmt1, (char *) "\n");
+ 		strcat((char *) cmt1, (char *) cmt);
+@@ -288,8 +320,8 @@
+       else if (fn == 0x01) {  /* PlainText Extension */
+ 	int j,sbsize,ch;
+ 	int tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg;
+-      
+-	SetISTR(ISTR_INFO, "%s:  %s", bname, 
++
++	SetISTR(ISTR_INFO, "%s:  %s", bname,
+ 		"PlainText extension found in GIF file.  Ignored.");
+ 
+ 	sbsize   = NEXTBYTE;
+@@ -302,12 +334,12 @@
+ 	fg       = NEXTBYTE;
+ 	bg       = NEXTBYTE;
+ 	i=12;
+-	for ( ; i<sbsize; i++) NEXTBYTE;   /* read rest of first subblock */
+-      
++	for ( ; i<sbsize; i++) SKIPBYTE;   /* read rest of first subblock */
++
+ 	if (DEBUG) fprintf(stderr,
+ 	   "PlainText: tgrid=%d,%d %dx%d  cell=%dx%d  col=%d,%d\n",
+ 	   tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg);
+-	
++
+ 	/* read (and ignore) data sub-blocks */
+ 	do {
+ 	  j = 0;
+@@ -326,16 +358,32 @@
+ 
+ 	if (DEBUG) fprintf(stderr,"Graphic Control extension\n\n");
+ 
+-	SetISTR(ISTR_INFO, "%s:  %s", bname, 
+-		"Graphic Control Extension in GIF file.  Ignored.");
+-	
+-	/* read (and ignore) data sub-blocks */
++	SetISTR(ISTR_INFO, "%s:  %s", bname,
++		"Graphic Control Extension ignored.");
++
++	/* read (and ignore) data sub-blocks, unless compositing with
++         * user-defined background */
+ 	do {
+-	  j = 0; sbsize = NEXTBYTE;
+-	  while (j<sbsize) { NEXTBYTE;  j++; }
++	  j = 0;
++	  sbsize = NEXTBYTE;
++	  /* GRR 19980314:  get transparent index out of block */
++	  if (have_imagebg && sbsize == 4 && Transparent < 0) {
++	    byte packed_fields = NEXTBYTE;
++
++	    j++;
++	    SKIPBYTE;  j++;
++	    SKIPBYTE;  j++;
++	    if (packed_fields & 1) {
++	      Transparent = NEXTBYTE;
++	      j++;
++	    }
++	  }
++	  while (j<sbsize) {
++	    SKIPBYTE;  j++;
++	  }
+ 	} while (sbsize);
+       }
+-      
++
+ 
+       else if (fn == 0xFF) {  /* Application Extension */
+ 	int j, sbsize;
+@@ -345,10 +393,10 @@
+ 	/* read (and ignore) data sub-blocks */
+ 	do {
+ 	  j = 0; sbsize = NEXTBYTE;
+-	  while (j<sbsize) { NEXTBYTE;  j++; }
++	  while (j<sbsize) { SKIPBYTE;  j++; }
+ 	} while (sbsize);
+       }
+-      
++
+ 
+       else { /* unknown extension */
+ 	int j, sbsize;
+@@ -358,48 +406,68 @@
+ 	SetISTR(ISTR_INFO,
+ 		"%s:  Unknown extension 0x%02x in GIF file.  Ignored.",
+ 		bname, fn);
+-	
++
+ 	/* read (and ignore) data sub-blocks */
+ 	do {
+ 	  j = 0; sbsize = NEXTBYTE;
+-	  while (j<sbsize) { NEXTBYTE;  j++; }
++	  while (j<sbsize) { SKIPBYTE;  j++; }
+ 	} while (sbsize);
+       }
+     }
+ 
+ 
+     else if (block == IMAGESEP) {
+-      if (DEBUG) fprintf(stderr,"imagesep (got=%d)  ",gotimage);
+-      if (DEBUG) fprintf(stderr,"  at start: offset=0x%lx\n",dataptr-RawGIF);
+-
+-      if (gotimage) {   /* just skip over remaining images */
+-	int i,misc,ch,ch1;
+-
+-	/* skip image header */
+-	NEXTBYTE;  NEXTBYTE;  /* left position */
+-	NEXTBYTE;  NEXTBYTE;  /* top position */
+-	NEXTBYTE;  NEXTBYTE;  /* width */
+-	NEXTBYTE;  NEXTBYTE;  /* height */
+-	misc = NEXTBYTE;      /* misc. bits */
+-
+-	if (misc & 0x80) {    /* image has local colormap.  skip it */
+-	  for (i=0; i< 1 << ((misc&7)+1);  i++) {
+-	    NEXTBYTE;  NEXTBYTE;  NEXTBYTE;
++      if (DEBUG) fprintf(stderr, "imagesep (page=%d)\n", pinfo->numpages+1);
++      if (DEBUG) fprintf(stderr, "  at start: offset=0x%lx\n",
++                         (unsigned long)(dataptr-RawGIF));
++
++      BitOffset = XC = YC = Pass = OutCount = 0;
++
++      if (pinfo->numpages > 0) {   /* do multipage stuff */
++	if (pinfo->numpages == 1) {    /* first time only... */
++	  xv_mktemp(pinfo->pagebname, "xvpgXXXXXX"); // a.k.a. close(mkstemp())
++	  if (pinfo->pagebname[0] == '\0') {
++	    ErrPopUp("LoadGIF: Unable to create temporary filename???",
++			"\nHow unlikely!");
++	    return 0;
++	  }
++	  /* GRR 20070328:  basename file doesn't go away, at least on Linux
++           *  (though all appended-number ones do); ergo, open for reading (see
++           *  if it's there), close, and explicitly unlink() if necessary */
++          /* GRR 20070506:  could/should call KillPageFiles() (xv.c) instead */
++	  fp = xv_fopen(pinfo->pagebname, "r");
++	  if (fp) {
++	    fclose(fp);
++	    unlink(pinfo->pagebname);  /* no errors during testing */
+ 	  }
+ 	}
+-
+-	NEXTBYTE;       /* minimum code size */
+-
+-	/* skip image data sub-blocks */
+-	do {
+-	  ch = ch1 = NEXTBYTE;
+-	  while (ch--) NEXTBYTE;
+-	  if ((dataptr - RawGIF) > filesize) break;      /* EOF */
+-	} while(ch1);
+-      }
+-
+-      else if (readImage(pinfo)) gotimage = 1;
+-      if (DEBUG) fprintf(stderr,"  at end:   dataptr=0x%lx\n",dataptr-RawGIF);
++	sprintf(tmpname, "%s%d", pinfo->pagebname, pinfo->numpages);
++	fp = xv_fopen(tmpname, "w");
++	if (!fp) {
++	  ErrPopUp("LoadGIF: Unable to open temp file", "\nDang!");
++	  return 0;
++	}
++	if (WriteGIF(fp, pinfo->pic, pinfo->type, pinfo->w, pinfo->h, pinfo->r,
++		 pinfo->g, pinfo->b, numcols, pinfo->colType, NULL)) {
++	  fclose(fp);
++	  ErrPopUp("LoadGIF: Error writing temp file", "\nBummer!");
++	  return 0;
++	}
++	fclose(fp);
++	free(pinfo->pic);
++	pinfo->pic = (byte *) NULL;
++	if (HasGlobalColormap) {
++	  memcpy(pinfo->r, r, sizeof r);
++	  memcpy(pinfo->g, g, sizeof g);
++	  memcpy(pinfo->b, b, sizeof b);
++	}
++        BitsPerPixel = GlobalBitsPerPixel;
++        numcols = ColorMapSize = GlobalColorMapSize;
++        BitMask = GlobalBitMask;
++      }
++      if (readImage(pinfo)) ++pinfo->numpages;
++      if (DEBUG) fprintf(stderr, "  at end:   offset=0x%lx\n",
++                         (unsigned long)(dataptr-RawGIF));
+     }
+ 
+ 
+@@ -416,9 +484,9 @@
+       /* don't mention bad block if file was trunc'd, as it's all bogus */
+       if ((dataptr - origptr) < filesize) {
+ 	sprintf(str, "Unknown block type (0x%02x) at offset 0x%lx",
+-		block, (dataptr - origptr) - 1);
++		block, (unsigned long)(dataptr - origptr) - 1);
+ 
+-	if (!gotimage) return gifError(pinfo, str);
++	if (!pinfo->numpages) return gifError(pinfo, str);
+ 	else gifWarning(str);
+       }
+ 
+@@ -431,8 +499,34 @@
+   free(RawGIF);	 RawGIF = NULL;
+   free(Raster);  Raster = NULL;
+ 
+-  if (!gotimage) 
++  if (!pinfo->numpages)
+      return( gifError(pinfo, "no image data found in GIF file") );
++  if (pinfo->numpages > 1) {
++    /* write the last page temp file */
++    int numpages = pinfo->numpages;
++    char *comment = pinfo->comment;
++    sprintf(tmpname, "%s%d", pinfo->pagebname, pinfo->numpages);
++    fp = xv_fopen(tmpname, "w");
++    if (!fp) {
++      ErrPopUp("LoadGIF: Unable to open temp file", "\nDang!");
++      return 0;
++    }
++    if (WriteGIF(fp, pinfo->pic, pinfo->type, pinfo->w, pinfo->h, pinfo->r,
++		 pinfo->g, pinfo->b, numcols, pinfo->colType, NULL)) {
++      fclose(fp);
++      ErrPopUp("LoadGIF: Error writing temp file", "\nBummer!");
++      return 0;
++    }
++    fclose(fp);
++    free(pinfo->pic);
++    pinfo->pic = (byte *) NULL;
++
++    /* load the first page temp file */
++    sprintf(tmpname, "%s%d", pinfo->pagebname, 1);
++    i = LoadGIF(tmpname, pinfo);
++    pinfo->numpages = numpages;
++    pinfo->comment = comment;
++  }
+ 
+   return 1;
+ }
+@@ -444,11 +538,12 @@
+ {
+   register byte ch, ch1, *ptr1, *picptr;
+   int           i, npixels, maxpixels;
++  boolean       HasLocalColormap;
+ 
+   npixels = maxpixels = 0;
+ 
+   /* read in values from the image descriptor */
+-  
++
+   ch = NEXTBYTE;
+   LeftOfs = ch + 0x100 * NEXTBYTE;
+   ch = NEXTBYTE;
+@@ -460,45 +555,68 @@
+ 
+   Misc = NEXTBYTE;
+   Interlace = ((Misc & INTERLACEMASK) ? True : False);
++  HasLocalColormap = ((Misc & COLORMAPMASK) ? True : False);
+ 
+-  if (Misc & 0x80) {
+-    for (i=0; i< 1 << ((Misc&7)+1); i++) {
++  if (HasLocalColormap) {
++    BitsPerPixel = (Misc & 7) + 1;
++    ColorMapSize = numcols = 1 << BitsPerPixel;  /* GRR 20070318 */
++    BitMask = ColorMapSize - 1;
++    if (DEBUG) fprintf(stderr,"  local color table, %d bits (%d entries)\n",
++      (Misc&7)+1, ColorMapSize);
++    for (i=0; i<ColorMapSize; i++) {
+       pinfo->r[i] = NEXTBYTE;
+       pinfo->g[i] = NEXTBYTE;
+       pinfo->b[i] = NEXTBYTE;
+     }
++    if (DEBUG > 1) {
++      for (i=0; i<ColorMapSize; i++) {
++        fprintf(stderr,"    (%3d  %02x,%02x,%02x)\n", i, pinfo->r[i],
++          pinfo->g[i], pinfo->b[i]);
++      }
++    }
+   }
+ 
+ 
+-  if (!HasColormap && !(Misc&0x80)) {
++  if (!HasGlobalColormap && !HasLocalColormap) {
+     /* no global or local colormap */
+-    SetISTR(ISTR_WARNING, "%s:  %s", bname, 
++    SetISTR(ISTR_WARNING, "%s:  %s", bname,
+ 	    "No colormap in this GIF file.  Assuming EGA colors.");
+   }
+-    
+ 
+-  
++
++  /* GRR 19980314 */
++  /* need not worry about size of EGA palette:  full 256 colors */
++  if (have_imagebg && Transparent >= 0 &&
++      Transparent < ((Misc&0x80)? (1 << ((Misc&7)+1)) : ColorMapSize) )
++  {
++    pinfo->r[Transparent] = (imagebgR >> 8);
++    pinfo->g[Transparent] = (imagebgG >> 8);
++    pinfo->b[Transparent] = (imagebgB >> 8);
++  }
++
++
++
+   /* Start reading the raster data. First we get the intial code size
+    * and compute decompressor constant values, based on this code size.
+    */
+-  
++
+   CodeSize = NEXTBYTE;
+ 
+   ClearCode = (1 << CodeSize);
+   EOFCode = ClearCode + 1;
+   FreeCode = FirstFree = ClearCode + 2;
+-  
++
+   /* The GIF spec has it that the code size is the code size used to
+    * compute the above values is the code size given in the file, but the
+    * code size used in compression/decompression is the code size given in
+    * the file plus one. (thus the ++).
+    */
+-  
++
+   CodeSize++;
+   InitCodeSize = CodeSize;
+   MaxCode = (1 << CodeSize);
+   ReadMask = MaxCode - 1;
+-  
++
+ 
+ 
+   /* UNBLOCK:
+@@ -506,7 +624,7 @@
+    * to the Raster array, turning it from a series of blocks into one long
+    * data stream, which makes life much easier for readCode().
+    */
+-  
++
+   ptr1 = Raster;
+   do {
+     ch = ch1 = NEXTBYTE;
+@@ -522,21 +640,24 @@
+ 
+ 
+   if (DEBUG) {
+-    fprintf(stderr,"xv: LoadGIF() - picture is %dx%d, %d bits, %sinterlaced\n",
++    fprintf(stderr,"LoadGIF: image is %dx%d, %d bits, %sinterlaced\n",
+ 	    Width, Height, BitsPerPixel, Interlace ? "" : "non-");
+   }
+-  
++
+ 
+   /* Allocate the 'pic' */
+-  maxpixels = Width*Height;
++  maxpixels = Width*Height;  /* 65535*65535 max (but everything is int) */
++  if (Width <= 0 || Height <= 0 || maxpixels/Width != Height)
++    return( gifError(pinfo, "image dimensions out of range") );
+   picptr = pic8 = (byte *) malloc((size_t) maxpixels);
+-  if (!pic8) return( gifError(pinfo, "couldn't malloc 'pic8'") );
++  if (!pic8) FatalError("LoadGIF: couldn't malloc 'pic8'");
++
++
+ 
+-  
+   /* Decompress the file, continuing until you see the GIF EOF code.
+    * One obvious enhancement is to add checking for corrupt files here.
+    */
+-  
++
+   Code = readCode();
+   while (Code != EOFCode) {
+     /* Clear code sets everything back to its initial value, then reads the
+@@ -563,58 +684,58 @@
+ 			    break; }
+ 
+       CurCode = InCode = Code;
+-      
++
+       /* If greater or equal to FreeCode, not in the hash table yet;
+        * repeat the last character decoded
+        */
+-      
++
+       if (CurCode >= FreeCode) {
+ 	CurCode = OldCode;
+ 	if (OutCount > 4096) {  /* printf("outcount1 blew up\n"); */ break; }
+ 	OutCode[OutCount++] = FinChar;
+       }
+-      
++
+       /* Unless this code is raw data, pursue the chain pointed to by CurCode
+        * through the hash table to its end; each code in the chain puts its
+        * associated output code on the output queue.
+        */
+-      
++
+       while (CurCode > BitMask) {
+ 	if (OutCount > 4096) break;   /* corrupt file */
+ 	OutCode[OutCount++] = Suffix[CurCode];
+ 	CurCode = Prefix[CurCode];
+       }
+-      
++
+       if (OutCount > 4096) { /* printf("outcount blew up\n"); */ break; }
+-      
++
+       /* The last code in the chain is treated as raw data. */
+-      
++
+       FinChar = CurCode & BitMask;
+       OutCode[OutCount++] = FinChar;
+-      
++
+       /* Now we put the data out to the Output routine.
+        * It's been stacked LIFO, so deal with it that way...
+        */
+ 
+       /* safety thing:  prevent exceeding range of 'pic8' */
+       if (npixels + OutCount > maxpixels) OutCount = maxpixels-npixels;
+-	
++
+       npixels += OutCount;
+       if (!Interlace) for (i=OutCount-1; i>=0; i--) *picptr++ = OutCode[i];
+                 else  for (i=OutCount-1; i>=0; i--) doInterlace(OutCode[i]);
+       OutCount = 0;
+ 
+       /* Build the hash table on-the-fly. No table is stored in the file. */
+-      
++
+       Prefix[FreeCode] = OldCode;
+       Suffix[FreeCode] = FinChar;
+       OldCode = InCode;
+-      
++
+       /* Point to the next slot in the table.  If we exceed the current
+        * MaxCode value, increment the code size unless it's already 12.  If it
+        * is, do nothing: the next code decompressed better be CLEAR
+        */
+-      
++
+       FreeCode++;
+       if (FreeCode >= MaxCode) {
+ 	if (CodeSize < 12) {
+@@ -627,20 +748,19 @@
+     Code = readCode();
+     if (npixels >= maxpixels) break;
+   }
+-  
++
+   if (npixels != maxpixels) {
+     SetISTR(ISTR_WARNING,"%s:  %s", bname,
+ 	    "This GIF file seems to be truncated.  Winging it.");
+     if (!Interlace)  /* clear->EOBuffer */
+-      xvbzero((char *) pic8+npixels, (size_t) (maxpixels-npixels));
++      xvbzero((char *) pic8+npixels,
++	      (size_t) (maxpixels-npixels<0 ? 0 : maxpixels-npixels));
+   }
+ 
+-  fclose(fp);
+-
+   /* fill in the PICINFO structure */
+ 
+   pinfo->pic     = pic8;
+-  pinfo->w       = Width;           
++  pinfo->w       = Width;
+   pinfo->h       = Height;
+   pinfo->type    = PIC8;
+   pinfo->frmType = F_GIF;
+@@ -650,8 +770,8 @@
+ 
+   sprintf(pinfo->fullInfo,
+ 	  "GIF%s, %d bit%s per pixel, %sinterlaced.  (%d bytes)",
+- 	  (gif89) ? "89" : "87", BitsPerPixel, 
+-	  (BitsPerPixel==1) ? "" : "s", 
++ 	  (gif89) ? "89" : "87", BitsPerPixel,
++	  (BitsPerPixel==1) ? "" : "s",
+  	  Interlace ? "" : "non-", filesize);
+ 
+   sprintf(pinfo->shrtInfo, "%dx%d GIF%s.",Width,Height,(gif89) ? "89" : "87");
+@@ -668,13 +788,13 @@
+  * maintain our location in the Raster array as a BIT Offset.  We compute
+  * the byte Offset into the raster array by dividing this by 8, pick up
+  * three bytes, compute the bit Offset into our 24-bit chunk, shift to
+- * bring the desired code to the bottom, then mask it off and return it. 
++ * bring the desired code to the bottom, then mask it off and return it.
+  */
+ 
+ static int readCode()
+ {
+   int RawCode, ByteOffset;
+-  
++
+   ByteOffset = BitOffset / 8;
+   RawCode = Raster[ByteOffset] + (Raster[ByteOffset + 1] << 8);
+   if (CodeSize >= 8)
+@@ -692,42 +812,47 @@
+ {
+   static byte *ptr = NULL;
+   static int   oldYC = -1;
+-  
++
++  if (Pass == -1) {  /* first time through - init stuff */
++    oldYC = -1;
++    Pass = 0;
++  }
++
+   if (oldYC != YC) {  ptr = pic8 + YC * Width;  oldYC = YC; }
+-  
++
+   if (YC<Height)
+     *ptr++ = Index;
+-  
++
+   /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
+-  
++
+   if (++XC == Width) {
+-    
++
+     /* deal with the interlace as described in the GIF
+      * spec.  Put the decoded scan line out to the screen if we haven't gone
+      * past the bottom of it
+      */
+-    
++
+     XC = 0;
+-    
++
+     switch (Pass) {
+     case 0:
+       YC += 8;
+       if (YC >= Height) { Pass++; YC = 4; }
+       break;
+-      
++
+     case 1:
+       YC += 8;
+       if (YC >= Height) { Pass++; YC = 2; }
+       break;
+-      
++
+     case 2:
+       YC += 4;
+       if (YC >= Height) { Pass++; YC = 1; }
+       break;
+-      
++
+     case 3:
+       YC += 2;  break;
+-      
++
+     default:
+       break;
+     }
+@@ -735,11 +860,11 @@
+ }
+ 
+ 
+-      
++
+ /*****************************/
+ static int gifError(pinfo, st)
+-     PICINFO *pinfo;
+-     char    *st;
++     PICINFO    *pinfo;
++     const char *st;
+ {
+   gifWarning(st);
+ 
+@@ -760,7 +885,7 @@
+ 
+ /*****************************/
+ static void gifWarning(st)
+-     char *st;
++     const char *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", bname, st);
+ }
+diff -ru xv-3.10a/xvgifwr.c xv-3.10a-enhancements/xvgifwr.c
+--- xv-3.10a/xvgifwr.c	1995-01-03 13:22:21.000000000 -0800
++++ xv-3.10a-enhancements/xvgifwr.c	2007-03-31 16:33:23.000000000 -0700
+@@ -2,11 +2,11 @@
+  * xvgifwr.c  -  handles writing of GIF files.  based on flgife.c and
+  *               flgifc.c from the FBM Library, by Michael Maudlin
+  *
+- * Contains: 
++ * Contains:
+  *   WriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
+  *            comment)
+  *
+- * Note: slightly brain-damaged, in that it'll only write non-interlaced 
++ * Note: slightly brain-damaged, in that it'll only write non-interlaced
+  *       GIF files (in the interests of speed, or something)
+  *
+  */
+@@ -34,7 +34,7 @@
+  *	James A. Woods          (decvax!ihnp4!ames!jaw)
+  *	Joe Orost               (decvax!vax135!petsd!joe)
+  *****************************************************************/
+- 
++
+ 
+ #include "xv.h"
+ 
+@@ -44,7 +44,6 @@
+ static int  curx, cury;
+ static long CountDown;
+ static int  Interlace;
+-static byte bw[2] = {0, 0xff};
+ 
+ static void putword     PARM((int, FILE *));
+ static void compress    PARM((int, FILE *, byte *, int));
+@@ -56,7 +55,7 @@
+ static void flush_char  PARM((void));
+ 
+ 
+-static byte pc2nc[256],r1[256],g1[256],b1[256];
++static byte pc2nc[256];
+ 
+ 
+ /*************************************************************/
+@@ -74,7 +73,8 @@
+   int   ColorMapSize, InitCodeSize, Background, BitsPerPixel;
+   int   i,j,nc;
+   byte *pic8;
+-  byte  rtemp[256],gtemp[256],btemp[256];
++  byte  rtemp[256],gtemp[256],btemp[256];  /* for 24-bit to 8-bit conversion */
++  byte  r1[256],g1[256],b1[256];           /* for duplicated-color remapping */
+ 
+   if (ptype == PIC24) {  /* have to quantize down to 8 bits */
+     pic8 = Conv24to8(pic, w, h, 256, rtemp,gtemp,btemp);
+@@ -97,7 +97,7 @@
+   for (i=0; i<numcols; i++) {
+     /* see if color #i is already used */
+     for (j=0; j<i; j++) {
+-      if (rmap[i] == rmap[j] && gmap[i] == gmap[j] && 
++      if (rmap[i] == rmap[j] && gmap[i] == gmap[j] &&
+ 	  bmap[i] == bmap[j]) break;
+     }
+ 
+@@ -115,15 +115,15 @@
+   /* figure out 'BitsPerPixel' */
+   for (i=1; i<8; i++)
+     if ( (1<<i) >= nc) break;
+-  
++
+   BitsPerPixel = i;
+ 
+   ColorMapSize = 1 << BitsPerPixel;
+-	
++
+   RWidth  = Width  = w;
+   RHeight = Height = h;
+   LeftOfs = TopOfs = 0;
+-	
++
+   CountDown = w * h;    /* # of pixels we'll be doing */
+ 
+   if (BitsPerPixel <= 1) InitCodeSize = 2;
+@@ -137,7 +137,7 @@
+     return (1);
+   }
+ 
+-  if (DEBUG) 
++  if (DEBUG)
+     fprintf(stderr,"WrGIF: pic=%lx, w,h=%dx%d, numcols=%d, Bits%d,Cmap=%d\n",
+ 	    (u_long) pic8, w,h,numcols,BitsPerPixel,ColorMapSize);
+ 
+@@ -152,7 +152,7 @@
+   i = 0x80;	                 /* Yes, there is a color map */
+   i |= (8-1)<<4;                 /* OR in the color resolution (hardwired 8) */
+   i |= (BitsPerPixel - 1);       /* OR in the # of bits per pixel */
+-  fputc(i,fp);          
++  fputc(i,fp);
+ 
+   fputc(Background, fp);         /* background color */
+ 
+@@ -290,7 +290,7 @@
+ /*
+  * compress stdin to stdout
+  *
+- * Algorithm:  use open addressing double hashing (no chaining) on the 
++ * Algorithm:  use open addressing double hashing (no chaining) on the
+  * prefix code / next character combination.  We do a variant of Knuth's
+  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+  * secondary probe.  Here, the modular division first probe is gives way
+@@ -370,7 +370,7 @@
+   cl_hash( (count_int) hsize_reg);            /* clear hash table */
+ 
+   output(ClearCode);
+-    
++
+   while (len) {
+     c = pc2nc[*data++];  len--;
+     in_count++;
+@@ -399,7 +399,7 @@
+       continue;
+     }
+ 
+-    if ( (long)HashTabOf (i) >= 0 ) 
++    if ( (long)HashTabOf (i) >= 0 )
+       goto probe;
+ 
+ nomatch:
+@@ -454,7 +454,7 @@
+     cur_accum |= ((long)code << cur_bits);
+   else
+     cur_accum = code;
+-	
++
+   cur_bits += n_bits;
+ 
+   while( cur_bits >= 8 ) {
+@@ -482,7 +482,7 @@
+ 	maxcode = MAXCODE(n_bits);
+     }
+   }
+-	
++
+   if( code == EOFCode ) {
+     /* At EOF, write the rest of the buffer */
+     while( cur_bits > 0 ) {
+@@ -492,11 +492,11 @@
+     }
+ 
+     flush_char();
+-	
++
+     fflush( g_outfile );
+ 
+ #ifdef FOO
+-    if( ferror( g_outfile ) ) 
++    if( ferror( g_outfile ) )
+       FatalError("unable to write GIF file");
+ #endif
+   }
+@@ -582,7 +582,7 @@
+ int c;
+ {
+   accum[ a_count++ ] = c;
+-  if( a_count >= 254 ) 
++  if( a_count >= 254 )
+     flush_char();
+ }
+ 
+@@ -596,4 +596,4 @@
+     fwrite(accum, (size_t) 1, (size_t) a_count, g_outfile );
+     a_count = 0;
+   }
+-}	
++}
+diff -ru xv-3.10a/xvgrab.c xv-3.10a-enhancements/xvgrab.c
+--- xv-3.10a/xvgrab.c	1994-12-22 14:34:47.000000000 -0800
++++ xv-3.10a-enhancements/xvgrab.c	2005-04-25 23:39:32.000000000 -0700
+@@ -6,7 +6,7 @@
+  *  Contains:
+  *     int Grab()             - handles the GRAB command
+  *     int LoadGrab();        - 'loads' the pic from the last succesful Grab
+- *            
++ *
+  */
+ 
+ #include "copyright.h"
+@@ -14,28 +14,60 @@
+ #define NEEDSTIME
+ #include "xv.h"
+ 
+-static byte *grabPic = (byte *) NULL;
+-static int  gbits;                              /* either '8' or '24' */
+-static byte grabmapR[256], grabmapG[256], grabmapB[256];  /* colormap */
+-static int  gWIDE,gHIGH;
+-static int  grabInProgress=0;
+-static int  hidewins = 0;
+-static GC   rootGC;
+-
+-static void   flashrect       PARM((int, int, int, int, int));
+-static void   startflash      PARM((void));
+-static void   endflash        PARM((void));
+-static int    grabImage       PARM((Window, int, int, int, int));
+-static void   ungrabX         PARM((void));
+-static int    convertImage    PARM((XImage *, XColor *, int, 
+-				    XWindowAttributes *));
+-
+-static int    lowbitnum       PARM((unsigned long));
+-static int    getxcolors      PARM((XWindowAttributes *, XColor **));
+-static Window xvClientWindow  PARM((Display *, Window));
++/* Allow flexibility in use of buttons JPD */
++#define WINDOWGRABMASK Button1Mask  /* JPD prefers Button2Mask */
++#define RECTGTRACKMASK Button2Mask  /* JPD prefers Button1Mask*/
++#define CANCELGRABMASK Button3Mask
+ 
++#define DO_GRABFLASH  /* JPD prefers not to do that; just a loss of time ... */
+ 
+ 
++union swapun {
++  CARD32 l;
++  CARD16 s;
++  CARD8  b[sizeof(CARD32)];
++};
++
++
++struct rectlist {
++  int x,y,w,h;
++  struct rectlist *next;
++};
++
++
++static byte            *grabPic = (byte *) NULL;
++static int              gptype;
++static byte             grabmapR[256], grabmapG[256], grabmapB[256];
++static int              gXOFF, gYOFF, gWIDE,gHIGH;
++static int              grabInProgress=0;
++static int              hidewins = 0;
++static GC               rootGC;
++static struct rectlist *regrabList;
++
++
++static void   flashrect           PARM((int, int, int, int, int));
++static void   startflash          PARM((void));
++static void   endflash            PARM((void));
++static void   ungrabX             PARM((void));
++static int    lowbitnum           PARM((unsigned long));
++static int    getxcolors          PARM((XWindowAttributes *, XColor **));
++
++static void   printWinTree        PARM((Window, int));
++static void   errSpace            PARM((int));
++
++static int    grabRootRegion      PARM((int, int, int, int));
++static int    grabWinImage        PARM((Window, VisualID, Colormap, int));
++static int    convertImageAndStuff PARM((XImage *, XColor *, int,
++					 XWindowAttributes *,
++					 int,int,int,int));
++
++static int    RectIntersect       PARM((int,int,int,int, int,int,int,int));
++
++static int    CountColors24       PARM((byte *, int, int,
++					int, int, int, int));
++
++static int    Trivial24to8        PARM((byte *, int, int, byte *,
++					byte *, byte *, byte *, int));
+ 
+ /***********************************/
+ int Grab()
+@@ -44,13 +76,15 @@
+      0 if cancelled */
+ 
+   int          i, x, y, x1, y1, x2, y2, ix, iy, iw, ih, rv;
+-  int          rx, ry, pretendGotB1, autograb;
+-  int          oldaclose;
+-  Window       rW, cW, clickWin, tmpwin;
++  int          rx, ry, GotButton, autograb;
++  int          cancelled = 0;
++  Window       rW, cW, clickWin;
+   unsigned int mask;
++#ifdef RECOLOR_GRAB_CURSOR
+   XColor       fc, bc;
++#endif
+ 
+-  pretendGotB1 = 0;
++  GotButton = 0;
+ 
+   if (grabInProgress) return 0;      /* avoid recursive grabs during delay */
+ 
+@@ -75,7 +109,7 @@
+     grabInProgress = 1; /* guard against recursive grabs during delay */
+     time(&startT);
+     while (1) {
+-      time(&t);  
++      time(&t);
+       if (t >= startT + grabDelay) break;
+       if (XPending(theDisp)>0) {
+ 	XEvent evt;
+@@ -91,25 +125,33 @@
+     grabInProgress = 0;
+   }
+ 
+-  
++
+   rootGC   = DefaultGC(theDisp, theScreen);
+-  
++
+   if (grabPic) {  /* throw away previous 'grabbed' pic, if there is one */
+     free(grabPic);  grabPic = (byte *) NULL;
+   }
+ 
+-
++  /* recolor cursor to indicate that grabbing is active? */
++  /* Instead, change cursor JPD */
++#ifdef RECOLOR_GRAB_CURSOR
+   fc.flags = bc.flags = DoRed | DoGreen | DoBlue;
+-  fc.red = fc.green = fc.blue = 0xffff;  
++  fc.red = fc.green = fc.blue = 0xffff;
+   bc.red = bc.green = bc.blue = 0x0000;
+   XRecolorCursor(theDisp, tcross, &fc, &bc);
++#endif
+ 
+ 
+   XBell(theDisp, 0);		/* beep once at start of grab */
+ 
+-  if (!autograb) XGrabButton(theDisp, (u_int) AnyButton, 0, rootW, False, 0, 
++  /* Change cursor to top_left_corner JPD */
++  XGrabPointer(theDisp, rootW, False,
++     PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
++     GrabModeAsync, GrabModeAsync, None, tlcorner, CurrentTime);
++
++  if (!autograb) XGrabButton(theDisp, (u_int) AnyButton, 0, rootW, False, 0,
+ 			     GrabModeAsync, GrabModeSync, None, tcross);
+-  
++
+   if (autograb) {
+     XGrabServer(theDisp);	 /* until we've done the grabImage */
+     if (!XQueryPointer(theDisp,rootW,&rW,&cW,&rx,&ry,&x1,&y1,&mask)) {
+@@ -118,7 +160,7 @@
+       rv = 0;
+       goto exit;
+     }
+-    else { pretendGotB1 = 1;  mask = Button1Mask; }
++    else { GotButton = 1;  mask = WINDOWGRABMASK; }
+   }
+ 
+   else {   /* !autograb */
+@@ -136,7 +178,7 @@
+       XNextEvent(theDisp, &evt);
+       i = HandleEvent(&evt, &done);
+       if (done) {                    /* only 'new image' cmd accepted=quit */
+-	if (i==QUIT) { 
++	if (i==QUIT) {
+ 	  XUngrabButton(theDisp, (u_int) AnyButton, 0, rootW);
+ 	  Quit(0);
+ 	}
+@@ -145,99 +187,75 @@
+ 
+     }
+   }
+-  
+-  
++
++  XUngrabPointer(theDisp, CurrentTime);
++  /* Reset cursor to XC_tcross JPD */
++  XGrabPointer(theDisp, rootW, False,
++     PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
++     GrabModeAsync, GrabModeAsync, None, tcross, CurrentTime);
++
+   /***
+    ***  got button click (or pretending we did, if autograb)
+    ***/
+-  
+ 
+-  if (mask & Button3Mask || rW!=rootW) {        /* Button3: CANCEL GRAB */
++  if (mask & CANCELGRABMASK || rW!=rootW) {        /* CANCEL GRAB */
+     while (1) {      /* wait for button to be released */
+       if (XQueryPointer(theDisp,rootW,&rW,&cW,&rx,&ry,&x1,&y1,&mask)) {
+-	if (!(mask & Button3Mask)) break;
++	if (!(mask & CANCELGRABMASK)) break;
+       }
+     }
+-    
++
+     XUngrabButton(theDisp, (u_int) AnyButton, 0, rootW);
+     XBell(theDisp, 0);
+     XBell(theDisp, 0);
+     rv = 0;
++    cancelled = 1;
+     goto exit;
+   }
+ 
+ 
+-
+-  if (mask & Button1Mask) {  /* Button1:  GRAB WINDOW (& FRAME, maybe)     */
+-    while (!pretendGotB1) {  /* wait for button to be released, if clicked */
++  if (mask & WINDOWGRABMASK) {  /* GRAB WINDOW (& FRAME, maybe)     */
++    while (!GotButton) {  /* wait for button to be released, if clicked */
+       int rx,ry,x1,y1;  Window rW, cW;
+       if (XQueryPointer(theDisp,rootW,&rW,&cW,&rx,&ry,&x1,&y1,&mask)) {
+-	if (!(mask & Button1Mask)) break;
++	if (!(mask & WINDOWGRABMASK)) break;
+       }
+     }
+-    
+-    if (!cW || cW == rootW) clickWin = rootW;
+-    else {
+-      int xr, yr;    Window chwin;
+-      XTranslateCoordinates(theDisp, rW, cW, rx, ry, &xr, &yr, &chwin);
+-      if (chwin != None) {
+-	XWindowAttributes clickxwa, parentxwa;
+-
+-	clickWin = xvClientWindow(theDisp, chwin);
+-
+-	/* decide if we want to just grab clickWin, or cW.
+-	   basically, if they're different in any important way 
+-	   (depth, visual, colormap), grab 'clickWin' only, 
+-	   as it's the important part */
+-
+-	if (!clickWin || 
+-	    (XGetWindowAttributes(theDisp, clickWin, &clickxwa)  &&
+-	     XGetWindowAttributes(theDisp, cW,       &parentxwa) &&
+-	     clickxwa.visual->class == parentxwa.visual->class   &&
+-	     clickxwa.colormap      == parentxwa.colormap        &&
+-	     clickxwa.depth         == parentxwa.depth)
+-	    )
+-	  clickWin = cW;   	  /* close enough! */
+-      }
+-      else clickWin = cW;
+-      
+-      if (DEBUG) 
+-	fprintf(stderr, "rW = %x, cW = %x, chwin = %x, clickWin = %x\n",
+-		(u_int) rW, (u_int) cW, (u_int) chwin, (u_int) clickWin);
+-    }
+-    
+-    
++
++  grabwin:
++
++    clickWin = (cW) ? cW : rootW;
++
+     if (clickWin == rootW) {   /* grab entire screen */
+       if (DEBUG) fprintf(stderr,"Grab: clicked on root window.\n");
+       ix = iy = 0;  iw = dispWIDE;  ih = dispHIGH;
+     }
+     else {
+       int x,y;  Window win;   unsigned int rw,rh,rb,rd;
+-      
++
+       if (XGetGeometry(theDisp,clickWin,&rW, &x, &y, &rw, &rh, &rb, &rd)) {
+ 	iw = (int) rw;  ih = (int) rh;
+-	
++
+ 	XTranslateCoordinates(theDisp, clickWin, rootW, 0, 0, &ix,&iy, &win);
+-	
+-	if (DEBUG) fprintf(stderr,"clickWin=0x%x: %d,%d %dx%d depth=%ud\n", 
+-			   (u_int) clickWin, ix, iy, iw, ih, rd);    
++
++	if (DEBUG) fprintf(stderr,"clickWin=0x%x: %d,%d %dx%d depth=%ud\n",
++			   (u_int) clickWin, ix, iy, iw, ih, rd);
+       }
+       else {
+ 	ix = iy = 0;  iw = dispWIDE;  ih = dispHIGH;  clickWin = rootW;
+ 	if (DEBUG) fprintf(stderr,"XGetGeometry failed? (using root win)\n");
+       }
+     }
+-    
+-    
++
+     /* range checking:  keep rectangle fully on-screen */
+     if (ix<0) { iw += ix;  ix = 0; }
+     if (iy<0) { ih += iy;  iy = 0; }
+     if (ix+iw>dispWIDE) iw = dispWIDE-ix;
+     if (iy+ih>dispHIGH) ih = dispHIGH-iy;
+-    
+-    
++
++
+     if (DEBUG) fprintf(stderr,"using %d,%d (%dx%d)\n", ix, iy, iw, ih);
+-    
++
+     /* flash the rectangle a bit... */
+     startflash();
+     for (i=0; i<5; i++) {
+@@ -249,23 +267,21 @@
+     endflash();
+   }
+ 
+-
+-  else {  /* Button2:  TRACK A RECTANGLE */
++  else {  /* TRACK A RECTANGLE */
+     int    origrx, origry;
+-    Window origcW;
+ 
+-    clickWin = rootW;  origcW = cW;
++    clickWin = rootW;
+     origrx = ix = x2 = rx;
+     origry = iy = y2 = ry;
+     iw = ih = 0;
+-    
++
+     XGrabServer(theDisp);
+     startflash();
+ 
+     /* Wait for button release while tracking rectangle on screen */
+     while (1) {
+       if (XQueryPointer(theDisp,rootW,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
+-	if (!(mask & Button2Mask)) break;
++	if (!(mask & RECTGTRACKMASK)) break;
+       }
+ 
+       flashrect(ix, iy, iw, ih, 0);                /* turn off rect */
+@@ -276,57 +292,63 @@
+ 	iw = abs(rx - x1);  ih = abs(ry - y1);
+ 	x2 = rx;  y2 = ry;
+       }
+-      
++
+       if (iw>1 && ih>1) flashrect(ix,iy,iw,ih,1);  /* turn on rect */
+     }
+ 
+     flashrect(ix, iy, iw, ih, 0);                  /* turn off rect */
++
++#ifdef DO_GRABFLASH
++    /* flash the rectangle a bit... */
++    for (i=0; i<5; i++) {
++      flashrect(ix, iy, iw, ih, 1);
++      XFlush(theDisp);  Timer(100);
++      flashrect(ix, iy, iw, ih, 0);
++      XFlush(theDisp);  Timer(100);
++    }
++#endif
++
+     endflash();
+-    
+-    XUngrabServer(theDisp);
+-    
+-    
+-    if (origcW == cW) {  /* maybe it's entirely in one window??? */
+-      if (cW) {    /* will be 0 if clicked in rootW */
+-	Window stwin, enwin, stwin1, enwin1;
+-	if (DEBUG) fprintf(stderr,"origcW=%x cW=%x   ", 
+-			   (u_int) origcW, (u_int) cW);
+-	XTranslateCoordinates(theDisp,rootW,cW, origrx,origry,&x,&y,&stwin);
+-	XTranslateCoordinates(theDisp,rootW,cW, rx,    ry,    &x,&y,&enwin);
+-	
+-	if (DEBUG) fprintf(stderr,"stwin=%x enwin=%x   ", 
+-			   (u_int) stwin, (u_int) enwin);
+-	if (stwin == enwin && stwin != None) {
+-	  stwin1 = xvClientWindow(theDisp, stwin);
+-	  enwin1 = xvClientWindow(theDisp, enwin);
+-	  if (DEBUG) fprintf(stderr,"stwin1=%x enwin1=%x   ", 
+-			     (u_int) stwin1, (u_int) enwin1);
+-	  
+-	  if (stwin1 == enwin1 && stwin1) clickWin = stwin1;
+-	  else clickWin = stwin;
+-	}
+-	if (DEBUG) fprintf(stderr,"\n");
+-      }
+-      else clickWin = rootW;
++
++    /* if rectangle has zero width or height, search for child window JPD */
++    if (iw==0 && ih==0) {
++       int xr, yr;
++       Window childW = 0;
++       if (rW && cW)
++          XTranslateCoordinates(theDisp, rW, cW, rx, ry, &xr, &yr, &childW);
++       if (childW)
++          cW = childW;
++       goto grabwin;
+     }
++
++    XUngrabServer(theDisp);
+   }
+-  
+ 
+   /***
+-   ***  now that clickWin,ix,iy,iw,ih are known, try to grab the bits...
++   ***  now that clickWin,ix,iy,iw,ih are known, try to grab the bits :
++   ***  grab screen area (ix,iy,iw,ih)
+    ***/
+ 
+ 
++  if (DEBUG>1) printWinTree(clickWin, 0);
++
+   WaitCursor();
+ 
+   if (!autograb) XGrabServer(theDisp);	 /* until we've done the grabImage */
+-  rv = grabImage(clickWin,ix,iy,iw,ih);  /* ungrabs the server & button */
++  rv = grabRootRegion(ix, iy, iw, ih);   /* ungrabs the server & button */
+ 
+   SetCursors(-1);
+ 
+-
+  exit:
+ 
++  XUngrabPointer(theDisp, CurrentTime);
++  XUngrabServer(theDisp);
++
++  if (startGrab) {
++    startGrab = 0;
++    if (cancelled) Quit(0);
++  }
++
+   if (hidewins) {                   /* remap XV windows */
+     autoclose += 2;                 /* force it on once */
+     if (mainW && dispMode == RMB_WINDOW) {
+@@ -337,25 +359,25 @@
+ 
+       if (DEBUG) fprintf(stderr,"==remapped mainW.  waiting for Config.\n");
+ 
+-      /* sit here until we see a MapNotify on mainW followed by a 
++      /* sit here until we see a MapNotify on mainW followed by a
+ 	 ConfigureNotify on mainW */
+ 
+       state = 0;
+-      while (1) {
++      while (state != 3) {
+ 	XEvent event;
+ 	XNextEvent(theDisp, &event);
+ 	HandleEvent(&event, &i);
+ 
+-	if (state==0 && event.type == MapNotify &&
+-	    event.xmap.window == mainW) state = 1;
++	if (!(state&1) && event.type == MapNotify &&
++	    event.xmap.window == mainW) state |= 1;
+ 
+-	if (state==1 && event.type == ConfigureNotify && 
+-	    event.xconfigure.window == mainW) break;
++	if (!(state&2) && event.type == ConfigureNotify &&
++	    event.xconfigure.window == mainW) state |= 2;
+       }
+ 
+       if (DEBUG) fprintf(stderr,"==after remapping mainW, GOT Config.\n");
+     }
+-      
++
+     else if (ctrlW) CtrlBox(1);
+   }
+ 
+@@ -364,6 +386,45 @@
+ 
+ 
+ /***********************************/
++int LoadGrab(pinfo)
++     PICINFO *pinfo;
++{
++  /* loads up (into XV structures) last image successfully grabbed.
++     returns '0' on failure, '1' on success */
++
++  int   i;
++
++  if (!grabPic) return 0;   /* no image to use */
++
++  pinfo->type = gptype;
++  if (pinfo->type == PIC8) {
++    for (i=0; i<256; i++) {
++      pinfo->r[i] = grabmapR[i];
++      pinfo->g[i] = grabmapG[i];
++      pinfo->b[i] = grabmapB[i];
++    }
++  }
++
++  pinfo->pic     = grabPic;
++  pinfo->normw   = pinfo->w   = gWIDE;
++  pinfo->normh   = pinfo->h   = gHIGH;
++  pinfo->frmType = -1;
++  pinfo->colType = -1;
++
++  sprintf(pinfo->fullInfo,"<%s internal>",
++	  (pinfo->type == PIC8) ? "8-bit" : "24-bit");
++
++  sprintf(pinfo->shrtInfo,"%dx%d image.",gWIDE, gHIGH);
++
++  pinfo->comment = (char *) NULL;
++
++  grabPic = (byte *) NULL;
++
++  return 1;
++}
++
++
++/***********************************/
+ static void flashrect(x,y,w,h,show)
+      int x,y,w,h,show;
+ {
+@@ -373,7 +434,7 @@
+   XSetPlaneMask(theDisp, rootGC, xorMasks[maskno]);
+ 
+   if (!show) {     /* turn off rectangle */
+-    if (isvis) 
++    if (isvis)
+       XDrawRectangle(theDisp, rootW, rootGC, x, y, (u_int) w-1, (u_int) h-1);
+ 
+     isvis = 0;
+@@ -391,15 +452,16 @@
+ 
+ /***********************************/
+ static void startflash()
+-{  
++{
+   /* set up for drawing a flashing rectangle */
+   XSetFunction(theDisp, rootGC, GXinvert);
+   XSetSubwindowMode(theDisp, rootGC, IncludeInferiors);
+ }
+ 
++
+ /***********************************/
+ static void endflash()
+-{  
++{
+   XSetFunction(theDisp, rootGC, GXcopy);
+   XSetSubwindowMode(theDisp, rootGC, ClipByChildren);
+   XSetPlaneMask(theDisp, rootGC, AllPlanes);
+@@ -408,21 +470,157 @@
+ 
+ 
+ /***********************************/
+-static int grabImage(clickWin, x, y, w, h)
+-     Window clickWin;
++static void ungrabX()
++{
++  XUngrabServer(theDisp);
++  XUngrabButton(theDisp, (u_int) AnyButton, 0, rootW);
++}
++
++
++/**************************************/
++static int lowbitnum(ul)
++     unsigned long ul;
++{
++  /* returns position of lowest set bit in 'ul' as an integer (0-31),
++   or -1 if none */
++
++  int i;
++  for (i=0; ((ul&1) == 0) && i<32;  i++, ul>>=1);
++  if (i==32) i = -1;
++  return i;
++}
++
++
++
++/**********************************************/
++/* getxcolors() function snarfed from 'xwd.c' */
++/**********************************************/
++
++#define lowbit(x) ((x) & (~(x) + 1))
++
++static int getxcolors(win_info, colors)
++     XWindowAttributes *win_info;
++     XColor **colors;
++{
++  int i, ncolors;
++
++  *colors = (XColor *) NULL;
++
++  if (win_info->visual->class == TrueColor) {
++    if (DEBUG>1) fprintf(stderr,"TrueColor visual:  no colormap needed\n");
++    return 0;
++  }
++
++  else if (!win_info->colormap) {
++    if (DEBUG>1) fprintf(stderr,"no colormap associated with window\n");
++    return 0;
++  }
++
++  ncolors = win_info->visual->map_entries;
++  if (DEBUG>1) fprintf(stderr,"%d entries in colormap\n", ncolors);
++
++  if (!(*colors = (XColor *) malloc (sizeof(XColor) * ncolors)))
++    FatalError("malloc failed in getxcolors()");
++
++
++  if (win_info->visual->class == DirectColor) {
++    Pixel red, green, blue, red1, green1, blue1;
++
++    if (DEBUG>1) fprintf(stderr,"DirectColor visual\n");
++
++    red = green = blue = 0;
++    red1   = lowbit(win_info->visual->red_mask);
++    green1 = lowbit(win_info->visual->green_mask);
++    blue1  = lowbit(win_info->visual->blue_mask);
++    for (i=0; i<ncolors; i++) {
++      (*colors)[i].pixel = red|green|blue;
++      (*colors)[i].pad = 0;
++      red += red1;
++      if (red > win_info->visual->red_mask)     red = 0;
++      green += green1;
++      if (green > win_info->visual->green_mask) green = 0;
++      blue += blue1;
++      if (blue > win_info->visual->blue_mask)   blue = 0;
++    }
++  }
++  else {
++    for (i=0; i<ncolors; i++) {
++      (*colors)[i].pixel = i;
++      (*colors)[i].pad = 0;
++    }
++  }
++
++  XQueryColors(theDisp, win_info->colormap, *colors, ncolors);
++
++  return(ncolors);
++}
++
++
++
++/*******************************************/
++static void printWinTree(win,tab)
++     Window win;
++     int    tab;
++{
++  u_int             i, nchildren;
++  Window            root, parent, *children, chwin;
++  XWindowAttributes xwa;
++  int               xr, yr;
++
++  if (!XGetWindowAttributes(theDisp, win, &xwa)) {
++    errSpace(tab);
++    fprintf(stderr,"pWT: can't XGetWindowAttributes(%08x)\n", (u_int) win);
++    return;
++  }
++
++  XTranslateCoordinates(theDisp, win, rootW, 0,0, &xr,&yr, &chwin);
++  if (xwa.map_state==IsViewable) {
++    errSpace(tab);
++    fprintf(stderr,"%08x: %4d,%4d %4dx%4d vis: %02x  cm=%x  %s\n",
++	    (u_int) win, xr,yr, xwa.width, xwa.height,
++	    (u_int) XVisualIDFromVisual(xwa.visual),
++	    (u_int) xwa.colormap,
++	    ((xwa.map_state==IsUnmapped)      ? "unmapped  "  :
++	     (xwa.map_state==IsUnviewable)    ? "unviewable"  :
++	     (xwa.map_state==IsViewable)      ? "viewable  "  :
++	     "<unknown> ")       );
++
++    if (!XQueryTree(theDisp, win, &root, &parent, &children, &nchildren)) {
++      errSpace(tab);
++      fprintf(stderr,"pWT: XQueryTree(%08x) failed\n", (u_int) win);
++      if (children) XFree((char *)children);
++      return;
++    }
++
++    for (i=0; i<nchildren; i++) printWinTree(children[i], tab+1);
++    if (children) XFree((char *)children);
++  }
++
++  return;
++}
++
++
++/***********************************/
++static void errSpace(n)
++     int n;
++{
++  for ( ; n>0; n--) putc(' ', stderr);
++}
++
++
++
++
++/***********************************/
++static int grabRootRegion(x, y, w, h)
+      int    x, y, w, h;
+ {
+   /* attempts to grab the specified rectangle of the root window
+-     returns '1' on success.  clickWin is used to figure out the depth
+-     and colormap to use */
++     returns '1' on success */
+ 
+-  XImage *image;
+-  XWindowAttributes xwa;
+-  XColor *colors;
+-  int ncolors, i, ix, iy;
+-  char str[256];
+-  Window win;
++  XWindowAttributes  xwa;
++  int                i;
+ 
++  regrabList = (struct rectlist *) NULL;
+ 
+   /* range checking */
+   if (x<0) { w += x;  x = 0; }
+@@ -430,86 +628,246 @@
+   if (x+w>dispWIDE) w = dispWIDE-x;
+   if (y+h>dispHIGH) h = dispHIGH-y;
+ 
+-  if (w==0 || h==0) {  /* selected nothing */
++  if (w<=0 || h<=0) {  /* selected nothing */
+     ungrabX();
+     return 0;
+   }
+ 
+-  if (!XGetWindowAttributes(theDisp, clickWin, &xwa)) {
+-    sprintf(str,"Unable to get window attributes for clicked-on window\n");
++
++  /* grab this region, using the default (root's) visual */
++
++  /* now for all top-level windows (children of root), in bottom->top order
++     if they intersect the grabregion
++       are they drawn entirely (including children) using default visual+cmap?
++       yes: if they intersect 'regrab' list, grab'em - else skip'em
++       no:  grab them, add their rectangle to 'regrab' list
++   */
++
++
++  /* make a 24bit grabPic */
++  gptype = PIC24;
++  gXOFF = x;  gYOFF = y;  gWIDE = w;  gHIGH = h;
++  grabPic = (byte *) malloc((size_t) gWIDE * gHIGH * 3);
++  if (!grabPic) {
+     ungrabX();
+-    ErrPopUp(str, "\nThat Sucks!");
++    ErrPopUp("Unable to malloc() space for grabbed image!", "\nBite Me!");
+     return 0;
+   }
+ 
+-
+-  XTranslateCoordinates(theDisp, rootW, clickWin, x, y, &ix, &iy, &win);
+-
+-  xerrcode = 0;
+-  image = XGetImage(theDisp, clickWin, ix, iy, (u_int) w, (u_int) h, 
+-		    AllPlanes, ZPixmap);
+-  if (xerrcode || !image || !image->data) {
+-    sprintf(str, "Unable to get image (%d,%d %dx%d) from display", ix,iy,w,h);
++  if (!XGetWindowAttributes(theDisp, rootW, &xwa)) {
+     ungrabX();
+-    ErrPopUp(str, "\nThat Sucks!");
++    ErrPopUp("Can't get window attributes for root window!", "\nBite Me!");
+     return 0;
+   }
+ 
+-  ncolors = getxcolors(&xwa, &colors);
++  i = grabWinImage(rootW, XVisualIDFromVisual(xwa.visual), xwa.colormap,0);
+ 
+   ungrabX();
+ 
+-  if (ncolors && DEBUG) {
+-    fprintf(stderr, "Colormap:\n");
+-    for (i=0; i<ncolors; i++)
+-      fprintf(stderr,"%02x%02x%02x  ",colors[i].red>>8, colors[i].green>>8,
+-	      colors[i].blue>>8);
+-    fprintf(stderr,"\n");
+-  }
+-
+-
+   XBell(theDisp, 0);    /* beep twice at end of grab */
+   XBell(theDisp, 0);
+ 
+-  i = convertImage(image, colors, ncolors, &xwa);
++  { /* free regrabList */
++    struct rectlist *rr, *tmprr;
++    rr = regrabList;
++    while (rr) {
++      tmprr = rr->next;
++      free((char *) rr);
++      rr = tmprr;
++    }
++    regrabList = (struct rectlist *) NULL;
++  }
+ 
+-  /* DO *NOT* use xvDestroyImage(), as the 'data' field was alloc'd by X, not
+-     necessarily through 'malloc() / free()' */
+-  XDestroyImage(image);   
+-  
+-  if (colors) free((char *) colors);
++  if (i) {
++    ErrPopUp("Warning: Problems occurred during grab.","\nWYSInWYG!");
++    return 0;
++  }
+ 
+-  return i;
++
++  /* if 256 or fewer colors in grabPic, make it a PIC8 */
++  i = CountColors24(grabPic, gWIDE, gHIGH, 0,0,gWIDE,gHIGH);
++  if (i<=256) {
++    byte *pic8;
++    pic8 = (byte *) malloc((size_t) (gWIDE * gHIGH));
++    if (pic8) {
++      if (Trivial24to8(grabPic, gWIDE,gHIGH, pic8,
++		       grabmapR,grabmapG,grabmapB,256)) {
++	free((char *) grabPic);
++	grabPic = pic8;
++	gptype = PIC8;
++      }
++    }
++  }
++
++  return 1;  /* full success */
+ }
+ 
+ 
+-static void ungrabX()
++/***********************************/
++static int grabWinImage(win, parentVid, parentCmap, toplevel)
++     Window win;
++     VisualID           parentVid;
++     Colormap           parentCmap;
++     int                toplevel;
+ {
+-  XUngrabServer(theDisp);
+-  XUngrabButton(theDisp, (u_int) AnyButton, 0, rootW);
+-}
++  /* grabs area of window (and its children) that intersects
++   * grab region (root coords: gXOFF,gYOFF,gWIDE,gHIGH), and stuffs
++   * relevant bits into the grabPic (a gWIDE*gHIGH PIC24)
++   *
++   * Note: special kludge for toplevel windows (children of root):
++   * since that's the only case where a window can be obscuring something
++   * that isn't its parent
++   *
++   * returns 0 if okay, 1 if problems occurred
++   */
++
++
++  int               i, rv, dograb;
++  int               wx, wy, ww, wh;      /* root coords of window */
++  int               gx, gy, gw, gh;      /* root coords of grab region of win*/
++  Window            chwin;               /* unused */
++  u_int             nchildren;
++  Window            root, parent, *children;
++  XWindowAttributes xwa;
+ 
++  /* first, quick checks to avoid recursing down useless branches */
+ 
++  if (!XGetWindowAttributes(theDisp, win, &xwa)) {
++    if (DEBUG) fprintf(stderr,"gWI: can't get win attr (%08x)\n", (u_int) win);
++    return 1;
++  }
+ 
++  if (xwa.class == InputOnly || xwa.map_state != IsViewable) return 0;
+ 
++  rv     = 0;
++  dograb = 1;
++  wx = 0;  wy = 0;  ww = (int) xwa.width;  wh = (int) xwa.height;
++
++  /* if this window doesn't intersect, none of its children will, either */
++  XTranslateCoordinates(theDisp, win, rootW, 0,0, &wx, &wy, &chwin);
++  if (!RectIntersect(wx,wy,ww,wh, gXOFF,gYOFF,gWIDE,gHIGH)) return 0;
++
++  gx = wx;  gy = wy;  gw = ww;  gh = wh;
++  CropRect2Rect(&gx,&gy,&gw,&gh, gXOFF,gYOFF,gWIDE,gHIGH);
++
++  if (win==rootW) {
++    /* always grab */
++  }
++
++  else if (XVisualIDFromVisual(xwa.visual) == parentVid &&
++	   ((xwa.visual->class==TrueColor) || xwa.colormap == parentCmap)) {
++
++    /* note: if both visuals are TrueColor, don't compare cmaps */
++
++    /* normally, if the vis/cmap info of a window is the same as its parent,
++       no need to regrab window.  special case if this is a toplevel
++       window, as it can be obscuring windows that *aren't* its parent */
++
++    if (toplevel) {
++      /* we probably already have this region.  Check it against regrabList
++	 If it intersects none, no need to grab.
++	 If it intersects one,  crop to that rectangle and grab
++	 if it intersects >1,   don't crop, just grab gx,gy,gw,gh */
++
++      struct rectlist *rr, *cr;
++
++      i=0; cr=rr=regrabList;
++      while (rr) {
++	if (RectIntersect(gx,gy,gw,gh, rr->x,rr->y,rr->w,rr->h)) {
++	  i++;  cr = rr;
++	}
++	rr = rr->next;
++      }
++
++      if (i==0) dograb=0;   /* no need to grab */
++
++      if (i==1) CropRect2Rect(&gx,&gy,&gw,&gh, cr->x,cr->y,cr->w,cr->h);
++    }
++    else dograb = 0;
++  }
++
++  else {
++    /* different vis/cmap from parent:
++       add to regrab list, if not already fully contained in list */
++    struct rectlist *rr;
++
++    /* check to see if fully contained... */
++    rr=regrabList;
++    while (rr && RectIntersect(gx,gy,gw,gh, rr->x,rr->y,rr->w,rr->h)!=2)
++      rr = rr->next;
++
++    if (!rr) {   /* add to list */
++      if (DEBUG)
++	fprintf(stderr,"added to regrabList: %d,%d %dx%d\n",gx,gy,gw,gh);
++
++      rr = (struct rectlist *) malloc(sizeof(struct rectlist));
++      if (!rr) return 1;
++      else {
++	rr->x = gx;  rr->y = gy;  rr->w = gw;  rr->h = gh;
++	rr->next = regrabList;
++	regrabList = rr;
++      }
++    }
++  }
++
++  /* at this point, we have to grab gx,gy,gw,gh from 'win' */
++
++  if (dograb) {
++    int     ix, iy, ncolors;
++    XColor *colors;
++    XImage *image;
++
++    XTranslateCoordinates(theDisp, rootW, win, gx, gy, &ix, &iy, &chwin);
++
++    if (DEBUG)
++      fprintf(stderr,"Grabbing win (%08x) %d,%d %dx%d\n",
++	      (u_int) win, gx,gy,gw,gh);
++
++    WaitCursor();
++
++    xerrcode = 0;
++    image = XGetImage(theDisp, win, ix, iy, (u_int) gw, (u_int) gh,
++		      AllPlanes, ZPixmap);
++    if (xerrcode || !image || !image->data) return 1;
++
++    ncolors = getxcolors(&xwa, &colors);
++    rv = convertImageAndStuff(image, colors, ncolors, &xwa,
++			      gx - gXOFF, gy - gYOFF, gw, gh);
++    XDestroyImage(image);   /* can't use xvDestroyImage: alloc'd by X! */
++    if (colors) free((char *) colors);
++  }
++
++
++  /* recurse into children to see if any of them are 'different'... */
++
++  if (!XQueryTree(theDisp, win, &root, &parent, &children, &nchildren)) {
++    if (DEBUG) fprintf(stderr,"XQueryTree(%08x) failed\n", (u_int) win);
++    if (children) XFree((char *)children);
++    return rv+1;
++  }
++
++  for (i=0; i<nchildren; i++) {
++    rv += grabWinImage(children[i], XVisualIDFromVisual(xwa.visual),
++		       xwa.colormap, (win==rootW));
++  }
++  if (children) XFree((char *)children);
++
++  return rv;
++}
+ 
+-union swapun {
+-  CARD32 l;
+-  CARD16 s;
+-  CARD8  b[sizeof(CARD32)];
+-};
+ 
+ 
+ /**************************************/
+-static int convertImage(image, colors, ncolors, xwap)
++static int convertImageAndStuff(image, colors, ncolors, xwap, gx,gy,gw,gh)
+      XImage *image;
+      XColor *colors;
+      int     ncolors;
+      XWindowAttributes *xwap;
++     int     gx,gy,gw,gh;      /* position within grabPic (guaranteed OK) */
+ {
+-  /* attempts to conver the image from whatever weird-ass format it might
+-     be in into something E-Z to deal with (either an 8-bit colormapped
+-     image, or a 24-bit image).  Returns '1' on success. */
++  /* attempts to convert the image from whatever weird-ass format it might
++     be in into a 24-bit RGB image, and stuff it into grabPic
++     Returns 0 on success, 1 on failure */
+ 
+   /* this code owes a lot to 'xwdtopnm.c', part of the pbmplus package,
+      written by Jef Poskanzer */
+@@ -528,7 +886,6 @@
+   int            isLsbMachine, flipBytes;
+   Visual         *visual;
+   char            errstr[256];
+-  static char    *foo[] = { "\nThat Sucks!" };
+ 
+ 
+   /* quiet compiler warnings */
+@@ -538,20 +895,20 @@
+   pixvalue  = 0;
+   rmask  = gmask  = bmask = 0;
+   rshift = gshift = bshift = 0;
+-
++  r8shift = g8shift = b8shift = 0;
+ 
+   /* determine byte order of the machine we're running on */
+   sw.l = 1;
+   isLsbMachine = (sw.b[0]) ? 1 : 0;
+ 
+-  if (xwap && xwap->visual) visual = xwap->visual;
+-                       else visual = theVisual;
++  visual = xwap->visual;
++
+ 
+-  if (DEBUG) {
++  if (DEBUG>1) {
+     fprintf(stderr,"convertImage:\n");
+     fprintf(stderr,"  %dx%d (offset %d), %s\n",
+-	    image->width, image->height, image->xoffset, 
+-	    (image->format == XYBitmap || image->format == XYPixmap) 
++	    image->width, image->height, image->xoffset,
++	    (image->format == XYBitmap || image->format == XYPixmap)
+ 	    ? "XYPixmap" : "ZPixmap");
+ 
+     fprintf(stderr,"byte_order = %s, bitmap_bit_order = %s, unit=%d, pad=%d\n",
+@@ -575,41 +932,17 @@
+     sprintf(errstr, "%s\nReturned image bitmap_unit (%d) non-standard.",
+ 	    "Can't deal with this display.", image->bitmap_unit);
+     ErrPopUp(errstr, "\nThat Sucks!");
+-    return 0;
++    return 1;
+   }
+ 
+   if (!ncolors && visual->class != TrueColor) {
+     sprintf(errstr, "%s\nOnly TrueColor displays can have no colormap.",
+ 	    "Can't deal with this display.");
+     ErrPopUp(errstr, "\nThat Sucks!");
+-    return 0;
++    return 1;
+   }
+ 
+ 
+-  /* build the 'global' grabPic stuff */
+-  gWIDE = image->width;  gHIGH = image->height;
+-
+-  if (visual->class == TrueColor || visual->class == DirectColor ||
+-      ncolors > 256) {
+-    grabPic = (byte *) malloc((size_t) gWIDE * gHIGH * 3);
+-    gbits = 24;
+-  }
+-  else {
+-    grabPic = (byte *) malloc((size_t) gWIDE * gHIGH);
+-    gbits = 8;
+-
+-    /* load up the colormap */
+-    for (i=0; i<ncolors; i++) {
+-      grabmapR[i] = colors[i].red   >> 8;
+-      grabmapG[i] = colors[i].green >> 8;
+-      grabmapB[i] = colors[i].blue  >> 8;
+-    }
+-  }
+-  
+-  if (!grabPic) FatalError("unable to malloc grabPic in convertImage()");
+-  pptr = grabPic;
+-
+-
+   if (visual->class == TrueColor || visual->class == DirectColor) {
+     unsigned int tmp;
+ 
+@@ -634,16 +967,35 @@
+     while (tmp >= 256) { tmp >>= 1;  b8shift -= 1; }
+     while (tmp < 128)  { tmp <<= 1;  b8shift += 1; }
+ 
+-    if (DEBUG)
++    if (DEBUG>1)
+       fprintf(stderr,"True/DirectColor: shifts=%d,%d,%d  8shifts=%d,%d,%d\n",
+ 	      rshift, gshift, bshift, r8shift, g8shift, b8shift);
+   }
+ 
+ 
+-  bits_per_item = image->bitmap_unit;
+-  bits_used = bits_per_item;
++  bits_per_item  = image->bitmap_unit;
+   bits_per_pixel = image->bits_per_pixel;
+ 
++
++  /* add code for freako 'exceed' server, where bitmapunit = 8
++     and bitsperpix = 32 (and depth=24)... */
++
++  if (bits_per_item < bits_per_pixel) {
++    bits_per_item = bits_per_pixel;
++
++    /* round bits_per_item up to next legal value, if necc */
++    if      (bits_per_item <  8) bits_per_item = 8;
++    else if (bits_per_item < 16) bits_per_item = 16;
++    else                         bits_per_item = 32;
++  }
++
++
++  /* which raises the question:  how (can?) you ever have a 24 bits per pix,
++     (ie, 3 bytes, no alpha/padding) */
++
++
++  bits_used = bits_per_item;  /* so it will get a new item first time */
++
+   if (bits_per_pixel == 32) pixmask = 0xffffffff;
+   else pixmask = (((CARD32) 1) << bits_per_pixel) - 1;
+ 
+@@ -652,14 +1004,15 @@
+ 
+   /* if we're on an lsbfirst machine, or the image came from an lsbfirst
+      machine, we should flip the bytes around.  NOTE:  if we're on an
+-     lsbfirst machine *and* the image came from an lsbfirst machine, 
++     lsbfirst machine *and* the image came from an lsbfirst machine,
+      *don't* flip bytes, as it should work out */
+ 
+-  /* pity we don't have a logical exclusive-or */
+   flipBytes = ( isLsbMachine && byte_order != LSBFirst) ||
+               (!isLsbMachine && byte_order == LSBFirst);
+ 
+   for (i=0; i<image->height; i++) {
++    pptr = grabPic + ((i+gy) * gWIDE + gx) * 3;
++
+     lineptr = (byte *) image->data + (i * image->bytes_per_line);
+     bptr = ((CARD8  *) lineptr) - 1;
+     sptr = ((CARD16 *) lineptr) - 1;
+@@ -667,35 +1020,39 @@
+     bits_used = bits_per_item;
+ 
+     for (j=0; j<image->width; j++) {
+-      
+       /* get the next pixel value from the image data */
+ 
+       if (bits_used == bits_per_item) {  /* time to move on to next b/s/l */
+ 	switch (bits_per_item) {
+-	case 8:  bptr++;  break;
+-	case 16: sptr++;  sval = *sptr;
+-	         if (flipBytes) {   /* swap CARD16 */
+-		   sw.s = sval;
+-		   tmpbyte = sw.b[0];
+-		   sw.b[0] = sw.b[1];
+-		   sw.b[1] = tmpbyte;
+-		   sval = sw.s;
+-		 }
+-	         break;
+-	case 32: lptr++;  lval = *lptr;
+-	         if (flipBytes) {   /* swap CARD32 */
+-		   sw.l = lval;
+-		   tmpbyte = sw.b[0];
+-		   sw.b[0] = sw.b[3];
+-		   sw.b[3] = tmpbyte;
+-		   tmpbyte = sw.b[1];
+-		   sw.b[1] = sw.b[2];
+-		   sw.b[2] = tmpbyte;
+-		   lval = sw.l;
+-		 }
+-	         break;
++	case 8:
++	  bptr++;  break;
++
++	case 16:
++	  sptr++;  sval = *sptr;
++	  if (flipBytes) {   /* swap CARD16 */
++	    sw.s = sval;
++	    tmpbyte = sw.b[0];
++	    sw.b[0] = sw.b[1];
++	    sw.b[1] = tmpbyte;
++	    sval = sw.s;
++	  }
++	  break;
++
++	case 32:
++	  lptr++;  lval = *lptr;
++	  if (flipBytes) {   /* swap CARD32 */
++	    sw.l = lval;
++	    tmpbyte = sw.b[0];
++	    sw.b[0] = sw.b[3];
++	    sw.b[3] = tmpbyte;
++	    tmpbyte = sw.b[1];
++	    sw.b[1] = sw.b[2];
++	    sw.b[2] = tmpbyte;
++	    lval = sw.l;
++	  }
++	  break;
+ 	}
+-		   
++
+ 	bits_used = 0;
+ 	if (bit_order == MSBFirst) bit_shift = bits_per_item - bits_per_pixel;
+ 	                      else bit_shift = 0;
+@@ -711,11 +1068,11 @@
+                             else bit_shift += bits_per_pixel;
+       bits_used += bits_per_pixel;
+ 
+-      
++
+       /* okay, we've got the next pixel value in 'pixvalue' */
+-      
++
+       if (visual->class == TrueColor || visual->class == DirectColor) {
+-	/* in either case, we have to take the pixvalue and 
++	/* in either case, we have to take the pixvalue and
+ 	   break it out into individual r,g,b components */
+ 	rval = (pixvalue & rmask) >> rshift;
+ 	gval = (pixvalue & gmask) >> gshift;
+@@ -741,212 +1098,165 @@
+ 	/* use pixel value as an index into colors array */
+ 
+ 	if (pixvalue >= ncolors) {
+-	  FatalError("convertImage(): pixvalue >= ncolors");
++	  fprintf(stderr, "WARNING: convertImage(): pixvalue >= ncolors\n");
++	  return 1;
+ 	}
+ 
+-	if (gbits == 24) {   /* too many colors for 8-bit colormap */
+-	  *pptr++ = (colors[pixvalue].red)   >> 8;
+-	  *pptr++ = (colors[pixvalue].green) >> 8;
+-	  *pptr++ = (colors[pixvalue].blue)  >> 8;
+-	}
+-	else *pptr++ = pixvalue & 0xff;
+-
++	*pptr++ = (colors[pixvalue].red)   >> 8;
++	*pptr++ = (colors[pixvalue].green) >> 8;
++	*pptr++ = (colors[pixvalue].blue)  >> 8;
+       }
+     }
+   }
+ 
+-  return 1;
++  return 0;
+ }
+ 
+ 
+ 
+-/**************************************/
+-static int lowbitnum(ul)
+-     unsigned long ul;
++/***********************************/
++static int RectIntersect(ax,ay,aw,ah, bx,by,bw,bh)
++     int ax,ay,aw,ah, bx,by,bw,bh;
+ {
+-  /* returns position of lowest set bit in 'ul' as an integer (0-31),
+-   or -1 if none */
++  /* returns 0 if rectangles A and B do not intersect
++     returns 1 if A partially intersects B
++     returns 2 if rectangle A is fully enclosed by B */
+ 
+-  int i;
+-  for (i=0; ((ul&1) == 0) && i<32;  i++, ul>>=1);
+-  if (i==32) i = -1;
+-  return i;
+-}
++  int ax1,ay1, bx1,by1;
+ 
++  ax1 = ax+aw-1;  ay1 = ay+ah-1;
++  bx1 = bx+bw-1;  by1 = by+bh-1;
+ 
++  if (ax1<bx || ax>bx1 || ay1<by || ay>by1) return 0;
+ 
+-/**************************************/
+-/* following code snarfed from 'xwd.c' */
+-/**************************************/
++  if (ax>=bx && ax1<=bx1 && ay>=by && ay1<=by) return 2;
+ 
+-#define lowbit(x) ((x) & (~(x) + 1))
+-
+-
+-static int getxcolors(win_info, colors)
+-     XWindowAttributes *win_info;
+-     XColor **colors;
+-{
+-  int i, ncolors;
+-  Colormap cmap;
+-
+-  *colors = (XColor *) NULL;
++  return 1;
++}
+ 
+-  if (win_info->visual->class == TrueColor) {
+-    if (DEBUG) fprintf(stderr,"TrueColor visual:  no colormap needed\n");
+-    return 0;
+-  }
+ 
+-  else if (!win_info->colormap) {
+-    if (DEBUG) fprintf(stderr,"no colormap associated with window\n");
+-    return 0;
+-  }
+ 
+-  ncolors = win_info->visual->map_entries;
+-  if (DEBUG) fprintf(stderr,"%d entries in colormap\n", ncolors);
+ 
+-  if (!(*colors = (XColor *) malloc (sizeof(XColor) * ncolors)))
+-    FatalError("malloc failed in getxcolors()");
+ 
++/** stuff needed to make new xvgrab work in 3.10a. **/
+ 
+-  if (win_info->visual->class == DirectColor) {
+-    Pixel red, green, blue, red1, green1, blue1;
++/********************************************/
++static int CountColors24(pic, pwide, phigh, x, y, w, h)
++     byte *pic;
++     int   pwide, phigh, x,y,w,h;
++{
++  /* counts the # of unique colors in a selected rect of a PIC24
++     returns '0-256' or >256 */
+ 
+-    if (DEBUG) fprintf(stderr,"DirectColor visual\n");
++  int    i, j, nc;
++  int    low, high, mid;
++  u_int  colors[257], col;
++  byte   *pp;
++
++  nc = 0;
++
++  for (i=y; nc<257 && i<y+h; i++) {
++    pp = pic + (i*pwide + x)*3;
++
++    for (j=x; nc<257 && j<x+w; j++, pp+=3) {
++      col = (((u_int) pp[0])<<16) + (((u_int) pp[1])<<8) + pp[2];
++
++      /* binary search the 'colors' array to see if it's in there */
++      low = 0;  high = nc-1;
++      while (low <= high) {
++	mid = (low+high)/2;
++	if      (col < colors[mid]) high = mid - 1;
++	else if (col > colors[mid]) low  = mid + 1;
++	else break;
++      }
+ 
+-    red = green = blue = 0;
+-    red1   = lowbit(win_info->visual->red_mask);
+-    green1 = lowbit(win_info->visual->green_mask);
+-    blue1  = lowbit(win_info->visual->blue_mask);
+-    for (i=0; i<ncolors; i++) {
+-      (*colors)[i].pixel = red|green|blue;
+-      (*colors)[i].pad = 0;
+-      red += red1;
+-      if (red > win_info->visual->red_mask)     red = 0;
+-      green += green1;
+-      if (green > win_info->visual->green_mask) green = 0;
+-      blue += blue1;
+-      if (blue > win_info->visual->blue_mask)   blue = 0;
+-    }
+-  }
+-  else {
+-    for (i=0; i<ncolors; i++) {
+-      (*colors)[i].pixel = i;
+-      (*colors)[i].pad = 0;
++      if (high < low) { /* didn't find color in list, add it. */
++	xvbcopy((char *) &colors[low], (char *) &colors[low+1],
++		(nc - low) * sizeof(u_int));
++	colors[low] = col;
++	nc++;
++      }
+     }
+   }
+ 
+-  XQueryColors(theDisp, win_info->colormap, *colors, ncolors);
+-
+-  return(ncolors);
++  return nc;
+ }
+-    
+-
+ 
+ 
+-
+-/***********************************/
+-int LoadGrab(pinfo)
+-     PICINFO *pinfo;
++/****************************/
++static int Trivial24to8(pic24, w,h, pic8, rmap,gmap,bmap, maxcol)
++     byte *pic24, *pic8, *rmap, *gmap, *bmap;
++     int   w,h,maxcol;
+ {
+-  /* loads up (into XV structures) last image successfully grabbed.
+-     returns '0' on failure, '1' on success */
+-
+-  int   i;
+-
+-  if (!grabPic) return 0;   /* no image to use */
+-
+-  if (gbits == 24) pinfo->type = PIC24;
+-  else {
+-    pinfo->type = PIC8;
++  /* scans picture until it finds more than 'maxcol' different colors.  If it
++     finds more than 'maxcol' colors, it returns '0'.  If it DOESN'T, it does
++     the 24-to-8 conversion by simply sticking the colors it found into
++     a colormap, and changing instances of a color in pic24 into colormap
++     indicies (in pic8) */
++
++  unsigned long colors[256],col;
++  int           i, nc, low, high, mid;
++  byte         *p, *pix;
++
++  if (maxcol>256) maxcol = 256;
++
++  /* put the first color in the table by hand */
++  nc = 0;  mid = 0;
++
++  for (i=w*h,p=pic24; i; i--) {
++    col  = (((u_long) *p++) << 16);
++    col += (((u_long) *p++) << 8);
++    col +=  *p++;
++
++    /* binary search the 'colors' array to see if it's in there */
++    low = 0;  high = nc-1;
++    while (low <= high) {
++      mid = (low+high)/2;
++      if      (col < colors[mid]) high = mid - 1;
++      else if (col > colors[mid]) low  = mid + 1;
++      else break;
++    }
+ 
+-    for (i=0; i<256; i++) {
+-      pinfo->r[i] = grabmapR[i];
+-      pinfo->g[i] = grabmapG[i];
+-      pinfo->b[i] = grabmapB[i];
++    if (high < low) { /* didn't find color in list, add it. */
++      if (nc>=maxcol) return 0;
++      xvbcopy((char *) &colors[low], (char *) &colors[low+1],
++	      (nc - low) * sizeof(u_long));
++      colors[low] = col;
++      nc++;
+     }
+   }
+ 
+-  pinfo->pic     = grabPic;
+-  pinfo->normw   = pinfo->w   = gWIDE;
+-  pinfo->normh   = pinfo->h   = gHIGH;
+-  pinfo->frmType = -1;
+-  pinfo->colType = -1;
+ 
+-  sprintf(pinfo->fullInfo,"<%s internal>", 
+-	  (pinfo->type == PIC8) ? "8-bit" : "24-bit");
+-  
+-  sprintf(pinfo->shrtInfo,"%dx%d image.",gWIDE, gHIGH);
+-  
+-  pinfo->comment = (char *) NULL;
++  /* run through the data a second time, this time mapping pixel values in
++     pic24 into colormap offsets into 'colors' */
+ 
+-  grabPic = (byte *) NULL;
+-
+-  return 1;
+-}
+-
+-
+-
+-
+-
+-#include <X11/Xlib.h>
+-#include <X11/Xatom.h>
+-
+-static Window TryChildren PARM((Display *, Window, Atom));
+-
+-/* Find a window with WM_STATE, else return '0' */
+-
+-static Window xvClientWindow (dpy, win)
+-    Display *dpy;
+-    Window win;
+-{
+-    Atom WM_STATE;
+-    Atom type = None;
+-    int format;
+-    unsigned long nitems, after;
+-    unsigned char *data;
+-    Window inf;
+-
+-    WM_STATE = XInternAtom(dpy, "WM_STATE", True);
+-    if (!WM_STATE) return win;
+-
+-    XGetWindowProperty(dpy, win, WM_STATE, 0L, 0L, False, AnyPropertyType,
+-		       &type, &format, &nitems, &after, &data);
+-    if (type) return win;
+-
+-    inf = TryChildren(dpy, win, WM_STATE);
+-
+-    return inf;
+-}
+-
+-static Window TryChildren (dpy, win, WM_STATE)
+-    Display *dpy;
+-    Window win;
+-    Atom WM_STATE;
+-{
+-    Window root, parent;
+-    Window *children;
+-    unsigned int nchildren;
+-    unsigned int i;
+-    Atom type = None;
+-    int format;
+-    unsigned long nitems, after;
+-    unsigned char *data;
+-    Window inf = 0;
+-
+-    if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren))
+-	return 0;
++  for (i=w*h,p=pic24, pix=pic8; i; i--,pix++) {
++    col  = (((u_long) *p++) << 16);
++    col += (((u_long) *p++) << 8);
++    col +=  *p++;
++
++    /* binary search the 'colors' array.  It *IS* in there */
++    low = 0;  high = nc-1;
++    while (low <= high) {
++      mid = (low+high)/2;
++      if      (col < colors[mid]) high = mid - 1;
++      else if (col > colors[mid]) low  = mid + 1;
++      else break;
++    }
+ 
+-    for (i = 0; !inf && (i < nchildren); i++) {
+-	XGetWindowProperty(dpy, children[i], WM_STATE, 0L, 0L, False,
+-			   AnyPropertyType, &type, &format, &nitems,
+-			   &after, &data);
+-	if (type)
+-	  inf = children[i];
++    if (high < low) {
++      fprintf(stderr,"Trivial24to8:  impossible situation!\n");
++      exit(1);
+     }
++    *pix = mid;
++  }
+ 
+-    for (i = 0; !inf && (i < nchildren); i++)
+-      inf = TryChildren(dpy, children[i], WM_STATE);
++  /* and load up the 'desired colormap' */
++  for (i=0; i<nc; i++) {
++    rmap[i] =  colors[i]>>16;
++    gmap[i] = (colors[i]>>8) & 0xff;
++    bmap[i] =  colors[i]     & 0xff;
++  }
+ 
+-    if (children) XFree((char *)children);
+-    return inf;
++  return 1;
+ }
+diff -ru xv-3.10a/xvgraf.c xv-3.10a-enhancements/xvgraf.c
+--- xv-3.10a/xvgraf.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvgraf.c	2007-05-12 14:03:08.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvgraf.c - GRAF window handling functions
+  *
+  * callable functions:
+@@ -52,7 +52,7 @@
+      Window parent;
+      int x,y;
+      unsigned long fg,bg;
+-     char *title;
++     const char *title;
+ {
+   /* NOTE:  CreateGraf does not initialize hands[], nhands, or spline,
+      as these could be initialized by X resources (or whatever),
+@@ -88,7 +88,7 @@
+   gp->win = XCreateSimpleWindow(theDisp, parent, x,y, GWIDE, GHIGH, 1, fg,bg);
+   if (!gp->win) FatalError("can't create graph (main) window");
+ 
+-  gp->gwin = XCreateSimpleWindow(theDisp, gp->win, 2, GHIGH-132, 
++  gp->gwin = XCreateSimpleWindow(theDisp, gp->win, 2, GHIGH-132,
+ 				 128, 128, 1, fg,bg);
+   if (!gp->gwin) FatalError("can't create graph (sub) window");
+ 
+@@ -96,7 +96,7 @@
+     BTCreate(&gp->butts[i], gp->win, GWIDE-GBWIDE-2, 1+i * (GBHIGH + 1),
+ 	     GBWIDE, GBHIGH, (char *) NULL, fg, bg, hicol, locol);
+     gp->butts[i].pix = gfbpix[i];
+-    gp->butts[i].pw = PW;  
++    gp->butts[i].pw = PW;
+     gp->butts[i].ph = PH;
+   }
+ 
+@@ -132,7 +132,7 @@
+ 
+   gp->gammamode = 0;     gp->gamma = 1.0;
+ }
+-  
++
+ 
+ /***************************************************/
+ void RedrawGraf(gp, gwin)
+@@ -148,7 +148,7 @@
+   else {
+     Draw3dRect(gp->win, 0,0, GWIDE-1, GHIGH-1, R3D_OUT, 1, hicol, locol,
+ 	       gp->bg);
+-    
++
+     XSetForeground(theDisp, theGC, gp->fg);
+     XSetBackground(theDisp, theGC, gp->bg);
+     DrawString(gp->win, 2, 1+ASCENT, gp->str);
+@@ -165,11 +165,11 @@
+ {
+   int i,x,y;
+   XPoint  pts[129], *pt;
+-  
++
+ 
+   if (gp->entergamma) {
+-    char *str1 = "Enter gamma";
+-    char *str2 = "value: ";
++    const char *str1 = "Enter gamma";
++    const char *str2 = "value: ";
+ 
+     XSetForeground(theDisp, theGC, gp->fg);
+     XSetBackground(theDisp, theGC, gp->bg);
+@@ -181,15 +181,15 @@
+     x = 10 + StringWidth(str2) + 8;
+     y = 30 + ASCENT + CHIGH + 3;
+     i = StringWidth(gp->gvstr);
+-    if (gp->entergamma < 0 && strlen(gp->gvstr)) { 
++    if (gp->entergamma < 0 && strlen(gp->gvstr)) {
+       /* show string highlited */
+       XFillRectangle(theDisp, gp->gwin, theGC, x-1, y-ASCENT-1,
+ 		     (u_int) i+2, (u_int) CHIGH+2);
+       XSetForeground(theDisp, theGC, gp->bg);
+     }
+-    else 
++    else
+       XDrawLine(theDisp, gp->gwin, theGC, x+i, y-ASCENT, x+i, y+DESCENT);
+-      
++
+     DrawString(gp->gwin, x,y, gp->gvstr);
+ 
+     return;
+@@ -267,7 +267,7 @@
+     if (i<N_GFB) {  /* found one */
+       if (BTTrack(bp)) {  /* it was selected */
+ 	switch (i) {
+-	case GFB_SPLINE: 
++	case GFB_SPLINE:
+ 	case GFB_LINE:
+ 	  gp->gammamode = 0;
+ 
+@@ -312,7 +312,7 @@
+ 	  if (gp->nhands < MAX_GHANDS) {
+ 	    /* find largest x-gap in handles, put new handle in mid */
+ 	    int lgap, lpos, x, y;
+-	    
++
+ 	    lgap = gp->hands[1].x - gp->hands[0].x;
+ 	    lpos = 1;
+ 	    for (j=1; j<gp->nhands-1; j++)
+@@ -320,11 +320,11 @@
+ 		lgap = gp->hands[j+1].x - gp->hands[j].x;
+ 		lpos = j+1;
+ 	      }
+-	  
++
+ 	    /* open up position in hands[] array */
+-	    xvbcopy((char *) &gp->hands[lpos], (char *) &gp->hands[lpos+1], 
++	    xvbcopy((char *) &gp->hands[lpos], (char *) &gp->hands[lpos+1],
+ 		    (gp->nhands - lpos) * sizeof(XPoint));
+-	  
++
+ 	    x = gp->hands[lpos-1].x + lgap/2;
+ 	    y = gp->func[x];
+ 	    gp->hands[lpos].x = x;
+@@ -343,7 +343,7 @@
+ 	      BTSetActive(&gp->butts[GFB_DELH], 1);
+ 	  }
+ 	  break;
+-		       
++
+ 	case GFB_DELH:
+ 	  if (gp->nhands > 2) {
+ 	    /* find (middle) point whose x-distance to previous
+@@ -361,9 +361,9 @@
+ 		mdist = dist;  mpos = j;
+ 	      }
+ 	    }
+-		       
++
+ 	    /* delete position 'mpos' in hands[] array */
+-	    xvbcopy((char *) &gp->hands[mpos+1], (char *) &gp->hands[mpos], 
++	    xvbcopy((char *) &gp->hands[mpos+1], (char *) &gp->hands[mpos],
+ 		    (gp->nhands-mpos-1) * sizeof(XPoint));
+ 
+ 	    gp->nhands--;
+@@ -408,16 +408,16 @@
+ 
+ 	/* keep original mouse position in 'mx,my', and warp mouse to center
+ 	   of screen */
+-	grab = !XGrabPointer(theDisp, gp->gwin, False, 0, GrabModeAsync, 
++	grab = !XGrabPointer(theDisp, gp->gwin, False, 0, GrabModeAsync,
+ 			  GrabModeAsync, None, inviso, (Time) CurrentTime);
+-	XWarpPointer(theDisp, None, rootW, 0,0,0,0, 
++	XWarpPointer(theDisp, None, rootW, 0,0,0,0,
+ 		     (int) dispWIDE/2, (int) dispHIGH/2);
+ 
+-	origx = dispWIDE/2;  origy = dispHIGH/2;  
++	origx = dispWIDE/2;  origy = dispHIGH/2;
+ 	orighx = gp->hands[h].x;  orighy = gp->hands[h].y;
+ 
+ 	gp->gammamode = 0;
+-	offx = gp->hands[h].x - origx;  
++	offx = gp->hands[h].x - origx;
+ 	offy = gp->hands[h].y - origy;
+ 
+ 	vertonly = (h==0 || h==(gp->nhands-1));
+@@ -434,7 +434,7 @@
+ 
+ 	  dx = x - origx;  dy = origy - y;   /* flip y axis */
+ 
+-	  /* new (virt) position of handle is (desired) 
++	  /* new (virt) position of handle is (desired)
+ 	     orighx + dx, orighy + dy */
+ 
+ 	  if (!vertonly) { /* keep this handle between its neighbors */
+@@ -448,7 +448,7 @@
+ 	  if (newx != gp->hands[h].x || newy != gp->hands[h].y) {
+ 	    /* this handle has moved... */
+ 	    XSetForeground(theDisp, theGC, gp->bg);
+-	    XFillRectangle(theDisp, gp->gwin, theGC, 
++	    XFillRectangle(theDisp, gp->gwin, theGC,
+ 		     (gp->hands[h].x/2)-3, ((255-gp->hands[h].y)/2)-3, 7,7);
+ 
+ 	    gp->hands[h].x = newx;  gp->hands[h].y = newy;
+@@ -464,7 +464,7 @@
+ 	}
+ 
+ 	drawHandPos(gp, -1);
+-	XWarpPointer(theDisp, None, gp->gwin, 0,0,0,0, 
++	XWarpPointer(theDisp, None, gp->gwin, 0,0,0,0,
+ 		     gp->hands[h].x/2, (255-gp->hands[h].y)/2);
+ 	if (grab) XUngrabPointer(theDisp, (Time) CurrentTime);
+       }
+@@ -480,24 +480,24 @@
+      int   hnum;
+ {
+   int w;
+-  char *tstr = "888,888";
+-  
++  const char *tstr = "888,888";
++
+   /* if hnum < 0, clears the text area */
+-  
++
+   XSetFont(theDisp, theGC, monofont);
+   w = XTextWidth(monofinfo, tstr, (int) strlen(tstr));
+ 
+-  if (hnum >= 0) sprintf(str,"%3d,%3d",gp->hands[hnum].x,gp->hands[hnum].y);
+-            else sprintf(str,"       ");
++  if (hnum >= 0) sprintf(dummystr,"%3d,%3d",gp->hands[hnum].x,gp->hands[hnum].y);
++            else sprintf(dummystr,"       ");
+ 
+   XSetForeground(theDisp, theGC, gp->fg);
+   XSetBackground(theDisp, theGC, gp->bg);
+-  XDrawImageString(theDisp, gp->win, theGC, 130-w, 1+ASCENT, 
+-		   str, (int) strlen(str));
++  XDrawImageString(theDisp, gp->win, theGC, 130-w, 1+ASCENT,
++		   dummystr, (int) strlen(dummystr));
+ 
+   XSetFont(theDisp, theGC, mfont);
+ }
+-  
++
+ 
+ /***************************************************/
+ int GrafKey(gp,str)
+@@ -518,7 +518,7 @@
+   }
+ 
+   while (*str) {
+-    if (gp->entergamma == -1 && 
++    if (gp->entergamma == -1 &&
+ 	(*str != '\012' && *str != '\015' && *str != '\033')) {
+       gp->entergamma = 1;
+       gp->gvstr[0] = '\0';
+@@ -529,7 +529,7 @@
+     len = strlen(gp->gvstr);
+ 
+     if (*str>= '0' && *str <= '9') {
+-      if (len < GVMAX) { 
++      if (len < GVMAX) {
+ 	gp->gvstr[len++] = *str;
+   	gp->gvstr[len] = '\0';
+ 	ok = 1;
+@@ -607,18 +607,18 @@
+ 
+   /* do sanity check.  (x-coords must be sorted (strictly increasing)) */
+ 
+-  for (i=0; i<gp->nhands; i++) { 
+-    RANGE(gp->hands[i].x, 0, 255); 
++  for (i=0; i<gp->nhands; i++) {
++    RANGE(gp->hands[i].x, 0, 255);
+     RANGE(gp->hands[i].y, 0, 255);
+   }
+ 
+   gp->hands[0].x = 0;  gp->hands[gp->nhands-1].x = 255;
+   for (i=1; i<gp->nhands-1; i++) {
+     if (gp->hands[i].x < i)  gp->hands[i].x = i;
+-    if (gp->hands[i].x > 256-gp->nhands+i)  
++    if (gp->hands[i].x > 256-gp->nhands+i)
+         gp->hands[i].x = 256-gp->nhands+i;
+ 
+-    if (gp->hands[i].x <= gp->hands[i-1].x) 
++    if (gp->hands[i].x <= gp->hands[i-1].x)
+       gp->hands[i].x = gp->hands[i-1].x + 1;
+   }
+ 
+@@ -647,17 +647,17 @@
+     else {   /* gp->gamma == 0.0 */
+       for (i=0; i<256; i++) gp->func[i] = 0;
+     }
+-      
+-    
++
++
+     for (i=0; i<gp->nhands; i++) {
+       gp->hands[i].y = gp->func[gp->hands[i].x];
+     }
+   }
+-   
++
+   else if (!gp->spline) {  /* do linear interpolation */
+       int y,x1,y1,x2,y2;
+       double yd;
+-      
++
+       for (i=0; i<gp->nhands-1; i++) {
+ 	x1 = gp->hands[ i ].x;  y1 = gp->hands[ i ].y;
+ 	x2 = gp->hands[i+1].x;  y2 = gp->hands[i+1].y;
+@@ -676,12 +676,12 @@
+     double yf[MAX_GHANDS];
+     double yd;
+ 
+-    for (i=0; i<gp->nhands; i++) { 
++    for (i=0; i<gp->nhands; i++) {
+       x[i] = gp->hands[i].x;  y[i] = gp->hands[i].y;
+     }
+-    
++
+     InitSpline(x, y, gp->nhands, yf);
+-  
++
+     for (i=0; i<256; i++) {
+       yd = EvalSpline(x, y, yf, gp->nhands, (double) i);
+       j = (int) floor(yd + 0.5);
+@@ -729,8 +729,8 @@
+ 
+ /*********************/
+ int Str2Graf(gp, str)
+-GRAF_STATE *gp;
+-char *str;
++     GRAF_STATE *gp;
++     const char *str;
+ {
+   /* parses strings of the form: "S 3 : 0,0 : 63,63 : 255,255",
+      (meaning SPLINE, 3 points, and the 3 sets of handle coordinates)
+@@ -744,14 +744,15 @@
+      thing tends to break optimizers */
+ 
+   char   tstr[256], tstr1[256], *sp, *dp;
++  const char *csp;
+   XPoint coords[MAX_GHANDS];
+   int    spline, nhands, i, x, y;
+ 
+   if (!str) return 1;  /* NULL strings don't parse well! */
+ 
+   /* first, strip all pesky whitespace from str */
+-  for (sp=str, dp=tstr; *sp; sp++) 
+-    if (*sp > ' ') { *dp = *sp;  dp++; }
++  for (csp=str, dp=tstr; *csp; csp++)
++    if (*csp > ' ') { *dp = *csp;  dp++; }
+   *dp = '\0';
+ 
+   /* check for 'gamma'-style str */
+@@ -761,10 +762,10 @@
+       gp->gammamode = 1;
+       sprintf(gp->gvstr, "%.5g", gp->gamma);
+       return 0;
+-      }
++    }
+     else return 1;
+   }
+-    
++
+   /* read Spline, or Line (S/L) character */
+   sp = tstr;
+   if      (*sp == 'S' || *sp == 's') spline = 1;
+@@ -784,7 +785,7 @@
+     while (*sp && *sp != ':') {*dp = *sp;  dp++;  sp++; }
+     *dp++ = '\0';
+     if (sscanf(tstr1,"%d,%d",&x, &y) != 2) return 1;
+-    if (x < 0 || x > 255 || 
++    if (x < 0 || x > 255 ||
+ 	y < 0 || y > 255) return 1;  /* out of range */
+     coords[i].x = x;  coords[i].y = y;
+   }
+@@ -837,7 +838,7 @@
+   IFSET(gp->gamma,      gsp->gamma);
+   IFSET(gp->nhands,     gsp->nhands);
+ 
+-  if (strcmp(gp->gvstr, gsp->gvstr)) 
++  if (strcmp(gp->gvstr, gsp->gvstr))
+     { strcpy(gp->gvstr, gsp->gvstr);  rv++; }
+ 
+   for (i=0; i<gp->nhands; i++) {
+@@ -880,7 +881,7 @@
+     sig = ((double) x[i]-x[i-1]) / ((double) x[i+1] - x[i-1]);
+     p = sig * y2[i-1] + 2.0;
+     y2[i] = (sig-1.0) / p;
+-    u[i] = (((double) y[i+1]-y[i]) / (x[i+1]-x[i])) - 
++    u[i] = (((double) y[i+1]-y[i]) / (x[i+1]-x[i])) -
+            (((double) y[i]-y[i-1]) / (x[i]-x[i-1]));
+     u[i] = (6.0 * u[i]/(x[i+1]-x[i-1]) - sig*u[i-1]) / p;
+   }
+@@ -912,9 +913,9 @@
+   if (h==0.0) FatalError("bad xvalues in splint\n");
+   a = (xa[khi]-x)/h;
+   b = (x-xa[klo])/h;
+-  return (a*ya[klo] + b*ya[khi] + ((a*a*a-a)*y2a[klo] +(b*b*b-b)*y2a[khi]) 
++  return (a*ya[klo] + b*ya[khi] + ((a*a*a-a)*y2a[klo] +(b*b*b-b)*y2a[khi])
+ 	  * (h*h) / 6.0);
+ }
+-    
++
+ 
+ 
+diff -ru xv-3.10a/xviff.c xv-3.10a-enhancements/xviff.c
+--- xv-3.10a/xviff.c	1995-01-13 11:54:54.000000000 -0800
++++ xv-3.10a-enhancements/xviff.c	2007-05-13 17:50:59.000000000 -0700
+@@ -39,14 +39,14 @@
+ 
+ static long filesize;
+ 
+-static int           readID       PARM((FILE *, char *));
+-static int           iffError     PARM((char *, char *));
++/* static int           readID       PARM((FILE *, char *));  DOES NOT EXIST */
++static int           iffError     PARM((const char *, const char *));
+ static void          decomprle    PARM((byte *, byte *, long, long));
+ static unsigned int  iff_getword  PARM((byte *));
+ static unsigned long iff_getlong  PARM((byte *));
+ 
+ 
+-static char *bname;
++static const char *bname;
+ 
+ 
+ /* Define internal ILBM types */
+@@ -65,16 +65,16 @@
+ /*******************************************/
+ {
+   /* returns '1' on success */
+-  
++
+   register byte bitmsk, rval, gval, bval;
+   register long col, colbit;
+   FILE          *fp;
+   int           rv;
+-  int           BMHDok, CMAPok, CAMGok, BODYok;
++  int           BMHDok, CMAPok, CAMGok;
+   int           bmhd_width, bmhd_height, bmhd_bitplanes, bmhd_transcol;
+   int           i, j, k, lineskip, colors, fmt;
+   byte          bmhd_masking, bmhd_compression;
+-  long          chunkLen, camg_viewmode, decomp_bufsize;
++  long          chunkLen, camg_viewmode;
+   byte          *databuf, *dataptr, *cmapptr, *picptr, *pic, *bodyptr;
+   byte          *workptr, *workptr2, *workptr3, *decomp_mem;
+ 
+@@ -138,6 +138,7 @@
+      BODY chunk was found or dataptr ran over end of file */
+ 
+   while ((rv<0) && (dataptr < (databuf + filesize))) {
++    int npixels = 0;
+     chunkLen = (iff_getlong(dataptr + 4) + 1) & 0xfffffffe; /* make even */
+ 
+     if (strncmp((char *) dataptr, "BMHD", (size_t) 4)==0) { /* BMHD chunk? */
+@@ -149,25 +150,30 @@
+       bmhd_transcol    = iff_getword(dataptr + 8 + 12);
+       BMHDok = 1;                                       /* got BMHD */
+       dataptr += 8 + chunkLen;                          /* to next chunk */
++
++      npixels = bmhd_width * bmhd_height;  /* 65535*65535 max */
++      if (bmhd_width <= 0 || bmhd_height <= 0
++          || npixels/bmhd_width != bmhd_height)
++        return (iffError(bname, "xviff: image dimensions out of range"));
+     }
+ 
+ 
+     else if (strncmp((char *) dataptr, "CMAP", (size_t) 4)==0) { /* CMAP ? */
+       cmapptr = dataptr + 8;
+       colors = chunkLen / 3;                            /* calc no of colors */
+-      
++
+       /* copy colors to color map */
+       for (i=0; i < colors; i++) {
+ 	pinfo->r[i] = *cmapptr++;
+ 	pinfo->g[i] = *cmapptr++;
+ 	pinfo->b[i] = *cmapptr++;
+       }
+-      
++
+       CMAPok = 1;                                       /* got CMAP */
+       dataptr += 8 + chunkLen;                          /* to next chunk */
+     }
+ 
+-    
++
+     else if (strncmp((char *) dataptr, "CAMG", (size_t) 4)==0) {  /* CAMG ? */
+       camg_viewmode = iff_getlong(dataptr + 8);             /* get viewmodes */
+       CAMGok = 1;                                       /* got CAMG */
+@@ -176,19 +182,28 @@
+ 
+ 
+     else if (strncmp((char *) dataptr, "BODY", (size_t) 4)==0) { /* BODY ? */
++      int byte_width = (((bmhd_width + 15) >> 4) << 1);  /* 8192 max */
++
+       bodyptr = dataptr + 8;                            /* -> BODY data */
+-      
++
+       if (BMHDok) {                                     /* BMHD found? */
+ 	/* if BODY is compressed, allocate buffer for decrunched BODY and
+ 	   decompress it (run length encoding) */
+-	
++
+ 	if (bmhd_compression == 1) {
+ 	  /* calc size of decrunch buffer - (size of the actual picture
+ 	     decompressed in interleaved Amiga bitplane format) */
+ 
+-	  decomp_bufsize = (((bmhd_width + 15) >> 4) << 1) 
+-  	                       * bmhd_height * bmhd_bitplanes;
+-	  
++	  int bytes_per_bitplane = byte_width * bmhd_height; /* 536862720 max */
++          long decomp_bufsize = bytes_per_bitplane * bmhd_bitplanes;
++
++	  if (byte_width <= 0 || bmhd_height <= 0 ||
++	      bytes_per_bitplane/byte_width != bmhd_height ||
++	      decomp_bufsize/bytes_per_bitplane != bmhd_bitplanes)
++	  {
++	    return (iffError(bname, "xviff: image dimensions out of range"));
++	  }
++
+ 	  if ((decomp_mem = (byte *)malloc((size_t) decomp_bufsize)) != NULL) {
+ 	    decomprle(dataptr + 8, decomp_mem, chunkLen, decomp_bufsize);
+ 	    bodyptr = decomp_mem;                 /* -> uncompressed BODY */
+@@ -200,12 +215,13 @@
+ 	    FatalError("xviff: cannot malloc() decrunch buffer");
+ 	  }
+ 	}
+-	
++
+ 
+ 	/* the following determines the type of the ILBM file.
+ 	   it's either NORMAL, EHB, HAM, HAM8 or 24BIT */
+-	
++
+ 	fmt = ILBM_NORMAL;                        /* assume normal ILBM */
++	/* FIXME:  does ILBM_NORMAL really support up to 255 bitplanes? */
+ 
+ 	if      (bmhd_bitplanes == 24) fmt = ILBM_24BIT;
+ 	else if (bmhd_bitplanes == 8) {
+@@ -216,7 +232,7 @@
+ 	  if (camg_viewmode & 0x80) fmt = ILBM_EHB;
+ 	  else if (camg_viewmode & 0x800) fmt = ILBM_HAM;
+ 	}
+-	
++
+ 
+ 	if (DEBUG) {
+ 	  fprintf(stderr, "LoadIFF: %s %dx%d, planes=%d (%d cols), comp=%d\n",
+@@ -225,9 +241,9 @@
+ 		  (fmt==ILBM_HAM8)   ? "HAM8 ILBM" :
+ 		  (fmt==ILBM_EHB)    ? "EHB ILBM" :
+ 		  (fmt==ILBM_24BIT)  ? "24BIT ILBM" : "unknown ILBM",
+-		  bmhd_width, bmhd_height, bmhd_bitplanes, 
++		  bmhd_width, bmhd_height, bmhd_bitplanes,
+ 		  1<<bmhd_bitplanes, bmhd_compression);
+-	}	  
++	}
+ 
+ 
+ 	if ((fmt==ILBM_NORMAL) || (fmt==ILBM_EHB) || (fmt==ILBM_HAM)) {
+@@ -248,8 +264,14 @@
+ 
+ 
+ 	if ((fmt == ILBM_HAM) || (fmt == ILBM_HAM8) || (fmt == ILBM_24BIT)) {
+-	  if ((picptr=(byte *) malloc((size_t)bmhd_width*bmhd_height*3))
+-	      ==NULL) {
++	  int bufsize = 3 * npixels;
++
++	  if (bufsize/3 != npixels) {
++	    if (databuf)    free(databuf);
++	    if (decomp_mem) free(decomp_mem);
++	    return (iffError(bname, "xviff: image dimensions out of range"));
++	  }
++	  if ((picptr=(byte *) malloc((size_t) bufsize)) == NULL) {
+ 	    if (databuf)    free(databuf);
+ 	    if (decomp_mem) free(decomp_mem);
+ 	    return (iffError(bname, "xviff: no memory for decoded picture"));
+@@ -258,8 +280,8 @@
+ 	  else {
+ 	    pic = picptr;
+ 	    workptr = bodyptr;
+-	    lineskip = ((bmhd_width + 15) >> 4) << 1;
+-	    
++	    lineskip = byte_width;
++
+ 	    for (i=0; i<bmhd_height; i++) {
+ 	      bitmsk = 0x80;
+ 	      workptr2 = workptr;
+@@ -338,28 +360,28 @@
+ 
+ 
+ 	else if ((fmt == ILBM_NORMAL) || (fmt == ILBM_EHB)) {
+-	  if ((picptr = (byte *) malloc((size_t) bmhd_width * bmhd_height))
+-	      == NULL) {
++	  /* if bmhd_width and bmhd_height are OK (checked in BMHD block
++	   * above; guaranteed by BMHDok), then npixels is OK, too */
++	  if ((picptr = (byte *) malloc((size_t) npixels)) == NULL) {
+ 	    if (databuf) free(databuf);
+ 	    if (decomp_mem) free(decomp_mem);
+ 	    return (iffError(bname, "xviff: no memory for decoded picture"));
+ 	  }
+-	  
++
+ 	  else if (fmt == ILBM_EHB) {
+ 	    if (DEBUG) fprintf(stderr,"Doubling CMAP for EHB mode\n");
+-	    
++
+ 	    for (i=0; i<32; i++) {
+ 	      pinfo->r[i + colors] = pinfo->r[i] >> 1;
+ 	      pinfo->g[i + colors] = pinfo->g[i] >> 1;
+ 	      pinfo->b[i + colors] = pinfo->b[i] >> 1;
+ 	    }
+ 	  }
+-	  
++
+ 	  pic = picptr;             /* ptr to chunky buffer */
+ 	  workptr = bodyptr;        /* ptr to uncmp'd pic, planar format */
+-	  
+-	  lineskip = ((bmhd_width + 15) >> 4) << 1;  /* # of bytes/line */
+-	  
++	  lineskip = byte_width;
++
+ 	  for (i=0; i<bmhd_height; i++) {
+ 	    bitmsk = 0x80;                      /* left most bit (mask) */
+ 	    workptr2 = workptr;                 /* work ptr to source */
+@@ -367,14 +389,14 @@
+ 	      col = 0;
+ 	      colbit = 1;
+ 	      workptr3 = workptr2;              /* ptr to byte in 1st pln */
+-	      
++
+ 	      for (k=0; k<bmhd_bitplanes; k++) {
+ 		if (*workptr3 & bitmsk)          /* if bit set in this pln */
+ 		  col = col + colbit;           /* add bit to chunky byte */
+ 		workptr3 += lineskip;           /* go to next line */
+ 		colbit <<= 1;                   /* shift color bit */
+ 	      }
+-	      
++
+ 	      *pic++ = col;                     /* write to chunky buffer */
+ 	      bitmsk = bitmsk >> 1;             /* shift mask to next bit */
+ 	      if (bitmsk == 0) {                /* if mask is zero */
+@@ -382,7 +404,7 @@
+ 		workptr2++;                     /* mv ptr to next byte */
+ 	      }
+ 	    }  /* for j ... */
+-	    
++
+ 	    workptr += lineskip * bmhd_bitplanes;  /* to next line */
+ 	  }  /* for i ... */
+ 
+@@ -399,7 +421,7 @@
+ 	pinfo->colType = F_FULLCOLOR;
+ 	pinfo->frmType = -1;
+ 
+-	sprintf(pinfo->fullInfo, "%s (%ld bytes)", 
++	sprintf(pinfo->fullInfo, "%s (%ld bytes)",
+ 		(fmt==ILBM_NORMAL) ? "IFF ILBM" :
+ 		(fmt==ILBM_HAM)    ? "HAM ILBM" :
+ 		(fmt==ILBM_HAM8)   ? "HAM8 ILBM" :
+@@ -414,7 +436,8 @@
+       }  /* if BMHDok */
+ 
+       else rv = 0;                   /* didn't get BMHD header */
+-    }
++
++    }  /* "BODY" chunk */
+ 
+     else {
+       if (DEBUG)
+@@ -440,10 +463,10 @@
+ 
+ /**************************************************************************
+   void decomprle(source, destination, source length, buffer size)
+-  
++
+   Decompress run-length encoded data from source to destination. Terminates
+   when source is decoded completely or destination buffer is full.
+-  
++
+   The decruncher is as optimized as I could make it, without risking
+   safety in case of corrupt BODY chunks.
+ ***************************************************************************/
+@@ -455,12 +478,12 @@
+      register long slen, dlen;
+ {
+   register byte codeByte, dataByte;
+-  
++
+   while ((slen > 0) && (dlen > 0)) {
+-    
++
+     /* read control byte */
+     codeByte = *sptr++;
+-    
++
+     if (codeByte < 0x80) {
+       codeByte++;
+       if ((slen > (long) codeByte) && (dlen >= (long) codeByte)) {
+@@ -522,7 +545,7 @@
+ 
+ /*******************************************/
+ static int iffError(fname, st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+diff -ru xv-3.10a/xvimage.c xv-3.10a-enhancements/xvimage.c
+--- xv-3.10a/xvimage.c	1995-01-13 16:11:36.000000000 -0800
++++ xv-3.10a-enhancements/xvimage.c	2007-03-18 18:13:51.000000000 -0700
+@@ -21,6 +21,16 @@
+  *            int  LoadPad(pinfo, fname);
+  */
+ 
++/* The following switch should better be provided at runtime for
++ * comparison purposes.
++ * At the moment it's only compile time, unfortunately.
++ * Who can make adaptions for use as a runtime switch by a menu option?
++ * [GRR 19980607:  now via do_fixpix_smooth global; macro renamed to ENABLE_]
++ * [see http://sylvana.net/fixpix/ for home page, further info]
++ */
++/* #define ENABLE_FIXPIX_SMOOTH */   /* GRR 19980607:  moved into xv.h */
++
++#define  NEEDSDIR             /* for S_IRUSR|S_IWUSR */
+ #include "copyright.h"
+ 
+ #include "xv.h"
+@@ -34,9 +44,11 @@
+ static void do_pan_calc       PARM((int, int, int *, int *));
+ static void crop1             PARM((int, int, int, int, int));
+ static int  doAutoCrop24      PARM((void));
+-static void floydDitherize1   PARM((XImage *, byte *, int, int, int, 
++static void floydDitherize1   PARM((XImage *, byte *, int, int, int,
+ 				    byte *, byte *,byte *));
++#if 0 /* NOTUSED */
+ static int  highbit           PARM((unsigned long));
++#endif
+ 
+ static int  doPadSolid        PARM((char *, int, int, int, int));
+ static int  doPadBggen        PARM((char *, int, int, int, int));
+@@ -46,6 +58,267 @@
+ static int  ReadImageFile1    PARM((char *, PICINFO *));
+ 
+ 
++/* The following array represents the pixel values for each shade
++ * of the primary color components.
++ * If 'p' is a pointer to a source image rgb-byte-triplet, we can
++ * construct the output pixel value simply by 'oring' together
++ * the corresponding components:
++ *
++ *	unsigned char *p;
++ *	unsigned long pixval;
++ *
++ *	pixval  = screen_rgb[0][*p++];
++ *	pixval |= screen_rgb[1][*p++];
++ *	pixval |= screen_rgb[2][*p++];
++ *
++ * This is both efficient and generic, since the only assumption
++ * is that the primary color components have separate bits.
++ * The order and distribution of bits does not matter, and we
++ * don't need additional variables and shifting/masking code.
++ * The array size is 3 KBytes total and thus very reasonable.
++ */
++
++static unsigned long screen_rgb[3][256];
++
++/* The following array holds the exact color representations
++ * reported by the system.
++ * This is useful for less than 24 bit deep displays as a base
++ * for additional dithering to get smoother output.
++ */
++
++static byte screen_set[3][256];
++
++/* The following routine initializes the screen_rgb and screen_set
++ * arrays.
++ * Since it is executed only once per program run, it does not need
++ * to be super-efficient.
++ *
++ * The method is to draw points in a pixmap with the specified shades
++ * of primary colors and then get the corresponding XImage pixel
++ * representation.
++ * Thus we can get away with any Bit-order/Byte-order dependencies.
++ *
++ * The routine uses some global X variables: theDisp, theScreen,
++ * and dispDEEP. Adapt these to your application as necessary.
++ * I've not passed them in as parameters, since for other platforms
++ * than X these may be different (see vfixpix.c), and so the
++ * screen_init() interface is unique.
++ *
++ * BUG: I've read in the "Xlib Programming Manual" from O'Reilly &
++ * Associates, that the DefaultColormap in TrueColor might not
++ * provide the full shade representation in XAllocColor.
++ * In this case one had to provide a 'best' colormap instead.
++ * However, my tests with Xaccel on a Linux-Box with a Mach64
++ * card were fully successful, so I leave that potential problem
++ * to you at the moment and would appreciate any suggestions...
++ */
++
++static void screen_init()
++{
++  static int init_flag; /* assume auto-init as 0 */
++  Pixmap check_map;
++  GC check_gc;
++  XColor check_col;
++  XImage *check_image;
++  int ci, i;
++
++  if (init_flag) return;
++  init_flag = 1;
++
++  check_map = XCreatePixmap(theDisp, RootWindow(theDisp,theScreen),
++			    1, 1, dispDEEP);
++  check_gc = XCreateGC(theDisp, check_map, 0, NULL);
++  for (ci = 0; ci < 3; ci++) {
++    for (i = 0; i < 256; i++) {
++      check_col.red = 0;
++      check_col.green = 0;
++      check_col.blue = 0;
++      /* Do proper upscaling from unsigned 8 bit (image data values)
++	 to unsigned 16 bit (X color representation). */
++      ((unsigned short *)&check_col.red)[ci] = (unsigned short)((i << 8) | i);
++      if (theVisual->class == TrueColor)
++	XAllocColor(theDisp, theCmap, &check_col);
++      else
++	xvAllocColor(theDisp, theCmap, &check_col);
++      screen_set[ci][i] =
++	(((unsigned short *)&check_col.red)[ci] >> 8) & 0xff;
++      XSetForeground(theDisp, check_gc, check_col.pixel);
++      XDrawPoint(theDisp, check_map, check_gc, 0, 0);
++      check_image = XGetImage(theDisp, check_map, 0, 0, 1, 1,
++			      AllPlanes, ZPixmap);
++      if (check_image) {
++	switch (check_image->bits_per_pixel) {
++	case 8:
++	  screen_rgb[ci][i] = *(CARD8 *)check_image->data;
++	  break;
++	case 16:
++	  screen_rgb[ci][i] = *(CARD16 *)check_image->data;
++	  break;
++	case 24:
++	  screen_rgb[ci][i] =
++	    ((unsigned long)*(CARD8 *)check_image->data << 16) |
++	    ((unsigned long)*(CARD8 *)(check_image->data + 1) << 8) |
++	    (unsigned long)*(CARD8 *)(check_image->data + 2);
++	  break;
++	case 32:
++	  screen_rgb[ci][i] = *(CARD32 *)check_image->data;
++	  break;
++	}
++	XDestroyImage(check_image);
++      }
++    }
++  }
++  XFreeGC(theDisp, check_gc);
++  XFreePixmap(theDisp, check_map);
++}
++
++
++#ifdef ENABLE_FIXPIX_SMOOTH
++
++/* The following code is based in part on:
++ *
++ * jquant1.c
++ *
++ * Copyright (C) 1991-1996, 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 1-pass color quantization (color mapping) routines.
++ * These routines provide mapping to a fixed color map using equally spaced
++ * color values.  Optional Floyd-Steinberg or ordered dithering is available.
++ */
++
++/* Declarations for Floyd-Steinberg dithering.
++ *
++ * Errors are accumulated into the array fserrors[], at a resolution of
++ * 1/16th of a pixel count.  The error at a given pixel is propagated
++ * to its not-yet-processed neighbors using the standard F-S fractions,
++ *		...	(here)	7/16
++ *		3/16	5/16	1/16
++ * We work left-to-right on even rows, right-to-left on odd rows.
++ *
++ * We can get away with a single array (holding one row's worth of errors)
++ * by using it to store the current row's errors at pixel columns not yet
++ * processed, but the next row's errors at columns already processed.  We
++ * need only a few extra variables to hold the errors immediately around the
++ * current column.  (If we are lucky, those variables are in registers, but
++ * even if not, they're probably cheaper to access than array elements are.)
++ *
++ * We provide (#columns + 2) entries per component; the extra entry at each
++ * end saves us from special-casing the first and last pixels.
++ */
++
++typedef INT16 FSERROR;		/* 16 bits should be enough */
++typedef int LOCFSERROR;		/* use 'int' for calculation temps */
++
++typedef struct { byte    *colorset;
++		 FSERROR *fserrors;
++	       } FSBUF;
++
++/* Floyd-Steinberg initialization function.
++ *
++ * It is called 'fs2_init' since it's specialized for our purpose and
++ * could be embedded in a more general FS-package.
++ *
++ * Returns a malloced FSBUF pointer which has to be passed as first
++ * parameter to subsequent 'fs2_dither' calls.
++ * The FSBUF structure does not need to be referenced by the calling
++ * application, it can be treated from the app like a void pointer.
++ *
++ * The current implementation does only require to free() this returned
++ * pointer after processing.
++ *
++ * Returns NULL if malloc fails.
++ *
++ * NOTE: The FSBUF structure is designed to allow the 'fs2_dither'
++ * function to work with an *arbitrary* number of color components
++ * at runtime! This is an enhancement over the IJG code base :-).
++ * Only fs2_init() specifies the (maximum) number of components.
++ */
++
++static FSBUF *fs2_init(width)
++int width;
++{
++  FSBUF *fs;
++  FSERROR *p;
++
++  fs = (FSBUF *)
++    malloc(sizeof(FSBUF) * 3 + ((size_t)width + 2) * sizeof(FSERROR) * 3);
++  if (fs == 0) return fs;
++
++  fs[0].colorset = screen_set[0];
++  fs[1].colorset = screen_set[1];
++  fs[2].colorset = screen_set[2];
++
++  p = (FSERROR *)(fs + 3);
++  memset(p, 0, ((size_t)width + 2) * sizeof(FSERROR) * 3);
++
++  fs[0].fserrors = p;
++  fs[1].fserrors = p + 1;
++  fs[2].fserrors = p + 2;
++
++  return fs;
++}
++
++/* Floyd-Steinberg dithering function.
++ *
++ * NOTE:
++ * (1) The image data referenced by 'ptr' is *overwritten* (input *and*
++ *     output) to allow more efficient implementation.
++ * (2) Alternate FS dithering is provided by the sign of 'nc'. Pass in
++ *     a negative value for right-to-left processing. The return value
++ *     provides the right-signed value for subsequent calls!
++ * (3) This particular implementation assumes *no* padding between lines!
++ *     Adapt this if necessary.
++ */
++
++static int fs2_dither(fs, ptr, nc, num_rows, num_cols)
++FSBUF *fs;
++byte *ptr;
++int nc, num_rows, num_cols;
++{
++  int abs_nc, ci, row, col;
++  LOCFSERROR delta, cur, belowerr, bpreverr;
++  byte *dataptr, *colsetptr;
++  FSERROR *errorptr;
++
++  if ((abs_nc = nc) < 0) abs_nc = -abs_nc;
++  for (row = 0; row < num_rows; row++) {
++    for (ci = 0; ci < abs_nc; ci++, ptr++) {
++      dataptr = ptr;
++      colsetptr = fs[ci].colorset;
++      errorptr = fs[ci].fserrors;
++      if (nc < 0) {
++	dataptr += (num_cols - 1) * abs_nc;
++	errorptr += (num_cols + 1) * abs_nc;
++      }
++      cur = belowerr = bpreverr = 0;
++      for (col = 0; col < num_cols; col++) {
++	cur += errorptr[nc];
++	cur += 8; cur >>= 4;
++	if ((cur += *dataptr) < 0) cur = 0;
++	else if (cur > 255) cur = 255;
++	*dataptr = cur & 0xff;
++	cur -= colsetptr[cur];
++	delta = cur << 1; cur += delta;
++	bpreverr += cur; cur += delta;
++	belowerr += cur; cur += delta;
++	errorptr[0] = (FSERROR)bpreverr;
++	bpreverr = belowerr;
++	belowerr = delta >> 1;
++	dataptr += nc;
++	errorptr += nc;
++      }
++      errorptr[0] = (FSERROR)bpreverr;
++    }
++    ptr += (num_cols - 1) * abs_nc;
++    nc = -nc;
++  }
++  return nc;
++}
++
++#endif /* ENABLE_FIXPIX_SMOOTH */
++
+ 
+ #define DO_CROP 0
+ #define DO_ZOOM 1
+@@ -74,7 +347,7 @@
+   GenerateEpic(w,h);
+   CreateXImage();
+ }
+-                
++
+ 
+ 
+ /********************************************/
+@@ -90,15 +363,15 @@
+ 
+   cp = cpic;
+   bperpix = (picType == PIC8) ? 1 : 3;
+-  
++
+   for (i=0; i<cHIGH; i++) {
+     if ((i&63)==0) WaitCursor();
+     pp = pic + (i+cYOFF) * (pWIDE*bperpix) + (cXOFF * bperpix);
+-    for (j=0; j<cWIDE*bperpix; j++) 
++    for (j=0; j<cWIDE*bperpix; j++)
+       *cp++ = *pp++;
+   }
+ }
+-  
++
+ 
+ 
+ /***********************************/
+@@ -112,10 +385,10 @@
+   clptr = NULL;  cxarrp = NULL;  cy = 0;  /* shut up compiler */
+ 
+   SetISTR(ISTR_EXPAND, "%.5g%% x %.5g%%  (%d x %d)",
+-	  100.0 * ((float) w) / cWIDE, 
++	  100.0 * ((float) w) / cWIDE,
+ 	  100.0 * ((float) h) / cHIGH, w, h);
+ 
+-  if (DEBUG) 
++  if (DEBUG)
+     fprintf(stderr,"GenerateEpic(%d,%d) eSIZE=%d,%d cSIZE=%d,%d epicode=%d\n",
+ 		     w,h,eWIDE,eHIGH,cWIDE,cHIGH, epicMode);
+ 
+@@ -124,7 +397,7 @@
+   eWIDE = w;  eHIGH = h;
+ 
+ 
+-  if (epicMode == EM_SMOOTH) {  
++  if (epicMode == EM_SMOOTH) {
+     if (picType == PIC8) {
+       epic = SmoothResize(cpic, cWIDE, cHIGH, eWIDE, eHIGH,
+ 			  rMap,gMap,bMap, rdisp,gdisp,bdisp, numcols);
+@@ -143,7 +416,7 @@
+ 
+ 
+   /* generate a 'raw' epic, as we'll need it for ColorDither if EM_DITH */
+-    
++
+   if (eWIDE==cWIDE && eHIGH==cHIGH) {  /* 1:1 expansion.  point epic at cpic */
+     epic = cpic;
+   }
+@@ -163,13 +436,13 @@
+     /* the scaling routine.  not really all that scary after all... */
+ 
+     /* OPTIMIZATON:  Malloc an eWIDE array of ints which will hold the
+-       values of the equation px = (pWIDE * ex) / eWIDE.  Faster than doing 
++       values of the equation px = (pWIDE * ex) / eWIDE.  Faster than doing
+        a mul and a div for every point in picture */
+ 
+     cxarr = (int *) malloc(eWIDE * sizeof(int));
+     if (!cxarr) FatalError("unable to allocate cxarr");
+ 
+-    for (ex=0; ex<eWIDE; ex++) 
++    for (ex=0; ex<eWIDE; ex++)
+       cxarr[ex] = bperpix * ((cWIDE * ex) / eWIDE);
+ 
+     elptr = epptr = epic;
+@@ -182,7 +455,7 @@
+       clptr = cpic + (cy * cWIDE * bperpix);
+ 
+       if (bperpix == 1) {
+-	for (ex=0, cxarrp = cxarr;  ex<eWIDE;  ex++, epptr++) 
++	for (ex=0, cxarrp = cxarr;  ex<eWIDE;  ex++, epptr++)
+ 	  *epptr = clptr[*cxarrp++];
+       }
+       else {
+@@ -190,7 +463,7 @@
+ 
+ 	for (ex=0, cxarrp = cxarr; ex<eWIDE; ex++,cxarrp++) {
+ 	  cp = clptr + *cxarrp;
+-	  for (j=0; j<bperpix; j++) 
++	  for (j=0; j<bperpix; j++)
+ 	    *epptr++ = *cp++;
+ 	}
+       }
+@@ -203,7 +476,7 @@
+   if (picType == PIC8 && epicMode == EM_DITH) {
+     byte *tmp;
+ 
+-    tmp = DoColorDither(NULL, epic, eWIDE, eHIGH, rMap,gMap,bMap, 
++    tmp = DoColorDither(NULL, epic, eWIDE, eHIGH, rMap,gMap,bMap,
+ 			rdisp,gdisp,bdisp, numcols);
+     if (tmp) {  /* success */
+       FreeEpic();
+@@ -214,7 +487,7 @@
+     }
+   }
+ }
+-                
++
+ 
+ 
+ /***********************************/
+@@ -233,7 +506,7 @@
+ static void do_zoom(mx,my)
+      int mx,my;
+ {
+-  int i,w,h,x,y,x2,y2;
++  int i;
+   int rx,ry,rx2,ry2, orx, ory, orw, orh;
+   int px,py,pw,ph,opx,opy,opw,oph,m;
+   Window rW, cW;  unsigned int mask;  int rtx, rty;
+@@ -254,10 +527,10 @@
+   while (1) {
+     if (!XQueryPointer(theDisp,mainW,&rW,&cW,&rtx,&rty,
+ 		       &mx,&my,&mask)) continue;
+-    
++
+     if (!(mask & ControlMask)) break;
+     if (!(mask & Button1Mask)) break;  /* button released */
+-    
++
+     compute_zoom_rect(mx, my, &px, &py, &pw, &ph);
+     if (px!=opx || py!=opy) {
+       XDrawRectangle(theDisp,mainW,theGC, orx,ory, (u_int)orw, (u_int)orh);
+@@ -283,7 +556,7 @@
+     XSetPlaneMask(theDisp, theGC, AllPlanes);
+     return;
+   }
+-    
++
+ 
+   for (i=0; i<4; i++) {
+     XDrawRectangle(theDisp, mainW, theGC, orx, ory, (u_int) orw, (u_int) orh);
+@@ -297,7 +570,7 @@
+   /* if rectangle is *completely* outside epic, don't zoom */
+   if (orx+orw<0 || ory+orh<0 || orx>=eWIDE || ory>=eHIGH) return;
+ 
+-  
++
+   crop1(opx, opy, opw, oph, DO_ZOOM);
+ }
+ 
+@@ -306,15 +579,15 @@
+ static void compute_zoom_rect(x, y, px, py, pw, ph)
+      int x, y, *px, *py, *pw, *ph;
+ {
+-  /* given a mouse pos (in epic coords), return x,y,w,h PIC coords for 
+-     a 'zoom in by 2x' rectangle to be tracked.  The rectangle stays 
++  /* given a mouse pos (in epic coords), return x,y,w,h PIC coords for
++     a 'zoom in by 2x' rectangle to be tracked.  The rectangle stays
+      completely within 'pic' boundaries, and moves in 'pic' increments */
+ 
+   CoordE2P(x, y, px, py);
+-  *pw = (cWIDE+1)/2;  
++  *pw = (cWIDE+1)/2;
+   *ph = (cHIGH+1)/2;
+ 
+-  *px = *px - (*pw)/2;  
++  *px = *px - (*pw)/2;
+   *py = *py - (*ph)/2;
+ 
+   RANGE(*px, 0, pWIDE - *pw);
+@@ -327,7 +600,7 @@
+ {
+   int x,y,w,h, x2,y2, ex,ey,ew,eh;
+ 
+-  /* compute a cropping rectangle (in pic coordinates) that's twice 
++  /* compute a cropping rectangle (in pic coordinates) that's twice
+      the size of eWIDE,eHIGH, centered around eWIDE/2, eHIGH/2, but no
+      larger than pWIDE,PHIGH */
+ 
+@@ -362,7 +635,7 @@
+   int i, ox,oy,offx,offy, rw,rh, px, py, dx, dy,m;
+   Window rW, cW;  unsigned int mask;  int rx, ry;
+ 
+-  offx = ox = mx;  
++  offx = ox = mx;
+   offy = oy = my;
+   rw = eWIDE-1;  rh = eHIGH-1;
+   m = 0;
+@@ -374,50 +647,50 @@
+ 
+   /* track until Button2 is released */
+   while (1) {
+-    if (!XQueryPointer(theDisp, mainW, &rW, &cW, &rx, &ry, 
++    if (!XQueryPointer(theDisp, mainW, &rW, &cW, &rx, &ry,
+ 		       &mx, &my, &mask)) continue;
+     if (!(mask & ControlMask)) break;  /* cancelled */
+     if (!(mask & Button2Mask)) break;  /* button released */
+-    
++
+     if (mask & ShiftMask) {    /* constrain mx,my to horiz or vertical */
+       if (abs(mx-offx) > abs(my-offy)) my = offy;
+       else mx = offx;
+     }
+-    
++
+     do_pan_calc(offx, offy, &mx, &my);
+-    
++
+     if (mx!=ox || my!=oy) {
+-      XDrawRectangle(theDisp, mainW, theGC, ox-offx, oy-offy, 
++      XDrawRectangle(theDisp, mainW, theGC, ox-offx, oy-offy,
+ 		     (u_int) rw, (u_int) rh);
+-      XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy, 
++      XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy,
+ 		     (u_int) rw, (u_int) rh);
+       ox = mx;  oy = my;
+     }
+     else {
+-      XDrawRectangle(theDisp, mainW, theGC, ox-offx, oy-offy, 
++      XDrawRectangle(theDisp, mainW, theGC, ox-offx, oy-offy,
+ 		     (u_int) rw, (u_int) rh);
+       m = (m+1)&7;
+       XSetPlaneMask(theDisp, theGC, xorMasks[m]);
+-      XDrawRectangle(theDisp, mainW, theGC, ox-offx, oy-offy, 
++      XDrawRectangle(theDisp, mainW, theGC, ox-offx, oy-offy,
+ 		     (u_int) rw, (u_int) rh);
+       XFlush(theDisp);
+       Timer(100);
+     }
+   }
+-      
++
+   mx = ox;  my = oy;  /* in case mx,my changed on button release */
+ 
+   if (!(mask & ControlMask)) {  /* cancelled */
+-    XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy, 
++    XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy,
+ 		   (u_int) rw, (u_int) rh);
+     XSetFunction(theDisp, theGC, GXcopy);
+     XSetPlaneMask(theDisp, theGC, AllPlanes);
+     return;
+   }
+-    
++
+ 
+   for (i=0; i<4; i++) {
+-    XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy, 
++    XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy,
+ 		   (u_int) rw, (u_int) rh);
+     XFlush(theDisp);
+     Timer(100);
+@@ -430,7 +703,7 @@
+   dx = px - cXOFF;  dy = py - cYOFF;
+ 
+   if (dx==0 && dy==0) {  /* didn't pan anywhere */
+-    XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy, 
++    XDrawRectangle(theDisp, mainW, theGC, mx-offx, my-offy,
+ 		   (u_int) rw, (u_int) rh);
+     XSetFunction(theDisp, theGC, GXcopy);
+     XSetPlaneMask(theDisp, theGC, AllPlanes);
+@@ -485,7 +758,7 @@
+ /***********************************/
+ void Crop()
+ {
+-  int i, x, y, w, h;
++  int x, y, w, h;
+ 
+   if (!HaveSelection()) return;
+ 
+@@ -499,8 +772,7 @@
+ static void crop1(x,y,w,h,zm)
+      int x,y,w,h,zm;
+ {
+-  int   i,j,oldew,oldeh,oldcx,oldcy;
+-  byte *cp, *pp;
++  int   oldew,oldeh,oldcx,oldcy;
+ 
+   oldcx = cXOFF;  oldcy = cYOFF;
+   oldew = eWIDE;  oldeh = eHIGH;
+@@ -529,7 +801,7 @@
+   if (cpic == pic) return;     /* not cropped */
+ 
+   BTSetActive(&but[BUNCROP],0);
+-  
++
+   if (epicMode == EM_SMOOTH) {   /* turn off smoothing */
+     epicMode = EM_RAW;  SetEpicMode();
+   }
+@@ -538,7 +810,7 @@
+   FreeEpic();
+   if (cpic && cpic !=  pic) free(cpic);
+   cpic = NULL;
+-  
++
+ 
+   w = (pWIDE * eWIDE) / cWIDE;   h = (pHIGH * eHIGH) / cHIGH;
+   if (w>maxWIDE || h>maxHIGH) {
+@@ -566,7 +838,7 @@
+   WUnCrop();
+   SetCropString();
+ }
+-  
++
+ 
+ /***********************************/
+ void AutoCrop()
+@@ -583,7 +855,7 @@
+       WCrop(eWIDE, eHIGH, cXOFF-oldcx, cYOFF-oldcy);
+     }
+   }
+-  
++
+   SetCursors(-1);
+ }
+ 
+@@ -650,7 +922,7 @@
+ 
+   /* do the actual cropping */
+   if (cleft || ctop || cbot || cright) {
+-    DoCrop(cXOFF+cleft, cYOFF+ctop, 
++    DoCrop(cXOFF+cleft, cYOFF+ctop,
+ 	    cWIDE-(cleft+cright), cHIGH-(ctop+cbot));
+     return 1;
+   }
+@@ -673,7 +945,7 @@
+ # define NEIGHBOR 16		/* within 6% of neighboring pixels */
+ # define MISSPCT 6		/* and up to 6% that don't match */
+ # define inabsrange(a,n) ( (a) < n && (a) > -n )
+-  
++
+ 
+   if (cHIGH<3 || cWIDE<3) return 0;
+ 
+@@ -739,7 +1011,7 @@
+   while (cleft + 1 < cWIDE) {  /* see if we can delete this line */
+     oldr = bgR; oldg = bgG; oldb = bgB;
+ 
+-    for (i=0, misses=0, cp1=cp; i<cHIGH && misses<maxmiss; 
++    for (i=0, misses=0, cp1=cp; i<cHIGH && misses<maxmiss;
+ 	 i++, cp1 += (cWIDE * 3)) {
+       r=cp1[0]-bgR;  g=cp1[1]-bgG;  b=cp1[2]-bgB;
+       R=cp1[0]-oldr; G=cp1[1]-oldg; B=cp1[2]-oldb;
+@@ -763,7 +1035,7 @@
+   while (cleft + cright + 1 < cWIDE) {  /* see if we can delete this line */
+     oldr = bgR; oldg = bgG; oldb = bgB;
+ 
+-    for (i=0, misses=0, cp1=cp; i<cHIGH && misses<maxmiss; 
++    for (i=0, misses=0, cp1=cp; i<cHIGH && misses<maxmiss;
+ 	 i++, cp1 += (cWIDE*3)) {
+       r=cp1[0]-bgR;  g=cp1[1]-bgG;  b=cp1[2]-bgB;
+       R=cp1[0]-oldr; G=cp1[1]-oldg; B=cp1[2]-oldb;
+@@ -784,8 +1056,8 @@
+   if (cleft || ctop || cbot || cright) {
+     if (cWIDE - (cleft + cright) < 1 ||
+ 	cHIGH - (ctop  + cbot  ) < 1) return 0;    /* sanity check */
+-    
+-    DoCrop(cXOFF+cleft, cYOFF+ctop, 
++
++    DoCrop(cXOFF+cleft, cYOFF+ctop,
+ 	   cWIDE-(cleft+cright), cHIGH-(ctop+cbot));
+     return 1;
+   }
+@@ -802,7 +1074,7 @@
+      and sticks likely values into eWIDE,eHIGH, assuming you wanted to
+      crop.  epic is not regnerated (but is freed) */
+ 
+-  int     i, j, k, bperpix;
++  int     i, j, bperpix;
+   byte   *cp, *pp;
+   double  expw, exph;
+ 
+@@ -837,7 +1109,7 @@
+   else {
+     /* at this point, we want to generate cpic, which will contain a
+        cWIDE*cHIGH subsection of 'pic', top-left at cXOFF,cYOFF */
+-    
++
+     cpic = (byte *) malloc((size_t) (cWIDE * cHIGH * bperpix));
+ 
+     if (cpic == NULL) {
+@@ -852,7 +1124,7 @@
+     cp = cpic;
+     for (i=0; i<cHIGH; i++) {
+       pp = pic + (i+cYOFF) * (pWIDE*bperpix) + (cXOFF * bperpix);
+-      for (j=0; j<cWIDE*bperpix; j++) 
++      for (j=0; j<cWIDE*bperpix; j++)
+ 	*cp++ = *pp++;
+     }
+   }
+@@ -861,7 +1133,7 @@
+   SetCropString();
+   BTSetActive(&but[BUNCROP], (cpic!=pic));
+ 
+-  eWIDE = (int) (cWIDE * expw);  
++  eWIDE = (int) (cWIDE * expw);
+   eHIGH = (int) (cHIGH * exph);
+ 
+   if (eWIDE>maxWIDE || eHIGH>maxHIGH) {  /* make 'normal' size */
+@@ -869,7 +1141,7 @@
+       double r,wr,hr;
+       wr = ((double) cWIDE) / maxWIDE;
+       hr = ((double) cHIGH) / maxHIGH;
+-      
++
+       r = (wr>hr) ? wr : hr;   /* r is the max(wr,hr) */
+       eWIDE = (int) ((cWIDE / r) + 0.5);
+       eHIGH = (int) ((cHIGH / r) + 0.5);
+@@ -906,12 +1178,12 @@
+      int dir;
+ {
+   int i;
+-  
++
+   /* dir=0: 90 degrees clockwise, else 90 degrees counter-clockwise */
+   WaitCursor();
+-  
++
+   RotatePic(pic, picType, &pWIDE, &pHIGH, dir);
+-  
++
+   /* rotate clipped version and modify 'clip' coords */
+   if (cpic != pic && cpic != NULL) {
+     if (!dir) {
+@@ -928,7 +1200,7 @@
+     RotatePic(cpic, picType, &cWIDE, &cHIGH,dir);
+   }
+   else { cWIDE = pWIDE;  cHIGH = pHIGH; }
+-  
++
+   /* rotate expanded version */
+   if (epic != cpic && epic != NULL) {
+     WaitCursor();
+@@ -940,7 +1212,7 @@
+   SetISTR(ISTR_RES,"%d x %d",pWIDE,pHIGH);
+ 
+   SetISTR(ISTR_EXPAND, "%.5g%% x %.5g%%  (%d x %d)",
+-	  100.0 * ((float) eWIDE) / cWIDE, 
++	  100.0 * ((float) eWIDE) / cWIDE,
+ 	  100.0 * ((float) eHIGH) / cHIGH, eWIDE, eHIGH);
+ }
+ 
+@@ -951,7 +1223,7 @@
+      int  *wp, *hp;
+      int   ptype, dir;
+ {
+-  /* rotates a w*h array of bytes 90 deg clockwise (dir=0) 
++  /* rotates a w*h array of bytes 90 deg clockwise (dir=0)
+      or counter-clockwise (dir != 0).  swaps w and h */
+ 
+   byte        *pic1, *pix1, *pix;
+@@ -960,7 +1232,7 @@
+ 
+   bperpix = (ptype == PIC8) ? 1 : 3;
+ 
+-  w = *wp;  h = *hp;  
++  w = *wp;  h = *hp;
+   pix1 = pic1 = (byte *) malloc((size_t) (w*h*bperpix));
+   if (!pic1) FatalError("Not enough memory to rotate!");
+ 
+@@ -968,15 +1240,15 @@
+   if (dir==0) {
+     for (i=0; i<w; i++) {       /* CW */
+       if (bperpix == 1) {
+-	for (j=h-1, pix=pic+(h-1)*w + i;  j>=0;  j--, pix1++, pix-=w) 
++	for (j=h-1, pix=pic+(h-1)*w + i;  j>=0;  j--, pix1++, pix-=w)
+ 	  *pix1 = *pix;
+       }
+       else {
+ 	int bperlin = w*bperpix;
+ 	int k;
+-	
+-	for (j=h-1, pix=pic+(h-1)*w*bperpix + i*bperpix;  
+-	     j>=0;  j--, pix -= bperlin) 
++
++	for (j=h-1, pix=pic+(h-1)*w*bperpix + i*bperpix;
++	     j>=0;  j--, pix -= bperlin)
+ 	  for (k=0; k<bperpix; k++) *pix1++ = pix[k];
+       }
+     }
+@@ -984,25 +1256,25 @@
+   else {
+     for (i=w-1; i>=0; i--) {    /* CCW */
+       if (bperpix == 1) {
+-	for (j=0, pix=pic+i; j<h; j++, pix1++, pix+=w) 
++	for (j=0, pix=pic+i; j<h; j++, pix1++, pix+=w)
+ 	  *pix1 = *pix;
+       }
+       else {
+ 	int k;
+ 	int bperlin = w*bperpix;
+-	
+-	for (j=0, pix=pic+i*bperpix; j<h; j++, pix+=bperlin) 
++
++	for (j=0, pix=pic+i*bperpix; j<h; j++, pix+=bperlin)
+ 	  for (k=0; k<bperpix; k++) *pix1++ = pix[k];
+       }
+     }
+   }
+-  
+-  
++
++
+   /* copy the rotated buffer into the original buffer */
+   xvbcopy((char *) pic1, (char *) pic, (size_t) (w*h*bperpix));
+-  
++
+   free(pic1);
+-  
++
+   /* swap w and h */
+   *wp = h;  *hp = w;
+ }
+@@ -1017,7 +1289,7 @@
+    *
+    * Note:  flips pic, cpic, and epic.  Doesn't touch Ximage, nor does it draw
+    */
+-  
++
+   WaitCursor();
+ 
+   if (HaveSelection()) {            /* only flip selection region */
+@@ -1026,7 +1298,7 @@
+   }
+ 
+   FlipPic(pic, pWIDE, pHIGH, dir);
+-  
++
+   /* flip clipped version */
+   if (cpic && cpic != pic) {
+     WaitCursor();
+@@ -1048,21 +1320,21 @@
+      int dir;
+ {
+   /* flips a w*h array of bytes horizontally (dir=0) or vertically (dir!=0) */
+-  
++
+   byte *plin;
+   int   i,j,k,l,bperpix,bperlin;
+-  
++
+   bperpix = (picType == PIC8) ? 1 : 3;
+   bperlin = w * bperpix;
+-  
++
+   if (dir==0) {                /* horizontal flip */
+     byte *leftp, *rightp;
+-    
++
+     for (i=0; i<h; i++) {
+       plin   = pic + i*bperlin;
+       leftp  = plin;
+       rightp = plin + (w-1)*bperpix;
+-      
++
+       for (j=0; j<w/2; j++, rightp -= (2*bperpix)) {
+ 	for (l=0; l<bperpix; l++, leftp++, rightp++) {
+ 	  k = *leftp;  *leftp = *rightp;  *rightp = k;
+@@ -1070,14 +1342,14 @@
+       }
+     }
+   }
+-  
++
+   else {                      /* vertical flip */
+     byte *topp, *botp;
+-    
++
+     for (i=0; i<w; i++) {
+       topp = pic + i*bperpix;
+       botp = pic + (h-1)*bperlin + i*bperpix;
+-      
++
+       for (j=0; j<h/2; j++, topp+=(w-1)*bperpix, botp-=(w+1)*bperpix) {
+ 	for (l=0; l<bperpix; l++, topp++, botp++) {
+ 	  k = *topp;  *topp = *botp;  *botp = k;
+@@ -1093,26 +1365,26 @@
+      int dir;
+ {
+   /* flips selected area in 'pic', regens cpic and epic appropriately */
+-  
++
+   int   x,y,w,h;
+   byte *plin;
+   int   i,j,k,l,bperpix;
+-  
++
+   GetSelRCoords(&x,&y,&w,&h);
+   CropRect2Rect(&x,&y,&w,&h, 0,0,pWIDE,pHIGH);
+   if (w<1) w=1;
+   if (h<1) h=1;
+-  
++
+   bperpix = (picType == PIC8) ? 1 : 3;
+-  
++
+   if (dir==0) {                /* horizontal flip */
+     byte *leftp, *rightp;
+-    
++
+     for (i=y; i<y+h; i++) {
+       plin   = pic + (i*pWIDE + x) * bperpix;
+       leftp  = plin;
+       rightp = plin + (w-1)*bperpix;
+-      
++
+       for (j=0; j<w/2; j++, rightp -= (2*bperpix)) {
+ 	for (l=0; l<bperpix; l++, leftp++, rightp++) {
+ 	  k = *leftp;  *leftp = *rightp;  *rightp = k;
+@@ -1120,14 +1392,14 @@
+       }
+     }
+   }
+-  
++
+   else {                      /* vertical flip */
+     byte *topp, *botp;
+-    
++
+     for (i=x; i<x+w; i++) {
+       topp = pic + ( y      * pWIDE + i) * bperpix;
+       botp = pic + ((y+h-1) * pWIDE + i) * bperpix;
+-      
++
+       for (j=0; j<h/2; j++, topp+=(pWIDE-1)*bperpix, botp-=(pWIDE+1)*bperpix) {
+ 	for (l=0; l<bperpix; l++, topp++, botp++) {
+ 	  k = *topp;  *topp = *botp;  *botp = k;
+@@ -1139,22 +1411,22 @@
+   GenerateCpic();
+   GenerateEpic(eWIDE,eHIGH);
+ }
+-    
++
+ 
+ /************************/
+ void InstallNewPic()
+ {
+   /* given a new pic and colormap, (or new 24-bit pic) installs everything,
+      regens cpic and epic, and redraws image */
+-  
++
+   /* toss old cpic and epic, if any */
+   FreeEpic();
+   if (cpic && cpic != pic) free(cpic);
+   cpic = NULL;
+-  
++
+   /* toss old colors, and allocate new ones */
+   NewPicGetColors(0,0);
+-  
++
+   /* generate cpic,epic,theImage from new 'pic' */
+   crop1(cXOFF, cYOFF, cWIDE, cHIGH, DO_ZOOM);
+   HandleDispMode();
+@@ -1166,15 +1438,15 @@
+ void DrawEpic()
+ {
+   /* given an 'epic', builds a new Ximage, and draws it.  Basically
+-     called whenever epic is changed, or whenever color allocation 
+-     changes (ie, the created X image will look different for the 
++     called whenever epic is changed, or whenever color allocation
++     changes (ie, the created X image will look different for the
+      same epic) */
+-  
++
+   CreateXImage();
+ 
+   if (useroot) MakeRootPic();
+   else DrawWindow(0,0,eWIDE,eHIGH);
+-  
++
+   if (HaveSelection()) DrawSelection(0);
+ }
+ 
+@@ -1189,7 +1461,7 @@
+   if (pic) free(pic);
+   xvDestroyImage(theImage);   theImage = NULL;
+   pic = egampic = epic = cpic = NULL;
+-  
++
+   if (picComments) free(picComments);
+   picComments = (char *) NULL;
+   ChangeCommentText();
+@@ -1203,7 +1475,7 @@
+      byte   *pic824, *rmap, *gmap, *bmap;
+      int     ptype, wide, high;
+ {
+-  /* does floyd-steinberg ditherizing algorithm.  
++  /* does floyd-steinberg ditherizing algorithm.
+    *
+    * takes a wide*high input image, of type 'ptype' (PIC8, PIC24)
+    *     (if PIC8, colormap is specified by rmap,gmap,bmap)
+@@ -1212,14 +1484,14 @@
+    *
+    * Note: this algorithm is *only* used when running on a 1-bit display
+    */
+-  
++
+   register byte   pix8, bit;
+   int            *thisline, *nextline;
+   int            *thisptr, *nextptr, *tmpptr;
+   int             i, j, err, bperpix, bperln, order;
+   byte           *pp, *image, w1, b1, w8, b8, rgb[256];
+-  
+-  
++
++
+   if (ptype == PIC8) {   /* monoify colormap */
+     for (i=0; i<256; i++)
+       rgb[i] = MONO(rmap[i], gmap[i], bmap[i]);
+@@ -1234,7 +1506,7 @@
+ 
+   thisline = (int *) malloc(wide * sizeof(int));
+   nextline = (int *) malloc(wide * sizeof(int));
+-  if (!thisline || !nextline) 
++  if (!thisline || !nextline)
+     FatalError("ran out of memory in floydDitherize1()\n");
+ 
+ 
+@@ -1249,10 +1521,10 @@
+       *tmpptr++ = fsgamcr[rgb[*pp]];
+   }
+ 
+-      
++
+   w1 = white&0x1;  b1=black&0x1;
+   w8 = w1<<7;  b8 = b1<<7;        /* b/w bit in high bit */
+-  
++
+ 
+   for (i=0; i<high; i++) {
+     if ((i&0x3f) == 0) WaitCursor();
+@@ -1326,7 +1598,7 @@
+ 
+ 
+ /************************/
+-byte *FSDither(inpic, intype, w, h, rmap, gmap, bmap, 
++byte *FSDither(inpic, intype, w, h, rmap, gmap, bmap,
+ 	      bval, wval)
+      byte *inpic, *rmap, *gmap, *bmap;
+      int   w,h, intype, bval, wval;
+@@ -1338,14 +1610,21 @@
+    * and 'wval' as the 'black' and 'white' pixel values, respectively
+    */
+ 
+-  int    i, j, err, w1, h1;
++  int    i, j, err, w1, h1, npixels, linebufsize;
+   byte  *pp, *outpic, rgb[256];
+   int   *thisline, *nextline, *thisptr, *nextptr, *tmpptr;
+ 
+ 
+-  outpic = (byte *) malloc((size_t) (w * h));
++  npixels = w * h;
++  linebufsize = w * sizeof(int);
++  if (w <= 0 || h <= 0 || npixels/w != h || linebufsize/w != sizeof(int)) {
++    SetISTR(ISTR_WARNING, "Invalid image dimensions for dithering");
++    return (byte *)NULL;
++  }
++
++  outpic = (byte *) malloc((size_t) npixels);
+   if (!outpic) return outpic;
+-    
++
+ 
+   if (intype == PIC8) {       /* monoify colormap */
+     for (i=0; i<256; i++)
+@@ -1353,9 +1632,9 @@
+   }
+ 
+ 
+-  thisline = (int *) malloc(w * sizeof(int));
+-  nextline = (int *) malloc(w * sizeof(int));
+-  if (!thisline || !nextline) 
++  thisline = (int *) malloc(linebufsize);
++  nextline = (int *) malloc(linebufsize);
++  if (!thisline || !nextline)
+     FatalError("ran out of memory in FSDither()\n");
+ 
+ 
+@@ -1394,13 +1673,13 @@
+     pp  = outpic + i * w;
+     thisptr = thisline;  nextptr = nextline;
+ 
+-    if (i&1 == 0) {  /* go right */
++    if ((i&1) == 0) {  /* go right */
+       for (j=0; j<w; j++, pp++, thisptr++, nextptr++) {
+ 	if (*thisptr<128) { err = *thisptr;     *pp = (byte) bval; }
+ 	             else { err = *thisptr-255; *pp = (byte) wval; }
+-	
++
+ 	if (j<w1) thisptr[1] += ((err*7)/16);
+-	
++
+ 	if (i<h1) {
+ 	  nextptr[0] += ((err*5)/16);
+ 	  if (j>0)  nextptr[-1] += ((err*3)/16);
+@@ -1414,9 +1693,9 @@
+       for (j=w-1; j>=0; j--, pp--, thisptr--, nextptr--) {
+ 	if (*thisptr<128) { err = *thisptr;     *pp = (byte) bval; }
+ 	             else { err = *thisptr-255; *pp = (byte) wval; }
+-	
++
+ 	if (j>0) thisptr[-1] += ((err*7)/16);
+-	
++
+ 	if (i<h1) {
+ 	  nextptr[0] += ((err*5)/16);
+ 	  if (j>0)  nextptr[-1] += (err/16);
+@@ -1449,8 +1728,8 @@
+   }
+ 
+ 
+-  if (picType == PIC8) 
+-    theImage = Pic8ToXImage(epic,     (u_int) eWIDE, (u_int) eHIGH, 
++  if (picType == PIC8)
++    theImage = Pic8ToXImage(epic,     (u_int) eWIDE, (u_int) eHIGH,
+ 			    cols, rMap, gMap, bMap);
+   else if (picType == PIC24)
+     theImage = Pic24ToXImage(egampic, (u_int) eWIDE, (u_int) eHIGH);
+@@ -1482,7 +1761,7 @@
+ 
+   if (!pic8) return xim;  /* shouldn't happen */
+ 
+-  if (DEBUG > 1) 
++  if (DEBUG > 1)
+     fprintf(stderr,"Pic8ToXImage(): creating a %dx%d Ximage, %d bits deep\n",
+ 	    wide, high, dispDEEP);
+ 
+@@ -1491,7 +1770,7 @@
+   if (dispDEEP == 1) {
+     byte  *imagedata;
+ 
+-    xim = XCreateImage(theDisp, theVisual, dispDEEP, XYPixmap, 0, NULL, 
++    xim = XCreateImage(theDisp, theVisual, dispDEEP, XYPixmap, 0, NULL,
+ 		       wide, high, 32, 0);
+     if (!xim) FatalError("couldn't create xim!");
+ 
+@@ -1506,11 +1785,11 @@
+ 
+   /* if ncols==0, do a 'black' and 'white' dither */
+   if (ncols == 0) {
+-    /* note that if dispDEEP > 8, dithpic will just have '0' and '1' instead 
++    /* note that if dispDEEP > 8, dithpic will just have '0' and '1' instead
+        of 'black' and 'white' */
+ 
+     dithpic = FSDither(pic8, PIC8, (int) wide, (int) high, rmap, gmap, bmap,
+-		       (int) ((dispDEEP <= 8) ? black : 0), 
++		       (int) ((dispDEEP <= 8) ? black : 0),
+ 		       (int) ((dispDEEP <= 8) ? white : 1));
+   }
+ 
+@@ -1521,14 +1800,14 @@
+   case 8: {
+     byte  *imagedata, *ip, *pp;
+     int   j, imWIDE, nullCount;
+-  
++
+     nullCount = (4 - (wide % 4)) & 0x03;  /* # of padding bytes per line */
+     imWIDE = wide + nullCount;
+- 
++
+     /* Now create the image data - pad each scanline as necessary */
+     imagedata = (byte *) malloc((size_t) (imWIDE * high));
+     if (!imagedata) FatalError("couldn't malloc imagedata");
+-    
++
+     pp = (dithpic) ? dithpic : pic8;
+ 
+     for (i=0, ip=imagedata; i<high; i++) {
+@@ -1543,9 +1822,9 @@
+ 
+       for (j=0; j<nullCount; j++, ip++) *ip = 0;
+     }
+-      
++
+     xim = XCreateImage(theDisp,theVisual,dispDEEP,ZPixmap,0,
+-		       (char *) imagedata,  wide,  high, 
++		       (char *) imagedata,  wide,  high,
+ 		       32, imWIDE);
+     if (!xim) FatalError("couldn't create xim!");
+   }
+@@ -1554,13 +1833,13 @@
+ 
+ 
+     /*********************************/
+-      
++
+   case 4: {
+     byte  *imagedata, *ip, *pp;
+     byte *lip;
+     int  bperline, half, j;
+ 
+-    xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL, 
++    xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
+ 		        wide,  high, 8, 0);
+     if (!xim) FatalError("couldn't create xim!");
+ 
+@@ -1569,7 +1848,7 @@
+     if (!imagedata) FatalError("couldn't malloc imagedata");
+     xim->data = (char *) imagedata;
+ 
+-    
++
+     pp = (dithpic) ? dithpic : pic8;
+ 
+     if (xim->bits_per_pixel == 4) {
+@@ -1601,20 +1880,20 @@
+     else FatalError("This display's too bizarre.  Can't create XImage.");
+   }
+     break;
+-      
++
+ 
+     /*********************************/
+-      
++
+   case 2: {  /* by M.Kossa at frec.bull.fr (Marc Kossa) */
+              /* MSBFirst mods added by dale at ntg.com (Dale Luck) */
+-             /* additional fixes by  evol at infko.uni-koblenz.de 
++             /* additional fixes by  evol at infko.uni-koblenz.de
+ 		(Randolf Werner) for NeXT 2bit grayscale with MouseX */
+ 
+     byte  *imagedata, *ip, *pp;
+     byte *lip;
+     int  bperline, half, j;
+ 
+-    xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL, 
++    xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
+ 		        wide,  high, 8, 0);
+     if (!xim) FatalError("couldn't create xim!");
+ 
+@@ -1674,11 +1953,11 @@
+ 	*ip = (dithpic) ? *pp : (byte) xcolors[*pp];
+       }
+     }
+-      
++
+     else FatalError("This display's too bizarre.  Can't create XImage.");
+   }
+     break;
+-      
++
+ 
+   /*********************************/
+ 
+@@ -1686,8 +1965,8 @@
+   case 6: {
+     byte  *imagedata, *ip, *pp;
+     int  bperline;
+-    
+-    xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL, 
++
++    xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
+ 		        wide,  high, 8, 0);
+     if (!xim) FatalError("couldn't create xim!");
+ 
+@@ -1707,17 +1986,16 @@
+     }
+   }
+     break;
+-      
++
+ 
+   /*********************************/
+ 
+   case 12:
+   case 15:
+   case 16: {
+-    unsigned short  *imagedata, *ip;
+-    byte  *pp;
++    byte  *imagedata, *ip, *pp;
+ 
+-    imagedata = (unsigned short *) malloc((size_t) (2*wide*high));
++    imagedata = (byte *) malloc((size_t) (2*wide*high));
+     if (!imagedata) FatalError("couldn't malloc imagedata");
+ 
+     xim = XCreateImage(theDisp,theVisual,dispDEEP,ZPixmap,0,
+@@ -1736,10 +2014,12 @@
+     if (xim->byte_order == MSBFirst) {
+       for (i=wide*high, ip=imagedata; i>0; i--,pp++) {
+ 	if (((i+1)&0x1ffff) == 0) WaitCursor();
+-	if (dithpic) {
+-	  *ip++ = ((*pp) ? white : black) & 0xffff;
+-	}
+-	else *ip++ = xcolors[*pp] & 0xffff;
++
++	if (dithpic) xcol = ((*pp) ? white : black) & 0xffff;
++		else xcol = xcolors[*pp] & 0xffff;
++
++	*ip++ = (xcol>>8) & 0xff;
++	*ip++ = (xcol) & 0xff;
+       }
+     }
+     else {   /* LSBFirst */
+@@ -1749,14 +2029,14 @@
+ 	if (dithpic) xcol = ((*pp) ? white : black) & 0xffff;
+ 	        else xcol = xcolors[*pp];
+ 
+-	/*  WAS *ip++ = ((xcol>>8) & 0xff) | ((xcol&0xff) << 8);  */
+-	*ip++ = (unsigned short) (xcol);
++	*ip++ = (xcol) & 0xff;
++	*ip++ = (xcol>>8) & 0xff;
+       }
+     }
+   }
+     break;
+ 
+-      
++
+     /*********************************/
+ 
+   case 24:
+@@ -1766,7 +2046,7 @@
+ 
+     imagedata = (byte *) malloc((size_t) (4*wide*high));
+     if (!imagedata) FatalError("couldn't malloc imagedata");
+-      
++
+     xim = XCreateImage(theDisp,theVisual,dispDEEP,ZPixmap,0,
+ 		       (char *) imagedata,  wide,  high, 32, 0);
+     if (!xim) FatalError("couldn't create xim!");
+@@ -1774,7 +2054,7 @@
+     do32 = (xim->bits_per_pixel == 32);
+ 
+     pp = (dithpic) ? dithpic : pic8;
+-      
++
+     if (xim->byte_order == MSBFirst) {
+       for (i=0, ip=imagedata; i<high; i++) {
+ 	if (((i+1)&0x7f) == 0) WaitCursor();
+@@ -1809,11 +2089,11 @@
+ 
+ 
+     /*********************************/
+-    
+-  default: 
+-    sprintf(str,"no code to handle this display type (%d bits deep)",
++
++  default:
++    sprintf(dummystr,"no code to handle this display type (%d bits deep)",
+ 	    dispDEEP);
+-    FatalError(str);
++    FatalError(dummystr);
+     break;
+   }
+ 
+@@ -1823,7 +2103,7 @@
+   return(xim);
+ }
+ 
+-static int foo = 0;
++
+ 
+ /***********************************/
+ XImage *Pic24ToXImage(pic24, wide, high)
+@@ -1831,7 +2111,7 @@
+      unsigned int   wide, high;
+ {
+   /*
+-   * this has to do the none-to-simple bit of converting the data in 'pic24'
++   * This has to do the none-too-simple bit of converting the data in 'pic24'
+    * into something usable by X.
+    *
+    * There are two major approaches:  if we're displaying on a TrueColor
+@@ -1840,12 +2120,12 @@
+    * variation of RGB the X device in question wants.  No color allocation
+    * is involved.
+    *
+-   * Alternately, if we're on a PseudoColor, GrayScale, StaticColor or 
+-   * StaticGray display, we're going to continue to operate in an 8-bit 
++   * Alternately, if we're on a PseudoColor, GrayScale, StaticColor or
++   * StaticGray display, we're going to continue to operate in an 8-bit
+    * mode.  (In that by this point, a 3/3/2 standard colormap has been
+    * created for our use (though all 256 colors may not be unique...), and
+    * we're just going to display the 24-bit picture by dithering with those
+-   * colors
++   * colors.)
+    *
+    */
+ 
+@@ -1861,7 +2141,7 @@
+   if (dispDEEP == 1) {
+     byte  *imagedata;
+ 
+-    xim = XCreateImage(theDisp, theVisual, dispDEEP, XYPixmap, 0, NULL, 
++    xim = XCreateImage(theDisp, theVisual, dispDEEP, XYPixmap, 0, NULL,
+ 		        wide,  high, 32, 0);
+     if (!xim) FatalError("couldn't create xim!");
+ 
+@@ -1883,33 +2163,17 @@
+     /* Non-ColorMapped Visuals:  TrueColor, DirectColor                     */
+     /************************************************************************/
+ 
+-    unsigned long r, g, b, rmask, gmask, bmask, xcol;
+-    int           rshift, gshift, bshift, bperpix, bperline, border, cshift;
+-    int           maplen;
++    unsigned long xcol;
++    int           bperpix, bperline;
+     byte         *imagedata, *lip, *ip, *pp;
+ 
+ 
+-    /* compute various shifting constants that we'll need... */
+-
+-    rmask = theVisual->red_mask;
+-    gmask = theVisual->green_mask;
+-    bmask = theVisual->blue_mask;
+-
+-    rshift = 7 - highbit(rmask);
+-    gshift = 7 - highbit(gmask);
+-    bshift = 7 - highbit(bmask);
+-
+-    maplen = theVisual->map_entries;
+-    if (maplen>256) maplen=256;
+-    cshift = 7 - highbit((u_long) (maplen-1));
+-
+     xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
+ 		        wide,  high, 32, 0);
+     if (!xim) FatalError("couldn't create X image!");
+ 
+     bperline = xim->bytes_per_line;
+     bperpix  = xim->bits_per_pixel;
+-    border   = xim->byte_order;
+ 
+     imagedata = (byte *) malloc((size_t) (high * bperline));
+     if (!imagedata) FatalError("couldn't malloc imagedata");
+@@ -1923,85 +2187,141 @@
+       FatalError(buf);
+     }
+ 
++    screen_init();
+ 
+-    lip = imagedata;  pp = pic24;
+-    for (i=0; i<high; i++, lip+=bperline) {
+-      for (j=0, ip=lip; j<wide; j++) {
+-	r = *pp++;  g = *pp++;  b = *pp++;
+-
+-	/* shift r,g,b so that high bit of 8-bit color specification is 
+-	 * aligned with high bit of r,g,b-mask in visual, 
+-	 * AND each component with its mask,
+-	 * and OR the three components together
+-	 */
+-
+-	if (theVisual->class == DirectColor) {
+-	  r = (u_long) directConv[(r>>cshift) & 0xff] << cshift;
+-	  g = (u_long) directConv[(g>>cshift) & 0xff] << cshift;
+-	  b = (u_long) directConv[(b>>cshift) & 0xff] << cshift;
+-	}
+-
+-
+-	/* shift the bits around */
+-	if (rshift<0) r = r << (-rshift);
+-	         else r = r >> rshift;
+-	
+-	if (gshift<0) g = g << (-gshift);
+-	         else g = g >> gshift;
+-
+-	if (bshift<0) b = b << (-bshift);
+-	         else b = b >> bshift;
+-
+-	r = r & rmask;
+-	g = g & gmask;
+-	b = b & bmask;
+-
+-	xcol = r | g | b;
+-
+-	if (bperpix == 32) {
+-	  if (border == MSBFirst) {
+-	    *ip++ = (xcol>>24) & 0xff;
+-	    *ip++ = (xcol>>16) & 0xff;
+-	    *ip++ = (xcol>>8)  & 0xff;
+-	    *ip++ =  xcol      & 0xff;
+-	  }
+-	  else {  /* LSBFirst */
+-	    *ip++ =  xcol      & 0xff;
+-	    *ip++ = (xcol>>8)  & 0xff;
+-	    *ip++ = (xcol>>16) & 0xff;
+-	    *ip++ = (xcol>>24) & 0xff;
+-	  }
+-	}
+-
+-	else if (bperpix == 24) {
+-	  if (border == MSBFirst) {
+-	    *ip++ = (xcol>>16) & 0xff;
+-	    *ip++ = (xcol>>8)  & 0xff;
+-	    *ip++ =  xcol      & 0xff;
+-	  }
+-	  else {  /* LSBFirst */
+-	    *ip++ =  xcol      & 0xff;
+-	    *ip++ = (xcol>>8)  & 0xff;
+-	    *ip++ = (xcol>>16) & 0xff;
+-	  }
+-	}
++#ifdef ENABLE_FIXPIX_SMOOTH
++    if (do_fixpix_smooth) {
++#if 0
++      /* If we wouldn't have to save the original pic24 image data,
++       * the following code would do the dither job by overwriting
++       * the image data, and the normal render code would then work
++       * without any change on that data.
++       * Unfortunately, this approach would hurt the xv assumptions...
++       */
++      if (bperpix < 24) {
++        FSBUF *fs = fs2_init(wide);
++        if (fs) {
++	  fs2_dither(fs, pic24, 3, high, wide);
++	  free(fs);
++        }
++      }
++#else
++      /* ...so we have to take a different approach with linewise
++       * dithering/rendering in a loop using a temporary line buffer.
++       */
++      if (bperpix < 24) {
++        FSBUF *fs = fs2_init(wide);
++        if (fs) {
++	  byte *row_buf = malloc((size_t)wide * 3);
++	  if (row_buf) {
++	    int nc = 3;
++	    byte *picp = pic24;  lip = imagedata;
++
++	    switch (bperpix) {
++	      case 8:
++	        for (i=0; i<high; i++, lip+=bperline, picp+=(size_t)wide*3) {
++	          memcpy(row_buf, picp, (size_t)wide * 3);
++	          nc = fs2_dither(fs, row_buf, nc, 1, wide);
++	          for (j=0, ip=lip, pp=row_buf; j<wide; j++) {
++	            xcol  = screen_rgb[0][*pp++];
++	            xcol |= screen_rgb[1][*pp++];
++	            xcol |= screen_rgb[2][*pp++];
++		    *ip++ = xcol & 0xff;
++	          }
++	        }
++		break;
++
++	      case 16:
++	        for (i=0; i<high; i++, lip+=bperline, picp+=(size_t)wide*3) {
++	          CARD16 *ip16 = (CARD16 *)lip;
++	          memcpy(row_buf, picp, (size_t)wide * 3);
++	          nc = fs2_dither(fs, row_buf, nc, 1, wide);
++	          for (j=0, pp=row_buf; j<wide; j++) {
++	            xcol  = screen_rgb[0][*pp++];
++	            xcol |= screen_rgb[1][*pp++];
++	            xcol |= screen_rgb[2][*pp++];
++		    *ip16++ = (CARD16)xcol;
++	          }
++	        }
++		break;
++	    } /* end switch */
++
++	    free(row_buf);
++	    free(fs);
+ 
+-	else if (bperpix == 16) {
+-	  if (border == MSBFirst) {
+-	    *ip++ = (xcol>>8)  & 0xff;
+-	    *ip++ =  xcol      & 0xff;
+-	  }
+-	  else {  /* LSBFirst */
+-	    *ip++ =  xcol      & 0xff;
+-	    *ip++ = (xcol>>8)  & 0xff;
++	    return xim;
+ 	  }
+-	}
+-
+-	else if (bperpix == 8) {
+-	  *ip++ =  xcol      & 0xff;
+-	}
++	  free(fs);
++        }
+       }
++#endif /* 0? */
+     }
++#endif /* ENABLE_FIXPIX_SMOOTH */
++
++    lip = imagedata;  pp = pic24;
++
++    switch (bperpix) {
++      case 8:
++        for (i=0; i<high; i++, lip+=bperline) {
++          for (j=0, ip=lip; j<wide; j++) {
++	    xcol  = screen_rgb[0][*pp++];
++	    xcol |= screen_rgb[1][*pp++];
++	    xcol |= screen_rgb[2][*pp++];
++	    *ip++ = xcol & 0xff;
++          }
++        }
++        break;
++
++      case 16:
++        for (i=0; i<high; i++, lip+=bperline) {
++          CARD16 *ip16 = (CARD16 *)lip;
++          for (j=0; j<wide; j++) {
++	    xcol  = screen_rgb[0][*pp++];
++	    xcol |= screen_rgb[1][*pp++];
++	    xcol |= screen_rgb[2][*pp++];
++	    *ip16++ = (CARD16)xcol;
++          }
++        }
++        break;
++
++      case 24:
++        for (i=0; i<high; i++, lip+=bperline) {
++          for (j=0, ip=lip; j<wide; j++) {
++	    xcol  = screen_rgb[0][*pp++];
++	    xcol |= screen_rgb[1][*pp++];
++	    xcol |= screen_rgb[2][*pp++];
++#ifdef USE_24BIT_ENDIAN_FIX
++	    if (border == MSBFirst) {
++	      *ip++ = (xcol>>16) & 0xff;
++	      *ip++ = (xcol>>8)  & 0xff;
++	      *ip++ =  xcol      & 0xff;
++	    }
++	    else {  /* LSBFirst */
++	      *ip++ =  xcol      & 0xff;
++	      *ip++ = (xcol>>8)  & 0xff;
++	      *ip++ = (xcol>>16) & 0xff;
++	    }
++#else /* GRR:  this came with the FixPix patch, but I don't think it's right */
++	    *ip++ = (xcol >> 16) & 0xff;    /* (no way to test, however, so  */
++	    *ip++ = (xcol >> 8)  & 0xff;    /* it's left enabled by default) */
++	    *ip++ =  xcol        & 0xff;
++#endif
++          }
++        }
++        break;
++
++      case 32:
++        for (i=0; i<high; i++, lip+=bperline) {
++          CARD32 *ip32 = (CARD32 *)lip;
++          for (j=0; j<wide; j++) {
++	    xcol  = screen_rgb[0][*pp++];
++	    xcol |= screen_rgb[1][*pp++];
++	    xcol |= screen_rgb[2][*pp++];
++	    *ip32++ = (CARD32)xcol;
++          }
++        }
++        break;
++    } /* end switch */
+   }
+ 
+   else {
+@@ -2019,17 +2339,17 @@
+     bwdith = 0;
+ 
+     if (ncols == 0 && dispDEEP != 1) {   /* do 'black' and 'white' dither */
+-      /* note that if dispDEEP > 8, pic8 will just have '0' and '1' instead 
++      /* note that if dispDEEP > 8, pic8 will just have '0' and '1' instead
+ 	 of 'black' and 'white' */
+ 
+-      pic8 = FSDither(pic24, PIC24, (int) wide, (int) high, NULL, NULL, NULL, 
+-		      (int) ((dispDEEP <= 8) ? black : 0), 
++      pic8 = FSDither(pic24, PIC24, (int) wide, (int) high, NULL, NULL, NULL,
++		      (int) ((dispDEEP <= 8) ? black : 0),
+ 		      (int) ((dispDEEP <= 8) ? white : 1));
+       bwdith = 1;
+     }
+ 
+     else {                               /* do color dither using stdcmap */
+-      pic8 = Do332ColorDither(pic24, NULL, (int) wide, (int) high, 
++      pic8 = Do332ColorDither(pic24, NULL, (int) wide, (int) high,
+ 			      NULL, NULL, NULL,
+ 			      stdrdisp, stdgdisp, stdbdisp, 256);
+     }
+@@ -2046,14 +2366,14 @@
+     case 8: {
+       byte  *imagedata, *ip, *pp;
+       int   j, imWIDE, nullCount;
+-  
++
+       nullCount = (4 - (wide % 4)) & 0x03;  /* # of padding bytes per line */
+       imWIDE = wide + nullCount;
+- 
++
+       /* Now create the image data - pad each scanline as necessary */
+       imagedata = (byte *) malloc((size_t) (imWIDE * high));
+       if (!imagedata) FatalError("couldn't malloc imagedata");
+-      
++
+       for (i=0, pp=pic8, ip=imagedata; i<high; i++) {
+ 	if (((i+1)&0x7f) == 0) WaitCursor();
+ 
+@@ -2066,7 +2386,7 @@
+       }
+ 
+       xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0,
+-			 (char *) imagedata,  wide,  high, 
++			 (char *) imagedata,  wide,  high,
+ 			 32, imWIDE);
+       if (!xim) FatalError("couldn't create xim!");
+     }
+@@ -2074,14 +2394,14 @@
+ 
+ 
+       /*********************************/
+-      
++
+     case 4: {
+       byte         *imagedata, *ip, *pp;
+       byte         *lip;
+       int           bperline, half, j;
+       unsigned long xcol;
+-      
+-      xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL, 
++
++      xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
+ 			  wide,  high, 32, 0);
+       if (!xim) FatalError("couldn't create xim!");
+ 
+@@ -2123,14 +2443,14 @@
+       else FatalError("This display's too bizarre.  Can't create XImage.");
+     }
+       break;
+-      
++
+ 
+ 
+       /*********************************/
+-      
++
+     case 2: {  /* by M.Kossa at frec.bull.fr (Marc Kossa) */
+                /* MSBFirst mods added by dale at ntg.com (Dale Luck) */
+-               /* additional fixes by  evol at infko.uni-koblenz.de 
++               /* additional fixes by  evol at infko.uni-koblenz.de
+ 		  (Randolf Werner) for NeXT 2bit grayscale with MouseX */
+ 
+       byte  *imagedata, *ip, *pp;
+@@ -2138,7 +2458,7 @@
+       int  bperline, half, j;
+       unsigned long xcol;
+ 
+-      xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL, 
++      xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
+ 			  wide,  high, 32, 0);
+       if (!xim) FatalError("couldn't create xim!");
+ 
+@@ -2201,22 +2521,22 @@
+ 	  }
+ 	}
+       }
+-      
++
+       else FatalError("This display's too bizarre.  Can't create XImage.");
+     }
+       break;
+-      
++
+ 
+       /*********************************/
+-    
++
+     case 6: {
+       byte  *imagedata, *lip, *ip, *pp;
+       int  bperline;
+-    
+-      xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL, 
++
++      xim = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
+ 			  wide,  high, 32, 0);
+       if (!xim) FatalError("couldn't create xim!");
+-      
++
+       if (xim->bits_per_pixel != 8)
+ 	FatalError("This display's too bizarre.  Can't create XImage.");
+ 
+@@ -2238,7 +2558,7 @@
+     }
+       break;
+ 
+-      
++
+       /*********************************/
+ 
+     case 15:
+@@ -2282,7 +2602,7 @@
+     }
+       break;
+ 
+-      
++
+       /*********************************/
+ 
+       /* this wouldn't seem likely to happen, but what the heck... */
+@@ -2295,7 +2615,7 @@
+ 
+       imagedata = (byte *) malloc((size_t) (4*wide*high));
+       if (!imagedata) FatalError("couldn't malloc imagedata");
+-      
++
+       xim = XCreateImage(theDisp,theVisual,dispDEEP,ZPixmap,0,
+ 			 (char *) imagedata, wide, high, 32, 0);
+       if (!xim) FatalError("couldn't create xim!");
+@@ -2303,7 +2623,7 @@
+       bperpix = xim->bits_per_pixel;
+ 
+       pp = pic8;
+-      
++
+       if (xim->byte_order == MSBFirst) {
+ 	for (i=wide*high, ip=imagedata; i>0; i--,pp++) {
+ 	  if (((i+1)&0x1ffff) == 0) WaitCursor();
+@@ -2327,7 +2647,7 @@
+ 	  if (bperpix == 32) *ip++ = 0;
+ 	}
+       }
+-    }     
++    }
+       break;
+ 
+     }   /* end of the switch */
+@@ -2346,7 +2666,7 @@
+      int mode;
+ {
+   /* move checkmark */
+-  conv24MB.flags[CONV24_8BIT]  = (mode==PIC8);  
++  conv24MB.flags[CONV24_8BIT]  = (mode==PIC8);
+   conv24MB.flags[CONV24_24BIT] = (mode==PIC24);
+ 
+   if (mode == PIC24) {
+@@ -2383,15 +2703,13 @@
+ void Change824Mode(mode)
+      int mode;
+ {
+-  static int oldcmapmode = -1;
+-
+   if (mode == picType) return;   /* same mode, do nothing */
+ 
+   Set824Menus(mode);
+ 
+   if (!pic) {  /* done all we wanna do when there's no pic */
+     picType = mode;
+-    return;  
++    return;
+   }
+ 
+   /* should probably actually *do* something involving colors, regenrating
+@@ -2453,6 +2771,7 @@
+ 
+ 
+ /***********************/
++#if 0 /* NOTUSED */
+ static int highbit(ul)
+ unsigned long ul;
+ {
+@@ -2465,6 +2784,7 @@
+   for (i=31; ((ul & hb) == 0) && i>=0;  i--, ul<<=1);
+   return i;
+ }
++#endif /* 0 - NOTUSED */
+ 
+ 
+ 
+@@ -2474,7 +2794,7 @@
+      int   ptype, w,h, sx,sy,sw,sh;
+ {
+   /* mallocs and returns the selected subimage (sx,sy,sw,sh) of pic.
+-     selection is guaranteed to be within pic boundaries.  
++     selection is guaranteed to be within pic boundaries.
+      NEVER RETURNS NULL */
+ 
+   byte *rpic, *sp, *dp;
+@@ -2520,7 +2840,6 @@
+      installs the new pic and all that...  Returns '0' on failure */
+ 
+   int   rv;
+-  char  loadName[256];
+ 
+   if (padPic)      free(padPic);
+   if (holdcomment) free(holdcomment);
+@@ -2530,8 +2849,8 @@
+ 
+   rv = 1;
+ 
+-  if ((mode != PAD_LOAD) && (wide == pWIDE && high == pHIGH && opaque==100)) {
+-    ErrPopUp("Padding to same size as pic while fully opaque has no effect.", 
++  if ((mode != PAD_LOAD) && (wide == cWIDE && high == cHIGH && opaque==100)) {
++    ErrPopUp("Padding to same size as pic while fully opaque has no effect.",
+ 	     "\nI see");
+     return 0;
+   }
+@@ -2539,8 +2858,8 @@
+   WaitCursor();
+ 
+   if      (mode == PAD_SOLID) rv = doPadSolid(str, wide, high, opaque,omode);
+-  else if (mode == PAD_BGGEN) rv = doPadBggen(str, wide, high, opaque,omode); 
+-  else if (mode == PAD_LOAD)  rv = doPadLoad (str, wide, high, opaque,omode); 
++  else if (mode == PAD_BGGEN) rv = doPadBggen(str, wide, high, opaque,omode);
++  else if (mode == PAD_LOAD)  rv = doPadLoad (str, wide, high, opaque,omode);
+ 
+   SetCursors(-1);
+ 
+@@ -2556,7 +2875,7 @@
+ 
+   return 1;
+ }
+-	      
++
+ 
+ /***********************************/
+ int LoadPad(pinfo, fname)
+@@ -2645,7 +2964,7 @@
+       return 0;
+     }
+   }
+-  
++
+ 
+ 
+   pic24 = (byte *) malloc(wide * high * 3 * sizeof(byte));
+@@ -2656,7 +2975,7 @@
+     return 0;
+   }
+ 
+-  
++
+   /* fill pic24 with solidRGB */
+   for (i=0,pp=pic24; i<wide*high; i++, pp+=3) {
+     pp[0] = (solidRGB>>16) & 0xff;
+@@ -2676,6 +2995,9 @@
+      char *str;
+      int   wide, high, opaque,omode;
+ {
++#ifndef USE_MKSTEMP
++  int tmpfd;
++#endif
+   int i;
+   byte *bgpic24;
+   char syscmd[512], fname[128], errstr[512];
+@@ -2697,7 +3019,18 @@
+ #else
+   strcpy(fname, "Sys$Disk:[]xvuXXXXXX");
+ #endif
++#ifdef USE_MKSTEMP
++  close(mkstemp(fname));
++#else
+   mktemp(fname);
++  tmpfd = open(fname, O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR);
++  if (tmpfd < 0) {
++    sprintf(errstr, "Error: can't create temporary file %s", fname);
++    ErrPopUp(errstr, "\nDoh!");
++    return 0;
++  }
++  close(tmpfd);
++#endif
+ 
+   /* run bggen to generate the background */
+   sprintf(syscmd, "bggen -g %dx%d %s > %s", wide, high, str, fname);
+@@ -2713,7 +3046,7 @@
+     ErrPopUp(errstr, "\nDoh!");
+     return 0;
+   }
+-    
++
+ 
+   /* read the file that's been created */
+   if (!ReadImageFile1(fname, &pinfo)) {
+@@ -2791,7 +3124,7 @@
+      int   wide, high, opaque,omode;
+ {
+   /* copies 'pic' onto the given 24-bit background image, converts back to
+-     8-bit (if necessary), and loads up pad* variables.  
++     8-bit (if necessary), and loads up pad* variables.
+      frees pic24 if necessary */
+ 
+   byte *pp, *p24;
+@@ -2806,30 +3139,30 @@
+ 
+   /* copy 'pic' centered onto pic24.  */
+ 
+-  sx = (wide - pWIDE) / 2;
+-  sy = (high - pHIGH) / 2;
+-  
+-  for (py = 0; py<pHIGH; py++) {
+-    ProgressMeter(0, pHIGH-1, py, "Pad");
++  sx = (wide - cWIDE) / 2;
++  sy = (high - cHIGH) / 2;
++
++  for (py = 0; py<cHIGH; py++) {
++    ProgressMeter(0, cHIGH-1, py, "Pad");
+     if ((py & 0x1f)==0) WaitCursor();
+ 
+     p24y = sy + py;
+     if (p24y >= 0 && p24y < high) {
+-      for (px=0; px<pWIDE; px++) {
++      for (px=0; px<cWIDE; px++) {
+ 	p24x = sx + px;
+ 	if (p24x >= 0 && p24x < wide) {
+ 	  p24 = pic24 + (p24y*wide  + p24x)*3;
+-	  
+-	  
++
++
+ 	  if (picType == PIC24) {                       /* src is PIC24 */
+-	    pp  = pic + (py * pWIDE + px)  *3;
++	    pp  = cpic + (py * cWIDE + px)  *3;
+ 	    r = pp[0];  g = pp[1];  b = pp[2];
+ 	  }
+ 	  else {                                        /* src is PIC8 */
+-	    pp  = pic + (py*pWIDE + px);
++	    pp  = cpic + (py*cWIDE + px);
+ 	    r = rMap[*pp];  g = gMap[*pp];  b = bMap[*pp];
+ 	  }
+-	  
++
+ 	  if (omode == PAD_ORGB) {
+ 	    rval = (r * fg) / 100 + ((int) p24[0] * bg) / 100;
+ 	    gval = (g * fg) / 100 + ((int) p24[1] * bg) / 100;
+@@ -2845,7 +3178,7 @@
+ 
+ 	    if (omode == PAD_OINT) {
+ 	      h = fh;
+-	      s = fs;  
++	      s = fs;
+ 	      /* v = (fv * fg) / 100.0 + (bv * bg) / 100.0; */
+ 	      v = (fv * bv * bw) + (fv * fw);
+ 	    }
+@@ -2855,18 +3188,18 @@
+ 	      h = fh;
+ 	      /* s = (fs * fg) / 100.0 + (bs * bg) / 100.0; */
+ 	      s = (fs * bs * bw) + (fs * fw);
+-	      v = fv;  
++	      v = fv;
+ 	    }
+ 	    else if (omode == PAD_OHUE) {   /* the hard one! */
+-	      int fdeg,bdeg,len1,len2;
+-		
++	      int fdeg,bdeg;
++
+ 	      fdeg = (fh<0) ? -1 : (int) floor(fh + 0.5);
+ 	      bdeg = (bh<0) ? -1 : (int) floor(bh + 0.5);
+ 
+ 	      if (fdeg>=0 && bdeg>=0) {           /* both are colors */
+ 		/* convert H,S onto x,y coordinates on the colorwheel for
+ 		   constant V */
+-		
++
+ 		double fx,fy, bx,by, ox,oy;
+ 
+ 		if (fg == 100 || bg == 100) {   /* E-Z special case */
+@@ -2874,17 +3207,17 @@
+ 		  else         { h = bh;  s = fs;  v=fv; }
+ 		}
+ 		else {  /* general case */
+-		  
++
+ 		  fh *= (3.14159 / 180.0);    /* -> radians */
+ 		  bh *= (3.14159 / 180.0);
+-		  
++
+ 		  fx = fs * cos(fh);  fy = fs * sin(fh);
+ 		  bx = bs * cos(bh);  by = bs * sin(bh);
+-		  
++
+ 		  /* compute pt. on line between fx,fy and bx,by */
+ 		  ox = (fx * (fg/100.0)) + (bx * (bg/100.0));
+ 		  oy = (fy * (fg/100.0)) + (by * (bg/100.0));
+-		  
++
+ 		  /* convert ox,oy back into hue,sat */
+ 		  s = sqrt((ox * ox) + (oy * oy));
+ 		  if (ox == 0.0) {
+@@ -2897,7 +3230,7 @@
+ 		    while (h<0.0) h += 360.0;
+ 		    while (h>=360.0) h -= 360.0;
+ 		  }
+-		  
++
+ 		  v = fv;
+ 		}
+ 	      }
+@@ -2924,7 +3257,7 @@
+ 	    v = (fv * bv * bw) + (fv * fw);
+ 	    hsv2rgb(h,s,v, &rval,&gval,&bval);
+ 	  }
+-	  
++
+ 	  RANGE(rval, 0, 255);  RANGE(gval, 0, 255);  RANGE(bval, 0, 255);
+ 	  *p24++ = rval;  *p24++ = gval;  *p24++ = bval;
+ 	}
+@@ -2958,16 +3291,19 @@
+ 
+ 
+ /*******************************/
+-static int ReadImageFile1(name, pinfo) 
++static int ReadImageFile1(name, pinfo)
+      char    *name;
+      PICINFO *pinfo;
+ {
+   int  i, ftype;
+-  char basefname[128], uncompname[128], errstr[256], *uncName, *readname;
++  char uncompname[128], errstr[256], *uncName, *readname;
++#ifdef VMS
++  char basefname[128];
++#endif
+ 
+   ftype = ReadFileType(name);
+ 
+-  if (ftype == RFT_COMPRESS) {    /* handle compressed/gzipped files */
++  if ((ftype == RFT_COMPRESS) || (ftype == RFT_BZIP2)) {  /* handle .Z,gz,bz2 */
+ #ifdef VMS
+     basefname[0] = '\0';
+     strcpy(basefname, name);     /* remove trailing .Z */
+@@ -2976,8 +3312,8 @@
+ #else
+     uncName = name;
+ #endif
+-    
+-    if (UncompressFile(uncName, uncompname)) {
++
++    if (UncompressFile(uncName, uncompname, ftype)) {
+       ftype = ReadFileType(uncompname);
+       readname = uncompname;
+     }
+@@ -3004,7 +3340,7 @@
+     KillPageFiles(pinfo->pagebname, pinfo->numpages);
+ 
+     if (!i || (i && (pinfo->w<=0 || pinfo->h<=0))) {
+-      if (i) { 
++      if (i) {
+ 	if (pinfo->pic)     free(pinfo->pic);
+ 	if (pinfo->comment) free(pinfo->comment);
+       }
+@@ -3018,9 +3354,3 @@
+ 
+   return 1;
+ }
+-
+-
+-
+-    
+-
+-
+diff -ru xv-3.10a/xvinfo.c xv-3.10a-enhancements/xvinfo.c
+--- xv-3.10a/xvinfo.c	1994-12-22 14:34:41.000000000 -0800
++++ xv-3.10a-enhancements/xvinfo.c	2007-05-13 14:11:03.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvinfo.c - 'Info' box handling functions
+  *
+  * callable functions:
+@@ -8,8 +8,8 @@
+  *                             maps/unmaps window, etc.
+  *   RedrawInfo(x,y,w,h)    -  called by 'expose' events
+  *   SetInfoMode(mode)      -  changes amount of info Info window shows
+- *   SetISTR(st, fmt, args) - sprintf's into ISTR #st.  Redraws it in window 
+- *   char *GetISTR(st)      - returns pointer to ISTR #st, or NULL if st bogus
++ *   SetISTR(st, fmt, args) -  sprintf's into ISTR #st.  Redraws it in window
++ *   char *GetISTR(st)      -  returns pointer to ISTR #st, or NULL if st bogus
+  */
+ 
+ #include "copyright.h"
+@@ -43,20 +43,20 @@
+ 
+ /***************************************************/
+ void CreateInfo(geom)
+-char *geom;
++     const char *geom;
+ {
+-  infoW = CreateWindow("xv info", "XVinfo", geom, INFOWIDE, INFOHIGH, 
++  infoW = CreateWindow("xv info", "XVinfo", geom, INFOWIDE, INFOHIGH,
+ 		       infofg, infobg, 0);
+   if (!infoW) FatalError("can't create info window!");
+-  
+-  pennPix = XCreatePixmapFromBitmapData(theDisp, infoW, 
++
++  pennPix = XCreatePixmapFromBitmapData(theDisp, infoW,
+ 	(char *) penn_bits, penn_width, penn_height, infofg, infobg, dispDEEP);
+ 
+   pnetPix = XCreatePixmapFromBitmapData(theDisp,infoW,
+-	(char *) pennnet_bits, pennnet_width, pennnet_height, 
++	(char *) pennnet_bits, pennnet_width, pennnet_height,
+ 	infofg, infobg, dispDEEP);
+ }
+-  
++
+ 
+ /***************************************************/
+ void InfoBox(vis)
+@@ -64,7 +64,7 @@
+ {
+   if (vis) XMapRaised(theDisp, infoW);
+   else     XUnmapWindow(theDisp, infoW);
+-  
++
+   infoUp = vis;
+ }
+ 
+@@ -74,23 +74,23 @@
+      int x,y,w,h;
+ {
+   int  i;
+-  
++
+   XSetForeground(theDisp, theGC, infofg);
+   XSetBackground(theDisp, theGC, infobg);
+ 
+   /* draw the two icons */
+   XCopyArea(theDisp, pennPix, infoW, theGC, 0, 0, penn_width, penn_height,
+ 	    36 - penn_width/2, 36 - penn_height/2);
+-  XCopyArea(theDisp, pnetPix, infoW, theGC, 0, 0, pennnet_width, 
+-	    pennnet_height, INFOWIDE - 36 - pennnet_width/2, 
++  XCopyArea(theDisp, pnetPix, infoW, theGC, 0, 0, pennnet_width,
++	    pennnet_height, INFOWIDE - 36 - pennnet_width/2,
+ 	    36 - pennnet_height/2);
+ 
+   /* draw the credits */
+-  sprintf(str,"XV   -   %s",REVDATE);
+-  CenterString(infoW, INFOWIDE/2, 36-LINEHIGH, str);
++  snprintf(dummystr, sizeof(dummystr), "XV   -   %s", REVDATE);
++  CenterString(infoW, INFOWIDE/2, 36-LINEHIGH, dummystr);
+   CenterString(infoW, INFOWIDE/2, 36,
+ 	       "by John Bradley  (bradley at dccs.upenn.edu)");
+-  CenterString(infoW, INFOWIDE/2, 36+LINEHIGH, 
++  CenterString(infoW, INFOWIDE/2, 36+LINEHIGH,
+ 	       "Copyright 1994, John Bradley  -  All Rights Reserved");
+ 
+ 
+@@ -131,16 +131,16 @@
+ static void drawFieldName(fnum)
+      int fnum;
+ {
+-  static char *fname[7] = { "Filename:", "Format:", "Resolution:", "Cropping:",
+-			    "Expansion:", "Selection:", "Colors:" };
++  static const char *fname[7] = { "Filename:", "Format:", "Resolution:",
++	"Cropping:", "Expansion:", "Selection:", "Colors:" };
+ 
+   XSetForeground(theDisp, theGC, infofg);
+   XSetBackground(theDisp, theGC, infobg);
+ 
+   if (infoMode == INF_NONE || infoMode == INF_STR) return;
+   if (infoMode == INF_PART && fnum>=3) return;
+-  
+-  XDrawString(theDisp, infoW, theGC, 10, TOPBASE + fnum*LINEHIGH, 
++
++  XDrawString(theDisp, infoW, theGC, 10, TOPBASE + fnum*LINEHIGH,
+ 	      fname[fnum], (int) strlen(fname[fnum]));
+ }
+ 
+@@ -150,7 +150,7 @@
+      int st;
+ {
+   /* erase area of string, and draw it with new contents */
+-  
++
+   if (infoMode == INF_NONE) return;
+   if (infoMode == INF_STR && st > ISTR_WARNING) return;
+   if (infoMode == INF_PART && st > ISTR_RES) return;
+@@ -170,12 +170,12 @@
+   }
+   else {
+     XSetForeground(theDisp, theGC, infobg);
+-    XFillRectangle(theDisp, infoW, theGC, 
+-		   STLEFT, TOPBASE - ASCENT + (st-ISTR_FILENAME)*LINEHIGH, 
++    XFillRectangle(theDisp, infoW, theGC,
++		   STLEFT, TOPBASE - ASCENT + (st-ISTR_FILENAME)*LINEHIGH,
+ 		   (u_int) INFOWIDE-STLEFT, (u_int) LINEHIGH);
+     XSetForeground(theDisp, theGC, infofg);
+     XDrawString(theDisp, infoW, theGC, STLEFT,
+-		TOPBASE	+ (st-ISTR_FILENAME)*LINEHIGH,	istrs[st], 
++		TOPBASE + (st-ISTR_FILENAME)*LINEHIGH, istrs[st],
+ 		(int) strlen(istrs[st]));
+   }
+ }
+@@ -187,21 +187,21 @@
+      int mode;
+ {
+   int y1, y2;
+-  
++
+   infoMode = mode;
+   if (infoUp) {   /* only do this if window is mapped */
+     y1 = TOPBASE - ASCENT;
+     y2 = INFOHIGH-43;
+-    
++
+     XSetForeground(theDisp, theGC, infobg);
+-    
+-    XFillRectangle(theDisp,infoW,theGC,0,y1, 
++
++    XFillRectangle(theDisp,infoW,theGC,0,y1,
+ 		   (u_int) INFOWIDE, (u_int) y2-y1);
+-    XFillRectangle(theDisp,infoW,theGC,0,INFOHIGH-39, 
++    XFillRectangle(theDisp,infoW,theGC,0,INFOHIGH-39,
+ 		   (u_int) INFOWIDE, (u_int) 17);
+-    XFillRectangle(theDisp,infoW,theGC,0,INFOHIGH-19, 
++    XFillRectangle(theDisp,infoW,theGC,0,INFOHIGH-19,
+ 		   (u_int) INFOWIDE, (u_int) 17);
+-    
++
+     drawStrings();
+   }
+ }
+@@ -233,14 +233,14 @@
+ 
+   if (stnum>=0 && stnum < NISTR) {
+     fmt = va_arg(args, char *);
+-    if (fmt) vsprintf(istrs[stnum], fmt, args);
++    if (fmt) vsnprintf(istrs[stnum], sizeof(istrs[stnum]), fmt, args);
+     else istrs[stnum][0] = '\0';
+   }
+   va_end(args);
+-  
++
+   if (stnum == ISTR_COLOR) {
+-    sprintf(istrs[ISTR_INFO], "%s  %s  %s", formatStr, 
+-	    (picType==PIC8) ? "8-bit mode." : "24-bit mode.",
++    snprintf(istrs[ISTR_INFO], sizeof(istrs[ISTR_INFO]), "%s  %s  %s",
++	    formatStr, (picType==PIC8) ? "8-bit mode." : "24-bit mode.",
+ 	    istrs[ISTR_COLOR]);
+   }
+ 
+@@ -250,22 +250,22 @@
+     XFlush(theDisp);
+   }
+ 
+-  if (ctrlUp && (stnum == ISTR_INFO || stnum == ISTR_WARNING || 
++  if (ctrlUp && (stnum == ISTR_INFO || stnum == ISTR_WARNING ||
+ 		 stnum == ISTR_COLOR)) {
+     DrawCtrlStr();
+     XFlush(theDisp);
+   }
+ 
+-  if (anyBrowUp && (stnum == ISTR_WARNING || stnum == ISTR_INFO) 
++  if (anyBrowUp && (stnum == ISTR_WARNING || stnum == ISTR_INFO)
+       && strlen(istrs[stnum])) {
+     SetBrowStr(istrs[stnum]);
+     XFlush(theDisp);
+   }
+ 
+-  if (stnum == ISTR_WARNING && !ctrlUp && !infoUp && !anyBrowUp && 
++  if (stnum == ISTR_WARNING && !ctrlUp && !infoUp && !anyBrowUp &&
+       strlen(istrs[stnum])) {
+     OpenAlert(istrs[stnum]);
+-    sleep(3);
++    sleep(1);  /* was 3, but _really_ slow for TIFFs with unknown tags... */
+     CloseAlert();
+   }
+ }
+diff -ru xv-3.10a/xviris.c xv-3.10a-enhancements/xviris.c
+--- xv-3.10a/xviris.c	1994-12-22 14:34:47.000000000 -0800
++++ xv-3.10a-enhancements/xviris.c	2007-05-13 17:49:50.000000000 -0700
+@@ -14,7 +14,7 @@
+  *
+  *      This code should work on machines with any byte order.
+  *
+- *	Could someone make this run real fast using multiple processors 
++ *	Could someone make this run real fast using multiple processors
+  *	or how about using memory mapped files to speed it up?
+  *
+  *				Paul Haeberli - 1991
+@@ -44,7 +44,7 @@
+     u_short 	zsize;
+     u_long 	min;
+     u_long 	max;
+-    u_long	wastebytes;	
++    u_long	wastebytes;
+     char 	name[80];
+     u_long	colormap;
+ 
+@@ -80,7 +80,7 @@
+ #define CHANOFFSET(z)	(3-(z))	/* this is byte order dependent */
+ 
+ 
+-static int      irisError     PARM((char *, char *));
++static int      irisError     PARM((const char *, const char *));
+ static byte    *getimagedata  PARM((FILE *, IMAGE *));
+ static void     interleaverow PARM((byte *, byte *, int, int));
+ static void     expandrow     PARM((byte *, byte *, int));
+@@ -97,8 +97,8 @@
+ static void     putlong       PARM((FILE *, u_long));
+ 
+ 
+-static char *loaderr;
+-static char *bname;
++static const char *loaderr;
++static const char *bname;
+ 
+ /*****************************************************/
+ int LoadIRIS(fname, pinfo)
+@@ -112,7 +112,8 @@
+   IMAGE   img;
+   byte   *rawdata, *rptr;
+   byte   *pic824,  *bptr;
+-  int     trunc, i, j;
++  int     trunc, i, npixels, bufsize;
++  u_short ii, jj;
+   long    filesize;
+ 
+   trunc = 0;
+@@ -133,11 +134,11 @@
+   img.imagic = getshort(fp);
+   img.type   = getshort(fp);
+   img.dim    = getshort(fp);
+-  img.xsize  = getshort(fp);
++  img.xsize  = getshort(fp);  /* u_short */
+   img.ysize  = getshort(fp);
+   img.zsize  = getshort(fp);
+ 
+-  if (FERROR(fp)) {
++  if (FERROR(fp) || img.xsize == 0 || img.ysize == 0 || img.zsize == 0) {
+     fclose(fp);
+     return irisError(bname, "error in header info");
+   }
+@@ -148,7 +149,7 @@
+   }
+ 
+   rawdata = getimagedata(fp, &img);
+-  if (!rawdata) {   
++  if (!rawdata) {
+     fclose(fp);
+     if (loaderr) irisError(bname, loaderr);
+     return 0;
+@@ -162,18 +163,22 @@
+   /* got the raw image data.  Convert to an XV image (1,3 bytes / pix) */
+ 
+ 
++  npixels = img.xsize * img.ysize;  /* 65535*65535 = (2^32 - 131071) max */
++  if (npixels/img.xsize != img.ysize)
++    return irisError(bname, "IRIS image dimensions out of range");
++
+   if (img.zsize < 3) {  /* grayscale */
+-    pic824 = (byte *) malloc((size_t) img.xsize * img.ysize);
++    pic824 = (byte *) malloc((size_t) npixels);
+     if (!pic824) FatalError("couldn't malloc pic824 in LoadIRIS()");
+ 
+     /* copy plane 3 from rawdata into pic824, inverting pic vertically */
+-    for (i=0, bptr=pic824; i<(int) img.ysize; i++) {
+-      rptr = rawdata + 3 + ((img.ysize - 1) - i) * (img.xsize * 4);
+-      for (j=0; j<(int) img.xsize; j++, bptr++, rptr+=4) *bptr = *rptr;
++    for (ii=0, bptr=pic824; ii<img.ysize; ii++) {
++      rptr = rawdata + 3 + ((img.ysize - 1) - ii) * (img.xsize * 4);
++      for (jj=0; jj<img.xsize; jj++, bptr++, rptr+=4) *bptr = *rptr;
+     }
+ 
+ 
+-    for (i=0; i<256; i++) 
++    for (i=0; i<256; i++)
+       pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
+ 
+     pinfo->pic  = pic824;
+@@ -188,13 +193,17 @@
+   }
+ 
+   else {  /* truecolor */
+-    pic824 = (byte *) malloc((size_t) img.xsize * img.ysize * 3);
++    bufsize = 3 * npixels;
++    if (npixels/img.xsize != img.ysize || bufsize/3 != npixels) {
++      return irisError(bname, "IRIS image dimensions out of range");
++    }
++    pic824 = (byte *) malloc((size_t) bufsize);
+     if (!pic824) FatalError("couldn't malloc pic824 in LoadIRIS()");
+-    
++
+     /* copy plane 3 from rawdata into pic824, inverting pic vertically */
+-    for (i=0, bptr=pic824; i<(int) img.ysize; i++) {
+-      rptr = rawdata + ((img.ysize - 1) - i) * (img.xsize * 4);
+-      for (j=0; j<(int) img.xsize; j++, rptr+=4) {
++    for (ii=0, bptr=pic824; ii<img.ysize; ii++) {
++      rptr = rawdata + ((img.ysize - 1) - ii) * (img.xsize * 4);
++      for (jj=0; jj<img.xsize; jj++, rptr+=4) {
+ 	*bptr++ = rptr[3];
+ 	*bptr++ = rptr[2];
+ 	*bptr++ = rptr[1];
+@@ -220,12 +229,12 @@
+   pinfo->comment = (char *) NULL;
+ 
+   return 1;
+-}     
++}
+ 
+ 
+ /*******************************************/
+ static int irisError(name, st)
+-  char *name, *st;
++  const char *name, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s: %s", name, st);
+   return 0;
+@@ -237,41 +246,53 @@
+      FILE  *fp;
+      IMAGE *img;
+ {
+-  /* read in a B/W RGB or RGBA iris image file and return a 
++  /* read in a B/W RGB or RGBA iris image file and return a
+      pointer to an array of 4-byte pixels, arranged ABGR, NULL on error */
+ 
+   byte   *base, *lptr;
+   byte   *verdat;
+-  int     y, z, pos, len, tablen;
++  int     y, z, tablen;
+   int     xsize, ysize, zsize;
+   int     bpp, rle, cur, badorder;
+-  int     rlebuflen;
++  int     rlebuflen, npixels, bufsize;
+ 
+ 
+   rle     = ISRLE(img->type);
+   bpp     = BPP(img->type);
+-  loaderr = (char *) NULL;
++  loaderr = (const char *) NULL;
+ 
+   if (bpp != 1) {
+     loaderr = "image must have 1 byte per pix chan";
+     return (byte *) NULL;
+   }
+ 
+-  xsize = img->xsize;
++  xsize = img->xsize;   /* all three are > 0 (checked by caller), <= 65535 */
+   ysize = img->ysize;
+   zsize = img->zsize;
++  npixels = xsize * ysize;  /* 65535*65535 = (2^32 - 131071) max */
++  if (npixels/xsize != ysize) {
++    loaderr = "IRIS image dimensions out of range";
++    return (byte *) NULL;
++  }
+ 
+   if (rle) {
+     byte *rledat;
+     u_long *starttab, *lengthtab;
+ 
+-    rlebuflen = 2 * xsize + 10;
++    rlebuflen = 2 * xsize + 10;  /* 10 <= rlebuflen <= 131080 */
+     tablen    = ysize * zsize;
+-    starttab  = (u_long *) malloc((size_t) tablen * sizeof(long));
+-    lengthtab = (u_long *) malloc((size_t) tablen * sizeof(long));
++    bufsize   = tablen * sizeof(long);
++
++    if (tablen/ysize != zsize || bufsize/tablen != sizeof(long)) {
++      loaderr = "IRIS image dimensions out of range";
++      return (byte *)NULL;
++    }
++
++    starttab  = (u_long *) malloc((size_t) bufsize);
++    lengthtab = (u_long *) malloc((size_t) bufsize);
+     rledat    = (byte *)   malloc((size_t) rlebuflen);
+ 
+-    if (!starttab || !lengthtab || !rledat) 
++    if (!starttab || !lengthtab || !rledat)
+       FatalError("out of memory in LoadIRIS()");
+ 
+     fseek(fp, 512L, 0);
+@@ -298,7 +319,13 @@
+     fseek(fp, (long) (512 + 2*tablen*4), 0);
+     cur = 512 + 2*tablen*4;
+ 
+-    base = (byte *) malloc((size_t) (xsize*ysize+TAGLEN) * 4);
++    bufsize = 4 * (npixels+TAGLEN);
++    if (bufsize/4 != (npixels+TAGLEN)) {
++      loaderr = "Bogus IRIS File!";
++      free(starttab);  free(lengthtab);  free(rledat);
++      return (byte *)NULL;
++    }
++    base = (byte *) malloc((size_t) bufsize);
+     if (!base) FatalError("out of memory in LoadIRIS()");
+ 
+     addimgtag(base,xsize,ysize);
+@@ -349,12 +376,17 @@
+   }      /* end of RLE case */
+ 
+   else {  /* not RLE */
++    bufsize = 4 * (npixels+TAGLEN);
++    if (bufsize/4 != (npixels+TAGLEN)) {
++      loaderr = "Bogus IRIS File!";
++      return (byte *)NULL;
++    }
++    base   = (byte *) malloc((size_t) bufsize);
+     verdat = (byte *) malloc((size_t) xsize);
+-    base   = (byte *) malloc((size_t) (xsize*ysize+TAGLEN) * 4);
+     if (!base || !verdat) FatalError("out of memory in LoadIRIS()");
+ 
+     addimgtag(base,xsize,ysize);
+-    
++
+     fseek(fp,512L,0);
+ 
+     for (z=0; z<zsize; z++) {
+@@ -457,7 +489,7 @@
+      byte *dptr;
+      int   xsize, ysize;
+ {
+-  /* this is used to extract image data from core dumps. 
++  /* this is used to extract image data from core dumps.
+      I doubt this is necessary...  --jhb */
+ 
+   dptr    = dptr + (xsize * ysize * 4);
+@@ -499,26 +531,31 @@
+      int   ptype, w, h, numcols, colorstyle;
+ {
+   /* writes a greyscale or 24-bit RGB IRIS file to the already open
+-     stream, rle compressed */
++     stream, RLE-compressed; returns 0 on success, -1 on minor error */
+ 
+   IMAGE img;
+-  int     i, j, pos, len, tablen, rlebuflen, zsize;
++  int     i, j, pos, len, tablen, rlebuflen, zsize, npixels, bufsize;
+   u_long *starttab, *lengthtab;
+   byte   *rlebuf, *pptr;
+   byte   *lumbuf, *lptr, *longpic;
+ 
+   xvbzero((char *) &img, sizeof(IMAGE));
+-  
++
+   /* write header information */
+   fwrite(&img, sizeof(IMAGE), (size_t) 1, fp);
+   fseek(fp, 0L, 0);
+ 
++  if (w <= 0 || h <= 0 || w > 65535 || h > 65535) {
++    SetISTR(ISTR_WARNING, "image dimensions too large for IRIS format");
++    return -1;
++  }
++
+   /* load up header */
+   img.imagic = IMAGIC;
+   img.type   = ITYPE_RLE | (1 & BPPMASK);   /* RLE, 1 byteperpix */
+   img.dim    = (colorstyle == F_FULLCOLOR) ? 3 : 2;
+-  img.xsize  = w;
+-  img.ysize  = h;
++  img.xsize  = (u_short)w;
++  img.ysize  = (u_short)h;
+   img.zsize  = zsize = (colorstyle == F_FULLCOLOR) ? 3 : 1;
+   img.min    = 0;
+   img.max    = 255;
+@@ -537,22 +574,33 @@
+   if (ferror(fp)) { fclose(fp);  return -1; }
+ 
+   /* allocate RLE compression tables & stuff */
+-  rlebuflen = 2*w + 10;
+-  tablen    = h * zsize;
++  rlebuflen = 2*w + 10;   /* 10 <= rlebuflen <= 131080 */
++  tablen    = h * zsize;  /*  1 <= tablen    <= 196605 */
+ 
++  /* no overflow is possible with any of these (given check on w,h above): */
+   starttab  = (u_long *) malloc((size_t) tablen * sizeof(long));
+   lengthtab = (u_long *) malloc((size_t) tablen * sizeof(long));
+   rlebuf    = (byte *)   malloc((size_t) rlebuflen);
+-  lumbuf    = (byte *)   malloc((size_t) w * 4);
++  lumbuf    = (byte *)   malloc((size_t) w * 4);   /* 262140 max */
+ 
+-  if (!starttab || !lengthtab || !rlebuf || !lumbuf) 
++  if (!starttab || !lengthtab || !rlebuf || !lumbuf)
+     FatalError("out of memory in WriteIRIS()");
+ 
+   pos = 512 + 2 * (tablen * 4);
+   fseek(fp, (long) pos, 0);
+ 
+   /* convert image into 4-byte per pix image that the compress routines want */
+-  longpic = (byte *) malloc((size_t) w * h * 4);
++  npixels = w * h;
++  bufsize = 4 * npixels;
++  if (npixels/w != h || bufsize/4 != npixels) {
++    SetISTR(ISTR_WARNING, "can't malloc longpic in WriteIRIS()");
++    free(starttab);
++    free(lengthtab);
++    free(rlebuf);
++    free(lumbuf);
++    return -1;
++  }
++  longpic = (byte *) malloc((size_t) bufsize);
+   if (!longpic) FatalError("couldn't malloc longpic in WriteIRIS()");
+ 
+   for (i=0, pptr=pic; i<h; i++) {
+@@ -574,7 +622,7 @@
+       }
+     }
+   }
+-      
++
+ 
+ 
+   /* compress and write the data */
+@@ -584,12 +632,13 @@
+       if (zsize == 1) {
+ 	lumrow(lptr, lumbuf, w);
+ 	len = compressrow(lumbuf, rlebuf, CHANOFFSET(j), w);
+-      } 
++      }
+       else {
+ 	len = compressrow(lptr, rlebuf, CHANOFFSET(j), w);
+       }
+ 
+       if (len > rlebuflen) {
++	/* this condition shouldn't kill XV, just abort writing the image */
+ 	FatalError("WriteIRIS: rlebuf is too small");
+ 	exit(1);
+       }
+@@ -618,10 +667,10 @@
+ 
+   return 0;
+ }
+-  
++
+ 
+ /*************************************/
+-static void lumrow(rgbptr, lumptr, n) 
++static void lumrow(rgbptr, lumptr, n)
+      byte *rgbptr, *lumptr;
+      int n;
+ {
+@@ -640,7 +689,7 @@
+      int   z, cnt;
+ {
+   byte *iptr, *ibufend, *sptr, *optr;
+-  short todo, cc;							
++  short todo, cc;
+   long  count;
+ 
+   lbuf    += z;
+@@ -685,7 +734,7 @@
+     cc = *iptr;
+     iptr += 4;
+     while ((iptr<ibufend) && (*iptr == cc))  iptr += 4;
+-    
++
+     count = (iptr-sptr)/4;
+     while (count) {
+       todo = count>126 ? 126:count;
+@@ -694,7 +743,7 @@
+       *optr++ = cc;
+     }
+   }
+-  
++
+   *optr++ = 0;
+   return (optr - rlebuf);
+ }
+diff -ru xv-3.10a/xvjpeg.c xv-3.10a-enhancements/xvjpeg.c
+--- xv-3.10a/xvjpeg.c	1995-01-05 00:17:13.000000000 -0800
++++ xv-3.10a-enhancements/xvjpeg.c	2007-05-13 17:47:11.000000000 -0700
+@@ -12,13 +12,17 @@
+ 
+ #include <setjmp.h>
+ 
+-#include "jpeglib.h"
++#include "jpeglib.h"   /* currently defines JPEG_APP0 but not JPEG_APP1 */
+ #include "jerror.h"
+ 
++#ifndef JPEG_APP1
++#  define JPEG_APP1 (JPEG_APP0 + 1)   /* EXIF marker */
++#endif
++
+ #define CREATOR_STR "CREATOR: "
+ 
+ #if BITS_IN_JSAMPLE != 8
+-  Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
++  Sorry, this code copes only with 8-bit JSAMPLEs. /* deliberate syntax err */
+ #endif
+ 
+ 
+@@ -30,12 +34,12 @@
+ #define J_BCANC  1
+ #define BUTTH    24
+ 
+-/* minimum size compression when doing a 'quick' image load.  (of course, if
+-   the image *is* smaller than this, you'll get whatever size it actually is.
++/* Minimum size compression when doing a 'quick' image load.  (Of course, if
++   the image *is* smaller than this, you'll get whatever size it actually is.)
+    This is currently hardcoded to be twice the size of a schnauzer icon, as
+    the schnauzer's the only thing that does a quick load... */
+ 
+-#define QUICKWIDE 160    
++#define QUICKWIDE 160
+ #define QUICKHIGH 120
+ 
+ struct my_error_mgr {
+@@ -51,19 +55,33 @@
+ static    void         clickJD            PARM((int, int));
+ static    void         doCmd              PARM((int));
+ static    void         writeJPEG          PARM((void));
++#if JPEG_LIB_VERSION > 60
++METHODDEF(void)        xv_error_exit      PARM((j_common_ptr));
++METHODDEF(void)        xv_error_output    PARM((j_common_ptr));
++METHODDEF(void)        xv_prog_meter      PARM((j_common_ptr));
++#else
+ METHODDEF void         xv_error_exit      PARM((j_common_ptr));
+ METHODDEF void         xv_error_output    PARM((j_common_ptr));
+ METHODDEF void         xv_prog_meter      PARM((j_common_ptr));
++#endif
+ static    unsigned int j_getc             PARM((j_decompress_ptr));
++#if JPEG_LIB_VERSION > 60
++METHODDEF(boolean)     xv_process_comment PARM((j_decompress_ptr));
++METHODDEF(boolean)     xv_process_app1    PARM((j_decompress_ptr));
++#else
+ METHODDEF boolean      xv_process_comment PARM((j_decompress_ptr));
++METHODDEF boolean      xv_process_app1    PARM((j_decompress_ptr));
++#endif
+ static    int          writeJFIF          PARM((FILE *, byte *, int,int,int));
+ 
+ 
+ 
+ /*** local variables ***/
+ static char *filename;
+-static char *fbasename;
++static const char *fbasename;
+ static char *comment;
++static byte *exifInfo;
++static int   exifInfoSize;   /* not a string => must track size explicitly */
+ static int   colorType;
+ 
+ static DIAL  qDial, smDial;
+@@ -80,28 +98,26 @@
+ /***************************************************/
+ void CreateJPEGW()
+ {
+-  XClassHint classh;
+-
+   jpegW = CreateWindow("xv jpeg","XVjpeg",NULL,JWIDE,JHIGH,infofg,infobg,0);
+   if (!jpegW) FatalError("can't create jpeg window!");
+-  
++
+   XSelectInput(theDisp, jpegW, ExposureMask | ButtonPressMask | KeyPressMask);
+-  
+-  DCreate(&qDial, jpegW, 10, 10, 80, 100, 1, 100, 75, 5, 
++
++  DCreate(&qDial, jpegW, 10, 10, 80, 100, 1.0, 100.0, 75.0, 1.0, 5.0,
+ 	  infofg, infobg, hicol, locol, "Quality", "%");
+-  
+-  DCreate(&smDial, jpegW, 120, 10, 80, 100, 0, 100, 0, 5, 
++
++  DCreate(&smDial, jpegW, 120, 10, 80, 100, 0.0, 100.0, 0.0, 1.0, 5.0,
+ 	  infofg, infobg, hicol, locol, "Smoothing", "%");
+-  
+-  BTCreate(&jbut[J_BOK], jpegW, JWIDE-180-1, JHIGH-10-BUTTH-1, 80, BUTTH, 
++
++  BTCreate(&jbut[J_BOK], jpegW, JWIDE-180-1, JHIGH-10-BUTTH-1, 80, BUTTH,
+ 	   "Ok", infofg, infobg, hicol, locol);
+-  
+-  BTCreate(&jbut[J_BCANC], jpegW, JWIDE-90-1, JHIGH-10-BUTTH-1, 80, BUTTH, 
++
++  BTCreate(&jbut[J_BCANC], jpegW, JWIDE-90-1, JHIGH-10-BUTTH-1, 80, BUTTH,
+ 	   "Cancel", infofg, infobg, hicol, locol);
+-  
++
+   XMapSubwindows(theDisp, jpegW);
+ }
+-  
++
+ 
+ /***************************************************/
+ void JPEGDialog(vis)
+@@ -122,32 +138,32 @@
+ {
+   /* check event to see if it's for one of our subwindows.  If it is,
+      deal accordingly, and return '1'.  Otherwise, return '0' */
+-  
++
+   int rv;
+   rv = 1;
+-  
++
+   if (!jpegUp) return 0;
+-  
++
+   if (xev->type == Expose) {
+     int x,y,w,h;
+     XExposeEvent *e = (XExposeEvent *) xev;
+     x = e->x;  y = e->y;  w = e->width;  h = e->height;
+-    
++
+     /* throw away excess expose events for 'dumb' windows */
+-    if (e->count > 0 && (e->window == qDial.win || 
++    if (e->count > 0 && (e->window == qDial.win ||
+ 			 e->window == smDial.win)) {}
+-    
++
+     else if (e->window == jpegW)       drawJD(x, y, w, h);
+     else if (e->window == qDial.win)   DRedraw(&qDial);
+     else if (e->window == smDial.win)  DRedraw(&smDial);
+     else rv = 0;
+   }
+-  
++
+   else if (xev->type == ButtonPress) {
+     XButtonEvent *e = (XButtonEvent *) xev;
+     int x,y;
+     x = e->x;  y = e->y;
+-    
++
+     if (e->button == Button1) {
+       if      (e->window == jpegW)      clickJD(x,y);
+       else if (e->window == qDial.win)  DTrack(&qDial,  x,y);
+@@ -156,18 +172,18 @@
+     }  /* button1 */
+     else rv = 0;
+   }  /* button press */
+-  
+-  
++
++
+   else if (xev->type == KeyPress) {
+     XKeyEvent *e = (XKeyEvent *) xev;
+     char buf[128];  KeySym ks;
+     int stlen;
+-    
++
+     stlen = XLookupString(e,buf,128,&ks,(XComposeStatus *) NULL);
+     buf[stlen] = '\0';
+-    
++
+     RemapKeyCheck(ks, buf, &stlen);
+-    
++
+     if (e->window == jpegW) {
+       if (stlen) {
+ 	if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
+@@ -181,12 +197,12 @@
+     else rv = 0;
+   }
+   else rv = 0;
+-  
++
+   if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
+     XBell(theDisp, 50);
+     rv = 1;   /* eat it */
+   }
+-  
++
+   return rv;
+ }
+ 
+@@ -205,23 +221,24 @@
+ static void drawJD(x,y,w,h)
+      int x,y,w,h;
+ {
+-  char *title  = "Save JPEG file...";
+-  char *title1 = "Quality value determines";
+-  char *title2 = "compression rate: higher";
+-  char *title3 = "quality = bigger file.";
+-  char *title4 = "Use smoothing if saving";
+-  char *title5 = "an 8-bit image (eg, a GIF).";
+-  
+-  char *qtitle1 = "Default = 75.";
+-  char *qtitle2 = "Useful range";
+-  char *qtitle3 = "is 5-95.";
+-  char *smtitle1 = "Default = 0 (none).";
+-  char *smtitle2 = "10-30 is enough";
+-  char *smtitle3 = "for typical GIFs.";
+-  
++  const char *title  = "Save JPEG file...";
++  const char *title1 = "Quality value determines";
++  const char *title2 = "compression rate: higher";
++  const char *title3 = "quality = bigger file.";
++  const char *title4 = "Use smoothing if saving";
++  const char *title5 = "an 8-bit image (eg, a GIF).";
++
++  const char *qtitle1 = "Default = 75.";
++  const char *qtitle2 = "Useful range";
++  const char *qtitle3 = "is 5-95.";
++
++  const char *smtitle1 = "Default = 0 (none).";
++  const char *smtitle2 = "10-30 is enough";
++  const char *smtitle3 = "for typical GIFs.";
++
+   int  i;
+   XRectangle xr;
+-  
++
+   xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
+   XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
+ 
+@@ -240,11 +257,11 @@
+   DrawString(jpegW,  15, 10+100+10+ASCENT,            qtitle1);
+   DrawString(jpegW,  15, 10+100+10+ASCENT+LINEHIGH,   qtitle2);
+   DrawString(jpegW,  15, 10+100+10+ASCENT+LINEHIGH*2, qtitle3);
+-  
++
+   DrawString(jpegW, 115, 10+100+10+ASCENT+LINEHIGH*0, smtitle1);
+   DrawString(jpegW, 115, 10+100+10+ASCENT+LINEHIGH*1, smtitle2);
+   DrawString(jpegW, 115, 10+100+10+ASCENT+LINEHIGH*2, smtitle3);
+-  
++
+   XSetClipMask(theDisp, theGC, None);
+ }
+ 
+@@ -255,14 +272,14 @@
+ {
+   int i;
+   BUTT *bp;
+-  
++
+   /* check BUTTs */
+-  
++
+   for (i=0; i<J_NBUTTS; i++) {
+     bp = &jbut[i];
+     if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
+   }
+-  
++
+   if (i<J_NBUTTS) {  /* found one */
+     if (BTTrack(bp)) doCmd(i);
+   }
+@@ -281,7 +298,7 @@
+ 
+     writeJPEG();
+     JPEGDialog(0);
+-    
++
+     fullname = GetDirFullName();
+     if (!ISPIPE(fullname[0])) {
+       XVCreatedFile(fullname);
+@@ -304,7 +321,7 @@
+ static void writeJPEG()
+ {
+   FILE          *fp;
+-  int            i, nc, rv, w, h, ptype, pfree;
++  int            i, nc, rv, w, h, npixels, ptype, pfree;
+   register byte *ip, *ep;
+   byte          *inpix, *rmap, *gmap, *bmap;
+   byte          *image8, *image24;
+@@ -322,6 +339,14 @@
+   WaitCursor();
+   inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap);
+ 
++  /* this case may not be possible to trigger, but not totally clear, so... */
++  npixels = w*h;
++  if (w <= 0 || h <= 0 || npixels/w < h) {
++    SetISTR(ISTR_WARNING, "%s:  image dimensions too large (%dx%d)",
++            fbasename, w, h);
++    return;
++  }
++
+   image8 = image24 = (byte *) NULL;
+ 
+ 
+@@ -332,37 +357,46 @@
+       if (i==nc) colorType = F_GREYSCALE;    /* made it all the way through */
+     }
+     else {  /* PIC24 */
+-      for (i=0,ip=inpix; i<w*h && ip[0]==ip[1] && ip[1]==ip[2]; i++,ip+=3);
+-      if (i==w*h) colorType = F_GREYSCALE;  /* all the way through */
++      for (i=0,ip=inpix; i<npixels && ip[0]==ip[1] && ip[1]==ip[2]; i++,ip+=3);
++      if (i==npixels) colorType = F_GREYSCALE;  /* all the way through */
+     }
+   }
+-  
+-  
++
++
+   /* first thing to do is build an 8/24-bit Greyscale/TrueColor image
+      (meaning: non-colormapped) */
+-  
++
+   if (colorType == F_GREYSCALE) {   /* build an 8-bit Greyscale image */
+-    image8 = (byte *) malloc((size_t) w * h);
++    image8 = (byte *) malloc((size_t) npixels);
+     if (!image8) FatalError("writeJPEG: unable to malloc image8\n");
+-    
++
+     if (ptype == PIC8) {
+-      for (i=0,ip=image8,ep=inpix; i<w * h; i++, ip++, ep++)
++      for (i=0,ip=image8,ep=inpix; i<npixels; i++, ip++, ep++)
+ 	*ip = MONO(rmap[*ep], gmap[*ep], bmap[*ep]);
+     }
+     else {  /* PIC24 */
+-      for (i=0,ip=image8,ep=inpix; i<w*h; i++, ip++, ep+=3)
++      for (i=0,ip=image8,ep=inpix; i<npixels; i++, ip++, ep+=3)
+ 	*ip = MONO(ep[0],ep[1],ep[2]);
+     }
+   }
+ 
+   else {    /* *not* F_GREYSCALE */
+     if (ptype == PIC8) {
+-      image24 = (byte *) malloc((size_t) w * h * 3);
++      int count = 3*npixels;
++
++      /* already know npixels > 0 (above) */
++      if (count/3 < npixels) {
++        SetISTR(ISTR_WARNING, "%s:  image dimensions too large (%dx%d)",
++                fbasename, w, h);
++        return;
++      }
++
++      image24 = (byte *) malloc((size_t) count);
+       if (!image24) {  /* this simply isn't going to work */
+ 	FatalError("writeJPEG: unable to malloc image24\n");
+       }
+ 
+-      for (i=0, ip=image24, ep=inpix; i<w*h; i++, ep++) {
++      for (i=0, ip=image24, ep=inpix; i<npixels; i++, ep++) {
+ 	*ip++ = rmap[*ep];
+ 	*ip++ = gmap[*ep];
+ 	*ip++ = bmap[*ep];
+@@ -374,16 +408,16 @@
+     }
+   }
+ 
+-  
++
+   /* in any event, we've got some valid image.  Do the JPEG Thing */
+   rv = writeJFIF(fp, (colorType==F_GREYSCALE) ? image8 : image24,
+ 		 w, h, colorType);
+-  
++
+   if      (colorType == F_GREYSCALE) free(image8);
+   else if (ptype == PIC8)            free(image24);
+ 
+   if (pfree) free(inpix);
+-  
++
+   if (CloseOutFile(fp, filename, rv) == 0) DirBox(0);
+   SetCursors(-1);
+ }
+@@ -400,7 +434,11 @@
+ 
+ 
+ /**************************************************/
+-METHODDEF void xv_error_exit(cinfo) 
++#if JPEG_LIB_VERSION > 60
++METHODDEF(void) xv_error_exit(cinfo)
++#else
++METHODDEF void  xv_error_exit(cinfo)
++#endif
+      j_common_ptr cinfo;
+ {
+   my_error_ptr myerr;
+@@ -412,7 +450,11 @@
+ 
+ 
+ /**************************************************/
+-METHODDEF void xv_error_output(cinfo) 
++#if JPEG_LIB_VERSION > 60
++METHODDEF(void) xv_error_output(cinfo)
++#else
++METHODDEF void  xv_error_output(cinfo)
++#endif
+      j_common_ptr cinfo;
+ {
+   my_error_ptr myerr;
+@@ -426,7 +468,11 @@
+ 
+ 
+ /**************************************************/
+-METHODDEF void xv_prog_meter(cinfo)
++#if JPEG_LIB_VERSION > 60
++METHODDEF(void) xv_prog_meter(cinfo)
++#else
++METHODDEF void  xv_prog_meter(cinfo)
++#endif
+      j_common_ptr cinfo;
+ {
+   struct jpeg_progress_mgr *prog;
+@@ -462,14 +508,16 @@
+   struct my_error_mgr              jerr;
+   JSAMPROW                         rowptr[1];
+   FILE                            *fp;
+-  static byte                     *pic;
++  const char                      *colorspace_name = "Color";
++  byte                            *pic, *pic_end;
+   long                             filesize;
+-  int                              i,w,h,bperpix;
++  int                              i,w,h,bperpix,bperline,count;
+ 
+ 
+   fbasename = BaseName(fname);
+   pic       = (byte *) NULL;
+   comment   = (char *) NULL;
++  exifInfo  = (byte *) NULL;
+ 
+   pinfo->type  = PIC8;
+ 
+@@ -485,14 +533,22 @@
+   jerr.pub.output_message = xv_error_output;
+ 
+   if (setjmp(jerr.setjmp_buffer)) {
++L1:
+     /* if we're here, it blowed up... */
+     jpeg_destroy_decompress(&cinfo);
+     fclose(fp);
+-    if (pic)     free(pic);
+-    if (comment) free(comment);
+-
+-    pinfo->pic = (byte *) NULL;
+-    pinfo->comment = (char *) NULL;
++    if (pic)      free(pic);
++    if (comment)  free(comment);
++    if (exifInfo) free(exifInfo);
++
++    pinfo->pic      = (byte *) NULL;
++    pinfo->comment  = (char *) NULL;
++    pinfo->exifInfo = (byte *) NULL;
++    pinfo->exifInfoSize = 0;
++
++    comment  = (char *) NULL;
++    exifInfo = (byte *) NULL;
++    exifInfoSize = 0;
+ 
+     return 0;
+   }
+@@ -500,6 +556,7 @@
+ 
+   jpeg_create_decompress(&cinfo);
+   jpeg_set_marker_processor(&cinfo, JPEG_COM, xv_process_comment);
++  jpeg_set_marker_processor(&cinfo, JPEG_APP1, xv_process_app1);
+ 
+   /* hook up progress meter */
+   prog.progress_monitor = xv_prog_meter;
+@@ -515,9 +572,8 @@
+ 
+ 
+   jpeg_calc_output_dimensions(&cinfo);
+-  w = cinfo.output_width;
+-  h = cinfo.output_height;
+-  pinfo->normw = w;  pinfo->normh = h;
++  pinfo->normw = w = cinfo.output_width;
++  pinfo->normh = h = cinfo.output_height;
+ 
+   if (quick) {
+     int wfac, hfac, fac;
+@@ -543,75 +599,120 @@
+   }
+ 
+ 
+-  if (cinfo.jpeg_color_space == JCS_GRAYSCALE) {
+-    cinfo.out_color_space = JCS_GRAYSCALE;
+-    cinfo.quantize_colors = FALSE;
+-    
+-    SetISTR(ISTR_INFO,"Loading %dx%d Greyscale JPEG (%ld bytes)...",
+-	    w,h,filesize);
+-    
+-    for (i=0; i<256; i++) pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
+-  }
+-  else {
+-    cinfo.out_color_space = JCS_RGB;
+-    cinfo.quantize_colors = FALSE;     /* default: give 24-bit image to XV */
+-    
+-    if (!quick && picType==PIC8 && conv24MB.flags[CONV24_LOCK] == 1) {
+-      /*
+-       * we're locked into 8-bit mode:
+-       *   if CONV24_FAST, use JPEG's one-pass quantizer
+-       *   if CONV24_SLOW, use JPEG's two-pass quantizer
+-       *   if CONV24_BEST, or other, ask for 24-bit image and hand it to XV
+-       */
+-      
+-      cinfo.desired_number_of_colors = 256;
+-      
+-      if (conv24 == CONV24_FAST || conv24 == CONV24_SLOW) {
+-	cinfo.quantize_colors = TRUE;
+-	state824=1;              /* image was converted from 24 to 8 bits */
+-	
+-	cinfo.two_pass_quantize = (conv24 == CONV24_SLOW);
++  cinfo.quantize_colors = FALSE;     /* default: give 24-bit image to XV */
++  switch (cinfo.num_components) {
++    case 1:
++      cinfo.out_color_space = JCS_GRAYSCALE;
++      colorspace_name = "Greyscale";
++      for (i=0; i<256; i++) pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
++      break;
++
++    case 3:
++      cinfo.out_color_space = JCS_RGB;
++      goto L2;
++
++    case 4:
++      cinfo.out_color_space = JCS_CMYK;
++      colorspace_name = "4-Plane Color";
++L2:
++      if (!quick && picType == PIC8 && conv24MB.flags[CONV24_LOCK] == 1) {
++        /*
++         * we're locked into 8-bit mode:
++         *   if CONV24_FAST, use JPEG's one-pass quantizer
++         *   if CONV24_SLOW, use JPEG's two-pass quantizer
++         *   if CONV24_BEST, or other, ask for 24-bit image and hand it to XV
++         */
++        cinfo.desired_number_of_colors = 256;
++
++        if (conv24 == CONV24_FAST || conv24 == CONV24_SLOW) {
++          cinfo.quantize_colors = TRUE;
++          state824 = 1; /* image was converted from 24 to 8 bits */
++          cinfo.two_pass_quantize = (conv24 == CONV24_SLOW);
++        }
+       }
+-    }
+-    
+-    SetISTR(ISTR_INFO,"Loading %dx%d Color JPEG (%ld bytes)...",
+-	    w,h,filesize);
+-  }
+-  
+-  jpeg_calc_output_dimensions(&cinfo);   /* note colorspace changes... */
+-    
++      break;
+ 
+-  if (cinfo.output_components != 1 && cinfo.output_components != 3) {
+-    SetISTR(ISTR_WARNING, "%s:  can't read %d-plane JPEG file!",
+-	    fbasename, cinfo.output_components);
+-    jpeg_destroy_decompress(&cinfo);
+-    fclose(fp);
+-    if (comment) free(comment);
+-    return 0;
++    default:
++      SetISTR(ISTR_WARNING, "%s:  can't read %d-plane JPEG file!",
++              fbasename, cinfo.output_components);
++      goto L1;
+   }
++  SetISTR(ISTR_INFO, "Loading %dx%d %s JPEG (%ld bytes)...", w, h,
++          colorspace_name, filesize);
++
++  jpeg_calc_output_dimensions(&cinfo);   /* note colorspace changes... */
+ 
+ 
+   bperpix = cinfo.output_components;
+   pinfo->type = (bperpix == 1) ? PIC8 : PIC24;
+ 
+-  pic = (byte *) malloc((size_t) (w * h * bperpix));
++  bperline = w * bperpix;
++  count = h * bperline;
++  if (w <= 0 || h <= 0 || bperline/w < bperpix || count/h < bperline) {
++    SetISTR(ISTR_WARNING, "%s:  image dimensions too large (%dx%d)",
++            fbasename, w, h);
++    goto L1;
++  }
++
++  pic = (byte *) malloc((size_t) count);
+   if (!pic) {
+     SetISTR(ISTR_WARNING, "%s:  can't read JPEG file - out of memory",
+ 	    fbasename);
+-    jpeg_destroy_decompress(&cinfo);
+-    fclose(fp);
+-    if (comment) free(comment);
+-    return 0;
++    goto L1;
+   }
+-  
++  pic_end = pic + count;
++
+   jpeg_start_decompress(&cinfo);
+ 
+   while (cinfo.output_scanline < cinfo.output_height) {
++    if (cinfo.output_scanline < 0) {   /* should never happen, but... */
++      SetISTR(ISTR_WARNING, "%s:  invalid negative scanline (%d)",
++              fbasename, cinfo.output_scanline);
++      goto L1;
++    }
+     rowptr[0] = (JSAMPROW) &pic[cinfo.output_scanline * w * bperpix];
+     (void) jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
+   }
+ 
+-  
++
++  /* Convert CMYK to RGB color space */
++
++  if (bperpix > 3) {
++    register byte *p = pic;
++
++    /* According to documentation accompanying the IJG JPEG Library, it appears
++     * that some versions of Adobe Systems' "Photoshop" write inverted CMYK
++     * data, where Byte 0 represents 100% ink coverage instead of 0% ink as
++     * you'd expect.  The JPEG Library's implementors made a policy decision
++     * not to correct for this in the Library, but instead force applications
++     * to deal with it; so we try to do that here:
++     */
++    if (cinfo.saw_Adobe_marker) { /* assume inverted data */
++      register byte *q = pic;
++
++      do {
++        register int cmy, k = 255 - q[3];
++
++        if ((cmy = *q++ - k) < 0) cmy = 0; *p++ = cmy; /* R */
++        if ((cmy = *q++ - k) < 0) cmy = 0; *p++ = cmy; /* G */
++        if ((cmy = *q++ - k) < 0) cmy = 0; *p++ = cmy; /* B */
++      } while (++q <= pic_end);
++    }
++    else { /* assume normal data */
++      register byte *q = pic;
++
++      do {
++        register int cmy, k = 255 - q[3];
++
++        if ((cmy = k - *q++) < 0) cmy = 0; *p++ = cmy; /* R */
++        if ((cmy = k - *q++) < 0) cmy = 0; *p++ = cmy; /* G */
++        if ((cmy = k - *q++) < 0) cmy = 0; *p++ = cmy; /* B */
++      } while (++q <= pic_end);
++    }
++    pic = realloc(pic,p-pic); /* Release extra storage */
++  }
++
++
+ 
+   /* return 'PICINFO' structure to XV */
+ 
+@@ -621,38 +722,59 @@
+   pinfo->frmType = F_JPEG;
+ 
+   if (cinfo.out_color_space == JCS_GRAYSCALE) {
+-    sprintf(pinfo->fullInfo, "Greyscale JPEG. (%ld bytes)", filesize);
+     pinfo->colType = F_GREYSCALE;
+-    
++
+     for (i=0; i<256; i++) pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
+   }
+   else {
+-    sprintf(pinfo->fullInfo, "Color JPEG. (%ld bytes)", filesize);
+     pinfo->colType = F_FULLCOLOR;
+ 
+     if (cinfo.quantize_colors) {
+-      for (i=0; i<cinfo.actual_number_of_colors; i++) {
+-	pinfo->r[i] = cinfo.colormap[0][i];
+-	pinfo->g[i] = cinfo.colormap[1][i];
+-	pinfo->b[i] = cinfo.colormap[2][i];
++      switch (bperpix) {
++        case 3:
++          for (i = 0; i < cinfo.actual_number_of_colors; i++) {
++            pinfo->r[i] = cinfo.colormap[0][i];
++            pinfo->g[i] = cinfo.colormap[1][i];
++            pinfo->b[i] = cinfo.colormap[2][i];
++          }
++          break;
++
++        case 4:
++          for (i = 0; i < cinfo.actual_number_of_colors; i++) {
++            register int cmy, k = cinfo.colormap[3][i];
++
++            if ((cmy = 255 - cinfo.colormap[0][i] - k) < 0) cmy = 0;
++            pinfo->r[i] = cmy;
++            if ((cmy = 255 - cinfo.colormap[1][i] - k) < 0) cmy = 0;
++            pinfo->g[i] = cmy;
++            if ((cmy = 255 - cinfo.colormap[2][i] - k) < 0) cmy = 0;
++            pinfo->b[i] = cmy;
++          }
++          break;
+       }
+     }
+   }
+-  
+-  sprintf(pinfo->shrtInfo, "%dx%d %s JPEG. ", w,h, 
+-	  (cinfo.out_color_space == JCS_GRAYSCALE) ? "Greyscale " : "Color ");
+-  
+-  pinfo->comment = comment;
++
++  sprintf(pinfo->fullInfo, "%s JPEG. (%ld bytes)", colorspace_name, filesize);
++  sprintf(pinfo->shrtInfo, "%dx%d %s JPEG. ", w, h, colorspace_name);
++
++  pinfo->comment      = comment;
++  pinfo->exifInfo     = exifInfo;
++  pinfo->exifInfoSize = exifInfoSize;
+ 
+   jpeg_finish_decompress(&cinfo);
+   jpeg_destroy_decompress(&cinfo);
+   fclose(fp);
+ 
+-  comment = (char *) NULL;
++  /* ownership transferred to pinfo */
++  comment  = (char *) NULL;
++  exifInfo = (byte *) NULL;
++  exifInfoSize = 0;
++
+   return 1;
+ }
+-  
+-  
++
++
+ 
+ 
+ /**************************************************/
+@@ -660,7 +782,7 @@
+      j_decompress_ptr cinfo;
+ {
+   struct jpeg_source_mgr *datasrc = cinfo->src;
+-  
++
+   if (datasrc->bytes_in_buffer == 0) {
+     if (! (*datasrc->fill_input_buffer) (cinfo))
+       ERREXIT(cinfo, JERR_CANT_SUSPEND);
+@@ -671,7 +793,11 @@
+ 
+ 
+ /**************************************************/
+-METHODDEF boolean xv_process_comment(cinfo)
++#if JPEG_LIB_VERSION > 60
++METHODDEF(boolean) xv_process_comment(cinfo)
++#else
++METHODDEF boolean  xv_process_comment(cinfo)
++#endif
+      j_decompress_ptr cinfo;
+ {
+   int          length, hasnull;
+@@ -688,7 +814,7 @@
+   }
+   else comment = (char *) realloc(comment, strlen(comment) + length + 1);
+   if (!comment) FatalError("out of memory in xv_process_comment");
+-  
++
+   oldsp = sp = comment + strlen(comment);
+   hasnull = 0;
+ 
+@@ -705,6 +831,41 @@
+ }
+ 
+ 
++/**************************************************/
++#if JPEG_LIB_VERSION > 60
++METHODDEF(boolean) xv_process_app1(cinfo)   /* Geoff H. Kuenning 20030331 */
++#else
++METHODDEF boolean  xv_process_app1(cinfo)
++#endif
++     j_decompress_ptr cinfo;
++{
++  int          length;
++  unsigned int ch;
++  byte         *sp;
++
++  length  = j_getc(cinfo) << 8;
++  length += j_getc(cinfo);
++  length -= 2;                  /* discount the length word itself */
++
++  if (!exifInfo) {
++    exifInfo = (byte *) malloc((size_t) length);
++    exifInfoSize = 0;
++  }
++  else exifInfo = (byte *) realloc(exifInfo, exifInfoSize + length);
++  if (!exifInfo) FatalError("out of memory in xv_process_app1 (EXIF info)");
++  
++  sp = exifInfo + exifInfoSize;
++  exifInfoSize += length;
++
++  while (length-- > 0) {
++    ch = j_getc(cinfo);
++    *sp++ = (byte) ch;
++  }
++
++  return TRUE;
++}
++
++
+ 
+ 
+ /***************************************************************************/
+@@ -759,8 +920,8 @@
+ 
+ 
+   jpeg_set_defaults(&cinfo);
+-  jpeg_set_quality(&cinfo, qDial.val, TRUE);
+-  cinfo.smoothing_factor = smDial.val;
++  jpeg_set_quality(&cinfo, (int)qDial.val, TRUE);
++  cinfo.smoothing_factor = (int)smDial.val;
+ 
+ 
+   jpeg_start_compress(&cinfo, TRUE);
+@@ -769,20 +930,20 @@
+   /*** COMMENT HANDLING ***/
+ 
+   sprintf(xvcmt, "%sXV %s  Quality = %d, Smoothing = %d\n",
+-	  CREATOR_STR, REVDATE, qDial.val, smDial.val);
+-  
++	  CREATOR_STR, REVDATE, (int)qDial.val, (int)smDial.val);
++
+   if (picComments) {   /* append XV comment */
+     char *sp, *sp1;  int done;
+ 
+     i   = strlen(picComments);
+     comment = (char *) malloc(i + strlen(xvcmt) + 2 + 1);
+     if (!comment) FatalError("out of memory in writeJFIF()");
+-    
++
+     strcpy(comment, picComments);
+-    
++
+     /* see if there's a line that starts with 'CREATOR: ' in the
+        comments.  If there is, rip it out. */
+-    
++
+     sp = comment;  done = 0;
+     while (!done && *sp) {
+       if (strncmp(sp, CREATOR_STR, strlen(CREATOR_STR)) == 0) {
+@@ -801,7 +962,7 @@
+       }
+     }
+ 
+-    /* count # of \n's at end of comment.  
++    /* count # of \n's at end of comment.
+        If none, add 2.   If one, add 1.  If two or more, add none. */
+ 
+     sp = comment + strlen(comment);
+@@ -814,15 +975,18 @@
+     strcat(comment, xvcmt);
+   }
+   else comment = xvcmt;
+-  
+-  
+-  jpeg_write_marker(&cinfo,JPEG_COM,(byte *) comment,(u_int) strlen(comment));
+-  
++
++
++  jpeg_write_marker(&cinfo, JPEG_COM, (byte *)comment, (u_int)strlen(comment));
++
++  if (picExifInfo) jpeg_write_marker(&cinfo, JPEG_APP1, (byte *)picExifInfo,
++                                     (u_int)picExifInfoSize);
++
+   while (cinfo.next_scanline < cinfo.image_height) {
+     rowptr[0] = (JSAMPROW) &pic[cinfo.next_scanline * w * bperpix];
+     (void) jpeg_write_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
+   }
+-  
++
+   jpeg_finish_compress(&cinfo);
+   jpeg_destroy_compress(&cinfo);
+   return 0;
+@@ -831,4 +995,27 @@
+ 
+ 
+ 
++
++/*******************************************/
++void
++VersionInfoJPEG()	/* GRR 19980605, 19980607 */
++{
++  int major = JPEG_LIB_VERSION / 10;
++  int minor = JPEG_LIB_VERSION % 10;
++  char minoralpha[2];
++
++  if (minor) {
++    minoralpha[0] = (char)(minor - 1 + 'a');
++    minoralpha[1] = '\0';
++  } else
++    minoralpha[0] = '\0';
++
++/* fprintf(stderr, "   Compiled with libjpeg %d.%d.\n", major, minor); */
++  fprintf(stderr, "   Compiled with libjpeg %d%s.\n", major, minoralpha);
++}
++
++
++
++
++
+ #endif  /* HAVE_JPEG */
+diff -ru xv-3.10a/xvmisc.c xv-3.10a-enhancements/xvmisc.c
+--- xv-3.10a/xvmisc.c	1995-01-13 15:41:34.000000000 -0800
++++ xv-3.10a-enhancements/xvmisc.c	2007-05-13 17:32:59.000000000 -0700
+@@ -21,13 +21,15 @@
+  *     void   LoadFishCursors()
+  *     void   WaitCursor()
+  *     void   SetCursors(int)
+- *     char  *BaseName(char *)
++ *     const char  *BaseName(const char *)
+  *     void   DrawTempGauge(win, x,y,w,h, percent, fg,bg,hi,lo, str)
+  *     void   ProgressMeter(min, max, val, str);
+  *     void   xvbcopy(src, dst, length)
+  *     int    xvbcmp (s1,  s2,  length)
+  *     void   xvbzero(s, length)
+  *     char  *xv_strstr(s1, s2)
++ *     FILE  *xv_fopen(str, str)
++ *     void   xv_mktemp(str)
+  *     void   Timer(milliseconds)
+  */
+ 
+@@ -36,6 +38,10 @@
+ #define NEEDSTIME
+ #include "xv.h"
+ 
++#ifdef __linux__	/* probably others, too, but being conservative */
++#  include <unistd.h>	/* getwd() */
++#endif
++
+ #include "bits/fc_left"
+ #include "bits/fc_leftm"
+ #include "bits/fc_left1"
+@@ -61,21 +67,24 @@
+ 
+   /* the following fakes 'XSetWMProtocols(theDisp, win, &atom_DELWIN, 1);' */
+ 
+-  if (! atom_PROTOCOLS) 
++  if (! atom_PROTOCOLS)
+     atom_PROTOCOLS = XInternAtom (theDisp, "WM_PROTOCOLS", False);
+ 
+   if (atom_PROTOCOLS == None) return;
+ 
+-  XChangeProperty(theDisp, win, atom_PROTOCOLS, XA_ATOM, 32, 
++  XChangeProperty(theDisp, win, atom_PROTOCOLS, XA_ATOM, 32,
+ 		  PropModeReplace, (unsigned char *) &atom_DELWIN, 1);
+ }
+ 
+ 
+ /***************************************************/
+ Window CreateWindow(name,clname,geom,defw,defh,fg,bg,usesize)
+-char         *name, *clname, *geom;
+-int           defw,defh,usesize;
+-unsigned long fg, bg;
++     const char   *name;
++     const char   *clname;
++     const char   *geom;
++     int           defw,defh;
++     unsigned long fg, bg;
++     int           usesize;
+ {
+   Window               win;
+   XSetWindowAttributes xswa;
+@@ -91,16 +100,24 @@
+   x = y = 1;
+   i = XParseGeometry(geom,&x,&y, (unsigned int *) &w, (unsigned int *) &h);
+ 
+-  if ((i&XValue || i&YValue)) hints.flags = USPosition;  
++  if ((i&XValue || i&YValue)) hints.flags = USPosition;
+                          else hints.flags = PPosition;
+-  
++
+   if (!usesize || !(i&WidthValue))  w = defw;
+   if (!usesize || !(i&HeightValue)) h = defh;
+ 
+-  hints.flags |= USSize;
++  hints.flags |= USSize | PWinGravity;
+ 
+-  if (i&XValue && i&XNegative) x = dispWIDE - w - abs(x);
+-  if (i&YValue && i&YNegative) y = dispHIGH - h - abs(y);
++  hints.win_gravity = NorthWestGravity;
++  if (i&XValue && i&XNegative) {
++    hints.win_gravity = NorthEastGravity;
++    x = dispWIDE - (w + 2 * bwidth) - abs(x);
++  }
++  if (i&YValue && i&YNegative) {
++    hints.win_gravity = (hints.win_gravity == NorthWestGravity) ?
++      SouthWestGravity : SouthEastGravity;
++    y = dispHIGH - (h + 2 * bwidth) - abs(y);
++  }
+ 
+ 
+ #define VROOT_TRANS
+@@ -130,77 +147,76 @@
+   xswamask = CWBackPixel | CWBorderPixel | CWColormap;
+   if (!usesize) xswamask |= CWBitGravity;
+ 
+-  win = XCreateWindow(theDisp, rootW, x, y, (u_int) w, (u_int) h, 
++  win = XCreateWindow(theDisp, rootW, x, y, (u_int) w, (u_int) h,
+ 		      (u_int) bwidth, (int) dispDEEP, InputOutput,
+ 		      theVisual, xswamask, &xswa);
+   if (!win) return(win);   /* leave immediately if couldn't create */
+ 
+ 
+-  XSetStandardProperties(theDisp, win, name, name, None, NULL, 0, &hints);
+-
+   xwmh.input = True;
+   xwmh.flags = InputHint;
+   if (iconPix) { xwmh.icon_pixmap = iconPix;  xwmh.flags |= IconPixmapHint; }
+-  XSetWMHints(theDisp, win, &xwmh);
+ 
+   if (clname && strlen(clname)) {
+     classh.res_name = "xv";
+-    classh.res_class = clname;
+-    XSetClassHint(theDisp, win, &classh);
++    classh.res_class = (char *) clname;
+     StoreDeleteWindowProp(win);
+   }
+ 
++  XmbSetWMProperties(theDisp, win, name, name, NULL, 0, &hints, &xwmh,
++      clname ? &classh : NULL);
++
+   return(win);
+ }
+-  
++
+ 
+ 
+ /**************************************************/
+ void DrawString(win,x,y,str)
+-     Window win;
+-     int x,y;
+-     char *str;
++     Window      win;
++     int         x,y;
++     const char *str;
+ {
+   XDrawString(theDisp, win, theGC, x, y, str, (int) strlen(str));
+ }
+ 
+-  
++
+ /**************************************************/
+ void CenterString(win,x,y,str)
+-     Window win;
+-     int x,y;
+-     char *str;
++     Window      win;
++     int         x,y;
++     const char *str;
+ {
+   DrawString(win, CENTERX(mfinfo, x, str), CENTERY(mfinfo, y), str);
+ }
+ 
+-  
++
+ /**************************************************/
+ void ULineString(win,x,y,str)
+-     Window win;
+-     int x,y;
+-     char *str;
++     Window      win;
++     int         x,y;
++     const char *str;
+ {
+   DrawString(win, x, y, str);
+-  XDrawLine(theDisp, win, theGC, x, y+DESCENT-1, 
++  XDrawLine(theDisp, win, theGC, x, y+DESCENT-1,
+ 	    x+StringWidth(str), y+DESCENT-1);
+ }
+ 
+-  
++
+ /**************************************************/
+ int StringWidth(str)
+-     char *str;
++     const char *str;
+ {
+   return(XTextWidth(mfinfo, str, (int) strlen(str)));
+ }
+ 
+-  
++
+ /**************************************************/
+ int CursorKey(ks, shift, dotrans)
+      KeySym ks;
+      int    shift, dotrans;
+ {
+-  /* called by the KeyPress/KeyRelease event handler to determine if a 
++  /* called by the KeyPress/KeyRelease event handler to determine if a
+      given keypress is a cursor key.  More complex than you'd think, since
+      certain Sun Keyboards generate a variety of odd keycodes, and not all
+      keyboards *have* all these keys.  Note that 'shifted' arrow keys
+@@ -225,29 +241,29 @@
+ 
+   int  i = CK_NONE;
+ 
+-  if      (ks==XK_Up    || ks==XK_KP_Up    || 
+-	   ks==XK_KP_8  || ks==XK_F28)             i=CK_UP;
++  if      (ks==XK_Up    || ks==XK_KP_Up    ||
++			   ks==XK_F28)             i=CK_UP;
+ 
+-  else if (ks==XK_Down  || ks==XK_KP_Down  || 
+-	   ks==XK_KP_2  || ks==XK_F34)             i=CK_DOWN;
++  else if (ks==XK_Down  || ks==XK_KP_Down  ||
++			   ks==XK_F34)             i=CK_DOWN;
+ 
+-  else if (ks==XK_Left  || ks==XK_KP_Left  || 
+-	   ks==XK_KP_4  || ks==XK_F30)             i=CK_LEFT;
++  else if (ks==XK_Left  || ks==XK_KP_Left  ||
++			   ks==XK_F30)             i=CK_LEFT;
+ 
+-  else if (ks==XK_Right || ks==XK_KP_Right || 
+-	   ks==XK_KP_6  || ks==XK_F32)             i=CK_RIGHT;
++  else if (ks==XK_Right || ks==XK_KP_Right ||
++			   ks==XK_F32)             i=CK_RIGHT;
+ 
+   else if (ks==XK_Prior || ks==XK_KP_Prior ||
+-	   ks==XK_KP_9  || ks==XK_F29)             i=CK_PAGEUP;
++			   ks==XK_F29)             i=CK_PAGEUP;
+ 
+   else if (ks==XK_Next  || ks==XK_KP_Next  ||
+-	   ks==XK_KP_3  || ks==XK_F35)             i=CK_PAGEDOWN;
++			   ks==XK_F35)             i=CK_PAGEDOWN;
+ 
+   else if (ks==XK_Home  || ks==XK_KP_Home  ||
+-	   ks==XK_KP_7  || ks==XK_F27)             i=CK_HOME;
++			   ks==XK_F27)             i=CK_HOME;
+ 
+   else if (ks==XK_End   || ks==XK_KP_End   ||
+-	   ks==XK_KP_1  || ks==XK_F33)             i=CK_END;
++			   ks==XK_F33)             i=CK_END;
+ 
+   else i = CK_NONE;
+ 
+@@ -257,7 +273,7 @@
+     else if (i==CK_UP)       i=CK_PAGEUP;
+     else if (i==CK_DOWN)     i=CK_PAGEDOWN;
+   }
+-  
++
+   return i;
+ }
+ 
+@@ -334,9 +350,9 @@
+   ev.window = win;
+   ev.x = x;  ev.y = y;  ev.width = w;  ev.height = h;
+   ev.count = 0;
+-  
++
+   XSendEvent(theDisp, win, False, NoEventMask, (XEvent *) &ev);
+-}    
++}
+ 
+ 
+ /***********************************/
+@@ -381,7 +397,7 @@
+      u_int  w, h;
+      u_long bg;
+ {
+-  /* stipple a rectangular region by drawing 'bg' where there's 1's 
++  /* stipple a rectangular region by drawing 'bg' where there's 1's
+      in the stipple pattern */
+ 
+   XSetFillStyle (theDisp, theGC, FillStippled);
+@@ -400,7 +416,7 @@
+      unsigned int  w,h;
+      unsigned long hi, lo, bg;
+ {
+-  int i,r,x1,y1;
++  int i, x1, y1;
+ 
+   x1 = x + (int) w;
+   y1 = y + (int) h;
+@@ -413,7 +429,7 @@
+       XDrawLine(theDisp, win, theGC, x+i, y1-i, x+i,  y+i);
+       XDrawLine(theDisp, win, theGC, x+i, y+i,  x1-i, y+i);
+     }
+-    
++
+     /* draw bot-right */
+     XSetForeground(theDisp, theGC, (inout==R3D_OUT) ? lo : hi);
+ 
+@@ -431,18 +447,18 @@
+     }
+   }
+ }
+-    
++
+ 
+ 
+ /**************************************************/
+ void SetCropString()
+ {
+   /* sets the crop string in the info box to be correct.  should
+-     be called whenever 'but[BCROP].active', cXOFF,cYOFF,cWIDE,cHIGH 
++     be called whenever 'but[BCROP].active', cXOFF,cYOFF,cWIDE,cHIGH
+      are changed */
+ 
+-  if (cpic != pic) 
+-    SetISTR(ISTR_CROP, "%dx%d rectangle starting at %d,%d",  
++  if (cpic != pic)
++    SetISTR(ISTR_CROP, "%dx%d rectangle starting at %d,%d",
+ 	    cWIDE, cHIGH, cXOFF, cYOFF);
+   else SetISTR(ISTR_CROP, "<none>");
+ }
+@@ -469,7 +485,7 @@
+   char *st;
+ 
+   /* give 'em time to read message */
+-  if (infoUp || ctrlUp || anyBrowUp) sleep(3); 
++  if (infoUp || ctrlUp || anyBrowUp) sleep(3);
+   else {
+     st = GetISTR(ISTR_INFO);
+     OpenAlert(st);
+@@ -477,11 +493,11 @@
+     CloseAlert();
+   }
+ }
+-    
++
+ 
+ /***********************************/
+ void FatalError (identifier)
+-      char *identifier;
++      const char *identifier;
+ {
+   fprintf(stderr, "%s: %s\n",cmd, identifier);
+   Quit(-1);
+@@ -491,12 +507,17 @@
+ /***********************************/
+ void Quit(i)
+      int i;
+-{ 
++{
+   /* called when the program exits.  frees everything explictly created
+      EXCEPT allocated colors.  This is used when 'useroot' is in operation,
+      as we have to keep the alloc'd colors around, but we don't want anything
+      else to stay */
+ 
++#ifdef AUTO_EXPAND
++  chdir(initdir);
++  Vdsettle();
++#endif
++
+   if (!theDisp) exit(i);   /* called before connection opened */
+ 
+   if (useroot && i==0) {   /* save the root info */
+@@ -516,14 +537,38 @@
+     if (jpegW) XDestroyWindow(theDisp, jpegW);
+ #endif
+ 
++#ifdef HAVE_JP2K
++    if (jp2kW) XDestroyWindow(theDisp, jp2kW);
++#endif
++
+ #ifdef HAVE_TIFF
+     if (tiffW) XDestroyWindow(theDisp, tiffW);
+ #endif
+ 
++#ifdef HAVE_PNG
++    if (pngW)  XDestroyWindow(theDisp, pngW);
++#endif
++
++#ifdef HAVE_PCD
++    if (pcdW)  XDestroyWindow(theDisp, pcdW);
++#endif
++
++#ifdef HAVE_PIC2
++    if (pic2W) XDestroyWindow(theDisp, pic2W);
++#endif
++
++#ifdef HAVE_MGCSFX
++    if (mgcsfxW) XDestroyWindow(theDisp, mgcsfxW);
++#endif
++
++#ifdef HAVE_PNG
++    if (pngW)  XDestroyWindow(theDisp, pngW);
++#endif
++
+     /* if NOT using stdcmap for images, free stdcmap */
+-    if (colorMapMode != CM_STDCMAP) { 
++    if (colorMapMode != CM_STDCMAP) {
+       int j;
+-      for (j=0; j<stdnfcols; j++) 
++      for (j=0; j<stdnfcols; j++)
+ 	xvFreeColors(theDisp, theCmap, &stdfreecols[j], 1, 0L);
+     }
+ 
+@@ -543,13 +588,13 @@
+       if (origlist[j][0] != '/') {  /* relative path, prepend 'initdir' */
+ 	sprintf(str,"%s/%s", initdir, origlist[j]);
+ 	if (unlink(str)) {
+-	  fprintf(stderr,"%s: can't delete '%s' - %s\n", 
++	  fprintf(stderr,"%s: can't delete '%s' - %s\n",
+ 		  cmd, str, ERRSTR(errno));
+ 	}
+       }
+       else {
+ 	if (unlink(origlist[j])) {
+-	  fprintf(stderr,"%s: can't delete '%s' - %s\n", 
++	  fprintf(stderr,"%s: can't delete '%s' - %s\n",
+ 		  cmd, origlist[j], ERRSTR(errno));
+ 	}
+       }
+@@ -567,7 +612,7 @@
+ void LoadFishCursors()
+ {
+ #define fc_w 16
+-#define fc_h 16 
++#define fc_h 16
+ 
+   Pixmap flpix,flmpix,fmpix,fmmpix,frpix,frmpix;
+   Pixmap fl1pix, fl1mpix, fr1pix, fr1mpix;
+@@ -592,7 +637,7 @@
+ 
+   fr1pix = XCreatePixmapFromBitmapData(theDisp, ctrlW, (char *) fc_right1_bits,
+ 	     fc_w, fc_h, 1L, 0L, 1);
+-  fr1mpix = XCreatePixmapFromBitmapData(theDisp, ctrlW, 
++  fr1mpix = XCreatePixmapFromBitmapData(theDisp, ctrlW,
+ 					(char *) fc_right1m_bits,
+ 	     fc_w, fc_h, 1L, 0L, 1);
+ 
+@@ -613,7 +658,7 @@
+   fr1curs= XCreatePixmapCursor(theDisp, fr1pix,fr1mpix,&fg, &bg, 8,8);
+   frcurs = XCreatePixmapCursor(theDisp, frpix, frmpix, &fg, &bg, 8,8);
+ 
+-  if (!flcurs || !fmcurs || !frcurs || !fl1curs || !fr1curs) 
++  if (!flcurs || !fmcurs || !frcurs || !fl1curs || !fr1curs)
+     { flcurs = fmcurs = frcurs = (Cursor) NULL; }
+ }
+ 
+@@ -633,8 +678,8 @@
+     time(&lastwaittime);
+     waiting=1;
+     xwmh.input       = True;
+-    xwmh.icon_pixmap = riconPix;  
+-    xwmh.icon_mask   = riconmask;  
++    xwmh.icon_pixmap = riconPix;
++    xwmh.icon_mask   = riconmask;
+     xwmh.flags = (InputHint | IconPixmapHint | IconMaskHint) ;
+     if (!useroot && mainW) XSetWMHints(theDisp, mainW, &xwmh);
+     if ( useroot && ctrlW) XSetWMHints(theDisp, ctrlW, &xwmh);
+@@ -665,8 +710,8 @@
+     if (waiting) {
+       waiting=0;
+       xwmh.input       = True;
+-      xwmh.icon_pixmap = iconPix;  
+-      xwmh.icon_mask   = iconmask;  
++      xwmh.icon_pixmap = iconPix;
++      xwmh.icon_mask   = iconmask;
+       xwmh.flags = (InputHint | IconPixmapHint | IconMaskHint) ;
+       if (!useroot && mainW) XSetWMHints(theDisp, mainW, &xwmh);
+       if ( useroot && ctrlW) XSetWMHints(theDisp, ctrlW, &xwmh);
+@@ -694,11 +739,11 @@
+ 
+   XFlush(theDisp);
+ }
+-  
++
+ 
+ static void set_cursors(mainc, otherc)
+      Cursor mainc, otherc;
+-{    
++{
+   if (!useroot && mainW) XDefineCursor(theDisp, mainW, mainc);
+   if (infoW) XDefineCursor(theDisp, infoW, otherc);
+   if (ctrlW) XDefineCursor(theDisp, ctrlW, otherc);
+@@ -708,42 +753,63 @@
+ 
+   SetBrowseCursor(otherc);
+   SetTextCursor(otherc);
+-  
++
+ #ifdef HAVE_JPEG
+   if (jpegW) XDefineCursor(theDisp, jpegW, otherc);
+ #endif
+-  
++
++#ifdef HAVE_JP2K
++  if (jp2kW) XDefineCursor(theDisp, jp2kW, otherc);
++#endif 
++
+ #ifdef HAVE_TIFF
+   if (tiffW) XDefineCursor(theDisp, tiffW, otherc);
+ #endif
++
++#ifdef HAVE_PNG
++  if (pngW)  XDefineCursor(theDisp, pngW, otherc);
++#endif
++
++#ifdef HAVE_PNG
++  if (pngW)  XDefineCursor(theDisp, pngW, otherc);
++#endif
++
++#ifdef HAVE_PCD
++  if (pcdW)  XDefineCursor(theDisp, pcdW, otherc);
++#endif
++
++#ifdef HAVE_PIC2
++  if (pic2W) XDefineCursor(theDisp, pic2W, otherc);
++#endif
++
++#ifdef HAVE_MGCSFX
++  if (mgcsfxW) XDefineCursor(theDisp, mgcsfxW, otherc);
++#endif
+ }
+ 
+ 
+ /***************************************************/
+-char *BaseName(fname)
+-     char *fname;
++const char *BaseName(fname)
++     const char *fname;
+ {
+-  char *basname;
++  const char *basname;
+ 
+-  /* given a complete path name ('/foo/bar/weenie.gif'), returns just the 
++  /* given a complete path name ('/foo/bar/weenie.gif'), returns just the
+      'simple' name ('weenie.gif').  Note that it does not make a copy of
+      the name, so don't be modifying it... */
+ 
+-  basname = (char *) rindex(fname, '/');
+-  if (!basname) basname = fname;
+-  else basname++;
+-
+-  return basname;
++  basname = (const char *) rindex(fname, '/');
++  return basname? basname+1 : fname;
+ }
+ 
+-  
++
+ /***************************************************/
+ void DrawTempGauge(win, x,y,w,h, ratio, fg,bg,hi,lo, str)
+-     Window win;
+-     int    x,y,w,h;
+-     double ratio;
+-     u_long fg,bg,hi,lo;
+-     char   *str;
++     Window      win;
++     int         x,y,w,h;
++     double      ratio;
++     u_long      fg,bg,hi,lo;
++     const char *str;
+ {
+   /* draws a 'temprature'-style horizontal progress meter in the specified
+      window, at the specified location */
+@@ -773,14 +839,14 @@
+     if (numchars) {      /* do string */
+       if (barwide < maxwide) {
+ 	XSetForeground(theDisp, theGC, bg);
+-	XFillRectangle(theDisp, win, theGC, x+3+barwide, y+3, 
++	XFillRectangle(theDisp, win, theGC, x+3+barwide, y+3,
+ 		       (u_int) (maxwide-barwide), (u_int) (h-5));
+       }
+-	
++
+       XSetFunction(theDisp, theGC, GXinvert);
+       XSetPlaneMask(theDisp, theGC, fg ^ bg);
+ 
+-      XDrawString(theDisp, win, theGC, CENTERX(mfinfo, (x+w/2), str), 
++      XDrawString(theDisp, win, theGC, CENTERX(mfinfo, (x+w/2), str),
+ 		  CENTERY(mfinfo, (y+h/2)), str, numchars);
+ 
+       XSetFunction(theDisp, theGC, GXcopy);
+@@ -789,18 +855,18 @@
+ 
+     else if (barwide < maxwide) {
+       XDrawLine(theDisp,win,theGC,x+3+barwide, y+h/2 + 0, x+w-3, y+h/2 + 0);
+-      
++
+       XSetForeground(theDisp, theGC, lo);
+       XDrawLine(theDisp,win,theGC,x+3+barwide, y+h/2 + 1, x+w-3, y+h/2 + 1);
+-      
++
+       XSetForeground(theDisp, theGC, hi);
+       XDrawLine(theDisp,win,theGC,x+3+barwide, y+h/2 + 2, x+w-3, y+h/2 + 2);
+-      
++
+       XSetForeground(theDisp, theGC, bg);
+-      XFillRectangle(theDisp, win, theGC, x+3+barwide, y+3, 
++      XFillRectangle(theDisp, win, theGC, x+3+barwide, y+3,
+ 		     (u_int) (maxwide-barwide), (u_int) (h/2 - 3));
+-      
+-      XFillRectangle(theDisp, win, theGC, x+3+barwide, y+h/2 + 3, 
++
++      XFillRectangle(theDisp, win, theGC, x+3+barwide, y+h/2 + 3,
+ 		     (u_int) (maxwide-barwide),(u_int)((h-3) - (h/2+3)) + 1);
+     }
+   }
+@@ -815,44 +881,44 @@
+     if (numchars) {
+       if (barwide < maxwide) {
+ 	XSetForeground(theDisp, theGC, bg);
+-	XFillRectangle(theDisp, win, theGC, x+1+barwide, y+1, 
++	XFillRectangle(theDisp, win, theGC, x+1+barwide, y+1,
+ 		       (u_int) (maxwide-barwide), (u_int) (h-1));
+       }
+-      
++
+       XSetFunction(theDisp, theGC, GXinvert);
+       XSetPlaneMask(theDisp, theGC, fg ^ bg);
+ 
+-      XDrawString(theDisp, win, theGC, CENTERX(mfinfo, (x+w/2), str), 
++      XDrawString(theDisp, win, theGC, CENTERX(mfinfo, (x+w/2), str),
+ 		  CENTERY(mfinfo, (y+h/2)), str, numchars);
+ 
+       XSetFunction(theDisp, theGC, GXcopy);
+       XSetPlaneMask(theDisp, theGC, AllPlanes);
+     }
+-    
++
+     else if (barwide < maxwide) {
+       XDrawLine(theDisp, win, theGC, x+1+barwide, y+h/2, x+w-1, y+h/2);
+-      
++
+       XSetForeground(theDisp, theGC, bg);
+-      XFillRectangle(theDisp, win, theGC, x+1+barwide, y+1, 
++      XFillRectangle(theDisp, win, theGC, x+1+barwide, y+1,
+ 		     (u_int) (maxwide-barwide), (u_int) (h/2 - 1));
+-      
+-      XFillRectangle(theDisp, win, theGC, x+1+barwide, y+h/2 + 1, 
++
++      XFillRectangle(theDisp, win, theGC, x+1+barwide, y+h/2 + 1,
+ 		     (u_int)(maxwide-barwide),(u_int)(((h-1) - (h/2+1))+1));
+     }
+   }
+ 
+   XFlush(theDisp);
+ }
+-    
++
+ 
+ 
+ /***************************************************/
+ void ProgressMeter(min, max, val, str)
+-     int min, max, val;
+-     char *str;
++     int         min, max, val;
++     const char *str;
+ {
+   /* called during 'long' operations (algorithms, smoothing, etc.) to
+-     give some indication that the program will ever finish.  Draws a 
++     give some indication that the program will ever finish.  Draws a
+      temperature gauge in either mainW (if not useRoot), or ctrlW.
+      Tries to be clever:  only draws gauge if it looks like the operation is
+      going to take more than a few seconds.  Calling with val == max removes
+@@ -887,7 +953,7 @@
+   if (!waiting) {     /* not waiting (or not waiting any longer) */
+     if (nowTime == lastTime && val<max) return;  /* max one draw per second */
+     lastTime = nowTime;
+-    DrawTempGauge(win, xpos, ypos, 100,19, doneness, 
++    DrawTempGauge(win, xpos, ypos, 100,19, doneness,
+ 		    infofg,infobg,hicol,locol,str);
+ 
+     if (val >= max) {            /* remove temp gauge */
+@@ -915,7 +981,7 @@
+ void XVCreatedFile(fullname)
+      char *fullname;
+ {
+-  /* called whenever a file has been deleted.  Updates browser & dir windows,
++  /* called whenever a file has been created.  Updates browser & dir windows,
+      if necessary */
+ 
+   BRCreatedFile(fullname);
+@@ -925,7 +991,8 @@
+ 
+ /***************************************************/
+ void xvbcopy(src, dst, len)
+-     char *src, *dst;
++     const char *src;
++     char *dst;
+      size_t  len;
+ {
+   /* Modern OS's (Solaris, etc.) frown upon the use of bcopy(),
+@@ -945,7 +1012,7 @@
+    */
+ 
+   if (src==dst || len<=0) return;    /* nothin' to do */
+-  
++
+   if (src<dst && src+len>dst) {  /* do a backward copy */
+     src = src + len - 1;
+     dst = dst + len - 1;
+@@ -957,11 +1024,11 @@
+     for ( ; len>0; len--, src++, dst++) *dst = *src;
+   }
+ }
+-    
++
+ 
+ /***************************************************/
+ int xvbcmp (s1, s2, len)
+-     char   *s1, *s2;
++     const char   *s1, *s2;
+      size_t  len;
+ {
+   for ( ; len>0; len--, s1++, s2++) {
+@@ -985,28 +1052,31 @@
+      char   *buf;
+      size_t  buflen;
+ {
+-  /* gets the current working directory.  No trailing '/' */
++  /* Gets the current working directory and puts it in buf.  No trailing '/'. */
+ 
+-  char *rv; 
++  const char *rv;
+ 
+ #ifdef USE_GETCWD
+-  rv = (char *) getcwd(buf, buflen);
++  rv = (const char *) getcwd(buf, buflen);
+ #else
+-  rv = (char *) getwd(buf);
++  rv = (const char *) getwd(buf);
+ #endif
+ 
+   if (!rv || strlen(rv)==0) {
+-    if (((rv=(char *) getenv("PWD"))==NULL) && 
+-	((rv=(char *) getenv("cwd"))==NULL)) rv = "./";
++    if (((rv=(const char *) getenv("PWD"))==NULL) &&
++	((rv=(const char *) getenv("cwd"))==NULL)) rv = "./";
+     strcpy(buf, rv);
+   }
++#ifdef AUTO_EXPAND
++  Vdtodir(buf);
++#endif
+ }
+ 
+ 
+ 
+ /***************************************************/
+ 
+-/* 
++/*
+  *	Source code for the "strstr" library routine.
+  *
+  * Copyright 1988 Regents of the University of California
+@@ -1020,10 +1090,11 @@
+  */
+ 
+ char *xv_strstr(string, substring)
+-     char *string;	        /* String to search. */
+-     char *substring;		/* Substring to try to find in string. */
++     const char *string;        /* String to search. */
++     const char *substring;	/* Substring to try to find in string. */
+ {
+-  register char *a, *b;
++  const char *a;
++  const char *b;
+ 
+   /* First scan quickly through the two strings looking for a
+    * single-character match.  When it's found, then compare the
+@@ -1031,14 +1102,14 @@
+    */
+ 
+   b = substring;
+-  if (*b == 0) return string;
++  if (*b == 0) return (char *) string;
+ 
+   for ( ; *string != 0; string += 1) {
+     if (*string != *b) continue;
+ 
+     a = string;
+     while (1) {
+-      if (*b == 0) return string;
++      if (*b == 0) return (char *) string;
+       if (*a++ != *b++) break;
+     }
+     b = substring;
+@@ -1052,7 +1123,8 @@
+ 
+ /***************************************************/
+ FILE *xv_fopen(fname, mode)
+-     char *fname, *mode;
++     const char *fname;
++     const char *mode;
+ {
+   FILE *fp;
+ 
+@@ -1066,72 +1138,90 @@
+ }
+ 
+ 
++/***************************************************/
++/* GRR 20050320:  added actual mk[s]temp() call... */
++void xv_mktemp(buf, fname)
++     char       *buf;
++     const char *fname;
++{
++#ifndef VMS
++  sprintf(buf, "%s/%s", tmpdir, fname);
++#else
++  sprintf(buf, "Sys$Disk:[]%s", fname);
++#endif
++#ifdef USE_MKSTEMP
++  close(mkstemp(buf));
++#else
++  mktemp(buf);
++#endif
++}
+ 
+ 
+-/*******/
++/***************************************************/
+ void Timer(msec)   /* waits for 'n' milliseconds */
+- int  msec;
+-/*******/
++     int  msec;
+ {
+   long usec;
+ 
+   if (msec <= 0) return;
++
+   usec = (long) msec * 1000;
+ 
+ 
+-#ifdef VMS
++#ifdef USLEEP
++  usleep(usec);
++  /* return */
++#endif
++
++
++#if defined(VMS) && !defined(USLEEP)
+   {
+     float ftime;
+     ftime = msec / 1000.0;
+     lib$wait(&ftime);
+-    return;
++    /* return */
+   }
+ #endif
+ 
+ 
+-#ifdef sgi
++#if defined(sgi) && !defined(USLEEP)
+   {
+     float ticks_per_msec;
+     long ticks;
+     ticks_per_msec = (float) CLK_TCK / 1000.0;
+     ticks = (long) ((float) msec * ticks_per_msec);
+     sginap(ticks);
+-    return;
++    /* return */
+   }
+ #endif
+ 
+ 
+-#if defined(SVR4) || defined(sco)
++/* does SGI define SVR4?  not sure... */
++#if (defined(SVR4) || defined(sco)) && !defined(sgi) && !defined(USLEEP)
+   {
+     struct pollfd dummy;
+     poll(&dummy, 0, msec);
+-    return;
++    /* return */
+   }
+ #endif
+ 
+ 
+-#ifdef USLEEP
+-  usleep(usec);  return;
+-#endif
+-
+-
+-#ifdef NOTIMER
+-  return;
+-#endif
+-
+-
+-#ifndef VMS
++#if !defined(USLEEP) && !defined(VMS) && !defined(sgi) && !defined(SVR4) && !defined(sco) && !defined(NOTIMER)
+   {
+-    /* default Timer() method now uses 'select()', which probably works
+-	on all systems *anyhow* (except for VMS...) */
+-    
++    /* default/fall-through Timer() method now uses 'select()', which
++     * probably works on all systems *anyhow* (except for VMS...) */
++
+     struct timeval time;
+ 
+     time.tv_sec = usec / 1000000L;
+     time.tv_usec = usec % 1000000L;
+     select(0, XV_FDTYPE NULL, XV_FDTYPE NULL, XV_FDTYPE NULL, &time);
++    /* return */
+   }
+-#endif /* VMS */
+-}
++#endif
+ 
+ 
++  /* NOTIMER case, fallthroughs, etc. ... but we return void, so who cares */
++  /* return */
++}
++
+diff -ru xv-3.10a/xvpbm.c xv-3.10a-enhancements/xvpbm.c
+--- xv-3.10a/xvpbm.c	1995-01-03 13:23:44.000000000 -0800
++++ xv-3.10a-enhancements/xvpbm.c	2007-05-13 17:44:03.000000000 -0700
+@@ -23,6 +23,15 @@
+  */
+ 
+ 
++typedef unsigned short  ush;
++typedef unsigned char   uch;
++
++#define alpha_composite(composite, fg, alpha, bg) {               \
++    ush temp = ((ush)(fg)*(ush)(alpha) +                          \
++                (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
++    (composite) = (uch)((temp + (temp >> 8)) >> 8);               \
++}
++
+ #define TRUNCSTR "File appears to be truncated."
+ 
+ static int garbage;
+@@ -31,17 +40,91 @@
+ static int loadpbm  PARM((FILE *, PICINFO *, int));
+ static int loadpgm  PARM((FILE *, PICINFO *, int, int));
+ static int loadppm  PARM((FILE *, PICINFO *, int, int));
++static int loadpam  PARM((FILE *, PICINFO *, int, int));
+ static int getint   PARM((FILE *, PICINFO *));
+ static int getbit   PARM((FILE *, PICINFO *));
+ static int getshort PARM((FILE *));
+-static int pbmError PARM((char *, char *));
++static int pbmError PARM((const char *, const char *));
++
++static const char *bname;
++
++
++#ifdef HAVE_MGCSFX
++/*
++ * When file read or file write is fail, probably it's caused by
++ * reading from pipe which has no data yet, or writing to pipe
++ * which is not ready yet.
++ * Then we can use system call select() on descriptor of pipe and wait.
++ * If you want, change 'undef' to 'define' in the following line.
++ * This feature is performance-killer.
++ */
++#undef FIX_PIPE_ERROR
++
++#ifdef __osf__
++#  ifdef __alpha
++#    define FIX_PIPE_ERROR
++#  endif
++#endif
++
++#endif /* HAVE_MGCSFX */
++
++
++#ifdef FIX_PIPE_ERROR
++
++int pipefdr;
++
++struct timeval timeout;
++int    width;
++fd_set fds;
++
++static void ready_read()
++{
++  if(pipefdr < 0) return; /* if file descriptor is not pipe, OK */
++  WaitCursor();
+ 
+-static char *bname;
++reselect:
++  /* setting of timeout */
++  timeout.tv_sec = 1;  /* 1 sec */
++  timeout.tv_usec = 0; /* 0 usec */
++
++  FD_ZERO(&fds);     /* clear bits */
++  FD_SET(pipefdr, &fds); /* set bit of fd in fds */
++
++  /* number of file descriptor to want check (0 $B!A(B width-1) */
++  width = pipefdr + 1;
++
++  /* select returns number of file descriptors */
++  if (select(width, &fds, NULL, NULL, &timeout) < 0){
++    if(DEBUG){
++      fprintf(stderr, "No file descriptors can't selected, waiting...\n");
++    }
++    goto reselect;
++  }
++
++  if (FD_ISSET(pipefdr, &fds)){
++    /* Now, descriptor of pipe is ready to read */
++    return;
++  }else{
++    if(DEBUG){
++      fprintf(stderr, "Can't read from pipe yet, waiting...\n");
++    }
++    goto reselect;
++  }
++
++}
++#endif /* FIX_PIPE_ERROR */
+ 
+ /*******************************************/
++#ifdef HAVE_MGCSFX
++int LoadPBM(fname, pinfo, fd)
++     char    *fname;
++     PICINFO *pinfo;
++     int      fd;
++#else
+ int LoadPBM(fname, pinfo)
+      char    *fname;
+      PICINFO *pinfo;
++#endif /* HAVE_MGCSFX */
+ /*******************************************/
+ {
+   /* returns '1' on success */
+@@ -50,6 +133,10 @@
+   int    c, c1;
+   int    maxv, rv;
+ 
++#ifdef FIX_PIPE_ERROR
++  pipefdr = fd;
++#endif
++
+   garbage = maxv = rv = 0;
+   bname = BaseName(fname);
+ 
+@@ -57,6 +144,22 @@
+   pinfo->comment = (char *) NULL;
+ 
+ 
++#ifdef HAVE_MGCSFX
++  if(fd < 0){
++    /* open the file */
++    fp = xv_fopen(fname,"r");
++    if (!fp) return (pbmError(bname, "can't open file"));
++
++    /* compute file length */
++    fseek(fp, 0L, 2);
++    filesize = ftell(fp);
++    fseek(fp, 0L, 0);
++  }else{
++    fp = fdopen(fd, "r");
++    if (!fp) return (pbmError(bname, "can't open file"));
++    filesize = 0; /* dummy */
++  }
++#else
+   /* open the file */
+   fp = xv_fopen(fname,"r");
+   if (!fp) return (pbmError(bname, "can't open file"));
+@@ -65,6 +168,7 @@
+   fseek(fp, 0L, 2);
+   filesize = ftell(fp);
+   fseek(fp, 0L, 0);
++#endif /* HAVE_MGCSFX */
+ 
+ 
+   /* read the first two bytes of the file to determine which format
+@@ -73,7 +177,8 @@
+      "P6" = raw pixmap */
+ 
+   c = getc(fp);  c1 = getc(fp);
+-  if (c!='P' || c1<'1' || c1>'6') return(pbmError(bname, "unknown format"));
++  if (c!='P' || c1<'1' || (c1>'6' && c1!='8'))	/* GRR alpha */
++    return(pbmError(bname, "unknown format"));
+ 
+   /* read in header information */
+   pinfo->w = getint(fp, pinfo);  pinfo->h = getint(fp, pinfo);
+@@ -104,6 +209,7 @@
+   if      (c1=='1' || c1=='4') rv = loadpbm(fp, pinfo, c1=='4' ? 1 : 0);
+   else if (c1=='2' || c1=='5') rv = loadpgm(fp, pinfo, c1=='5' ? 1 : 0, maxv);
+   else if (c1=='3' || c1=='6') rv = loadppm(fp, pinfo, c1=='6' ? 1 : 0, maxv);
++  else if            (c1=='8') rv = loadpam(fp, pinfo,           1    , maxv);
+ 
+   fclose(fp);
+ 
+@@ -115,7 +221,7 @@
+   }
+ 
+   return rv;
+-}  
++}
+ 
+ 
+ 
+@@ -127,15 +233,21 @@
+ {
+   byte *pic8;
+   byte *pix;
+-  int   i,j,bit,w,h;
++  int   i,j,bit,w,h,npixels;
++
++  w = pinfo->w;
++  h = pinfo->h;
+ 
+-  w = pinfo->w;  h = pinfo->h;
+-  pic8 = (byte *) calloc((size_t) w * h, (size_t) 1);
+-  if (!pic8) return pbmError(bname, "couldn't malloc 'pic8'");
++  npixels = w * h;
++  if (w <= 0 || h <= 0 || npixels/w != h)
++    return pbmError(bname, "image dimensions too large");
++
++  pic8 = (byte *) calloc((size_t) npixels, (size_t) 1);
++  if (!pic8) FatalError("couldn't malloc 'pic8' for PBM");
+ 
+   pinfo->pic  = pic8;
+   pinfo->type = PIC8;
+-  sprintf(pinfo->fullInfo, "PBM, %s format.  (%ld bytes)", 
++  sprintf(pinfo->fullInfo, "PBM, %s format.  (%ld bytes)",
+ 	  (raw) ? "raw" : "ascii", filesize);
+   sprintf(pinfo->shrtInfo, "%dx%d PBM.", w, h);
+   pinfo->colType = F_BWDITHER;
+@@ -153,7 +265,7 @@
+       for (j=0; j<w; j++, pix++) *pix = getbit(fp, pinfo);
+     }
+ 
+-    if (numgot != w*h) pbmError(bname, TRUNCSTR);
++    if (numgot != npixels) pbmError(bname, TRUNCSTR);
+     if (garbage) {
+       return(pbmError(bname, "Garbage characters in image data."));
+     }
+@@ -192,17 +304,23 @@
+      int      raw, maxv;
+ {
+   byte *pix, *pic8;
+-  int   i,j,bitshift,w,h, holdmaxv;
++  int   i,j,bitshift,w,h,npixels, holdmaxv;
++
+ 
++  w = pinfo->w;
++  h = pinfo->h;
+ 
+-  w = pinfo->w;  h = pinfo->h;
+-  pic8 = (byte *) calloc((size_t) w*h, (size_t) 1);
+-  if (!pic8) return(pbmError(bname, "couldn't malloc 'pic8'"));
++  npixels = w * h;
++  if (w <= 0 || h <= 0 || npixels/w != h)
++    return pbmError(bname, "image dimensions too large");
++
++  pic8 = (byte *) calloc((size_t) npixels, (size_t) 1);
++  if (!pic8) FatalError("couldn't malloc 'pic8' for PGM");
+ 
+ 
+   pinfo->pic  = pic8;
+   pinfo->type = PIC8;
+-  sprintf(pinfo->fullInfo, "PGM, %s format.  (%ld bytes)", 
++  sprintf(pinfo->fullInfo, "PGM, %s format.  (%ld bytes)",
+ 	  (raw) ? "raw" : "ascii", filesize);
+   sprintf(pinfo->shrtInfo, "%dx%d PGM.", pinfo->w, pinfo->h);
+   pinfo->colType = F_GREYSCALE;
+@@ -236,11 +354,24 @@
+       }
+     }
+     else {
+-      numgot = fread(pic8, (size_t) 1, (size_t) w*h, fp);  /* read raw data */
++#ifdef FIX_PIPE_ERROR
++  reread:
++      numgot += fread(pic8 + numgot, (size_t) 1, (size_t) w*h - numgot, fp); /* read raw data */
++      if(errno == EINTR){
++        if(DEBUG){
++	  fprintf(stderr,
++	  "Can't read all data from pipe, call select and waiting...\n");
++	}
++	ready_read();
++	goto reread;
++      }
++#else
++      numgot = fread(pic8, (size_t)1, (size_t)npixels, fp);  /* read raw data */
++#endif
+     }
+   }
+ 
+-  if (numgot != w*h) pbmError(bname, TRUNCSTR);   /* warning only */
++  if (numgot != npixels) pbmError(bname, TRUNCSTR);   /* warning only */
+ 
+   if (garbage) {
+     return (pbmError(bname, "Garbage characters in image data."));
+@@ -256,18 +387,24 @@
+      PICINFO *pinfo;
+      int      raw, maxv;
+ {
+-  byte *pix, *pic24, scale[256], *pic8;
+-  int   i,j,bitshift, w, h, holdmaxv;
++  byte *pix, *pic24, scale[256];
++  int   i,j,bitshift, w, h, npixels, bufsize, holdmaxv;
++
++  w = pinfo->w;
++  h = pinfo->h;
+ 
+-  w = pinfo->w;  h = pinfo->h;
++  npixels = w * h;
++  bufsize = 3*npixels;
++  if (w <= 0 || h <= 0 || npixels/w != h || bufsize/3 != npixels)
++    return pbmError(bname, "image dimensions too large");
+ 
+   /* allocate 24-bit image */
+-  pic24 = (byte *) calloc((size_t) w*h*3, (size_t) 1);
+-  if (!pic24) FatalError("couldn't malloc 'pic24'");
++  pic24 = (byte *) calloc((size_t) bufsize, (size_t) 1);
++  if (!pic24) FatalError("couldn't malloc 'pic24' for PPM");
+ 
+   pinfo->pic  = pic24;
+   pinfo->type = PIC24;
+-  sprintf(pinfo->fullInfo, "PPM, %s format.  (%ld bytes)", 
++  sprintf(pinfo->fullInfo, "PPM, %s format.  (%ld bytes)",
+ 	  (raw) ? "raw" : "ascii", filesize);
+   sprintf(pinfo->shrtInfo, "%dx%d PPM.", w, h);
+   pinfo->colType = F_FULLCOLOR;
+@@ -297,20 +434,149 @@
+       }
+     }
+     else {
+-      numgot = fread(pic24, (size_t) 1, (size_t) w*h*3, fp);  /* read data */
++#ifdef FIX_PIPE_ERROR
++  reread:
++      numgot += fread(pic24 + numgot, (size_t) 1, (size_t) w*h*3 - numgot, fp);  /* read data */
++      if(errno == EINTR){
++        if(DEBUG){
++	  fprintf(stderr,
++	  "Can't read all data from pipe, call select and waiting...\n");
++	}
++	ready_read();
++	goto reread;
++      }
++#else
++      numgot = fread(pic24, (size_t) 1, (size_t) bufsize, fp);  /* read data */
++#endif
+     }
+   }
+-  
+-  if (numgot != w*h*3) pbmError(bname, TRUNCSTR);
++
++  if (numgot != bufsize) pbmError(bname, TRUNCSTR);
+ 
+   if (garbage)
+     return(pbmError(bname, "Garbage characters in image data."));
+ 
+ 
+-  /* have to scale all RGB values up (Conv24to8 expects RGB values to
+-     range from 0-255 */
++  /* have to scale up all RGB values (Conv24to8 expects RGB values to
++     range from 0-255) */
+ 
+-  if (maxv<255) { 
++  if (maxv<255) {
++    for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv;
++
++    for (i=0, pix=pic24; i<h; i++) {
++      if ((i&0x3f)==0) WaitCursor();
++      for (j=0; j<w*3; j++, pix++) *pix = scale[*pix];
++    }
++  }
++
++  return 1;
++}
++
++
++/*******************************************/
++static int loadpam(fp, pinfo, raw, maxv)	/* unofficial RGBA extension */
++     FILE    *fp;
++     PICINFO *pinfo;
++     int      raw, maxv;
++{
++  byte *p, *pix, *pic24, *linebuf, scale[256], bgR, bgG, bgB, r, g, b, a;
++  int   i, j, bitshift, w, h, npixels, bufsize, linebufsize, holdmaxv;
++
++  w = pinfo->w;
++  h = pinfo->h;
++
++  npixels = w * h;
++  bufsize = 3*npixels;
++  linebufsize = 4*w;
++  if (w <= 0 || h <= 0 || npixels/w != h || bufsize/3 != npixels ||
++      linebufsize/4 != w)
++    return pbmError(bname, "image dimensions too large");
++
++  /* allocate 24-bit image */
++  pic24 = (byte *) calloc((size_t) bufsize, (size_t) 1);
++  if (!pic24) FatalError("couldn't malloc 'pic24' for PAM");
++
++  /* allocate line buffer for pre-composited RGBA data */
++  linebuf = (byte *) malloc((size_t) linebufsize);
++  if (!linebuf) {
++    free(pic24);
++    FatalError("couldn't malloc 'linebuf' for PAM");
++  }
++
++  pinfo->pic  = pic24;
++  pinfo->type = PIC24;
++  sprintf(pinfo->fullInfo, "PAM, %s format.  (%ld bytes)",
++	  (raw) ? "raw" : "ascii", filesize);
++  sprintf(pinfo->shrtInfo, "%dx%d PAM.", w, h);
++  pinfo->colType = F_FULLCOLOR;
++
++
++  /* if maxv>255, keep dropping bits until it's reasonable */
++  holdmaxv = maxv;
++  bitshift = 0;
++  while (maxv>255) { maxv = maxv>>1;  bitshift++; }
++
++
++  numgot = 0;
++
++  if (!raw) {					/* GRR:  not alpha-ready */
++    return pbmError(bname, "can't handle non-raw PAM image");
++/*
++    for (i=0, pix=pic24; i<h; i++) {
++      if ((i&0x3f)==0) WaitCursor();
++      for (j=0; j<w*3; j++, pix++)
++	*pix = (byte) (getint(fp, pinfo) >> bitshift);
++    }
++ */
++  }
++  else { /* raw */
++    if (holdmaxv>255) {				/* GRR:  not alpha-ready */
++      return pbmError(bname, "can't handle PAM image with maxval > 255");
++/*
++      for (i=0, pix=pic24; i<h; i++) {
++	if ((i&0x3f)==0) WaitCursor();
++	for (j=0; j<w*3; j++,pix++)
++	  *pix = (byte) (getshort(fp) >> bitshift);
++      }
++ */
++    }
++    else {
++      if (have_imagebg) {			/* GRR:  alpha-ready */
++        bgR = (imagebgR >> 8);
++        bgG = (imagebgG >> 8);
++        bgB = (imagebgB >> 8);
++      } else {
++        bgR = bgG = bgB = 0;
++      }
++      for (i=0, pix=pic24; i<h; i++) {
++        numgot += fread(linebuf, (size_t) 1, (size_t) linebufsize, fp);  /* read data */
++	if ((i&0x3f)==0) WaitCursor();
++	for (j=0, p=linebuf; j<w; j++) {
++          r = *p++;
++          g = *p++;
++          b = *p++;
++          a = *p++;
++          alpha_composite(*pix++, r, a, bgR)
++          alpha_composite(*pix++, g, a, bgG)
++          alpha_composite(*pix++, b, a, bgB)
++	}
++      }
++    }
++  }
++
++  free(linebuf);
++
++  /* in principle this could overflow, but not critical */
++  if (numgot != w*h*4) pbmError(bname, TRUNCSTR);
++
++  if (garbage)
++    return(pbmError(bname, "Garbage characters in image data."));
++
++
++  /* have to scale up all RGB values (Conv24to8 expects RGB values to
++     range from 0-255) */
++
++  if (maxv<255) {
+     for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv;
+ 
+     for (i=0, pix=pic24; i<h; i++) {
+@@ -360,8 +626,8 @@
+ 	  pinfo->comment[0] = '\0';
+ 	}
+ 	else {
+-	  tmpptr = (char *) realloc(pinfo->comment, 
+-		      strlen(pinfo->comment) + strlen(cmt) + 1); 
++	  tmpptr = (char *) realloc(pinfo->comment,
++		      strlen(pinfo->comment) + strlen(cmt) + 1);
+ 	  if (!tmpptr) FatalError("realloc failure in xvpbm.c getint");
+ 	  pinfo->comment = tmpptr;
+ 	}
+@@ -409,7 +675,18 @@
+ 
+   numgot++;
+ 
++  /* Sometime after 1995, NetPBM's ppm(5) man page was changed to say, "Each
++   * sample is represented in pure binary by either 1 or 2 bytes.  If the
++   * Maxval is less than  256, it is 1 byte.  Otherwise, it is 2 bytes.  The
++   * most significant byte is first."  This change is incompatible with
++   * images created for viewing with all previous versions of XV, however,
++   * so both approaches are left available as a compile-time option.  (Could
++   * make it runtime-selectable, too, but unclear whether anybody cares.) */
++#ifdef ASSUME_RAW_PPM_LSB_FIRST  /* legacy approach */
+   return (c2 << 8) | c1;
++#else /* MSB first */
++  return (c1 << 8) | c2;
++#endif
+ }
+ 
+ 
+@@ -445,8 +722,8 @@
+ 	  pinfo->comment[0] = '\0';
+ 	}
+ 	else {
+-	  tmpptr = (char *) realloc(pinfo->comment, 
+-		      strlen(pinfo->comment) + strlen(cmt) + 1); 
++	  tmpptr = (char *) realloc(pinfo->comment,
++		      strlen(pinfo->comment) + strlen(cmt) + 1);
+ 	  if (!tmpptr) FatalError("realloc failure in xvpbm.c getint");
+ 	  pinfo->comment = tmpptr;
+ 	}
+@@ -470,7 +747,7 @@
+ 
+ /*******************************************/
+ static int pbmError(fname, st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+@@ -490,7 +767,7 @@
+      char *comment;
+ {
+   /* writes a PBM/PGM/PPM file to the already open stream
+-     if (raw), writes as RAW bytes, otherwise writes as ASCII 
++     if (raw), writes as RAW bytes, otherwise writes as ASCII
+      'colorstyle' single-handedly determines the type of file written
+      if colorstyle==0, (Full Color) a PPM file is written
+      if colorstyle==1, (Greyscale)  a PGM file is written
+@@ -546,7 +823,7 @@
+ 	  }
+ 	}
+ 	else {
+-	  if (ptype==PIC8) 
++	  if (ptype==PIC8)
+ 	    fprintf(fp,"%3d %3d %3d ",rmap[*pix], gmap[*pix], bmap[*pix]);
+ 	  else
+ 	    fprintf(fp,"%3d %3d %3d ",pix[0], pix[1], pix[2]);
+@@ -554,7 +831,7 @@
+ 	  len+=12;
+ 	  if (len>58) { fprintf(fp,"\n");  len=0; }
+ 	}
+-	
++
+ 	pix += (ptype==PIC24) ? 3 : 1;
+       }
+     }
+@@ -584,7 +861,7 @@
+ 
+   else if (colorstyle==2) {             /* 1-bit B/W stipple */
+     int bit,k,flipbw;
+-    char *str0, *str1;
++    const char *str0, *str1;
+ 
+     /* shouldn't happen */
+     if (ptype == PIC24) FatalError("PIC24 and B/W Stipple in WritePBM()\n");
+@@ -626,10 +903,3 @@
+ 
+   return 0;
+ }
+-
+-
+-	  
+-	  
+-
+-
+-
+diff -ru xv-3.10a/xvpcx.c xv-3.10a-enhancements/xvpcx.c
+--- xv-3.10a/xvpcx.c	1995-01-10 15:06:37.000000000 -0800
++++ xv-3.10a-enhancements/xvpcx.c	2007-05-13 18:46:27.000000000 -0700
+@@ -29,17 +29,17 @@
+ #define PCX_YMAXH   11
+                           /* hres (12,13) and vres (14,15) not used */
+ #define PCX_CMAP    16    /* start of 16*3 colormap data */
+-#define PCX_PLANES  65 
++#define PCX_PLANES  65
+ #define PCX_BPRL    66
+ #define PCX_BPRH    67
+ 
+ #define PCX_MAPSTART 0x0c	/* Start of appended colormap	*/
+ 
+ 
+-static int  pcxLoadImage8  PARM((char *, FILE *, PICINFO *, byte *));
+-static int  pcxLoadImage24 PARM((char *, FILE *, PICINFO *, byte *));
++static int  pcxLoadImage8  PARM((const char *, FILE *, PICINFO *, byte *));
++static int  pcxLoadImage24 PARM((const char *, FILE *, PICINFO *, byte *));
+ static void pcxLoadRaster  PARM((FILE *, byte *, int, byte *, int, int));
+-static int  pcxError       PARM((char *, char *));
++static int  pcxError       PARM((const char *, const char *));
+ 
+ 
+ 
+@@ -51,9 +51,9 @@
+ {
+   FILE  *fp;
+   long   filesize;
+-  char  *bname, *errstr;
+-  byte   hdr[128], *image;
++  byte   hdr[128];
+   int    i, colors, gray, fullcolor;
++  const char  *bname;
+ 
+   pinfo->type = PIC8;
+   pinfo->pic     = (byte *) NULL;
+@@ -64,7 +64,7 @@
+   /* open the stream */
+   fp = xv_fopen(fname,"r");
+   if (!fp) return (pcxError(bname, "unable to open file"));
+-  
++
+ 
+   /* figure out the file size */
+   fseek(fp, 0L, 2);
+@@ -84,10 +84,10 @@
+     return pcxError(bname,"unrecognized magic number");
+   }
+ 
+-  pinfo->w = (hdr[PCX_XMAXL] + ((int) hdr[PCX_XMAXH]<<8)) 
++  pinfo->w = (hdr[PCX_XMAXL] + ((int) hdr[PCX_XMAXH]<<8))
+            - (hdr[PCX_XMINL] + ((int) hdr[PCX_XMINH]<<8));
+ 
+-  pinfo->h = (hdr[PCX_YMAXL] + ((int) hdr[PCX_YMAXH]<<8)) 
++  pinfo->h = (hdr[PCX_YMAXL] + ((int) hdr[PCX_YMAXH]<<8))
+            - (hdr[PCX_YMINL] + ((int) hdr[PCX_YMINH]<<8));
+ 
+   pinfo->w++;  pinfo->h++;
+@@ -96,10 +96,10 @@
+   fullcolor = (hdr[PCX_BPP] == 8 && hdr[PCX_PLANES] == 3);
+ 
+   if (DEBUG) {
+-    fprintf(stderr,"PCX: %dx%d image, version=%d, encoding=%d\n", 
++    fprintf(stderr,"PCX: %dx%d image, version=%d, encoding=%d\n",
+ 	    pinfo->w, pinfo->h, hdr[PCX_VER], hdr[PCX_ENC]);
+     fprintf(stderr,"   BitsPerPixel=%d, planes=%d, BytePerRow=%d, colors=%d\n",
+-	    hdr[PCX_BPP], hdr[PCX_PLANES], 
++	    hdr[PCX_BPP], hdr[PCX_PLANES],
+ 	    hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8),
+ 	    colors);
+   }
+@@ -190,9 +190,9 @@
+ 
+   if (colors > 2 || (colors==2 && !gray)) {  /* grayscale or PseudoColor */
+     pinfo->colType = (gray) ? F_GREYSCALE : F_FULLCOLOR;
+-    sprintf(pinfo->fullInfo, 
+-	    "%s PCX, %d plane%s, %d bit%s per pixel.  (%ld bytes)", 
+-	    (gray) ? "Greyscale" : "Color", 
++    sprintf(pinfo->fullInfo,
++	    "%s PCX, %d plane%s, %d bit%s per pixel.  (%ld bytes)",
++	    (gray) ? "Greyscale" : "Color",
+ 	    hdr[PCX_PLANES], (hdr[PCX_PLANES]==1) ? "" : "s",
+ 	    hdr[PCX_BPP],    (hdr[PCX_BPP]==1) ? "" : "s",
+ 	    filesize);
+@@ -212,21 +212,27 @@
+ 
+ /*****************************/
+ static int pcxLoadImage8(fname, fp, pinfo, hdr)
+-     char    *fname;
++     const char *fname;
+      FILE    *fp;
+      PICINFO *pinfo;
+      byte    *hdr;
+ {
+   /* load an image with at most 8 bits per pixel */
+-  
++
+   byte *image;
+-  
++  int count;
++
+   /* note:  overallocation to make life easier... */
+-  image = (byte *) malloc((size_t) (pinfo->h + 1) * pinfo->w + 16);
++  count = (pinfo->h + 1) * pinfo->w + 16;  /* up to 65537*65536+16 (~ 65552) */
++  if (pinfo->w <= 0 || pinfo->h <= 0 || count/pinfo->w < pinfo->h) {
++    pcxError(fname, "Bogus 8-bit PCX file!!");
++    return (0);
++  }
++  image = (byte *) malloc((size_t) count);
+   if (!image) FatalError("Can't alloc 'image' in pcxLoadImage8()");
+-  
+-  xvbzero((char *) image, (size_t) ((pinfo->h+1) * pinfo->w + 16));
+-  
++
++  xvbzero((char *) image, (size_t) count);
++
+   switch (hdr[PCX_BPP]) {
+   case 1:   pcxLoadRaster(fp, image, 1, hdr, pinfo->w, pinfo->h);   break;
+   case 8:   pcxLoadRaster(fp, image, 8, hdr, pinfo->w, pinfo->h);   break;
+@@ -243,31 +249,39 @@
+ 
+ /*****************************/
+ static int pcxLoadImage24(fname, fp, pinfo, hdr)
+-     char *fname;
++     const char *fname;
+      FILE *fp;
+      PICINFO *pinfo;
+      byte *hdr;
+ {
+   byte *pix, *pic24, scale[256];
+-  int   c, i, j, w, h, maxv, cnt, planes, bperlin, nbytes;
+-  
++  int   c, i, j, w, h, maxv, cnt, planes, bperlin, nbytes, count;
++
+   w = pinfo->w;  h = pinfo->h;
+-  
+-  planes = (int) hdr[PCX_PLANES];
+-  bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);
+-  
++
++  planes = (int) hdr[PCX_PLANES];  /* 255 max, but can't get here unless = 3 */
++  bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);  /* 65535 max */
++
++  j = h*planes;          /* w and h are limited to 65536, planes to 3 */
++  count = w*j;           /* ...so this could wrap up to 3 times */
++  nbytes = bperlin*j;    /* ...and this almost 3 times */
++  if (w <= 0 || h <= 0 || planes <= 0 || bperlin <= 0 ||
++      j/h < planes || count/w < j || nbytes/bperlin < j) {
++    pcxError(fname, "Bogus 24-bit PCX file!!");
++    return (0);
++  }
++
+   /* allocate 24-bit image */
+-  pic24 = (byte *) malloc((size_t) w*h*planes);
+-  if (!pic24) FatalError("couldn't malloc 'pic24'");
+-  
+-  xvbzero((char *) pic24, (size_t) w*h*planes);
+-  
++  pic24 = (byte *) malloc((size_t) count);
++  if (!pic24) FatalError("Can't malloc 'pic24' in pcxLoadImage24()");
++
++  xvbzero((char *) pic24, (size_t) count);
++
+   maxv = 0;
+   pix = pinfo->pic = pic24;
+   i = 0;      /* planes, in this while loop */
+   j = 0;      /* bytes per line, in this while loop */
+-  nbytes = bperlin*h*planes;
+- 
++
+   while (nbytes > 0 && (c = getc(fp)) != EOF) {
+     if ((c & 0xC0) == 0xC0) {   /* have a rep. count */
+       cnt = c & 0x3F;
+@@ -275,9 +289,9 @@
+       if (c == EOF) { getc(fp); break; }
+     }
+     else cnt = 1;
+-    
++
+     if (c > maxv)  maxv = c;
+-    
++
+     while (cnt-- > 0) {
+       if (j < w) {
+ 	*pix = c;
+@@ -297,19 +311,19 @@
+       }
+     }
+   }
+-  
+-  
++
++
+   /* scale all RGB to range 0-255, if they aren't */
+ 
+-  if (maxv<255) { 
++  if (maxv<255) {
+     for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv;
+-    
++
+     for (i=0, pix=pic24; i<h; i++) {
+       if ((i&0x3f)==0) WaitCursor();
+       for (j=0; j<w*planes; j++, pix++) *pix = scale[*pix];
+     }
+   }
+-  
++
+   return 1;
+ }
+ 
+@@ -321,13 +335,13 @@
+      byte    *image, *hdr;
+      int      depth,w,h;
+ {
+-  /* supported:  8 bits per pixel, 1 plane, or 1 bit per pixel, 1-8 planes */
++  /* supported:  8 bits per pixel, 1 plane; or 1 bit per pixel, 1-8 planes */
+ 
+   int row, bcnt, bperlin, pad;
+   int i, j, b, cnt, mask, plane, pmask;
+   byte *oldimage;
+ 
+-  bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);
++  bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);  /* 65535 max */
+   if (depth == 1) pad = (bperlin * 8) - w;
+              else pad = bperlin - w;
+ 
+@@ -342,7 +356,7 @@
+       if (b == EOF) { getc(fp); return; }
+     }
+     else cnt = 1;
+-    
++
+     for (i=0; i<cnt; i++) {
+       if (depth == 1) {
+ 	for (j=0, mask=0x80; j<8; j++) {
+@@ -351,12 +365,12 @@
+ 	}
+       }
+       else *image++ = (byte) b;
+-      
++
+       bcnt++;
+-	
++
+       if (bcnt == bperlin) {     /* end of a line reached */
+ 	bcnt = 0;
+-	plane++;  
++	plane++;
+ 
+ 	if (plane >= (int) hdr[PCX_PLANES]) {   /* moved to next row */
+ 	  plane = 0;
+@@ -367,19 +381,19 @@
+ 	}
+ 	else {   /* next plane, same row */
+ 	  image = oldimage;
+-	}	
++	}
+ 
+ 	pmask = 1 << plane;
+       }
+     }
+   }
+-}    
++}
+ 
+ 
+ 
+ /*******************************************/
+ static int pcxError(fname,st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+diff -ru xv-3.10a/xvpds.c xv-3.10a-enhancements/xvpds.c
+--- xv-3.10a/xvpds.c	1995-01-03 13:25:52.000000000 -0800
++++ xv-3.10a-enhancements/xvpds.c	2007-05-12 14:08:47.000000000 -0700
+@@ -22,23 +22,23 @@
+    Choice of algorithm for 16->8 bit conversion--linear or histogram stretch.
+     (adds CONV24_HIST item in "24/8 bit" pull-down menu.)
+    Uses any "palette.tab" file in cwd to color PDS/VICAR image.
+- 
++
+  * 9-2-91    began integration.	 Much of this code is lifted from vicar.c,
+  	     which I wrote for xloadimage.  This is a little simpler, though.
+- 
++
+  * 10-17-91  pdsuncomp is called with system(), which typically feeds the
+  	     commandline to sh.  Make sure that your .profile adds wherever
+  	     you have pdsuncomp to the PATH, like
+- 
++
+  		PATH=$PATH:/usr/local/bin
+- 
++
+  * 11-15-91  substituted vdcomp from Viking CD's for pdsuncomp. I added
+              recognition of - and shut off various messages
+- 
++
+  * 1-5-92    merged into xv rel 2
+- 
++
+  * 3-11-92   cleaned up some comments
+- 
++
+  * 3-24-92   Got some new CD's from NASA of mosics and other processed Viking
+              stuff.  There are actually records terminated with CRNLCR in
+              these images, as well as ones that identify the spacecraft name
+@@ -46,14 +46,14 @@
+              yet further to deal with these.  There's a Sun 4 XView binary for
+              an image display program on these discs, but it's nowhere near as
+              neat as the good Mr. Bradley's XV.
+- 
+- 
++
++
+  * Sources of these CD's:
+  *
+  *  National Space Science Data Center
+  *  Goddard Space Flight Center
+  *  Code 933.4
+- *  Greenbelt, Maryland  
++ *  Greenbelt, Maryland
+  *  (301) 286-6695
+  *   or call
+  *  (301) 286-9000 (300,1200,2400 bps)
+@@ -77,8 +77,7 @@
+  * Huffman-encoded, and the encoding histogram follows the ASCII headers.
+  * To decode these, we use a slightly modified version of "vdcomp.c" from the
+  * NASA Viking CD-ROMS.  For xv to work, you need to have vdcomp compiled
+- * and in your search path.  vdcomp.c should be included with this
+-distribution.
++ * and in your search path.  vdcomp.c should be included with this distribution.
+  *
+  * I've heard that newer discs have FITS images on them.  If they do, support
+  * for them will be added when I get one.  Until then, you can use fitstopgm.
+@@ -91,10 +90,10 @@
+  * Copyright 1989, 1990 by Anthony A. Datri
+  *
+  * Permission to use, copy, and distribute for non-commercial purposes,
+- * is hereby granted without fee, providing that the above copyright   
++ * is hereby granted without fee, providing that the above copyright
+  * notice appear in all copies, that both the copyright notice and this
+  * permission notice appear in supporting documentation.
+- * 
++ *
+  * In exception to the above, permission to John Bradley is hereby granted to
+  * distribute this code as he sees fit within the context of his "xv" image
+  * viewer.
+@@ -102,7 +101,7 @@
+  * This software is provided "as is" without any express or implied warranty.
+  */
+ 
+-
++#define  NEEDSDIR       /* for S_IRUSR|S_IWUSR */
+ #include "xv.h"
+ 
+ #ifdef HAVE_PDS
+@@ -129,27 +128,32 @@
+ 
+ /* This is arbitrary.  Everything I've seen so far fits in 50 chars */
+ #define COMMENTSIZE	50
++#define INOTESIZE	1000
+ 
+ 
+ static int	lastwasinote = FALSE;
+-static char	scanbuff         [MAX_SIZE], 
+-                rtbuff         [RTBUFFSIZE], 
+-		inote	   [20*COMMENTSIZE],
+-                infobuff      [COMMENTSIZE],
+-		spacecraft    [COMMENTSIZE],
+-		target        [COMMENTSIZE],
+-		filtname      [COMMENTSIZE],
+-		gainmode      [COMMENTSIZE],
+-		editmode      [COMMENTSIZE],
+-		scanmode      [COMMENTSIZE],
+-		exposure      [COMMENTSIZE],
+-		shuttermode   [COMMENTSIZE],
+-		mphase        [COMMENTSIZE],
+-		iname         [COMMENTSIZE],
+-		itime         [COMMENTSIZE],
+-                garbage       [1020],
++static char	scanbuff         [MAX_SIZE+1],
++                rtbuff         [RTBUFFSIZE+1],
++		inote	        [INOTESIZE+1],
++                infobuff      [COMMENTSIZE+1],
++		spacecraft    [COMMENTSIZE+1],
++		target        [COMMENTSIZE+1],
++		filtname      [COMMENTSIZE+1],
++		gainmode      [COMMENTSIZE+1],
++		editmode      [COMMENTSIZE+1],
++		scanmode      [COMMENTSIZE+1],
++		exposure      [COMMENTSIZE+1],
++		shuttermode   [COMMENTSIZE+1],
++		mphase        [COMMENTSIZE+1],
++		iname         [COMMENTSIZE+1],
++		itime         [COMMENTSIZE+1],
++                garbage       [1024],
+ 		*tmptmp,
+ 		pdsuncompfname[FNAMESIZE];
++
++#define SSTR(l)			"%" #l "s"
++#define S(l)			SSTR(l)
++
+ byte *image;
+ static int elaphe;
+ 
+@@ -203,10 +207,10 @@
+ 		  }
+                 return(count);
+ 
+-    case EOF:	*bp='\0';  return(count);		    
+-    
++    case EOF:	*bp='\0';  return(count);
++
+     case '\0':  return(count);
+-    
++
+     default:	count++;  *bp++ = c;
+     }
+   }
+@@ -242,7 +246,7 @@
+  * disc seem to leave off the first two bytes.  Sigh.  This may sometimes be
+  * a distinction between the fixed and variable-record files.
+  */
+-            
++
+ /*******************************************/
+ int LoadPDS(fname, pinfo)
+      char    *fname;
+@@ -250,13 +254,16 @@
+ {
+   /* returns '1' on success, '0' on failure */
+ 
+-  int tempnum;
++  int tempnum, bytewidth, bufsize;
++#ifndef USE_MKSTEMP
++  int tmpfd;
++#endif
+   FILE	*zf;
+   static int isfixed,teco,i,j,itype,vaxbyte,
+              recsize,hrecsize,irecsize,isimage,labelrecs,labelsofar,
+-             x,y,lpsize,lssize,samplesize,returnp,labelsize,yy;
++             w,h,lpsize,lssize,samplesize,returnp,labelsize,yy;
+   char	*tmp;
+-  char  *ftypstr;
++  const char   *ftypstr;
+   unsigned long filesize;
+   char  sampletype[64];
+ 
+@@ -265,7 +272,7 @@
+   returnp = isimage = FALSE;
+   itype   = PDSTRASH;
+ 
+-  teco = i = j = recsize = hrecsize = irecsize = labelrecs = x = y = 0;
++  teco = i = j = recsize = hrecsize = irecsize = labelrecs = w = h = 0;
+   lpsize = lssize = samplesize = labelsize = labelsofar = 0;
+ 
+   (*pdsuncompfname) = (*iname) = (*target) = (*filtname) = (*garbage) = '\0';
+@@ -363,7 +370,7 @@
+ 	 * length indicator. If the length indicator is odd, then a pad byte
+ 	 * is appended to the end of the record so that all records contain
+ 	 * an even number of bytes." */
+-	                                                                    
++
+ 	i=getc(zf);
+ 	j=getc(zf);
+ 	if (j == EOF) {
+@@ -371,7 +378,7 @@
+ 	  fclose(zf);
+ 	  return 0;
+ 	}
+-	
++
+ 	teco = i + (j << 8);
+ 	if (teco % 2) teco++;
+ 
+@@ -380,7 +387,7 @@
+ 	  fclose(zf);
+ 	  return 0;
+ 	}
+-	
++
+ 	scanbuff[teco]='\0';
+       }
+ 
+@@ -397,7 +404,7 @@
+ 
+       if (strcmp(scanbuff,"END") == 0) {
+ 	break;
+-      } else if (sscanf(scanbuff," RECORD_TYPE = %s",rtbuff) == 1) {
++      } else if (sscanf(scanbuff, " RECORD_TYPE = " S(RTBUFFSIZE), rtbuff) == 1) {
+ 	if (strncmp(rtbuff,"VARIABLE_LENGTH", (size_t) 15) == 0) {
+ 	  /*		itype=PDSVARIABLE; */
+ 	} else if (strncmp(rtbuff,"FIXED_LENGTH", (size_t) 12) == 0) {
+@@ -416,7 +423,7 @@
+ 	    if (irecsize == 0) irecsize=recsize;
+ 	lastwasinote=FALSE;
+ 	continue;
+-      } else if (sscanf(scanbuff," FILE_TYPE = %s", rtbuff) != 0) {
++      } else if (sscanf(scanbuff, " FILE_TYPE = " S(RTBUFFSIZE), rtbuff) != 0) {
+ 	lastwasinote=FALSE;
+ 	if (strncmp(rtbuff,"IMAGE", (size_t) 5) == 0) {
+ 	  isimage=TRUE;
+@@ -429,11 +436,11 @@
+ 		 (sscanf(scanbuff," LABEL_RECORDS = %d", &labelrecs) == 1)) {
+ 	lastwasinote=FALSE;
+ 	continue;
+-      } else if (sscanf(scanbuff," IMAGE_LINES = %d",&y) == 1) {
++      } else if (sscanf(scanbuff," IMAGE_LINES = %d",&h) == 1) {
+ 	isimage=TRUE; lastwasinote=FALSE; continue;
+-      } else if (sscanf(scanbuff," LINE_SAMPLES = %d",&x) == 1) {
++      } else if (sscanf(scanbuff," LINE_SAMPLES = %d",&w) == 1) {
+ 	lastwasinote=FALSE; continue;
+-      } else if (sscanf(scanbuff," LINES = %d",&y) == 1) {
++      } else if (sscanf(scanbuff," LINES = %d",&h) == 1) {
+ 	isimage=TRUE; lastwasinote=FALSE; continue;
+       } else if (sscanf(scanbuff," HEADER_RECORD_BYTES = %d",&hrecsize)==1) {
+ 	lastwasinote=FALSE; continue;
+@@ -445,74 +452,74 @@
+ 	lastwasinote=FALSE; continue;
+       } else if (sscanf(scanbuff," SAMPLE_BITS = %d", &samplesize) == 1) {
+ 	lastwasinote=FALSE; continue;
+-      } else if (sscanf(scanbuff," SAMPLE_TYPE = %s", sampletype) == 1) {
++      } else if (sscanf(scanbuff, " SAMPLE_TYPE = " S(64), sampletype) == 1) {
+ 	lastwasinote=FALSE; continue;
+-      } else if (sscanf(scanbuff," SPACECRAFT_NAME = %s %s",
++      } else if (sscanf(scanbuff," SPACECRAFT_NAME = " S(COMMENTSIZE) " " S(1023),
+ 			spacecraft,garbage) == 2 ) {
+-	strcat(spacecraft,xv_strstr(scanbuff, spacecraft)+strlen(spacecraft));
++	const char *tmp = xv_strstr(scanbuff, spacecraft) + strlen(spacecraft);
++	strncat(spacecraft, tmp, COMMENTSIZE - strlen(spacecraft));
+ 	lastwasinote=FALSE;  continue;
+-      } else if (sscanf(scanbuff," SPACECRAFT_NAME = %s", spacecraft) == 1) {
++      } else if (sscanf(scanbuff, " SPACECRAFT_NAME = " S(COMMENTSIZE), spacecraft) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," TARGET_NAME = %s", target) == 1) {
++      } else if (sscanf(scanbuff, " TARGET_NAME = " S(COMMENTSIZE), target) == 1) {
+ 	lastwasinote=FALSE; continue;
+-      } else if (sscanf(scanbuff," TARGET_BODY = %s", target) == 1) {
++      } else if (sscanf(scanbuff, " TARGET_BODY = " S(COMMENTSIZE), target) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," MISSION_PHASE_NAME = %s", mphase) == 1) {
++      } else if (sscanf(scanbuff, " MISSION_PHASE_NAME = " S(COMMENTSIZE), mphase) == 1) {
+ 	lastwasinote=FALSE; continue;
+-      } else if (sscanf(scanbuff," MISSION_PHASE = %s", mphase) == 1) {
++      } else if (sscanf(scanbuff, " MISSION_PHASE = " S(COMMENTSIZE), mphase) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," INSTRUMENT_NAME = %s", iname) == 1) {
++      } else if (sscanf(scanbuff, " INSTRUMENT_NAME = " S(COMMENTSIZE), iname) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," GAIN_MODE_ID = %s", gainmode) == 1) {
++      } else if (sscanf(scanbuff, " GAIN_MODE_ID = " S(COMMENTSIZE), gainmode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," INSTRUMENT_GAIN_STATE = %s",gainmode)==1) {
++      } else if (sscanf(scanbuff, " INSTRUMENT_GAIN_STATE = " S(COMMENTSIZE), gainmode) ==1 ) {
+ 	lastwasinote=FALSE; continue;
+-	
+-      } else if (sscanf(scanbuff," EDIT_MODE_ID = %s", editmode) == 1) {
++
++      } else if (sscanf(scanbuff, " EDIT_MODE_ID = " S(COMMENTSIZE), editmode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," INSTRUMENT_EDIT_MODE = %s", editmode)==1) {
++      } else if (sscanf(scanbuff, " INSTRUMENT_EDIT_MODE = " S(COMMENTSIZE), editmode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," SCAN_MODE_ID = %s", scanmode) == 1) {
++      } else if (sscanf(scanbuff, " SCAN_MODE_ID = " S(COMMENTSIZE), scanmode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," INSTRUMENT_SCAN_RATE = %s", scanmode)==1) {
++      } else if (sscanf(scanbuff, " INSTRUMENT_SCAN_RATE = " S(COMMENTSIZE), scanmode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," SHUTTER_MODE_ID = %s", shuttermode) == 1) {
++      } else if (sscanf(scanbuff, " SHUTTER_MODE_ID = " S(COMMENTSIZE), shuttermode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," INSTRUMENT_SHUTTER_MODE = %s",
+-			shuttermode) == 1) {
++      } else if (sscanf(scanbuff, " INSTRUMENT_SHUTTER_MODE = " S(COMMENTSIZE), shuttermode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," SCAN_MODE_ID = %s", scanmode) == 1) {
++      } else if (sscanf(scanbuff, " SCAN_MODE_ID = " S(COMMENTSIZE), scanmode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," INSTRUMENT_SCAN_RATE = %s", scanmode)==1) {
++      } else if (sscanf(scanbuff, " INSTRUMENT_SCAN_RATE = " S(COMMENTSIZE), scanmode) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," SPACECRAFT_EVENT_TIME = %s", itime) == 1) {
++      } else if (sscanf(scanbuff, " SPACECRAFT_EVENT_TIME = " S(COMMENTSIZE), itime) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," IMAGE_TIME = %s", itime) == 1) {
++      } else if (sscanf(scanbuff, " IMAGE_TIME = " S(COMMENTSIZE), itime) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," FILTER_NAME = %s", filtname) == 1) {
++      } else if (sscanf(scanbuff, " FILTER_NAME = " S(COMMENTSIZE), filtname) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff," INSTRUMENT_FILTER_NAME = %s",filtname)==1) {
++      } else if (sscanf(scanbuff, " INSTRUMENT_FILTER_NAME = " S(COMMENTSIZE), filtname) == 1) {
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if ((sscanf(scanbuff," EXPOSURE_DURATION = %s", exposure) == 1)
+-	      || (sscanf(scanbuff," INSTRUMENT_EXPOSURE_DURATION = %s",
+-			 exposure) == 1)) {
++      } else if ((sscanf(scanbuff, " EXPOSURE_DURATION = " S(COMMENTSIZE), exposure) == 1)
++	      || (sscanf(scanbuff, " INSTRUMENT_EXPOSURE_DURATION = " S(COMMENTSIZE),
++			 exposure)) == 1) {
+ 	tmptmp = (char *) index(scanbuff,'=');
+ 	tmptmp++;
+ 	while((*tmptmp) == ' ')
+@@ -520,10 +527,10 @@
+ 	strcpy(exposure,tmptmp);
+ 	lastwasinote=FALSE; continue;
+ 
+-      } else if (sscanf(scanbuff, "NOTE = %s", inote) == 1) {
++      } else if (sscanf(scanbuff, "NOTE = " S(INOTESIZE), inote) == 1) {
+ 	tmptmp = (char *) index(scanbuff,'='); tmptmp++;
+ 	while (((*tmptmp) == ' ') || ((*tmptmp)  == '"')) tmptmp++;
+-	strcpy(inote,tmptmp);
++	strncpy(inote, tmptmp, INOTESIZE - 1);
+ 	strcat(inote," ");
+ 
+ 	/*   evil and somewhat risky:  A "note" (really, any textual
+@@ -531,11 +538,11 @@
+ 	 *     get my hands on the clown who designed this format...
+ 	 *                             What we basically assume here
+ 	 *        is that a NOTE record that doesn't end with a " is
+-	 *    followed by some number of continuations, one of which 
++	 *    followed by some number of continuations, one of which
+ 	 *   will have a " in it.  If this turns out to not be true,
+ 	 *          well, we'll segmentation fault real soon. We use
+ 	 * lastwasinote as a semaphore to indicate that the previous
+-	 *       record was an unfinished NOTE record.  We clear the	  
++	 *       record was an unfinished NOTE record.  We clear the
+ 	 *      flag in each of the above record types for potential
+ 	 *   error recovery, although it really breaks up the beauty
+ 	 * of the cascading sscanfs.  Dykstra'd love me for this one */
+@@ -548,7 +555,7 @@
+       } else if (lastwasinote) {
+ 	tmptmp=scanbuff;
+ 	while (((*tmptmp) == ' ') || ((*tmptmp)  == '"')) tmptmp++;
+-	strcat(inote,tmptmp);
++	strncat(inote, tmptmp, INOTESIZE - strlen(inote) - 1);
+ 	strcat(inote," ");
+ 	if (index(tmptmp,'"') != NULL)
+ 	    lastwasinote=FALSE;
+@@ -568,10 +575,10 @@
+       fclose(zf);
+       return 0;
+     }
+-    
++
+     vaxbyte = strncmp(sampletype, "VAX_", (size_t) 4) == 0 ||
+       strncmp(sampletype, "LSB_", (size_t) 4) == 0;
+-    
++
+   } else if (itype == VICAR) {
+     /* we've got a VICAR file.  Let's find out how big the puppy is */
+     ungetc(' ', zf);
+@@ -582,8 +589,8 @@
+ 	SetISTR(ISTR_WARNING,"LoadPDS: bad NL in VICAR\n");
+ 	returnp=TRUE;
+       }
+-      
+-      if (sscanf(tmp," NL = %d",&y) != 1) {
++
++      if (sscanf(tmp," NL = %d",&h) != 1) {
+ 	SetISTR(ISTR_WARNING,"LoadPDS: bad scan NL in VICAR\n");
+ 	returnp=TRUE;
+       }
+@@ -593,7 +600,7 @@
+ 	returnp=TRUE;
+       }
+ 
+-      if (sscanf(tmp, " NS = %d",&x) != 1) {
++      if (sscanf(tmp, " NS = %d",&w) != 1) {
+ 	SetISTR(ISTR_WARNING,"LoadPDS: bad scan NS in VICAR\n");
+ 	returnp=TRUE;
+       }
+@@ -625,6 +632,13 @@
+     returnp=TRUE;
+   }
+ 
++  /* samplesize can be arbitrarily large (up to int limit) in non-VICAR files */
++  if (samplesize != 8 && samplesize != 16) {
++    SetISTR(ISTR_WARNING,"LoadPDS: %d bits per pixel not supported",
++      samplesize);
++    returnp=TRUE;
++  }
++
+   if (returnp) {
+     fclose(zf);
+     return 0;
+@@ -640,27 +654,27 @@
+ 
+   *infobuff='\0';
+   if (*spacecraft) {
+-    strcat(infobuff,spacecraft);
++    strncat(infobuff, spacecraft, sizeof(infobuff) - 1);
+   }
+ 
+   if (*target) {
+-    strcat(infobuff,", ");
+-    strcat(infobuff,target);
++    strncat(infobuff, ", ", sizeof(infobuff) - strlen(infobuff) - 1);
++    strncat(infobuff, target, sizeof(infobuff) - strlen(infobuff) - 1);
+   }
+ 
+   if (*filtname) {
+-    strcat(infobuff,", ");
+-    strcat(infobuff,filtname);
++    strncat(infobuff, ", ", sizeof(infobuff) - strlen(infobuff) - 1);
++    strncat(infobuff, filtname, sizeof(infobuff) - strlen(infobuff) - 1);
+   }
+ 
+   if (*itime) {
+-    strcat(infobuff,", ");
+-    strcat(infobuff,itime);
++    strncat(infobuff, ", ", sizeof(infobuff) - strlen(infobuff) - 1);
++    strncat(infobuff, itime, sizeof(infobuff) - strlen(infobuff) - 1);
+   }
+ 
+-  SetISTR(ISTR_WARNING,infobuff);
++  SetISTR(ISTR_WARNING, "%s", infobuff);
+ 
+-  strcpy(pdsuncompfname,fname);
++  strncpy(pdsuncompfname,fname,sizeof(pdsuncompfname) - 1);
+   ftypstr = "";
+ 
+   switch (itype) {
+@@ -688,12 +702,26 @@
+     fclose(zf);
+ 
+ #ifndef VMS
+-    sprintf(pdsuncompfname,"%s/xvhuffXXXXXX", tmpdir);
+-    mktemp(pdsuncompfname);
+-    sprintf(scanbuff,"%s %s - 4 >%s",PDSUNCOMP,fname,pdsuncompfname);
++    snprintf(pdsuncompfname, sizeof(pdsuncompfname) - 1, "%s/xvhuffXXXXXX", tmpdir);
+ #else
+     strcpy(pdsuncompfname,"sys$disk:[]xvhuffXXXXXX");
++#endif
++
++#ifdef USE_MKSTEMP
++    close(mkstemp(pdsuncompfname));
++#else
+     mktemp(pdsuncompfname);
++    tmpfd = open(pdsuncompfname,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR);
++    if (tmpfd < 0) {
++      SetISTR(ISTR_WARNING,"Unable to create temporary file.");
++      return 0;
++    }
++    close(tmpfd);
++#endif
++
++#ifndef VMS
++    sprintf(scanbuff,"%s '%s' - 4 > %s", PDSUNCOMP, fname, pdsuncompfname);
++#else
+     sprintf(scanbuff,"%s %s %s 4",PDSUNCOMP,fname,pdsuncompfname);
+ #endif
+ 
+@@ -727,63 +755,72 @@
+     fread(scanbuff, (size_t) labelsize, (size_t) 1, zf);
+   }
+ 
+-  x *= samplesize/8;
++  /* samplesize is bits per pixel; guaranteed at this point to be 8 or 16 */
++  bytewidth = w * (samplesize/8);
++  bufsize = bytewidth * h;
++  if (w <= 0 || h <= 0 || bytewidth/w != (samplesize/8) ||
++      bufsize/bytewidth != h)
++  {
++    SetISTR(ISTR_WARNING,"LoadPDS: image dimensions out of range (%dx%dx%d)",
++      w, h, samplesize/8);
++    fclose(zf);
++    return 0;
++  }
+ 
+-  image = (byte *) malloc((size_t) x*y);
++  image = (byte *) malloc((size_t) bufsize);
+   if (image == NULL) {
+-    SetISTR(ISTR_WARNING,"LoadPDS: couldn't malloc %d",x*y);
+     fclose(zf);
+     if (isfixed == FALSE)
+       unlink(pdsuncompfname);
+-    exit(1);
++    FatalError("LoadPDS: can't malloc image buffer");
+   }
+ 
+   if ((lssize || lpsize) &&
+        ((itype == PDSFIXED) || (itype == VIKINGFIXED) || (itype == VICAR)) ) {
+     /* ARrrrgh.  Some of these images have crud intermixed with the image, */
+     /* preventing us from freading in one fell swoop */
+-    /* (whatever a fell swoop is */
++    /* (whatever a fell swoop is) */
+ 
+-    for (yy=0; yy<y; yy++) {
+-      if (lpsize && 
+-	  ((teco=(fread(scanbuff,(size_t) lpsize,(size_t) 1,zf))) != 1)) {
++    for (yy=0; yy<h; yy++) {
++      if (lpsize &&
++	  (teco=fread(scanbuff,(size_t) lpsize,(size_t) 1,zf)) != 1) {
+ 	SetISTR(ISTR_WARNING, "LoadPDS: unexpected EOF reading prefix");
+ 	fclose(zf);
+ 	return 0;
+       }
+-      
+-      if ((teco=(fread(image+(yy*x), (size_t) x, (size_t) 1,zf))) != 1) {
++
++      teco = fread(image+(yy*bytewidth), (size_t) bytewidth, (size_t) 1,zf);
++      if (teco != 1) {
+ 	SetISTR(ISTR_WARNING, "LoadPDS: unexpected EOF reading line %d",yy);
+ 	fclose(zf);
+ 	return 0;
+       }
+ 
+-      if (lssize && 
+-	  ((teco=(fread(scanbuff,(size_t) lssize,(size_t) 1,zf))) != 1)) {
++      if (lssize &&
++	  (teco=fread(scanbuff,(size_t) lssize,(size_t) 1,zf)) != 1) {
+ 	SetISTR(ISTR_WARNING, "LoadPDS: unexpected EOF reading suffix");
+ 	fclose(zf);
+ 	return 0;
+       }
+     }
+ 
+-  } else if ((yy=fread(image, (size_t) x*y, (size_t) 1, zf)) != 1) {
++  } else if ((yy=fread(image, (size_t) bytewidth*h, (size_t) 1, zf)) != 1) {
+     SetISTR(ISTR_WARNING,"LoadPDS: error reading image data");
+     fclose(zf);
+     if (itype==PDSVARIABLE || itype==VIKINGVARIABLE)
+       unlink(pdsuncompfname);
+-
+     return 0;
+   }
+ 
+-    fclose(zf);
++  fclose(zf);
+ 
+ 
+   if (isfixed == FALSE)
+     unlink(pdsuncompfname);
+ 
+   pinfo->pic = image;
+-  pinfo->w   = x;
+-  pinfo->h    = y;
++  pinfo->w   = w;   /* true pixel-width now (no longer bytewidth!) */
++  pinfo->h   = h;
+ 
+   if (samplesize == 16)
+      if (Convert16BitImage(fname, pinfo,
+@@ -798,27 +835,27 @@
+   if (pinfo->comment) {
+     char tmp[256];
+     *(pinfo->comment) = '\0';
+-    
+-    sprintf(tmp, "Spacecraft: %-28sTarget: %-32s\n", spacecraft, target);
+-    strcat(pinfo->comment, tmp);
+-    
+-    sprintf(tmp, "Filter: %-32sMission phase: %-24s\n", filtname, mphase);
+-    strcat(pinfo->comment, tmp);
+-    
+-    sprintf(tmp, "Image time: %-28sGain mode: %-29s\n", itime, gainmode);
+-    strcat(pinfo->comment, tmp);
+-    
+-    sprintf(tmp, "Edit mode: %-29sScan mode: %-29s\n", editmode, scanmode);
+-    strcat(pinfo->comment, tmp);
+-    
+-    sprintf(tmp, "Exposure: %-30sShutter mode: %-25s\n", exposure,shuttermode);
+-    strcat(pinfo->comment, tmp);
+-    
+-    sprintf(tmp, "Instrument: %-28sImage time: %-28s\n", iname, itime);
+-    strcat(pinfo->comment, tmp);
+-    
+-    sprintf(tmp, "Image Note: %-28s", inote);
+-    strcat(pinfo->comment, tmp);
++
++    sprintf(tmp, "Spacecraft: %-28.28sTarget: %-32.32s\n", spacecraft, target);
++    strncat(pinfo->comment, tmp, 2000 - strlen(pinfo->comment) - 1);
++
++    sprintf(tmp, "Filter: %-32.32sMission phase: %-24.24s\n", filtname, mphase);
++    strncat(pinfo->comment, tmp, 2000 - strlen(pinfo->comment) - 1);
++
++    sprintf(tmp, "Image time: %-28.28sGain mode: %-29.29s\n", itime, gainmode);
++    strncat(pinfo->comment, tmp, 2000 - strlen(pinfo->comment) - 1);
++
++    sprintf(tmp, "Edit mode: %-29.29sScan mode: %-29.29s\n", editmode, scanmode);
++    strncat(pinfo->comment, tmp, 2000 - strlen(pinfo->comment) - 1);
++
++    sprintf(tmp, "Exposure: %-30.30sShutter mode: %-25.25s\n", exposure,shuttermode);
++    strncat(pinfo->comment, tmp, 2000 - strlen(pinfo->comment) - 1);
++
++    sprintf(tmp, "Instrument: %-28.28sImage time: %-28.28s\n", iname, itime);
++    strncat(pinfo->comment, tmp, 2000 - strlen(pinfo->comment) - 1);
++
++    sprintf(tmp, "Image Note: %-28.28s", inote);
++    strncat(pinfo->comment, tmp, 2000 - strlen(pinfo->comment) - 1);
+   }
+ 
+   if (LoadPDSPalette(fname, pinfo))  return 1;
+@@ -868,23 +905,20 @@
+   m = 65536 * sizeof(byte);
+   lut = (byte *) malloc(m);
+   if (lut == NULL) {
+-    SetISTR(ISTR_WARNING,"LoadPDS: couldn't malloc %d", m);
+-    return 0;
++    FatalError("LoadPDS: can't malloc LUT buffer");
+   }
+-  pinfo->w /= 2;
+ 
+   /* allocate histogram table */
+   m = 65536 * sizeof(long);
+   hist = (long *) malloc(m);
+   if (hist == NULL) {
+-    SetISTR(ISTR_WARNING,"LoadPDS: couldn't malloc %d", m);
+     free(lut);
+-    return 0;
++    FatalError("LoadPDS: can't malloc histogram buffer");
+   }
+ 
+   /* check whether histogram file exists */
+ #ifdef VMS
+-  c = (char *) rindex(strcpy(name, 
++  c = (char *) rindex(strcpy(name,
+ 			     (c = (char *) rindex(fname, ':')) ? c+1 : fname),
+ 		      ']');
+ #else
+@@ -947,14 +981,20 @@
+     }
+   }
+ 
+-  /* allocate new 8-bit image */
+   free(hist);
++
++  /* allocate new 8-bit image */
+   n = pinfo->w * pinfo->h;
++  if (pinfo->w <= 0 || pinfo->h <= 0 || n/pinfo->w != pinfo->h) {
++    SetISTR(ISTR_WARNING,"LoadPDS: image dimensions out of range (%dx%d)",
++      pinfo->w, pinfo->h);
++    free(lut);
++    return 0;
++  }
+   pPix8 = (byte *)malloc(n*sizeof(byte));
+   if (pPix8 == NULL) {
+-    SetISTR(ISTR_WARNING,"LoadPDS: couldn't malloc %d", n*sizeof(byte));
+     free(lut);
+-    return 0;
++    FatalError("LoadPDS: can't malloc 16-to-8-bit conversion buffer");
+   }
+ 
+   /* convert the 16-bit image to 8-bit */
+@@ -979,16 +1019,16 @@
+   FILE    *fp;
+   char    name[1024], buf[256], *c;
+   int     i, n, r, g, b;
+-  
++
+ #ifdef VMS
+-  c = (char *) rindex(strcpy(name, 
++  c = (char *) rindex(strcpy(name,
+ 			     (c = (char *) rindex(fname, ':')) ? c+1 : fname),
+ 		      ']');
+ #else
+   c = (char *) rindex(strcpy(name, fname), '/');
+ #endif /* VMS */
+   (void)strcpy(c ? c+1 : name, "palette.tab");
+-  
++
+   if ((fp = xv_fopen(name, "r")) == NULL)
+     return 0;
+   for (i = 0; i < 256; i++) {
+@@ -1014,7 +1054,3 @@
+ 
+ 
+ #endif /* HAVE_PDS */
+-
+-
+-
+-
+diff -ru xv-3.10a/xvpictoppm.c xv-3.10a-enhancements/xvpictoppm.c
+--- xv-3.10a/xvpictoppm.c	1995-01-13 11:57:14.000000000 -0800
++++ xv-3.10a-enhancements/xvpictoppm.c	2005-04-10 09:36:04.000000000 -0700
+@@ -77,7 +77,7 @@
+   FILE *fp;
+   byte  *icon8, *pic24, *ip, *pp;
+   char  buf[256];
+-  int   i, builtin, w, h, mv;
++  int   i, builtin, w, h, maxval, npixels, p24sz;
+ 
+   fp = stdin;
+   builtin = 0;
+@@ -88,42 +88,45 @@
+   /* read comments until we see '#END_OF_COMMENTS', or hit EOF */
+   while (1) {
+     if (!fgets(buf, 256, fp)) errexit();
+-    
++
+     if (!strncmp(buf, "#END_OF_COMMENTS", (size_t) 16)) break;
+ 
+     else if (!strncmp(buf, "#BUILTIN:",   (size_t)  9)) {
+       builtin = 1;
+-      fprintf(stderr,"Built-In icon:  no image to convert!\n");
++      fprintf(stderr, "Built-in icon:  no image to convert\n");
+       exit(1);
+     }
+   }
+ 
+ 
+   /* read width, height, maxval */
+-  if (!fgets(buf, 256, fp) || sscanf(buf, "%d %d %d", &w, &h, &mv) != 3) 
++  if (!fgets(buf, 256, fp) || sscanf(buf, "%d %d %d", &w, &h, &maxval) != 3)
+     errexit();
+ 
++  npixels = w * h;
++  p24sz = 3 * npixels;
+ 
+-  if (w<1 || h<1 || mv != 255) {
+-    fprintf(stderr,"Bogus thumbnail file!\n");
++  if (w <= 0 || h <= 0 || maxval != 255 || npixels/w != h || p24sz/3 != npixels)
++  {
++    fprintf(stderr, "Thumbnail dimensions out of range\n");
+     exit(1);
+   }
+ 
+ 
+   /* read binary data */
+-  icon8 = (byte *) malloc((size_t) w * h);
++  icon8 = (byte *) malloc((size_t) npixels);
+   if (!icon8) errexit();
+ 
+-  i = fread(icon8, (size_t) 1, (size_t) w*h, fp);
+-  if (i != w*h) errexit();
++  i = fread(icon8, (size_t) 1, (size_t) npixels, fp);
++  if (i != npixels) errexit();
++
+ 
+-  
+   /* make 24-bit version of icon */
+-  pic24 = (byte *) malloc((size_t) w * h * 3);
++  pic24 = (byte *) malloc((size_t) p24sz);
+   if (!pic24) errexit();
+ 
+   /* convert icon from 332 to 24-bit image */
+-  for (i=0, ip=icon8, pp=pic24;  i<w*h;  i++, ip++, pp+=3) {
++  for (i=0, ip=icon8, pp=pic24;  i<npixels;  i++, ip++, pp+=3) {
+     pp[0] = ( ((int) ((*ip >> 5) & 0x07)) * 255) / 7;
+     pp[1] = ( ((int) ((*ip >> 2) & 0x07)) * 255) / 7;
+     pp[2] = ( ((int) ((*ip >> 0) & 0x03)) * 255) / 3;
+@@ -160,10 +163,3 @@
+ 
+   if (ferror(fp)) errexit();
+ }
+-
+-
+-	  
+-	  
+-
+-
+-
+diff -ru xv-3.10a/xvpm.c xv-3.10a-enhancements/xvpm.c
+--- xv-3.10a/xvpm.c	1994-12-22 14:34:40.000000000 -0800
++++ xv-3.10a-enhancements/xvpm.c	2007-05-13 17:34:04.000000000 -0700
+@@ -42,9 +42,9 @@
+ /***** end PM.H *****/
+ 
+ 
+-pmpic  thePic;
++static pmpic thePic;
+ 
+-static int  pmError  PARM((char *, char *));
++static int  pmError  PARM((const char *, const char *));
+ static int  flip4    PARM((int));
+ static int  getint32 PARM((FILE *));
+ static void putint32 PARM((int, FILE *));
+@@ -60,8 +60,8 @@
+ 
+   FILE  *fp;
+   byte  *pic8;
+-  int    isize,i,flipit,w,h;
+-  char  *bname;
++  int    isize,i,flipit,w,h,npixels,nRGBbytes;
++  const char  *bname;
+ 
+   bname = BaseName(fname);
+   thePic.pm_image = (char *) NULL;
+@@ -103,10 +103,11 @@
+     thePic.pm_cmtsize = flip4(thePic.pm_cmtsize);
+     }
+ 
+-  w = thePic.pm_ncol;  h = thePic.pm_nrow;
++  w = thePic.pm_ncol;
++  h = thePic.pm_nrow;
+ 
+   /* make sure that the input picture can be dealt with */
+-  if ( thePic.pm_nband!=1 || 
++  if ( thePic.pm_nband!=1 ||
+       (thePic.pm_form!=PM_I && thePic.pm_form!=PM_C) ||
+       (thePic.pm_form==PM_I && thePic.pm_np>1) ||
+       (thePic.pm_form==PM_C && (thePic.pm_np==2 || thePic.pm_np>4)) ) {
+@@ -114,20 +115,27 @@
+     fprintf(stderr,"(ie, 1-plane PM_I, or 1-, 3-, or 4-plane PM_C)\n");
+ 
+     return pmError(bname, "PM file in unsupported format");
+-  }	
++  }
+ 
+ 
+   isize = pm_isize(&thePic);
++  npixels = w*h;
++  nRGBbytes = 3*npixels;
++
++  /* make sure image is more-or-less valid (and no overflows) */
++  if (isize <= 0 || w <= 0 || h <= 0 || npixels/w < h ||
++      nRGBbytes/3 < npixels || thePic.pm_cmtsize < 0)
++    return pmError(bname, "Bogus PM file!!");
+ 
+-  if (DEBUG) 
++  if (DEBUG)
+     fprintf(stderr,"%s: LoadPM() - loading a %dx%d %s pic, %d planes\n",
+-	    cmd, w, h, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C", 
++	    cmd, w, h, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C",
+ 	    thePic.pm_np);
+ 
+-	      
++
+   /* allocate memory for picture and read it in */
+   thePic.pm_image = (char *) malloc((size_t) isize);
+-  if (thePic.pm_image == NULL) 
++  if (thePic.pm_image == NULL)
+     return( pmError(bname, "unable to malloc PM picture") );
+ 
+   if (fread(thePic.pm_image, (size_t) isize, (size_t) 1, fp) != 1)   {
+@@ -147,7 +155,7 @@
+       }
+     }
+   }
+-   
++
+   fclose(fp);
+ 
+ 
+@@ -155,11 +163,11 @@
+     int  *intptr;
+     byte *pic24, *picptr;
+ 
+-    if ((pic24 = (byte *) malloc((size_t) w*h*3))==NULL) {
++    if ((pic24 = (byte *) malloc((size_t) nRGBbytes))==NULL) {
+       if (thePic.pm_cmt) free(thePic.pm_cmt);
+       return( pmError(bname, "unable to malloc 24-bit picture") );
+     }
+-      
++
+     intptr = (int *) thePic.pm_image;
+     picptr = pic24;
+ 
+@@ -190,7 +198,7 @@
+   else if (thePic.pm_form == PM_C && thePic.pm_np>1) {
+     byte *pic24, *picptr, *rptr, *gptr, *bptr;
+ 
+-    if ((pic24 = (byte *) malloc((size_t) w*h*3))==NULL) {
++    if ((pic24 = (byte *) malloc((size_t) nRGBbytes))==NULL) {
+       if (thePic.pm_cmt) free(thePic.pm_cmt);
+       return( pmError(bname, "unable to malloc 24-bit picture") );
+     }
+@@ -210,12 +218,12 @@
+     pinfo->pic  = pic24;
+     pinfo->type = PIC24;
+   }
+-  
++
+ 
+   else if (thePic.pm_form == PM_C && thePic.pm_np==1) {
+     /* don't have to convert, just point pic at thePic.pm_image */
+     pic8 = (byte *) thePic.pm_image;
+-    for (i=0; i<256; i++) 
++    for (i=0; i<256; i++)
+       pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;  /* build mono cmap */
+ 
+     pinfo->pic  = pic8;
+@@ -228,13 +236,13 @@
+   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
+ 
+   pinfo->frmType = F_PM;
+-  pinfo->colType = (thePic.pm_form==PM_I || thePic.pm_np>1) 
++  pinfo->colType = (thePic.pm_form==PM_I || thePic.pm_np>1)
+                          ? F_FULLCOLOR : F_GREYSCALE;
+-  sprintf(pinfo->fullInfo,"PM, %s.  (%d plane %s)  (%ld bytes)",
+-	  (thePic.pm_form==PM_I || thePic.pm_np>1) 
++  sprintf(pinfo->fullInfo,"PM, %s.  (%d plane %s)  (%d bytes)",
++	  (thePic.pm_form==PM_I || thePic.pm_np>1)
+ 	        ? "24-bit color" : "8-bit greyscale",
+ 	  thePic.pm_np, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C",
+-	  isize + PM_IOHDR_SIZE + thePic.pm_cmtsize);
++	  isize + (int)PM_IOHDR_SIZE + thePic.pm_cmtsize);
+ 
+   sprintf(pinfo->shrtInfo, "%dx%d PM.", w,h);
+   pinfo->comment = thePic.pm_cmt;
+@@ -313,7 +321,7 @@
+ 
+   else if (colorstyle == 1) {    /* GreyScale: 8 bits per pixel */
+     byte rgb[256];
+-    
++
+     if (ptype == PIC8) {
+       for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
+       for (i=0, p=pic; i<w*h; i++, p++) {
+@@ -351,7 +359,7 @@
+ 
+ /*****************************/
+ static int pmError(fname, st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   if (thePic.pm_image != NULL) free(thePic.pm_image);
+diff -ru xv-3.10a/xvpopup.c xv-3.10a-enhancements/xvpopup.c
+--- xv-3.10a/xvpopup.c	1995-01-19 10:09:31.000000000 -0800
++++ xv-3.10a-enhancements/xvpopup.c	2007-04-15 15:02:32.000000000 -0700
+@@ -1,5 +1,5 @@
+-/* 
+- * xvpopup.c - popup "Are you sure?  Yes/No/Maybe" sort of dialog box
++/*
++ * xvpopup.c - pop up "Are you sure?  Yes/No/Maybe" sort of dialog box
+  *
+  * callable functions:
+  *
+@@ -13,16 +13,16 @@
+  *   OpenAlert(str)        -  maps a button-less window
+  *   CloseAlert()          -  closes a button-less window
+  *   PUCheckEvent(event)   -  called by event handler
+- *   TextRect()            -  draws semi-complex strings in a rectangle
+  */
+ 
+ #include "copyright.h"
+ 
+ #include "xv.h"
+ 
+-#include "bits/icon"
++#define OMIT_ICON_BITS
++#include "bits/icon"   /* icon_bits[] not used, but icon_width/height are */
+ 
+-#define PUWIDE 400
++#define PUWIDE 480
+ #define PUHIGH 170
+ 
+ #define PAD_PUWIDE 480
+@@ -30,8 +30,9 @@
+ 
+ #define BUTTH   24
+ 
+-static int  doPopUp       PARM((char *, char **, int, int, char *));
++static int  doPopUp       PARM((const char *, const char **, int, int, const char *));
+ static void attachPUD     PARM((void));
++static void TextRect      PARM((Window, const char *, int, int, int, int, u_long));
+ static void createPUD     PARM((void));
+ static void drawPUD       PARM((int, int, int, int));
+ static void drawPadOMStr  PARM((void));
+@@ -41,8 +42,8 @@
+ static void changedGSBuf  PARM((void));
+ static void drawGSBuf     PARM((void));
+ static void buildPadLists PARM((void));
+-static void build1PadList PARM((char *, char **, char **, int *,
+-				char **, char **, int));
++static void build1PadList PARM((const char *, const char **, const char **, int *,
++				const char **, const char **, int));
+ 
+ 
+ /* values 'popUp' can take */
+@@ -57,20 +58,21 @@
+ #define HIDESTR  "Hide XV windows"
+ 
+ /* local variables */
+-Window popW;
+-int    nbts, selected, popUp=0, firsttime=1;
+-int    puwide = PUWIDE;
+-int    puhigh = PUHIGH;
+-BUTT  *bts;
+-char  *text;
+-char   accel[8];
+-
+-char *gsBuf, *gsFilter;       /* stuff needed for GetStrPopUp() handling */
+-int   gsBufLen, gsAllow, gsCurPos, gsStPos, gsEnPos;
+-int   gsx, gsy, gsw, gsh;
++static Window      popW;
++static int         nbts, selected, popUp=0, firsttime=1;
++static int         puwide = PUWIDE;
++static int         puhigh = PUHIGH;
++static BUTT       *bts;
++static const char *text;
++static char        accel[8];
++
++static char       *gsBuf;       /* stuff needed for GetStrPopUp() handling */
++static const char *gsFilter;
++static int         gsBufLen, gsAllow, gsCurPos, gsStPos, gsEnPos;
++static int         gsx, gsy, gsw, gsh;
+ 
+ /* stuff for GrabPopUp */
+-CBUTT ahideCB;
++static CBUTT ahideCB;
+ 
+ 
+ /*** stuff for PadPopUp ***/
+@@ -82,48 +84,51 @@
+ static int    padMode, padOMode;
+ static DIAL   padWDial, padHDial, padODial;
+ 
+-static int    padMthdLen=3;
+-static char  *padMthdNames[] = { "Solid Fill", "Run 'bggen'", "Load Image" };
++static int         padMthdLen=3;
++static const char *padMthdNames[] = { "Solid Fill", "Run 'bggen'", "Load Image" };
+ 
+-static int    padColDefLen = 9;
+-static char  *padColDefNames[] = { "black", "red",  "yellow", "green", 
+-				   "cyan",  "blue", "magenta", "white", 
+-				   "50% gray" };
+-
+-static char  *padColDefVals[]  = { "black", "red", "yellow", "green",
+-				   "cyan",  "blue", "magenta", "white",
+-                                   "gray50" };
+-
+-static int    padBgDefLen = 8;
+-static char  *padBgDefNames[] = {
+-  "Black->White",
+-  "Blue Gradient",
+-  "RGB Rainbow",
+-  "Full Rainbow",
+-  "Color Assortment",
+-  "Green Tiles",
+-  "Red Balls",
+-  "Red+Yellow Diamonds" };
+-
+-static char  *padBgDefVals[]  = { 
+-  "black white", 
+-  "100 100 255  50 50 150",
+-  "red green blue",
+-  "black red yellow green blue purple black",
+-  "black white red black yellow white green black cyan white blue black magenta white red yellow green cyan blue magenta red",
+-  "green black -r 30 -G 32x32",
+-  "red black -r 45 -G 32x32",
+-  "red yellow -r 45 -G 32x32" };
++static int         padColDefLen = 9;
++static const char *padColDefNames[] = { "black", "red",  "yellow", "green",
++					"cyan",  "blue", "magenta", "white",
++					"50% gray" };
++
++static const char *padColDefVals[]  = { "black", "red", "yellow", "green",
++					"cyan",  "blue", "magenta", "white",
++					"gray50" };
++
++static int         padBgDefLen = 8;
++static const char *padBgDefNames[] = { "Black->White",
++				       "Blue Gradient",
++				       "RGB Rainbow",
++				       "Full Rainbow",
++				       "Color Assortment",
++				       "Green Tiles",
++				       "Red Balls",
++				       "Red+Yellow Diamonds" };
++
++static const char *padBgDefVals[] = { "black white",
++				      "100 100 255  50 50 150",
++				      "red green blue",
++				      "black red yellow green blue purple black",
++				      "black white red black yellow white green black cyan white blue black magenta white red yellow green cyan blue magenta red",
++				      "green black -r 30 -G 32x32",
++				      "red black -r 45 -G 32x32",
++				      "red yellow -r 45 -G 32x32" };
+ 
+ 
+ /* this should match with PAD_O* defs in xv.h */
+-static char *padOMStr[] = { "RGB", "Int.", "Hue", "Sat." };
++static const char *padOMStr[] = { "RGB", "Int.", "Hue", "Sat." };
+ 
+ #define PAD_MAXDEFLEN 10
+-static int    padColLen = 0, padBgLen = 0, padLoadLen = 0;
+-static char  *padColNames [PAD_MAXDEFLEN], *padColVals [PAD_MAXDEFLEN];
+-static char  *padBgNames  [PAD_MAXDEFLEN], *padBgVals  [PAD_MAXDEFLEN];
+-static char  *padLoadNames[PAD_MAXDEFLEN], *padLoadVals[PAD_MAXDEFLEN];
++static int         padColLen = 0;
++static const char *padColNames [PAD_MAXDEFLEN];
++static const char *padColVals  [PAD_MAXDEFLEN];
++static int         padBgLen = 0;
++static const char *padBgNames  [PAD_MAXDEFLEN];
++static const char *padBgVals   [PAD_MAXDEFLEN];
++static int         padLoadLen = 0;
++static const char *padLoadNames[PAD_MAXDEFLEN];
++static const char *padLoadVals [PAD_MAXDEFLEN];
+ 
+ 
+ /***************************************************/
+@@ -150,11 +155,11 @@
+     if (wy + h > dispHIGH) wy = dispHIGH - h;
+   }
+ 
+-  
++
+   if (winCtrPosKludge) {
+     wx -= (p_offx + ch_offx);
+     wy -= (p_offy + ch_offy);
+-  } 
++  }
+   else {
+     wx -= (ch_offx);
+     wy -= (ch_offy);
+@@ -174,16 +179,20 @@
+ 
+ /***************************************************/
+ int PopUp(txt, labels, n)
+-     char *txt, *labels[];
+-     int   n;
++     const char *txt;
++     const char *labels[];
++     int         n;
+ {
+   return doPopUp(txt, labels, n, ISPOPUP, "xv confirm");
+ }
+ 
++
+ /***************************************************/
+ static int doPopUp(txt, labels, n, poptyp, wname)
+-     char *txt, *labels[], *wname;
+-     int   n, poptyp;
++     const char *txt;
++     const char *labels[];
++     int         n, poptyp;
++     const char *wname;
+ {
+   int    i;
+   XEvent event;
+@@ -197,17 +206,17 @@
+   /* attach controls to popW, now that it exists */
+   if      (poptyp==ISGRAB) ahideCB.win = popW;
+   else if (poptyp == ISPAD) {
+-    
++
+     if (!padHaveDooDads) {
+       DCreate(&padWDial, popW, 16,      puhigh-16-100-1,75,100,
+-	      1, 2048, pWIDE, 10,
++	      1.0, 2048.0, (double)pWIDE, 1.0, 10.0,
+ 	      infofg, infobg, hicol, locol, "Width", NULL);
+       DCreate(&padHDial, popW, 16+1+75, puhigh-16-100-1,75,100,
+-	      1, 2048, pHIGH, 10,
++	      1.0, 2048.0, (double)pHIGH, 1.0, 10.0,
+ 	      infofg, infobg, hicol, locol, "Height", NULL);
+ 
+       DCreate(&padODial, popW, 16+1+75+75+9, puhigh-16-100-1,75,100,
+-	      0, 100, 100, 10,
++	      0.0, 100.0, 100.0, 1.0, 10.0,
+ 	      infofg, infobg, hicol, locol, "Opaque", NULL);
+ 
+       MBCreate(&padMthdMB, popW, 100-2+44, 10, 140, 19, NULL,
+@@ -230,8 +239,8 @@
+     XMapWindow(theDisp, padWDial.win);
+     XMapWindow(theDisp, padHDial.win);
+     XMapWindow(theDisp, padODial.win);
+-  }      
+-  
++  }
++
+ 
+   XResizeWindow(theDisp, popW, (u_int) puwide, (u_int) puhigh);
+   XStoreName   (theDisp, popW, wname);
+@@ -257,10 +266,10 @@
+   }
+   else if (poptyp == ISPAD) {
+     BTSetActive(&bts[0], (int) strlen(gsBuf));
+-    i = pWIDE * 3;  RANGE(i,2048,9999);  
+-    DSetRange(&padWDial, 1, i, padWDial.val, 10);
+-    i = pHIGH * 3;  RANGE(i,2048,9999);  
+-    DSetRange(&padHDial, 1, i, padHDial.val, 10);
++    i = pWIDE * 3;  RANGE(i,2048,9999);
++    DSetRange(&padWDial, 1.0, (double)i, padWDial.val, 1.0, 10.0);
++    i = pHIGH * 3;  RANGE(i,2048,9999);
++    DSetRange(&padHDial, 1.0, (double)i, padHDial.val, 1.0, 10.0);
+ 
+     DSetActive(&padWDial, (padMode!=PAD_LOAD));  /* DSetRange activates dial */
+     DSetActive(&padHDial, (padMode!=PAD_LOAD));
+@@ -283,18 +292,22 @@
+     }
+   }
+ 
+-  /* center first button in window around mouse position, with constraint that 
++  /* center first button in window around mouse position, with constraint that
+      window be fully on the screen */
+ 
+-  CenterMapWindow(popW, 40 + bts[0].x, BUTTH/2 + bts[0].y, puwide, puhigh);
+   popUp = poptyp;
++  if (startGrab == 2)
++    startGrab = 4;
++  else {
++    CenterMapWindow(popW, 40 + bts[0].x, BUTTH/2 + bts[0].y, puwide, puhigh);
+ 
+-  /* MUST wait for VisibilityNotify event to come in, else we run the risk
+-     of UnMapping the window *before* the Map request completed.  This 
+-     appears to be bad, (It leaves an empty window frame up.) though it
+-     generally only happens on slow servers.  Better safe than screwed... */
++    /* MUST wait for VisibilityNotify event to come in, else we run the risk
++       of UnMapping the window *before* the Map request completed.  This
++       appears to be bad, (It leaves an empty window frame up.) though it
++       generally only happens on slow servers.  Better safe than screwed... */
+ 
+-  XWindowEvent(theDisp, popW, VisibilityChangeMask, &event);
++    XWindowEvent(theDisp, popW, VisibilityChangeMask, &event);
++  }
+ 
+   /* block until this window gets closed */
+   while (popUp) {
+@@ -312,7 +325,8 @@
+ 
+ /***************************************************/
+ void ErrPopUp(txt, label)
+-     char *txt, *label;
++     const char *txt;
++     const char *label;
+ {
+   /* simplified interface to PopUp.  Takes a string and the label for the
+      (one) button */
+@@ -323,7 +337,10 @@
+ 
+ /***************************************************/
+ int GetStrPopUp(txt, labels, n, buf, buflen, filstr, allow)
+-     char *txt, *labels[], *buf, *filstr;
++     const char *txt;
++     const char *labels[];
++     char *buf;
++     const char *filstr;
+      int   n, buflen, allow;
+ {
+   /* pops up a window with a prompt string, a 1-line editable
+@@ -338,10 +355,10 @@
+      button labels have 1-character accellerators at the front, same
+      as in PopUp().  Note that it would be suboptimal to make any
+      of the 1-character accellerators be the same character as one of
+-     the edit-text command keys 
++     the edit-text command keys
+ 
+      Also note that the filter string should only contain normal printable
+-     characters (' ' through '\177'), as ctrl chars are pre-filtered 
++     characters (' ' through '\177'), as ctrl chars are pre-filtered
+      (ie, interpreted as emacs-like commands) */
+ 
+   gsBuf = buf;        gsBufLen = buflen;
+@@ -358,7 +375,7 @@
+     gsy = PUHIGH - 10 - BUTTH - 10 - gsh - 20;
+ 
+   gsw = PUWIDE - gsx - 10;
+-  
++
+   changedGSBuf();      /* careful!  popW doesn't exist yet! */
+ 
+   return doPopUp(txt, labels, n, ISGETSTR, "xv prompt");
+@@ -371,9 +388,9 @@
+ {
+   /* pops up Grab options dialog box */
+ 
+-  int  rv;
+-  char delaybuf[32], grabTxt[1024];
+-  static char *grabLabels[] = { "\nGrab", "aAutoGrab", "\033Cancel" };
++  int                rv;
++  char               delaybuf[32], grabTxt[1024];
++  static const char *grabLabels[] = { "\nGrab", "aAutoGrab", "\033Cancel" };
+ 
+   sprintf(delaybuf,"%d", *pDelay);
+   gsBuf = delaybuf;          gsBufLen = 3;
+@@ -390,7 +407,7 @@
+   changedGSBuf();      /* careful!  popW doesn't exist yet! */
+ 
+   /* window value gets filled in in doPopUp() */
+-  CBCreate(&ahideCB, (Window) NULL, 
++  CBCreate(&ahideCB, (Window) NULL,
+ 	   PUWIDE-10-18-StringWidth(HIDESTR),
+ 	   gsy+2, HIDESTR, infofg, infobg, hicol, locol);
+   ahideCB.val = *pHide;
+@@ -417,9 +434,9 @@
+ {
+   /* pops up 'Pad' options dialog box */
+ 
+-  int         rv, oldW, oldH, oldO;
+-  static int  firsttime=1;
+-  static char *labels[] = { "\nOk", "\033Cancel" };
++  int                rv, oldW, oldH, oldO;
++  static int         firsttime=1;
++  static const char *labels[] = { "\nOk", "\033Cancel" };
+ 
+   if (firsttime) {
+     padSbuf[0] = '\0';
+@@ -464,10 +481,10 @@
+ 
+   changedGSBuf();      /* careful!  popW doesn't exist yet! */
+ 
+-  if (padHaveDooDads) { 
+-    oldW = padWDial.val;  
+-    oldH = padHDial.val;
+-    oldO = padODial.val;
++  if (padHaveDooDads) {
++    oldW = (int)padWDial.val;
++    oldH = (int)padHDial.val;
++    oldO = (int)padODial.val;
+   }
+   else { oldW = pWIDE;  oldH = pHIGH;  oldO = 100; }
+ 
+@@ -486,9 +503,9 @@
+   }
+ 
+   if (rv == 1) {   /* cancelled:  restore normal values */
+-    DSetVal(&padWDial, oldW);
+-    DSetVal(&padHDial, oldH);
+-    DSetVal(&padODial, oldO);
++    DSetVal(&padWDial, (double)oldW);
++    DSetVal(&padHDial, (double)oldH);
++    DSetVal(&padODial, (double)oldO);
+   }
+ 
+   XUnmapWindow(theDisp, padWDial.win);
+@@ -496,11 +513,11 @@
+   XUnmapWindow(theDisp, padODial.win);
+ 
+   /* load up return values */
+-  *pMode   = padMode;  
+-  *pStr    = padBuf;  
+-  *pWide   = padWDial.val;
+-  *pHigh   = padHDial.val;
+-  *pOpaque = padODial.val;
++  *pMode   = padMode;
++  *pStr    = padBuf;
++  *pWide   = (int)padWDial.val;
++  *pHigh   = (int)padHDial.val;
++  *pOpaque = (int)padODial.val;
+   *pOmode  = padOMode;
+ 
+   return rv;
+@@ -513,8 +530,6 @@
+   /* generates padCol* and padBg* lists used in 'Defaults' MBUTT.  Grabs
+      all the X resources values it can, and adds appropriate defaults */
+ 
+-  int  i;
+-
+   rd_str_cl("foo", "", 1);                    /* rebuild database */
+ 
+   build1PadList("color", padColVals, padColNames, &padColLen,
+@@ -524,49 +539,52 @@
+ 		padBgDefVals, padBgDefNames, padBgDefLen);
+ 
+   build1PadList("load", padLoadVals, padLoadNames, &padLoadLen,
+-		(char **) NULL, (char **) NULL, 0);
++		(const char **) NULL, (const char **) NULL, 0);
+ }
+-	
+-      
++
++
+ /***************************************************/
+ static void build1PadList(typstr, vals, nams, lenp, dvals, dnams, dlen)
+-     char *typstr, **vals, **nams, **dvals, **dnams;
+-     int  *lenp, dlen;
+-{
+-  int i;
+-  char resname[128], name[256], value[256];
++     const char  *typstr;
++     const char **vals, **nams;
++     const char **dvals, **dnams;
++     int         *lenp, dlen;
++{
++  int   i;
++  char  resname[128];
++  char *copy;
+ 
+   for (i=0; i<*lenp; i++) {   /* kill old lists */
+-    free(nams[i]);
+-    free(vals[i]);
++    free((char *) nams[i]);
++    free((char *) vals[i]);
+   }
+   *lenp = 0;
+ 
+   for (i=0; i<10; i++) {
+     sprintf(resname, "pad.%s.val%d", typstr, i);
+     if (rd_str_cl(resname, "Dialog.Menu.Slot",0)) {    /* got one! */
+-      vals[*lenp] = (char *) malloc(strlen(def_str)+1);
+-      if (!vals[*lenp]) continue;
+-      strcpy(vals[*lenp], def_str);
+-      
++      copy = strdup(def_str);
++      if (!copy) continue;
++      vals[*lenp] = copy;
++
+       sprintf(resname, "pad.%s.name%d", typstr, i);
+       if (rd_str_cl(resname, "Dialog.Menu.Slot",0)) {  /* and it has a name! */
+-	nams[*lenp] = (char *) malloc(strlen(def_str)+1);
+-	if (!nams[*lenp]) { free(vals[*lenp]); continue; }
+-	strcpy(nams[*lenp], def_str);
+-
++        copy = strdup(def_str);
++	if (!copy) { free((char *) vals[*lenp]); continue; }
+       }
+       else {  /* it doesn't have a name.  fabricate one */
+-	nams[*lenp] = (char *) malloc((size_t) 32);
+-	if (!nams[*lenp]) { free(vals[*lenp]); continue; }
+-	strncpy(nams[*lenp], vals[*lenp], (size_t) 31);
++	copy = malloc((size_t) 32);
++	if (!copy) { free((char *) vals[*lenp]); continue; }
++	strncpy(copy, vals[*lenp], (size_t) 31);
++	copy[31] = '\0';
+       }
+-      
+-      if (strlen(nams[*lenp]) > (size_t) 20) {   /* fix long names */
+-	char *sp = nams[*lenp] + 18;
++      if (strlen(copy) > (size_t) 20) {   /* fix long names */
++	char *sp = copy + 18;
++
+ 	*sp++ = '.';  *sp++ = '.';  *sp++ = '.';  *sp++ = '\0';
+       }
+-	
++      nams[*lenp] = copy;
++
+       *lenp = (*lenp) + 1;
+     }
+   }
+@@ -574,16 +592,17 @@
+ 
+   /* add 'built-in' defaults to the lists */
+   for (i=0; i<dlen && *lenp<PAD_MAXDEFLEN; i++) {
+-    vals[*lenp] = (char *) malloc(strlen(dvals[i])+1);
+-    if (!vals[*lenp]) break;
+-    strcpy(vals[*lenp], dvals[i]);
+-
+-    nams[*lenp] = (char *) malloc(strlen(dnams[i])+1);
+-    if (!nams[*lenp]) { free(vals[*lenp]); break; }
+-    strcpy(nams[*lenp], dnams[i]);
++    copy = strdup(dvals[i]);
++    if (!copy) break;
++    vals[*lenp] = copy;
++
++    copy = strdup(dnams[i]);
++    if (!copy) { free((char *) vals[*lenp]); break; }
++    nams[*lenp] = copy;
++
+     *lenp = (*lenp) + 1;
+   }
+-}    
++}
+ 
+ 
+ 
+@@ -603,9 +622,9 @@
+ 
+ /***************************************************/
+ void OpenAlert(txt)
+-     char *txt;
++     const char *txt;
+ {
+-  /* pops up a window with txt displayed in it (*no buttons*).  
++  /* pops up a window with txt displayed in it (*no buttons*).
+      returns immediately.  window is closed by 'CloseAlert()'.
+      No 'PopUp()' calls are allowed while an Alert is displayed. */
+ 
+@@ -624,14 +643,14 @@
+   puwide = PUWIDE;  puhigh = PUHIGH;
+   XResizeWindow(theDisp, popW, (u_int) puwide, (u_int) puhigh);
+ 
+-  /* center last button in window around mouse position, with constraint that 
++  /* center last button in window around mouse position, with constraint that
+      window be fully on the screen */
+ 
+   CenterMapWindow(popW, puwide/2, puhigh/2, puwide, puhigh);
+   popUp = ISALERT;
+ 
+   /* MUST wait for VisibilityNotify event to come in, else we run the risk
+-     of UnMapping the window *before* the Map request completed.  This 
++     of UnMapping the window *before* the Map request completed.  This
+      appears to be bad, (It leaves an empty window frame up.) though it
+      generally only happens on slow servers.  Better safe than screwed... */
+ 
+@@ -695,7 +714,7 @@
+     XKeyEvent *e = (XKeyEvent *) xev;
+     char buf[128];  KeySym ks;
+     int stlen, i, shift, ck;
+-	
++
+     stlen = XLookupString(e,buf,128,&ks,(XComposeStatus *) NULL);
+     shift = e->state & ShiftMask;
+     ck = CursorKey(ks, shift, 0);
+@@ -725,7 +744,7 @@
+ 	rv = 1;
+       }
+ 
+-      if (!rv && (popUp==ISGETSTR || popUp==ISGRAB || popUp==ISPAD)) { 
++      if (!rv && (popUp==ISGETSTR || popUp==ISGRAB || popUp==ISPAD)) {
+ 	if (e->window == popW) { doGetStrKey(buf[0]);  rv = 1; }
+       }
+     }
+@@ -765,26 +784,31 @@
+ #define TR_MAXLN 10
+ 
+ /***************************************************/
+-void TextRect(win, txt, x, y, w, h, fg)
+-     Window  win;
+-     char   *txt;
+-     int     x,y,w,h;
+-     u_long  fg;
+-{
+-  char *sp, *ep, *oldep, *start[TR_MAXLN];
+-  int   i, inbreak, lineno, top, hardcr, maxln, len[TR_MAXLN];
++static void TextRect(win, txt, x, y, w, h, fg)
++     Window      win;
++     const char *txt;
++     int         x,y,w,h;
++     u_long      fg;
++{
++  /* draws semi-complex strings in a rectangle */
++
++  const char *sp;
++  const char *ep;
++  const char *oldep;
++  const char *start[TR_MAXLN];
++  int         i, inbreak, lineno, top, hardcr, maxln, len[TR_MAXLN];
+ 
+   XSetForeground(theDisp, theGC, fg);
+-  
++
+   sp = txt;  lineno = hardcr = 0;
+ 
+-  maxln = h / LINEHIGH;  
++  maxln = h / LINEHIGH;
+   RANGE(maxln,0,TR_MAXLN);
+   while (*sp && lineno<maxln) {
+ 
+     /* drop off any leading spaces (except on first line or after \n) */
+     if (sp!=txt && !hardcr) {
+-      while(*sp==' ') sp++;
++      while (*sp==' ') sp++;
+     }
+ 
+     hardcr = 0;   ep = sp;
+@@ -797,7 +821,7 @@
+     while (XTextWidth(mfinfo, sp, (int)(ep-sp))<= w && *ep && *ep!='\n') ep++;
+     if (*ep=='\n') { ep++;  hardcr=1; }   /* eat newline */
+ 
+-    /* if we got too wide, back off until we find a break position 
++    /* if we got too wide, back off until we find a break position
+        (last char before a space or a '/') */
+ 
+     if (XTextWidth(mfinfo, sp, (int)(ep-sp)) > w) {
+@@ -812,7 +836,7 @@
+     }
+ 
+     start[lineno] = sp;  len[lineno] = ep-sp;
+-    
++
+     /* make sure we don't print a trailing '\n' character! */
+     if (len[lineno] > 0) {
+       while (sp[len[lineno]-1] == '\n') len[lineno] = len[lineno] - 1;
+@@ -835,7 +859,7 @@
+ /***************************************************/
+ static void createPUD()
+ {
+-  popW = CreateWindow("xv confirm", "XVconfirm", "+0+0", 
++  popW = CreateWindow("xv confirm", "XVconfirm", "+0+0",
+ 		      PUWIDE, PUHIGH, infofg, infobg, 0);
+   if (!popW) FatalError("can't create popup window!");
+ 
+@@ -847,7 +871,7 @@
+   bts = (BUTT *) NULL;
+   nbts = selected = firsttime = 0;
+ }
+-  
++
+ 
+ /***************************************************/
+ static void attachPUD()
+@@ -913,24 +937,24 @@
+       XDrawLine(theDisp, popW, theGC, 16+1+75+75+5, puhigh-140 + 6+8,
+ 		16+1+75+75+5, puhigh-10-4);
+     }
+-      
++
+ 
+     XSetForeground(theDisp, theGC, infofg);
+-    XDrawRectangle(theDisp, popW, theGC, 268, puhigh-140, 
++    XDrawRectangle(theDisp, popW, theGC, 268, puhigh-140,
+ 		   (u_int) puwide - 10 - 268, 130-BUTTH-10);
+-    Draw3dRect(popW, 268+1, puhigh-140+1, (u_int) puwide -10-268-2, 
++    Draw3dRect(popW, 268+1, puhigh-140+1, (u_int) puwide -10-268-2,
+ 	       130-2 - BUTTH-10, R3D_IN,2,hicol,locol,infobg);
+-    
+-    TextRect(popW,padInst,268+5, puhigh-140+3, puwide-10-268-10, 
++
++    TextRect(popW,padInst,268+5, puhigh-140+3, puwide-10-268-10,
+ 	     130-6 - BUTTH-10, infofg);
+   }
+ 
+   else {
+     XCopyPlane(theDisp, iconPix, popW, theGC, 0,0, icon_width, icon_height,
+ 	       10,10+(puhigh-30-BUTTH-icon_height)/2, 1L);
+-    
++
+     xt = 10+icon_width+20;  yt = 10;
+-    
++
+     if (popUp == ISGETSTR) {
+       TextRect(popW, text, xt, yt, puwide-10-xt, gsy-20, infofg);
+       drawGSBuf();
+@@ -947,23 +971,23 @@
+ /***************************************************/
+ static void drawPadOMStr()
+ {
+-  CenterString(popW, padODial.x + (padODial.w - 13)/2, 
++  CenterString(popW, padODial.x + (padODial.w - 13)/2,
+ 	       puhigh-16-100-12, padOMStr[padOMode]);
+ }
+-  
++
+ /***************************************************/
+ static void clickPUD(x,y)
+      int x,y;
+ {
+   int i;
+-  BUTT *bp;
+-  
++  BUTT *bp = NULL;
++
+   for (i=0; i<nbts; i++) {
+     bp = &bts[i];
+     if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
+   }
+-  
+-  if (i<nbts && BTTrack(bp)) {
++
++  if (i<nbts && bp && BTTrack(bp)) {
+     popUp = 0;  selected = i;  return;
+   }
+ 
+@@ -972,8 +996,8 @@
+   else if (popUp == ISPAD) {
+     if (PTINRECT(x, y, padDButt.x, padDButt.y, padDButt.w, padDButt.h)) {
+       if (BTTrack(&padDButt)) {
+-	DSetVal(&padWDial, pWIDE);
+-	DSetVal(&padHDial, pHIGH);
++	DSetVal(&padWDial, (double)pWIDE);
++	DSetVal(&padHDial, (double)pHIGH);
+       }
+     }
+ 
+@@ -1017,11 +1041,11 @@
+       gsCurPos = strlen(gsBuf);
+       gsStPos = gsEnPos = 0;
+       changedGSBuf();
+-      if (ctrlColor) 
+-	XClearArea(theDisp, popW, gsx+3,gsy+3, 
++      if (ctrlColor)
++	XClearArea(theDisp, popW, gsx+3,gsy+3,
+ 		   (u_int)gsw-5, (u_int)gsh-5, False);
+       else
+-	XClearArea(theDisp, popW, gsx+1,gsy+1, 
++	XClearArea(theDisp, popW, gsx+1,gsy+1,
+ 		   (u_int)gsw-1, (u_int)gsh-1, False);
+       drawGSBuf();
+ 
+@@ -1032,7 +1056,7 @@
+       DSetActive (&padWDial,  (i!=PAD_LOAD));
+       DSetActive (&padHDial,  (i!=PAD_LOAD));
+ 
+-      XClearArea(theDisp, popW, 184+5, puhigh-140+3, 
++      XClearArea(theDisp, popW, 184+5, puhigh-140+3,
+ 		 (u_int) puwide-10-184-10, 130-6 - BUTTH-10, True);
+ 
+       padMode = i;
+@@ -1049,11 +1073,11 @@
+       gsCurPos = strlen(gsBuf);
+       gsStPos = gsEnPos = 0;
+       changedGSBuf();
+-      if (ctrlColor) 
+-	XClearArea(theDisp, popW, gsx+3,gsy+3, 
++      if (ctrlColor)
++	XClearArea(theDisp, popW, gsx+3,gsy+3,
+ 		   (u_int)gsw-5, (u_int)gsh-5, False);
+       else
+-	XClearArea(theDisp, popW, gsx+1,gsy+1, 
++	XClearArea(theDisp, popW, gsx+1,gsy+1,
+ 		   (u_int)gsw-1, (u_int)gsh-1, False);
+       drawGSBuf();
+ 
+@@ -1079,8 +1103,8 @@
+   /* handle characters typed at GetStrPopUp window.  Button accel. keys
+      have already been checked for elsewhere.  Practical upshot is that
+      we don't have to do anything with ESC or Return (as these will normally
+-     be Cancel and Ok buttons) 
+- 
++     be Cancel and Ok buttons)
++
+      Normally returns '0'.  Returns '1' if character wasn't accepted, for
+      whatever reason. */
+ 
+@@ -1089,7 +1113,7 @@
+   len = strlen(gsBuf);
+   if (gsFilter) flen = strlen(gsFilter);
+            else flen = 0;
+-  
++
+ 
+   if (c>=' ' && c<'\177') {              /* 'NORMAL' CHARACTERS */
+     if (flen) {                          /* check filter string */
+@@ -1097,7 +1121,7 @@
+       if (!gsAllow && i< flen) return 1;    /* found in 'disallow' filter */
+       if ( gsAllow && i==flen) return 1;    /* not found in 'allow' filter */
+     }
+-    
++
+     if (len >= gsBufLen-1) return 1;     /* at max length */
+ 
+     xvbcopy(&gsBuf[gsCurPos], &gsBuf[gsCurPos+1], (size_t) len-gsCurPos+1);
+@@ -1105,7 +1129,7 @@
+   }
+ 
+ 
+-  else if (c=='\010' || c=='\177') {    /* BS or DEL */
++  else if (c=='\010') {                 /* BS */
+     if (gsCurPos==0) return 1;                     /* at beginning of str */
+     xvbcopy(&gsBuf[gsCurPos], &gsBuf[gsCurPos-1], (size_t) len-gsCurPos+1);
+     gsCurPos--;
+@@ -1128,7 +1152,7 @@
+     gsCurPos = len;
+   }
+ 
+-  else if (c=='\004') {                 /* ^D: delete character at gsCurPos */
++  else if (c=='\004' || c=='\177') {    /* ^D or DEL: delete character at gsCurPos */
+     if (gsCurPos==len) return 1;
+     xvbcopy(&gsBuf[gsCurPos+1], &gsBuf[gsCurPos], (size_t) len-gsCurPos);
+   }
+@@ -1147,7 +1171,7 @@
+ 
+   changedGSBuf();      /* compute gsEnPos, gsStPos */
+ 
+-  if (ctrlColor) 
++  if (ctrlColor)
+     XClearArea(theDisp, popW, gsx+3,gsy+3, (u_int)gsw-5, (u_int)gsh-5, False);
+   else
+     XClearArea(theDisp, popW, gsx+1,gsy+1, (u_int)gsw-1, (u_int)gsh-1, False);
+@@ -1175,7 +1199,7 @@
+ /***************************************************/
+ static void changedGSBuf()
+ {
+-  /* cursor position (or whatever) may have changed.  adjust displayed 
++  /* cursor position (or whatever) may have changed.  adjust displayed
+      portion of gsBuf */
+ 
+   int len;
+@@ -1212,7 +1236,7 @@
+ 
+   XSetForeground(theDisp, theGC, infofg);
+   XDrawRectangle(theDisp, popW, theGC, gsx, gsy, (u_int) gsw, (u_int) gsh);
+-  Draw3dRect(popW, gsx+1, gsy+1, (u_int) gsw-2, (u_int) gsh-2, 
++  Draw3dRect(popW, gsx+1, gsy+1, (u_int) gsw-2, (u_int) gsh-2,
+ 	     R3D_IN, 2, hicol,locol,infobg);
+ 
+   XSetForeground(theDisp, theGC, infofg);
+diff -ru xv-3.10a/xvps.c xv-3.10a-enhancements/xvps.c
+--- xv-3.10a/xvps.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvps.c	2007-05-12 15:25:59.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvps.c - Postscript dialog box, file output functions
+  *
+  * callable functions:
+@@ -71,10 +71,13 @@
+ static void psColorImage   PARM((FILE *));
+ static void psColorMap     PARM((FILE *fp, int, int, byte *, byte *, byte *));
+ static void psRleCmapImage PARM((FILE *, int));
+-static void epsPreview     PARM((FILE *, byte *, int, int, int, int, 
++static void epsPreview     PARM((FILE *, byte *, int, int, int, int,
+ 				 byte *, byte *, byte *, int));
+-static int  writeBWStip    PARM((FILE *, byte *, char *, int, int, int));
++static int  writeBWStip    PARM((FILE *, byte *, const char *, int, int, int));
+ 
++#ifdef GS_PATH
++static void buildCmdStr    PARM((char *, char *, char *, int, int));
++#endif
+ 
+ 
+ /* local variables */
+@@ -123,7 +126,7 @@
+ void CreatePSD(geom)
+ char *geom;
+ {
+-  psW = CreateWindow("xv postscript", "XVps", geom, 
++  psW = CreateWindow("xv postscript", "XVps", geom,
+ 		     PSWIDE, PSHIGH, infofg, infobg, 0);
+   if (!psW) FatalError("can't create postscript window!");
+ 
+@@ -139,9 +142,9 @@
+   CBCreate(&encapsCB, psW, 240, 7, "preview", infofg, infobg, hicol, locol);
+   CBCreate(&pscompCB, psW, 331, 7, "compress", infofg, infobg, hicol, locol);
+ 
+-  DCreate(&xsDial, psW, 240, 30, 80, 100, 10, 800, 100, 5, 
++  DCreate(&xsDial, psW, 240, 30, 80, 100, 10.0, 800.0, 100.0, 0.5, 5.0,
+ 	  infofg, infobg, hicol, locol, "Width", "%");
+-  DCreate(&ysDial, psW, 331, 30, 80, 100, 10, 800, 100, 5, 
++  DCreate(&ysDial, psW, 331, 30, 80, 100, 10.0, 800.0, 100.0, 0.5, 5.0,
+ 	  infofg, infobg, hicol, locol, "Height", "%");
+   xsDial.drawobj = changedScale;
+   ysDial.drawobj = changedScale;
+@@ -154,38 +157,38 @@
+   RBCreate(orientRB, psW, 36+80, 240+18, "Landscape", infofg, infobg,
+ 	   hicol, locol);
+ 
+-  paperRB = RBCreate(NULL, psW,36, 240+18+36, "8.5\"x11\"", 
++  paperRB = RBCreate(NULL, psW,36, 240+18+36, "8.5\"x11\"",
+ 		     infofg, infobg, hicol, locol);
+   RBCreate(paperRB, psW, 36+80,    240+18+36, "A4",
+ 	   infofg, infobg, hicol, locol);
+-  RBCreate(paperRB, psW, 36+122,   240+18+36, "B5",         
++  RBCreate(paperRB, psW, 36+122,   240+18+36, "B5",
+ 	   infofg, infobg, hicol, locol);
+-  RBCreate(paperRB, psW, 36+164,   240+18+36, "A3",         
++  RBCreate(paperRB, psW, 36+164,   240+18+36, "A3",
+ 	   infofg, infobg, hicol, locol);
+   RBCreate(paperRB, psW, 36,       240+36+36, "8.5\"x14\"",
+ 	   infofg, infobg, hicol, locol);
+-  RBCreate(paperRB, psW, 36+80,    240+36+36, "11\"x17\"",  
++  RBCreate(paperRB, psW, 36+80,    240+36+36, "11\"x17\"",
+ 	   infofg, infobg, hicol, locol);
+-  RBCreate(paperRB, psW, 36,       240+54+36, "4\"x5\"",    
++  RBCreate(paperRB, psW, 36,       240+54+36, "4\"x5\"",
+ 	   infofg, infobg, hicol, locol);
+-  RBCreate(paperRB, psW, 36+80,    240+54+36, "35mm slide", 
++  RBCreate(paperRB, psW, 36+80,    240+54+36, "35mm slide",
+ 	   infofg, infobg, hicol, locol);
+ 
+-  BTCreate(&psbut[PS_BOK], psW, PSWIDE-180, PSHIGH-10-BUTTH, 80, BUTTH, 
++  BTCreate(&psbut[PS_BOK], psW, PSWIDE-180, PSHIGH-10-BUTTH, 80, BUTTH,
+ 	   "Ok", infofg, infobg, hicol, locol);
+-  BTCreate(&psbut[PS_BCANC], psW, PSWIDE-90, PSHIGH-10-BUTTH, 80, BUTTH, 
++  BTCreate(&psbut[PS_BCANC], psW, PSWIDE-90, PSHIGH-10-BUTTH, 80, BUTTH,
+ 	   "Cancel", infofg, infobg, hicol, locol);
+ 
+-  BTCreate(&psbut[PS_BCENT], psW, 240, 154, 55, BUTTH-2, 
++  BTCreate(&psbut[PS_BCENT], psW, 240, 154, 55, BUTTH-2,
+ 	   "Center", infofg, infobg, hicol, locol);
+-  BTCreate(&psbut[PS_BORG], psW,  298, 154, 55, BUTTH-2, 
++  BTCreate(&psbut[PS_BORG], psW,  298, 154, 55, BUTTH-2,
+ 	   "Origin", infofg, infobg, hicol, locol);
+-  BTCreate(&psbut[PS_BMAX], psW,  356, 154, 55, BUTTH-2, 
++  BTCreate(&psbut[PS_BMAX], psW,  356, 154, 55, BUTTH-2,
+ 	   "Max",    infofg, infobg, hicol, locol);
+ 
+-  BTCreate(&psbut[PS_BPOSX], psW, 256-14, 190+13-8, 8,8, "", 
++  BTCreate(&psbut[PS_BPOSX], psW, 256-14, 190+13-8, 8,8, "",
+ 	   infofg, infobg, hicol, locol);
+-  BTCreate(&psbut[PS_BPOSY], psW, 256-14, 190+26-8, 8,8, "", 
++  BTCreate(&psbut[PS_BPOSY], psW, 256-14, 190+26-8, 8,8, "",
+ 	   infofg, infobg, hicol, locol);
+ 
+   posxType = posyType = 0;
+@@ -236,17 +239,17 @@
+ 
+   if (rd_int("psres")) {             /* xv.psres:  default paper resolution */
+     if (def_int >= 10 && def_int <= 720) {
+-      int i = (int) ((PIX2INCH * 100) / def_int);
++      double v = (PIX2INCH * 100) / def_int;
+ 
+-      DSetVal(&xsDial, i);
+-      DSetVal(&ysDial, i);
++      DSetVal(&xsDial, v);
++      DSetVal(&ysDial, v);
+     }
+   }
+ 
+ 
+   XMapSubwindows(theDisp, psW);
+ }
+-  
++
+ 
+ /***************************************************/
+ void PSDialog(vis)
+@@ -289,7 +292,7 @@
+     x = e->x;  y = e->y;  w = e->width;  h = e->height;
+ 
+     /* throw away excess expose events for 'dumb' windows */
+-    if (e->count > 0 && 
++    if (e->count > 0 &&
+ 	(e->window == xsDial.win || e->window == ysDial.win ||
+ 	 e->window == pageF)) {}
+ 
+@@ -332,7 +335,7 @@
+     XKeyEvent *e = (XKeyEvent *) xev;
+     char buf[128];  KeySym ks;
+     int  stlen, shift, ck;
+-	
++
+     stlen = XLookupString(e,buf,128,&ks,(XComposeStatus *) NULL);
+     shift = e->state & ShiftMask;
+     ck    = CursorKey(ks, shift, 0);
+@@ -403,7 +406,7 @@
+ static void drawPSD(x,y,w,h)
+ int x,y,w,h;
+ {
+-  char *title = "Save PostScript File...";
++  const char *title = "Save PostScript File...";
+   int  i,cx;
+   XRectangle xr;
+ 
+@@ -463,12 +466,14 @@
+ /***************************************************/
+ static void drawPosStr()
+ {
+-  int x,y;
+-  double cmx, cmy, inx, iny;
+-  char   str[64], str1[64], *xst, *yst;
++  int         x,y;
++  double      cmx, cmy, inx, iny;
++  char        str[64], str1[64];
++  const char *xst, *yst;
+ 
+   x = 256;  y = 190 + 13;
+-  inx = iny = 0;  xst = yst = (char *) NULL;
++  inx = iny = 0;
++  xst = yst = (const char *) NULL;
+ 
+   switch (posxType) {
+   case 0:  xst = "Left: ";  inx = pos_inx;                      break;
+@@ -497,7 +502,7 @@
+   XSetFont(theDisp, theGC, mfont);
+ }
+ 
+-  
++
+ /***************************************************/
+ static void drawSizeStr()
+ {
+@@ -522,7 +527,7 @@
+   XSetFont(theDisp, theGC, mfont);
+ }
+ 
+-  
++
+ /***************************************************/
+ static void drawResStr()
+ {
+@@ -540,9 +545,9 @@
+   XSetFont(theDisp, theGC, mfont);
+ }
+ 
+-  
+-  
+-  
++
++
++
+ /***************************************************/
+ static void drawPage()
+ {
+@@ -554,7 +559,7 @@
+   XSetForeground(theDisp, theGC, infofg);
+   XDrawRectangle(theDisp, pageF, theGC, pageRect.x, pageRect.y,
+ 		 (u_int) pageRect.width, (u_int) pageRect.height);
+-  
++
+   drawIRect(1);
+ }
+ 
+@@ -611,7 +616,7 @@
+   unsigned int mask;
+   double       offx, offy, newx, newy;
+ 
+-  /* compute offset (in inches) between 'drag point' and 
++  /* compute offset (in inches) between 'drag point' and
+      the top-left corner of the image */
+ 
+   offx = ((mx - pageRect.x) / in2pix) - pos_inx;
+@@ -642,7 +647,7 @@
+   char *fullname;
+ 
+   switch (cmd) {
+-  case PS_BOK:    writePS();    
++  case PS_BOK:    writePS();
+                   PSDialog(0);
+                   fullname = GetDirFullName();
+                   if (!ISPIPE(fullname[0])) {
+@@ -721,15 +726,15 @@
+ 
+   GetSaveSize(&w, &h);
+ 
+-  sz_inx = (double) w / PIX2INCH * (xsDial.val / 100.0);  
+-  sz_iny = (double) h / PIX2INCH * (ysDial.val / 100.0);  
++  sz_inx = (double) w / PIX2INCH * (xsDial.val / 100.0);
++  sz_iny = (double) h / PIX2INCH * (ysDial.val / 100.0);
+ 
+   /* round to integer .001ths of an inch */
+   sz_inx = floor(sz_inx * 1000.0 + 0.5) / 1000.0;
+   sz_iny = floor(sz_iny * 1000.0 + 0.5) / 1000.0;
+ 
+-  dpix = (int) (PIX2INCH / (xsDial.val / 100.0));  
+-  dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));  
++  dpix = (int) (PIX2INCH / (xsDial.val / 100.0));
++  dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));
+ 
+   /* make sure 'center' of image is still on page */
+   hsx = sz_inx/2;  hsy = sz_iny/2;
+@@ -783,20 +788,20 @@
+ {
+   int x,y,w,h;
+   XRectangle xr;
+-  
++
+   x = pageRect.x + (int) (pos_inx * in2pix);
+   y = pageRect.y + (int) (pos_iny * in2pix);
+   w = sz_inx * in2pix;
+   h = sz_iny * in2pix;
+-  
++
+   xr.x = pageRect.x + 1;
+   xr.y = pageRect.y + 1;
+   xr.width  = pageRect.width - 1;
+   xr.height = pageRect.height - 1;
+-  
++
+   if (draw) XSetForeground(theDisp, theGC, infofg);
+        else XSetForeground(theDisp, theGC, infobg);
+-  
++
+   XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
+   XDrawRectangle(theDisp, pageF, theGC, x, y, (u_int) w, (u_int) h);
+   XDrawLine(theDisp, pageF, theGC, x, y, x+w, y+h);
+@@ -836,18 +841,18 @@
+   if (scx < scy) { sz_iny = h * scx; }
+             else { sz_inx = w * scy; }
+ 
+-  DSetVal(&xsDial, (int) ((100 * (sz_inx * PIX2INCH) / w) + .5));
++  DSetVal(&xsDial, 100 * (sz_inx * PIX2INCH) / w);
+   DSetVal(&ysDial, xsDial.val);
+ 
+-  sz_inx = (double) w / PIX2INCH * (xsDial.val / 100.0);  
+-  sz_iny = (double) h / PIX2INCH * (ysDial.val / 100.0);  
++  sz_inx = (double) w / PIX2INCH * (xsDial.val / 100.0);
++  sz_iny = (double) h / PIX2INCH * (ysDial.val / 100.0);
+ 
+   /* round to integer .001ths of an inch */
+   sz_inx = floor(sz_inx * 1000.0 + 0.5) / 1000.0;
+   sz_iny = floor(sz_iny * 1000.0 + 0.5) / 1000.0;
+ 
+-  dpix = (int) (PIX2INCH / (xsDial.val / 100.0));  
+-  dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));  
++  dpix = (int) (PIX2INCH / (xsDial.val / 100.0));
++  dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));
+ 
+   pos_inx = psizex/2 - sz_inx/2;
+   pos_iny = psizey/2 - sz_iny/2;
+@@ -888,7 +893,7 @@
+ static void writePS()
+ {
+   FILE *fp;
+-  int   i, j, q, err, rpix, gpix, bpix, nc, ptype;
++  int   i, j, err, rpix, gpix, bpix, nc, ptype;
+   int   iw, ih, ox, oy, slen, lwidth, bits, colorps, w, h, pfree;
+   double iwf, ihf;
+   byte *inpix, *rmap, *gmap, *bmap;
+@@ -900,13 +905,19 @@
+   if (!fp) return;
+ 
+   WaitCursor();
+-  
++
+   inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap);
+ 
+-    
++  if (w <= 0 || h <= 0 || w*2 < w) {
++    SetISTR(ISTR_WARNING,"%s:  Image dimensions out of range", filename);
++    CloseOutFile(fp, filename, 1);
++    return;
++  }
++
++
+   /* printed image will have size iw,ih (in picas) */
+   iw = (int) (sz_inx * 72.0 + 0.5);
+-  ih = (int) (sz_iny * 72.0 + 0.5);   
++  ih = (int) (sz_iny * 72.0 + 0.5);
+   iwf = sz_inx * 72.0;
+   ihf = sz_iny * 72.0;
+ 
+@@ -923,12 +934,12 @@
+   fprintf(fp,"%%%%Creator: XV %s  -  by John Bradley\n",REVDATE);
+ 
+   if (RBWhich(orientRB)==ORNT_LAND)   /* Landscape mode */
+-    fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n", 
++    fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n",
+ 	    (int) (pos_iny * 72.0 + 0.5),
+ 	    (int) (pos_inx * 72.0 + 0.5),
+ 	    (int) (pos_iny * 72.0 + 0.5) + ih,
+ 	    (int) (pos_inx * 72.0 + 0.5) + iw);
+-  else 
++  else
+     fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n", ox, oy, ox+iw, oy+ih);
+ 
+   fprintf(fp,"%%%%Pages: 1\n");
+@@ -943,9 +954,9 @@
+   case F_BWDITHER:  slen = (w+7)/8;  bits = 1;  colorps = 0;  break;
+   default:  FatalError("unknown colorType in writePS()");   break;
+   }
+-  
++
+   if (encapsCB.val) epsPreview(fp, inpix, ptype, colorType, w, h,
+-			       rmap,gmap,bmap, 
++			       rmap,gmap,bmap,
+ 			       (RBWhich(orientRB)==ORNT_LAND) );
+ 
+   fprintf(fp,"%%%%EndProlog\n\n");
+@@ -978,7 +989,7 @@
+     fprintf(fp,"%% print in landscape mode\n");
+     fprintf(fp,"90 rotate 0 %d translate\n\n",(int) (-psizey*72.0));
+   }
+-    
++
+   if (RBWhich(paperRB) == PSZ_4BY5 ||
+       RBWhich(paperRB) == PSZ_35MM) {
+     fprintf(fp,"%% we're going to a 4x5 or a 35mm film recorder.\n");
+@@ -1083,12 +1094,12 @@
+ 	    gpix = inpix[1];
+ 	    bpix = inpix[2];
+ 	  }
+-	  
+-	  if (colorps) { 
++
++	  if (colorps) {
+ 	    err = fprintf(fp,"%02x%02x%02x",rpix,gpix,bpix);
+ 	    lwidth+=6;
+ 	  }
+-      
++
+ 	  else {  /* greyscale */
+ 	    err = fprintf(fp,"%02x", MONO(rpix,gpix,bpix));
+ 	    lwidth+=2;
+@@ -1106,7 +1117,7 @@
+       fprintf(fp,"\n\n");
+       fprintf(fp,"%%\n");
+       fprintf(fp,"%% Compression made this file %.2f%% %s\n",
+-	      100.0 * ((double) outbytes) / 
++	      100.0 * ((double) outbytes) /
+ 	      ((double) eWIDE * eHIGH * ((colorps) ? 3 : 1)),
+ 	      "of the uncompressed size.");
+       fprintf(fp,"%%\n");
+@@ -1147,10 +1158,10 @@
+    *
+    * returns length of the rleline vector
+    */
+-  
++
+   int  i, j, blocklen, isrun, rlen;
+   byte block[256], pix;
+-  
++
+   blocklen = isrun = rlen = 0;
+ 
+   for (i=0; i<wide; i++) {
+@@ -1186,7 +1197,7 @@
+ 	}
+       }
+     }
+-	
++
+     else {   /* not a run */
+       if (pix == block[blocklen-1]) {   /* case 3:  non-run, prev==cur */
+ 	if (blocklen>1) {               /*  have a non-run block to flush */
+@@ -1215,7 +1226,7 @@
+ 
+       else {
+ 	rleline[rlen++] = (blocklen-1) | 0x80;
+-	for (j=0; j<blocklen; j++) 
++	for (j=0; j<blocklen; j++)
+ 	  rleline[rlen++] = block[j];
+       }
+ 
+@@ -1231,15 +1242,15 @@
+ 
+     else {
+       rleline[rlen++] = (blocklen-1) | 0x80;
+-      for (j=0; j<blocklen; j++) 
++      for (j=0; j<blocklen; j++)
+ 	rleline[rlen++] = block[j];
+     }
+   }
+ 
+   return rlen;
+ }
+-	  
+-	    
++
++
+ /**********************************************/
+ static void psColorImage(fp)
+ FILE *fp;
+@@ -1276,7 +1287,7 @@
+   fprintf(fp,"    %% Utility procedure for colorimage operator.\n");
+   fprintf(fp,"    %% This procedure takes two procedures off the\n");
+   fprintf(fp,"    %% stack and merges them into a single procedure.\n\n");
+-  
++
+   fprintf(fp,"    /mergeprocs { %% def\n");
+   fprintf(fp,"      dup length\n");
+   fprintf(fp,"      3 -1 roll\n");
+@@ -1326,12 +1337,12 @@
+   for (i=0; i<nc; i++) {
+     if (color) fprintf(fp,"%02x%02x%02x ", rmap[i],gmap[i],bmap[i]);
+     else fprintf(fp,"%02x ", MONO(rmap[i],gmap[i],bmap[i]));
+-    
++
+     if ((i%10) == 9) fprintf(fp,"\n");
+   }
+   if (i%10) fprintf(fp,"\n");
+   fprintf(fp,"pop pop   %% lose return values from readhexstring\n\n\n");
+-		 
++
+ }
+ 
+ 
+@@ -1407,7 +1418,7 @@
+ 
+ 
+ /**********************************************/
+-static void epsPreview(fp, pic, ptype, colorType, w, h, rmap,gmap,bmap, 
++static void epsPreview(fp, pic, ptype, colorType, w, h, rmap,gmap,bmap,
+ 		       landscape)
+      FILE *fp;
+      byte *pic;
+@@ -1420,21 +1431,37 @@
+ 
+ 
+   if (landscape) {  /* generate a rotated version of the pic */
+-    int bperpix;
++    int npixels, bufsize;
+     byte *lpic;
+ 
+-    bperpix = (ptype == PIC8) ? 1 : 3;
+-    lpic = (byte *) malloc((size_t) w * h * bperpix);
++    npixels = w * h;
++    if (w <= 0 || h <= 0 || npixels/w != h) {
++      SetISTR(ISTR_WARNING,"%s:  Image dimensions out of range", filename);
++/*    CloseOutFile(fp, filename, 1);  can't do since caller still writing */
++      return;
++    }
++    if (ptype == PIC8)
++      bufsize = npixels;
++    else {
++      bufsize = 3*npixels;
++      if (bufsize/3 != npixels) {
++        SetISTR(ISTR_WARNING,"%s:  Image dimensions out of range", filename);
++/*      CloseOutFile(fp, filename, 1);  can't do since caller still writing */
++        return;
++      }
++    }
++
++    lpic = (byte *) malloc((size_t) bufsize);
+     if (!lpic) FatalError("can't alloc mem to rotate image in epsPreview");
+ 
+-    xvbcopy((char *) pic, (char *) lpic, (size_t) w * h * bperpix);
++    xvbcopy((char *) pic, (char *) lpic, (size_t) bufsize);
+     RotatePic(lpic, ptype, &w, &h, 0);
+     pic = lpic;
+   }
+-    
++
+ 
+   /* put in an EPSI preview */
+-  
++
+   if (colorType != F_BWDITHER) { /* have to generate a preview */
+     prev = FSDither(pic, ptype, w, h, rmap,gmap,bmap, 0, 1);
+ 
+@@ -1451,8 +1478,8 @@
+     flipbw = (MONO(rmap[0],gmap[0],bmap[0]) > MONO(rmap[1],gmap[1],bmap[1]));
+   }
+ 
+- 
+-  fprintf(fp,"%%%%BeginPreview: %d %d %d %d\n", w, h, 1, 
++
++  fprintf(fp,"%%%%BeginPreview: %d %d %d %d\n", w, h, 1,
+ 	  (w/(72*4) + 1) * h);
+ 
+   writeBWStip(fp, prev, "% ", w, h, !flipbw);
+@@ -1468,10 +1495,10 @@
+ static int writeBWStip(fp, pic, prompt, w, h, flipbw)
+      FILE *fp;
+      byte *pic;
+-     char *prompt;
++     const char *prompt;
+      int  w, h, flipbw;
+ {
+-  /* write the given 'pic' (B/W stippled, 1 byte per pixel, 0=blk,1=wht) 
++  /* write the given 'pic' (B/W stippled, 1 byte per pixel, 0=blk,1=wht)
+      out as hexadecimal, max of 72 hex chars per line.
+ 
+      if 'flipbw', then 0=white, 1=black
+@@ -1535,39 +1562,46 @@
+      document is multiple pages, a series of PNM files are created, and
+      the first one is loaded (but not deleted) */
+ 
+-
+-  char tmp[512], tmp1[512], tmpname[64];
+-  int  gsresult, nump, i, filetype;
+-  char *rld;
++#ifdef GS_PATH
++  #define CMDSIZE	1024
++  char tmp[512], gscmd[512], cmdstr[CMDSIZE], tmpname[64];
++  int  gsresult, nump, i, filetype, doalert, epsf;
++#endif
+ 
+   pinfo->pic     = (byte *) NULL;
+   pinfo->comment = (char *) NULL;
+ 
+-
+ #ifdef GS_PATH
+ 
++  doalert = (!quick && !ctrlUp && !infoUp);  /* open alert if no info wins */
++  epsf    = 0;
++
+ #ifndef VMS
+   sprintf(tmpname, "%s/xvpgXXXXXX", tmpdir);
+ #else
+   sprintf(tmpname, "Sys$Scratch:xvpgXXXXXX");
+ #endif
+ 
++#ifdef USE_MKSTEMP
++  close(mkstemp(tmpname));
++#else
+   mktemp(tmpname);
+-  if (tmpname[0] == '\0') {   /* mktemp() blew up */
+-    sprintf(str,"LoadPS: Unable to create temporary filename???");
+-    ErrPopUp(str, "\nHow unlikely!");
++#endif
++  if (tmpname[0] == '\0') {   /* mktemp() or mkstemp() blew up */
++    sprintf(dummystr,"LoadPS: Unable to create temporary filename???");
++    ErrPopUp(dummystr, "\nHow unlikely!");
+     return 0;
+   }
+   strcat(tmpname,".");
+ 
+ 
+-  /* build command string */
++  /* build 'gscmd' string */
+ 
+ #ifndef VMS  /* VMS needs quotes around mixed case command lines */
+-  sprintf(tmp, "%s -sDEVICE=%s -r%d -q -dNOPAUSE -sOutputFile=%s%%d ",
++  sprintf(gscmd, "%s -sDEVICE=%s -r%d -q -dSAFER -dNOPAUSE -sOutputFile=%s%%d ",
+ 	  GS_PATH, gsDev, gsRes, tmpname);
+ #else
+-  sprintf(tmp, 
++  sprintf(gscmd,
+ 	  "%s \"-sDEVICE=%s\" -r%d -q \"-dNOPAUSE\" \"-sOutputFile=%s%%d\" ",
+ 	  GS_PATH, gsDev, gsRes, tmpname);
+ #endif
+@@ -1575,74 +1609,60 @@
+ 
+ #ifdef GS_LIB
+ #  ifndef VMS
+-     sprintf(tmp1, "-I%s ", GS_LIB);
++     sprintf(tmp, "-I%s ", GS_LIB);
+ #  else
+-     sprintf(tmp1, "\"-I%s\"", GS_LIB);
++     sprintf(tmp, "\"-I%s\" ", GS_LIB);
+ #  endif
+-   strcat(tmp, tmp1);
++   strcat(gscmd, tmp);
+ #endif
+ 
+-  if (gsGeomStr) {
+-    sprintf(tmp1, "-g%s ", gsGeomStr);
+-    strcat(tmp, tmp1);
+-  }
+-
+-  /* if 'quick' is set, stop processing after first page by tacking
+-     some PostScript commands that break the 'showpage' operator onto
+-     the front of the stream passed to the ghostscript interpreter */
+ 
++   /* prevent some potential naughtiness... */
+ #ifndef VMS
+-  if (quick) {
+-    sprintf(tmp1, "echo '%s' | cat - %s | %s -",
+-	    "/showpage { showpage quit } bind def",   /* mk showpage exit */
+-	    fname,  tmp);
+-    strcpy(tmp, tmp1);
+-  }
+-  else {
+-    strcat(tmp, " -- ");
+-    strcat(tmp, fname);
+-  }
+-#else /* VMS */
+-  /* VMS doesn't have pipes or an 'echo' command and GS doesn't like
+-     Unix-style file names as input files in the VMS version */
+-  strcat(tmp, " -- ");
+-  rld = strrchr(fname, '/');     /* Pointer to last '/' */
+-  if (rld) rld++;                /* Pointer to filename */
+-      else rld = fname;          /* No path - use original string */
+-  strcat(tmp, rld);
++   strcat(gscmd, "-dSAFER ");
++#else
++   strcat(gscmd, "\"-dSAFER\" ");
+ #endif
+ 
+ 
++  if (gsGeomStr) {
++    sprintf(tmp, "-g%s ", gsGeomStr);
++    strcat(gscmd, tmp);
++  }
+ 
+ 
+-  WaitCursor();
+-
+-  if (DEBUG) fprintf(stderr,"LoadPS:  executing command '%s'\n", tmp);
+-  SetISTR(ISTR_INFO, "Running '%s'...", GS_PATH);
++  do {
++    buildCmdStr(cmdstr, gscmd, fname, quick, epsf);
+ 
+-  sprintf(tmp1, "Running %s", tmp);
+-  if (!quick && !ctrlUp && !infoUp) OpenAlert(tmp1);
++    if (DEBUG) fprintf(stderr,"LoadPS:  executing command '%s'\n", cmdstr);
++    SetISTR(ISTR_INFO, "Running '%s'...", GS_PATH);
++    sprintf(tmp, "Running %s", cmdstr);
++    if (doalert && epsf==0) OpenAlert(tmp);  /* open alert first time only */
+ 
+-#ifndef VMS
+-  gsresult = system(tmp);
+-#else
+-  gsresult = !system(tmp);
++    WaitCursor();
++    gsresult = system(cmdstr);
++    WaitCursor();
++#ifdef VMS
++    gsresult = !gsresult;   /* VMS returns non-zero if OK */
+ #endif
+ 
+-  WaitCursor();
++    /* count # of files produced... */
++    for (i=1; i<1000; i++) {
++      struct stat st;
++      sprintf(tmp, "%s%d", tmpname, i);
++      if (stat(tmp, &st)!=0) break;
++    }
++    nump = i-1;
++    WaitCursor();
+ 
+-  if (!quick && !ctrlUp && !infoUp) CloseAlert();
++    /* EPSF hack:  if gsresult==0 (OK) and 0 pages produced,
++       try tacking a 'showpage' onto the end of the file, do it again... */
++
++    if (!gsresult && !nump && !epsf) epsf++;
++  } while (!gsresult && !nump && epsf<2);
++
++  if (doalert) CloseAlert();
+ 
+-  /* figure out how many page files were created, by stating files. 
+-     breaks out on first failure, assuming there won't be any more after
+-     that, and it would complicate matters too much anyhow... */
+-
+-  for (i=1; i<1000; i++) {
+-    struct stat st;
+-    sprintf(tmp, "%s%d", tmpname, i);
+-    if (stat(tmp, &st)!=0) break;
+-  }
+-  nump = i-1;
+ 
+   WaitCursor();
+ 
+@@ -1664,7 +1684,7 @@
+       return 0;
+     }
+ 
+-    SetISTR(ISTR_INFO, "Running '%s'...  Done.  (%d page%s)", 
++    SetISTR(ISTR_INFO, "Running '%s'...  Done.  (%d page%s)",
+ 	    GS_PATH, nump, (nump==1) ? "" : "s");
+   }
+ 
+@@ -1677,8 +1697,8 @@
+ 
+   sprintf(tmp, "%s%d", tmpname, 1);
+   filetype = ReadFileType(tmp);
+-  
+-  if (filetype == RFT_ERROR || filetype == RFT_UNKNOWN || 
++
++  if (filetype == RFT_ERROR || filetype == RFT_UNKNOWN ||
+       filetype == RFT_COMPRESS) {  /* shouldn't happen */
+     SetISTR(ISTR_WARNING, "Couldn't load first page '%s'", tmp);
+     KillPageFiles(tmpname, nump);
+@@ -1695,7 +1715,7 @@
+     KillPageFiles(tmpname, nump);
+     SetCursors(-1);
+     return 0;
+-  }    
++  }
+ 
+ 
+   /* SUCCESS! */
+@@ -1712,3 +1732,54 @@
+ 		 we don't have 'gs' package */
+ }
+ 
++
++
++/******************************************************************/
++#ifdef GS_PATH
++void buildCmdStr(str, gscmd, xname, quick, epsf)
++     char *str, *gscmd, *xname;
++     int   quick, epsf;
++{
++  /* note 'epsf' set only on files that don't have a showpage cmd */
++  char *x, *y, *fname;
++
++  x = (char *) malloc((5 * strlen(xname))+3);
++  if (!x)
++	FatalError("malloc failure in xvps.c buildCmdStr");
++  fname = x;
++  *x++ = 0x27;
++
++  for (y = xname; *y; ++y) {
++     if (0x27 == *y) {
++       strcpy(x, "'\"'\"'");
++       x += strlen(x);
++     } else *x++ = *y;
++  }
++  strcpy (x, "'");
++
++#ifndef VMS
++
++  if      (epsf)  snprintf(str, CMDSIZE, "echo '\n showpage ' | cat %s - | %s -",
++			  fname, gscmd);
++
++  else if (quick) snprintf(str, CMDSIZE, "echo %s | cat - %s | %s -",
++			  "/showpage { showpage quit } bind def",
++			  fname,  gscmd);
++
++  else            snprintf(str, CMDSIZE, "%s -- %s", gscmd, fname);
++
++#else /* VMS */
++  /* VMS doesn't have pipes or an 'echo' command and GS doesn't like
++     Unix-style filenames as input files in the VMS version */
++  strcat(tmp, " -- ");
++  rld = strrchr(fname, '/');     /* Pointer to last '/' */
++  if (rld) rld++;                /* Pointer to filename */
++  else rld = fname;              /* No path - use original string */
++  strcat(tmp, rld);
++#endif  /* VMS */
++  free(fname);
++}
++#endif  /* GS_PATH */
++
++
++
+diff -ru xv-3.10a/xvrle.c xv-3.10a-enhancements/xvrle.c
+--- xv-3.10a/xvrle.c	1995-01-19 09:27:47.000000000 -0800
++++ xv-3.10a-enhancements/xvrle.c	2007-05-13 17:49:34.000000000 -0700
+@@ -28,7 +28,7 @@
+ #define GETINT(fp) (c=getc(fp), c1=getc(fp), (c1<<8) + c )
+ 
+ static void read_rle PARM((FILE *, byte *, int, int, int, int));
+-static int  rleError PARM((char *, char *));
++static int  rleError PARM((const char *, const char *));
+ 
+ 
+ 
+@@ -44,9 +44,10 @@
+   byte   maps[3][256];
+   int    xpos, ypos, w, h, flags, ncolors, pixelbits, ncmap, cmaplen;
+   int    cmtlen;
+-  byte  *img, *pic8;
++  byte  *img;
+   long filesize;
+-  char  *bname, *errstr;
++  const char *bname;
++  const char *errstr;
+ 
+   pinfo->type = PIC8;
+   pinfo->pic     = (byte *) NULL;
+@@ -57,7 +58,7 @@
+   /* open the stream */
+   fp = xv_fopen(fname,"r");
+   if (!fp) return (rleError(bname, "unable to open file"));
+-  
++
+ 
+   /* figure out the file size */
+   fseek(fp, 0L, 2);
+@@ -85,7 +86,7 @@
+   if (DEBUG) {
+     fprintf(stderr,"RLE: %dx%d image at %d,%d\n", w, h, xpos, ypos);
+     fprintf(stderr,"flags: 0x%02x  (%s%s%s%s)\n",
+-	    flags, 
++	    flags,
+ 	    (flags & H_CLEARFIRST)    ? "CLEARFIRST " : "",
+ 	    (flags & H_NO_BACKGROUND) ? "NO_BG " : "",
+ 	    (flags & H_ALPHA)         ? "ALPHA " : "",
+@@ -93,7 +94,7 @@
+ 
+     fprintf(stderr, "%d bands, %d pixelbits, %d cmap bands, %d cmap entries\n",
+ 	    ncolors, pixelbits, ncmap, cmaplen);
+-  }  
++  }
+ 
+   if (!(flags & H_NO_BACKGROUND)) {
+     if (DEBUG) fprintf(stderr, "background value: ");
+@@ -212,7 +213,7 @@
+       for (i=0, ip=img; i<w*h; i++, ip++) *ip = bgcol[0];
+     }
+     else {
+-      for (i=0, ip=img; i<w*h; i++) 
++      for (i=0, ip=img; i<w*h; i++)
+ 	for (j=0; j<3; j++, ip++) *ip = bgcol[j];
+     }
+   }
+@@ -250,7 +251,7 @@
+   /* finally, convert into XV internal format */
+ 
+   pinfo->pic = img;
+-  pinfo->w   = w;  
++  pinfo->w   = w;
+   pinfo->h   = h;
+   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
+   pinfo->frmType = -1;    /* no default format to save in */
+@@ -260,7 +261,7 @@
+     if (ncmap == 0 || ncmap == 1) {   /* grey, or grey with gamma curve */
+       pinfo->colType = F_GREYSCALE;
+       sprintf(pinfo->fullInfo, "Greyscale RLE.  (%ld bytes)", filesize);
+-      for (i=0; i<256; i++) 
++      for (i=0; i<256; i++)
+ 	pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
+     }
+     else {
+@@ -272,7 +273,7 @@
+ 	pinfo->b[i] = maps[2][i];
+       }
+     }
+-    
++
+     sprintf(pinfo->shrtInfo, "%dx%d RLE.",w, h);
+   }
+ 
+@@ -294,7 +295,7 @@
+      int   w, h, ncolors, ncmap;
+ {
+   int posx, posy, plane, bperpix, i, pixval, skipcalls;
+-  int opcode, operand, done, c, c1;    
++  int opcode, operand, done, c, c1;
+   byte *ip;
+ 
+   posx = posy = plane = done = skipcalls = 0;
+@@ -324,7 +325,7 @@
+     case RSkipPixelsOp:
+       if (opcode & LONG_OP) { getc(fp);  operand = GETINT(fp); }
+       else operand = getc(fp);
+-      
++
+       posx += operand;
+       break;
+ 
+@@ -340,7 +341,7 @@
+ 	c = getc(fp);
+ 	if (plane<ncolors && posy<h && (posx+i < w)) *ip = c;
+       }
+-      
++
+       if (operand & 1) getc(fp);  /* word boundary */
+       posx += operand;
+       break;
+@@ -358,7 +359,7 @@
+       for (i=0; i<operand; i++, ip+=bperpix) {
+ 	if (plane<ncolors && posy<h && (posx+i < w)) *ip = pixval;
+       }
+-      
++
+       /*  if (operand & 1) getc(fp); */  /* word boundary */
+       posx += operand;
+       break;
+@@ -373,7 +374,7 @@
+ 
+ /*******************************************/
+ static int rleError(fname,st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+diff -ru xv-3.10a/xvroot.c xv-3.10a-enhancements/xvroot.c
+--- xv-3.10a/xvroot.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvroot.c	2004-05-16 18:07:52.000000000 -0700
+@@ -22,7 +22,7 @@
+ /***********************************/
+ void MakeRootPic()
+ {
+-  /* called after 'epic' has been generated (if we're using root).  
++  /* called after 'epic' has been generated (if we're using root).
+      creates the XImage and the pixmap, sets the root to the new
+      pixmap, and refreshes the display */
+ 
+@@ -44,6 +44,7 @@
+   case RM_MIRROR:
+   case RM_IMIRROR: rpixw = 2*eWIDE;  rpixh = 2*eHIGH;  break;
+   case RM_CSOLID:
++  case RM_UPLEFT:
+   case RM_CWARP:
+   case RM_CBRICK:  rpixw = dispWIDE; rpixh = dispHIGH; break;
+ 
+@@ -67,32 +68,32 @@
+ 
+ 
+   if (rmode == RM_NORMAL || rmode == RM_TILE) {
+-    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0, 
++    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
+ 	      (u_int) eWIDE, (u_int) eHIGH);
+   }
+ 
+   else if (rmode == RM_MIRROR || rmode == RM_IMIRROR) {
+     /* quadrant 2 */
+-    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0, 
++    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
+ 	      (u_int) eWIDE, (u_int) eHIGH);
+     if (epic == NULL) FatalError("epic == NULL in RM_MIRROR code...\n");
+ 
+     /* quadrant 1 */
+     FlipPic(epic, eWIDE, eHIGH, 0);   /* flip horizontally */
+     CreateXImage();
+-    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,0, 
++    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,0,
+ 	      (u_int) eWIDE, (u_int) eHIGH);
+ 
+     /* quadrant 4 */
+     FlipPic(epic, eWIDE, eHIGH, 1);   /* flip vertically */
+     CreateXImage();
+-    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,eHIGH, 
++    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,eHIGH,
+ 	      (u_int) eWIDE, (u_int) eHIGH);
+ 
+     /* quadrant 3 */
+     FlipPic(epic, eWIDE, eHIGH, 0);   /* flip horizontally */
+     CreateXImage();
+-    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,eHIGH, 
++    XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,eHIGH,
+ 	      (u_int) eWIDE, (u_int) eHIGH);
+ 
+     FlipPic(epic, eWIDE, eHIGH, 1);   /* flip vertically  (back to orig) */
+@@ -101,7 +102,7 @@
+ 
+ 
+   else if (rmode == RM_CENTER || rmode == RM_CENTILE || rmode == RM_CSOLID ||
+-	   rmode == RM_CWARP || rmode == RM_CBRICK) {
++	   rmode == RM_CWARP || rmode == RM_CBRICK || rmode == RM_UPLEFT) {
+     /* do some stuff to set up the border around the picture */
+ 
+     if (rmode != RM_CENTILE) {
+@@ -122,15 +123,15 @@
+       for (i=ay; i < (int) eHIGH; i+=h) {
+ 	for (j=ax; j < (int) eWIDE; j+=w) {
+ 	  /* if image goes off tmpPix, only draw subimage */
+-	  
++
+ 	  x = j;  y = i;  w1 = w;  h1 = h;  offx = offy = 0;
+ 	  if (x<0)           { offx = -x;  w1 -= offx;  x = 0; }
+ 	  if (x+w1>eWIDE) { w1 = (eWIDE-x); }
+ 
+ 	  if (y<0)           { offy = -y;  h1 -= offy;  y = 0; }
+ 	  if (y+h1>eHIGH)    { h1 = (eHIGH-y); }
+-	  
+-	  XPutImage(theDisp, tmpPix, theGC, theImage, offx, offy, 
++
++	  XPutImage(theDisp, tmpPix, theGC, theImage, offx, offy,
+ 		    x, y, (u_int) w1, (u_int) h1);
+ 	}
+       }
+@@ -138,9 +139,15 @@
+ 
+     else if (rmode == RM_CSOLID) { }
+ 
++    else if (rmode == RM_UPLEFT) {
++
++      XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
++		(u_int) eWIDE, (u_int) eHIGH);
++    }
++
+     else if (rmode == RM_CWARP) {          /* warp effect */
+       XSetForeground(theDisp, theGC, rootfg);
+-      for (i=0; i<=dispWIDE; i+=8) 
++      for (i=0; i<=dispWIDE; i+=8)
+ 	XDrawLine(theDisp,tmpPix,theGC, i,0, (int) dispWIDE-i,(int) dispHIGH);
+       for (i=0; i<=dispHIGH; i+=8)
+ 	XDrawLine(theDisp,tmpPix,theGC, 0,i, (int) dispWIDE, (int) dispHIGH-i);
+@@ -150,16 +157,16 @@
+       XSetForeground(theDisp, theGC, rootfg);
+       for (i=k=0; i<dispHIGH; i+=20,k++) {
+ 	XDrawLine(theDisp, tmpPix, theGC, 0, i, (int) dispWIDE, i);
+-	for (j=(k&1) * 20 + 10; j<dispWIDE; j+=40) 
++	for (j=(k&1) * 20 + 10; j<dispWIDE; j+=40)
+ 	  XDrawLine(theDisp, tmpPix, theGC, j,i,j,i+20);
+       }
+     }
+ 
+ 
+     /* draw the image centered on top of the background */
+-    if (rmode != RM_CENTILE) 
+-      XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 
+-		((int) dispWIDE-eWIDE)/2, ((int) dispHIGH-eHIGH)/2, 
++    if ((rmode != RM_CENTILE) && (rmode != RM_UPLEFT))
++      XPutImage(theDisp, tmpPix, theGC, theImage, 0,0,
++		((int) dispWIDE-eWIDE)/2, ((int) dispHIGH-eHIGH)/2,
+ 		(u_int) eWIDE, (u_int) eHIGH);
+   }
+ 
+@@ -172,7 +179,7 @@
+     if (dispWIDE == eWIDE) {
+       /* horizontal center line */
+       int y, ay;
+-      
++
+       y = eHIGH - ((dispHIGH/2)%eHIGH); /* Starting point in picture to copy */
+       ay = 0;    /* Vertical anchor point */
+       while (ay < dispHIGH) {
+@@ -189,7 +196,7 @@
+     else if (dispHIGH == eHIGH) {
+       /* vertical centerline */
+       int x, ax;
+-      
++
+       x = eWIDE - ((dispWIDE/2)%eWIDE); /* Starting point in picture to copy */
+       ax = 0;    /* Horizontal anchor point */
+       while (ax < dispWIDE) {
+@@ -206,10 +213,10 @@
+     else {
+       /* vertical and horizontal centerlines */
+       int x,y, ax,ay;
+-      
++
+       y = eHIGH - ((dispHIGH/2)%eHIGH); /* Starting point in picture to copy */
+       ay = 0;    /* Vertical anchor point */
+-      
++
+       while (ay < dispHIGH) {
+ 	x = eWIDE - ((dispWIDE/2)%eWIDE);/* Starting point in picture to cpy */
+ 	ax = 0;    /* Horizontal anchor point */
+@@ -276,8 +283,8 @@
+     gc_init.foreground = BlackPixel(theDisp, theScreen);
+     gc_init.background = WhitePixel(theDisp, theScreen);
+     gc = XCreateGC(theDisp, vrootW, GCForeground|GCBackground, &gc_init);
+-    pix = XCreatePixmap(theDisp, vrootW, root_weave_width, 
+-			root_weave_height, 
++    pix = XCreatePixmap(theDisp, vrootW, root_weave_width,
++			root_weave_height,
+ 			(unsigned int) DefaultDepth(theDisp, theScreen));
+ 
+     XCopyPlane(theDisp, bitmap, pix, gc, 0,0, root_weave_width,
+@@ -333,8 +340,8 @@
+   prop = XInternAtom(theDisp, "_XSETROOT_ID", True);
+   if (prop == None) return;    /* no old pixmap to kill */
+ 
+-  if (XGetWindowProperty(theDisp, vrootW, prop, 0L, 1L, True, 
+-			 AnyPropertyType, &type, &format, &length, 
++  if (XGetWindowProperty(theDisp, vrootW, prop, 0L, 1L, True,
++			 AnyPropertyType, &type, &format, &length,
+ 			 &after, &data) == Success) {
+ 
+     if (type==XA_PIXMAP && format==32 && length==1 && after==0 && data) {
+@@ -348,4 +355,4 @@
+ 
+ 
+ 
+-    
++
+diff -ru xv-3.10a/xvscrl.c xv-3.10a-enhancements/xvscrl.c
+--- xv-3.10a/xvscrl.c	1994-12-22 14:34:41.000000000 -0800
++++ xv-3.10a-enhancements/xvscrl.c	2004-05-16 18:07:56.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * xvscrl.c - Scroll Bar handling functions
+  *
+  * callable functions:
+@@ -6,7 +6,7 @@
+  *   SCCreate()   -  creates the Scroll Bar window.
+  *   SCChange()   -  resize/repositions the Scroll Bar window.
+  *   SCSetRange() -  sets min/max/current values of control
+- *   SCSetVal()   -  sets value of control 
++ *   SCSetVal()   -  sets value of control
+  *   SCRedraw()   -  redraws scroll bar
+  *   SCTrack()    -  called when clicked.  Operates control 'til mouseup
+  */
+@@ -50,7 +50,7 @@
+ 
+ 
+ /***************************************************/
+-void SCCreate(sp, parent, x, y, vert, len, minv, maxv, curv, page, 
++void SCCreate(sp, parent, x, y, vert, len, minv, maxv, curv, page,
+ 	          fg, bg, hi, lo, func)
+ SCRL         *sp;
+ Window        parent;
+@@ -71,7 +71,7 @@
+     downhPix = MakePix1(parent, downh_bits,  downh_width,  downh_height);
+     uph1Pix  = MakePix1(parent, uph1_bits,   uph1_width,   uph1_height);
+     downh1Pix= MakePix1(parent, downh1_bits, downh1_width, downh1_height);
+-    
++
+     sgray    = XCreatePixmapFromBitmapData(theDisp, parent,
+ 		(char *) scrlgray_bits, scrlgray_width, scrlgray_height,
+ 					   fg,bg,dispDEEP);
+@@ -124,7 +124,7 @@
+   sp->len  = len;
+   sp->uplit = sp->dnlit = 0;
+ 
+-  if (vert) XMoveResizeWindow(theDisp, sp->win, x,y, 
++  if (vert) XMoveResizeWindow(theDisp, sp->win, x,y,
+ 			      (u_int) sp->tsize,(u_int) len);
+   else      XMoveResizeWindow(theDisp, sp->win, x,y,
+ 			      (u_int) len, (u_int) sp->tsize);
+@@ -144,7 +144,7 @@
+   if (maxv<minv) maxv=minv;
+   sp->min = minv;    sp->max = maxv;    sp->page = page;
+   sp->active =  (minv < maxv);
+-  
++
+   /* adjust scroll bar background */
+   if (sp->active) {
+     if (ctrlColor) XSetWindowBackground(theDisp, sp->win, sp->lo);
+@@ -174,7 +174,7 @@
+ 
+   sp->val = curv;
+ 
+-  if (sp->active) 
++  if (sp->active)
+     sp->tpos = sp->tmin + ((sp->tmax - sp->tmin)*(curv - sp->min))
+                / (sp->max - sp->min);
+ 
+@@ -194,20 +194,20 @@
+   XSetBackground(theDisp, theGC, sp->bg);
+ 
+   XClearWindow(theDisp, sp->win);
+-  
++
+   drawArrow(sp,UPLINE);      /* draw up/down arrows */
+   drawArrow(sp,DNLINE);
+ 
+   XSetForeground(theDisp, theGC, sp->fg);
+ 
+-  if (sp->vert) {    
++  if (sp->vert) {
+     XDrawLine(theDisp, sp->win, theGC, 0, sp->tsize, sp->tsize, sp->tsize);
+-    XDrawLine(theDisp, sp->win, theGC, 0, sp->len-sp->tsize-1, 
++    XDrawLine(theDisp, sp->win, theGC, 0, sp->len-sp->tsize-1,
+ 	      sp->tsize, sp->len-sp->tsize-1);
+   }
+   else {                       /* horizontal version */
+     XDrawLine(theDisp, sp->win, theGC, sp->tsize, 0, sp->tsize, sp->tsize);
+-    XDrawLine(theDisp, sp->win, theGC, sp->len - sp->tsize-1, 0, 
++    XDrawLine(theDisp, sp->win, theGC, sp->len - sp->tsize-1, 0,
+ 	      sp->len - sp->tsize-1, sp->tsize);
+   }
+ 
+@@ -225,7 +225,7 @@
+ 
+   if (arr == UPLINE) {
+     XSetForeground(theDisp, theGC, sp->bg);
+-    XFillRectangle(theDisp, sp->win, theGC, 0, 0, 
++    XFillRectangle(theDisp, sp->win, theGC, 0, 0,
+ 		   (u_int) sp->tsize, (u_int) sp->tsize);
+ 
+     if (sp->vert) butpix = (sp->uplit) ? up1Pix  : upPix;
+@@ -235,14 +235,14 @@
+     XSetBackground(theDisp, theGC, sp->bg);
+     XCopyPlane(theDisp, butpix, sp->win, theGC, 0, 0, up_width,up_height,
+ 	       3,3, 1L);
+-    Draw3dRect(sp->win, 0,0, (u_int) sp->tsize-1, (u_int) sp->tsize-1, 
++    Draw3dRect(sp->win, 0,0, (u_int) sp->tsize-1, (u_int) sp->tsize-1,
+ 	       (sp->uplit) ? R3D_IN : R3D_OUT, 2, sp->hi, sp->lo, sp->bg);
+   }
+ 
+   else if (arr == DNLINE) {
+     if (sp->vert) {
+       XSetForeground(theDisp, theGC, sp->bg);
+-      XFillRectangle(theDisp, sp->win, theGC, 0, sp->len - sp->tsize, 
++      XFillRectangle(theDisp, sp->win, theGC, 0, sp->len - sp->tsize,
+ 		     (u_int) sp->tsize, (u_int) sp->tsize);
+       butpix = (sp->dnlit) ? down1Pix : downPix;
+ 
+@@ -251,8 +251,8 @@
+       XCopyPlane(theDisp, butpix, sp->win, theGC, 0, 0, up_width,up_height,
+ 		 3, sp->len - 3 - up_height, 1L);
+ 
+-      Draw3dRect(sp->win, 0, sp->len - sp->tsize, 
+-		 (u_int) sp->tsize-1, (u_int) sp->tsize-1, 
++      Draw3dRect(sp->win, 0, sp->len - sp->tsize,
++		 (u_int) sp->tsize-1, (u_int) sp->tsize-1,
+ 		 (sp->dnlit) ? R3D_IN : R3D_OUT, 2, sp->hi, sp->lo, sp->bg);
+     }
+ 
+@@ -267,8 +267,8 @@
+       XCopyPlane(theDisp, butpix, sp->win, theGC, 0, 0, up_width,up_height,
+ 		 sp->len - 3 - up_width, 3, 1L);
+ 
+-      Draw3dRect(sp->win, sp->len - sp->tsize, 0, 
+-		 (u_int) sp->tsize-1, (u_int) sp->tsize-1, 
++      Draw3dRect(sp->win, sp->len - sp->tsize, 0,
++		 (u_int) sp->tsize-1, (u_int) sp->tsize-1,
+ 		 (sp->dnlit) ? R3D_IN : R3D_OUT, 2, sp->hi, sp->lo, sp->bg);
+     }
+   }
+@@ -283,17 +283,17 @@
+ {
+   if (sp->vert) {
+     /* clear out thumb area with background color */
+-    XClearArea(theDisp, sp->win, 0, sp->tsize+1, (u_int) sp->tsize, 
++    XClearArea(theDisp, sp->win, 0, sp->tsize+1, (u_int) sp->tsize,
+ 	       (u_int) ((sp->len-sp->tsize-1)-(sp->tsize+1)), False);
+ 
+     if (sp->active) {  /* a thumb is necessary */
+ 
+       XSetForeground(theDisp, theGC, sp->bg);
+-      XFillRectangle(theDisp, sp->win, theGC, 1, sp->tpos+1, 
++      XFillRectangle(theDisp, sp->win, theGC, 1, sp->tpos+1,
+ 		     (u_int) (sp->tsize-2), (u_int) (sp->tsize-2));
+ 
+       XSetForeground(theDisp, theGC, sp->fg);
+-      XDrawRectangle(theDisp, sp->win, theGC, 0, sp->tpos, 
++      XDrawRectangle(theDisp, sp->win, theGC, 0, sp->tpos,
+ 		     (u_int) (sp->tsize-1), (u_int) (sp->tsize-1));
+ 
+       XDrawLine(theDisp, sp->win, theGC, 9-3, sp->tpos+6, 9+3, sp->tpos+6);
+@@ -301,7 +301,7 @@
+       XDrawLine(theDisp, sp->win, theGC, 9-3, sp->tpos+10,9+3, sp->tpos+10);
+       XDrawLine(theDisp, sp->win, theGC, 9-3, sp->tpos+12,9+3, sp->tpos+12);
+ 
+-      Draw3dRect(sp->win, 1, sp->tpos+1, 
++      Draw3dRect(sp->win, 1, sp->tpos+1,
+ 		 (u_int) sp->tsize-3, (u_int) sp->tsize-3, R3D_OUT,2,
+ 		 sp->hi, sp->lo, sp->bg);
+     }
+@@ -309,17 +309,17 @@
+ 
+   else {   /* horizontal */
+     /* clear out thumb area with background color */
+-    XClearArea(theDisp, sp->win, sp->tsize+1, 0, 
+-	       (u_int) ((sp->len-sp->tsize-1)-(sp->tsize+1)), 
++    XClearArea(theDisp, sp->win, sp->tsize+1, 0,
++	       (u_int) ((sp->len-sp->tsize-1)-(sp->tsize+1)),
+ 	       (u_int) sp->tsize, False);
+ 
+     if (sp->active) {  /* a thumb is necessary */
+       XSetForeground(theDisp, theGC, sp->bg);
+-      XFillRectangle(theDisp, sp->win, theGC, sp->tpos+1, 1, 
++      XFillRectangle(theDisp, sp->win, theGC, sp->tpos+1, 1,
+ 		     (u_int) (sp->tsize-2), (u_int) (sp->tsize-2));
+ 
+       XSetForeground(theDisp, theGC, sp->fg);
+-      XDrawRectangle(theDisp, sp->win, theGC, sp->tpos, 0, 
++      XDrawRectangle(theDisp, sp->win, theGC, sp->tpos, 0,
+ 		     (u_int) (sp->tsize-1), (u_int) (sp->tsize-1));
+ 
+       XDrawLine(theDisp, sp->win, theGC, sp->tpos+6, 9-3, sp->tpos+6, 9+3);
+@@ -327,7 +327,7 @@
+       XDrawLine(theDisp, sp->win, theGC, sp->tpos+10,9-3, sp->tpos+10,9+3);
+       XDrawLine(theDisp, sp->win, theGC, sp->tpos+12,9-3, sp->tpos+12,9+3);
+ 
+-      Draw3dRect(sp->win, sp->tpos+1, 1, 
++      Draw3dRect(sp->win, sp->tpos+1, 1,
+ 		 (u_int) sp->tsize-3, (u_int) sp->tsize-3, R3D_OUT,2,
+ 		 sp->hi, sp->lo, sp->bg);
+     }
+@@ -450,8 +450,8 @@
+     case DNLINE:                     /* arrows */
+       pos = whereInScrl(sp,x,y);
+       if (pos == ipos) {
+-	if (!lit) { 
+-	  lit = 1; 
++	if (!lit) {
++	  lit = 1;
+ 	  if (ipos == UPLINE) { sp->uplit = 1;  drawArrow(sp,UPLINE); }
+ 	                 else { sp->dnlit = 1;  drawArrow(sp,DNLINE); }
+ 	}
+@@ -467,16 +467,16 @@
+ 	  }
+ 	}
+       }
+-      
++
+       else {
+-	if (lit) { 
+-	  lit = 0; 
++	if (lit) {
++	  lit = 0;
+ 	  if (ipos == UPLINE) { sp->uplit = 0;  drawArrow(sp,UPLINE); }
+ 	                 else { sp->dnlit = 0;  drawArrow(sp,DNLINE); }
+ 	}
+       }
+       break;
+-      
++
+     }
+   }
+ 
+diff -ru xv-3.10a/xvsmooth.c xv-3.10a-enhancements/xvsmooth.c
+--- xv-3.10a/xvsmooth.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvsmooth.c	2004-05-16 18:07:59.000000000 -0700
+@@ -4,11 +4,11 @@
+  *  Contains:
+  *            byte *SmoothResize(src8, swide, shigh, dwide, dhigh,
+  *                               rmap, gmap, bmap, rdmap, gdmap, bdmap, maplen)
+- *            byte *Smooth24(pic824, is24, swide, shigh, dwide, dhigh, 
++ *            byte *Smooth24(pic824, is24, swide, shigh, dwide, dhigh,
+  *                               rmap, gmap, bmap)
+- *            byte *DoColorDither(pic24, pic8, w, h, rmap,gmap,bmap, 
++ *            byte *DoColorDither(pic24, pic8, w, h, rmap,gmap,bmap,
+  *                                rdisp, gdisp, bdisp, maplen)
+- *            byte *Do332ColorDither(pic24, pic8, w, h, rmap,gmap,bmap, 
++ *            byte *Do332ColorDither(pic24, pic8, w, h, rmap,gmap,bmap,
+  *                                rdisp, gdisp, bdisp, maplen)
+  */
+ 
+@@ -18,21 +18,21 @@
+ 
+ static int smoothX  PARM((byte *, byte *, int, int, int, int, int,
+ 			  byte *, byte *, byte *));
+-static int smoothY  PARM((byte *, byte *, int, int, int, int, int, 
++static int smoothY  PARM((byte *, byte *, int, int, int, int, int,
+ 			  byte *, byte *, byte *));
+ static int smoothXY PARM((byte *, byte *, int, int, int, int, int,
+ 			  byte *, byte *, byte *));
+ 
+ 
+ /***************************************************/
+-byte *SmoothResize(srcpic8, swide, shigh, dwide, dhigh, 
++byte *SmoothResize(srcpic8, swide, shigh, dwide, dhigh,
+ 		   rmap, gmap, bmap, rdmap, gdmap, bdmap, maplen)
+      byte *srcpic8, *rmap, *gmap, *bmap, *rdmap, *gdmap, *bdmap;
+      int   swide, shigh, dwide, dhigh, maplen;
+ {
+-  /* generic interface to Smooth and ColorDither code.  
+-     given an 8-bit-per, swide * shigh image with colormap rmap,gmap,bmap, 
+-     will generate a new 8-bit-per, dwide * dhigh image, which is dithered 
++  /* generic interface to Smooth and ColorDither code.
++     given an 8-bit-per, swide * shigh image with colormap rmap,gmap,bmap,
++     will generate a new 8-bit-per, dwide * dhigh image, which is dithered
+      using colors found in rdmap, gdmap, bdmap arrays */
+ 
+   /* returns ptr to a dwide*dhigh array of bytes, or NULL on failure */
+@@ -50,7 +50,7 @@
+ 
+   return (byte *) NULL;
+ }
+-    
++
+ 
+ 
+ /***************************************************/
+@@ -83,29 +83,29 @@
+   bperpix = (is24) ? 3 : 1;
+ 
+   /* decide which smoothing routine to use based on type of expansion */
+-  if      (dwide <  swide && dhigh <  shigh) 
++  if      (dwide <  swide && dhigh <  shigh)
+     retval = smoothXY(pic24, pic824, is24, swide, shigh, dwide, dhigh,
+ 		      rmap, gmap, bmap);
+ 
+-  else if (dwide <  swide && dhigh >= shigh) 
++  else if (dwide <  swide && dhigh >= shigh)
+     retval = smoothX (pic24, pic824, is24, swide, shigh, dwide, dhigh,
+ 		      rmap, gmap, bmap);
+ 
+-  else if (dwide >= swide && dhigh <  shigh) 
++  else if (dwide >= swide && dhigh <  shigh)
+     retval = smoothY (pic24, pic824, is24, swide, shigh, dwide, dhigh,
+ 		      rmap, gmap, bmap);
+ 
+   else {
+     /* dwide >= swide && dhigh >= shigh */
+ 
+-    /* cx,cy = original pixel in pic824.  px,py = relative position 
+-       of pixel ex,ey inside of cx,cy as percentages +-50%, +-50%.  
++    /* cx,cy = original pixel in pic824.  px,py = relative position
++       of pixel ex,ey inside of cx,cy as percentages +-50%, +-50%.
+        0,0 = middle of pixel */
+ 
+     /* we can save a lot of time by precomputing cxtab[] and pxtab[], both
+        dwide arrays of ints that contain values for the equations:
+          cx = (ex * swide) / dwide;
+-         px = ((ex * swide * 100) / dwide) - (cx * 100) - 50; */
++         px = ((ex * swide * 128) / dwide) - (cx * 128) - 64; */
+ 
+     cxtab = (int *) malloc(dwide * sizeof(int));
+     if (!cxtab) { free(pic24);  return NULL; }
+@@ -115,17 +115,17 @@
+ 
+     for (ex=0; ex<dwide; ex++) {
+       cxtab[ex] = (ex * swide) / dwide;
+-      pxtab[ex] = (((ex * swide)* 100) / dwide) 
+-	           - (cxtab[ex] * 100) - 50;
++      pxtab[ex] = (((ex * swide)* 128) / dwide)
++	           - (cxtab[ex] * 128) - 64;
+     }
+-    
++
+     for (ey=0; ey<dhigh; ey++) {
+       byte *pptr, rA, gA, bA, rB, gB, bB, rC, gC, bC, rD, gD, bD;
+ 
+       ProgressMeter(0, (dhigh)-1, ey, "Smooth");
+ 
+       cy = (ey * shigh) / dhigh;
+-      py = (((ey * shigh) * 100) / dhigh) - (cy * 100) - 50;
++      py = (((ey * shigh) * 128) / dhigh) - (cy * 128) - 64;
+       if (py<0) { y1 = cy-1;  if (y1<0) y1=0; }
+            else { y1 = cy+1;  if (y1>shigh-1) y1=shigh-1; }
+ 
+@@ -162,7 +162,7 @@
+ 	  cC = pic824[cyOff + x1];   /* left/right center pixel */
+ 	  cD = pic824[cyOff + cx];   /* center pixel */
+ 	}
+-	 
++
+ 	/* quick check */
+ 	if (!is24 && cA == cB && cB == cC && cC == cD) {
+ 	  /* set this pixel to the same color as in pic8 */
+@@ -172,36 +172,36 @@
+ 	else {
+ 	  /* compute weighting factors */
+ 	  apx = abs(px);  apy = abs(py);
+-	  pA = (apx * apy) / 100;
+-	  pB = (apy * (100 - apx)) / 100;
+-	  pC = (apx * (100 - apy)) / 100;
+-	  pD = 100 - (pA + pB + pC);
++	  pA = (apx * apy) >> 7; /* div 128 */
++	  pB = (apy * (128 - apx)) >> 7; /* div 128 */
++	  pC = (apx * (128 - apy)) >> 7; /* div 128 */
++	  pD = 128 - (pA + pB + pC);
+ 
+ 	  if (is24) {
+-	    *pp++ = ((int) (pA * rA))/100 + ((int) (pB * rB))/100 + 
+-	            ((int) (pC * rC))/100 + ((int) (pD * rD))/100;
++	    *pp++ = (((int) (pA * rA))>>7) + (((int) (pB * rB))>>7) +
++	            (((int) (pC * rC))>>7) + (((int) (pD * rD))>>7);
+ 
+-	    *pp++ = ((int) (pA * gA))/100 + ((int) (pB * gB))/100 + 
+-	            ((int) (pC * gC))/100 + ((int) (pD * gD))/100;
++	    *pp++ = (((int) (pA * gA))>>7) + (((int) (pB * gB))>>7) +
++	            (((int) (pC * gC))>>7) + (((int) (pD * gD))>>7);
+ 
+-	    *pp++ = ((int) (pA * bA))/100 + ((int) (pB * bB))/100 + 
+-	            ((int) (pC * bC))/100 + ((int) (pD * bD))/100;
++	    *pp++ = (((int) (pA * bA))>>7) + (((int) (pB * bB))>>7) +
++	            (((int) (pC * bC))>>7) + (((int) (pD * bD))>>7);
+ 	  }
+ 	  else {  /* 8-bit pic */
+-	    *pp++ = ((int) (pA * rmap[cA]))/100 + ((int)(pB * rmap[cB]))/100 + 
+-	            ((int) (pC * rmap[cC]))/100 + ((int)(pD * rmap[cD]))/100;
++	    *pp++ = (((int)(pA * rmap[cA]))>>7) + (((int)(pB * rmap[cB]))>>7) +
++	            (((int)(pC * rmap[cC]))>>7) + (((int)(pD * rmap[cD]))>>7);
+ 
+-	    *pp++ = ((int) (pA * gmap[cA]))/100 + ((int)(pB * gmap[cB]))/100 + 
+-	            ((int) (pC * gmap[cC]))/100 + ((int)(pD * gmap[cD]))/100;
++	    *pp++ = (((int)(pA * gmap[cA]))>>7) + (((int)(pB * gmap[cB]))>>7) +
++	            (((int)(pC * gmap[cC]))>>7) + (((int)(pD * gmap[cD]))>>7);
+ 
+-	    *pp++ = ((int)(pA * bmap[cA]))/100 + ((int)(pB * bmap[cB]))/100 + 
+-  	            ((int)(pC * bmap[cC]))/100 + ((int)(pD * bmap[cD]))/100;
++	    *pp++ = (((int)(pA * bmap[cA]))>>7) + (((int)(pB * bmap[cB]))>>7) +
++  	            (((int)(pC * bmap[cC]))>>7) + (((int)(pD * bmap[cD]))>>7);
+ 	  }
+ 	}
+       }
+     }
+ 
+-    free(cxtab);  
++    free(cxtab);
+     free(pxtab);
+     retval = 0;    /* okay */
+   }
+@@ -218,7 +218,7 @@
+ 
+ 
+ /***************************************************/
+-static int smoothX(pic24, pic824, is24, swide, shigh, dwide, dhigh, 
++static int smoothX(pic24, pic824, is24, swide, shigh, dwide, dhigh,
+ 		   rmap, gmap, bmap)
+ byte *pic24, *pic824, *rmap, *gmap, *bmap;
+ int   is24, swide, shigh, dwide, dhigh;
+@@ -253,7 +253,7 @@
+ 
+   bperpix = (is24) ? 3 : 1;
+ 
+-  for (j=0; j<=swide; j++) 
++  for (j=0; j<=swide; j++)
+     pixarr[j] = (j*dwide + (15*swide)/16) / swide;
+ 
+   cptr = pic824;  cptr1 = cptr + swide * bperpix;
+@@ -280,7 +280,7 @@
+ 	lbufG[j] = ((int) ((*cptr++ * pcnt0) + (*cptr1++ * pcnt1))) >> 6;
+ 	lbufB[j] = ((int) ((*cptr++ * pcnt0) + (*cptr1++ * pcnt1))) >> 6;
+       }
+-    } 
++    }
+     else {  /* 8-bit input pic */
+       for (j=0; j<swide; j++, cptr++, cptr1++) {
+ 	lbufR[j] = ((int)((rmap[*cptr]* pcnt0) + (rmap[*cptr1]* pcnt1))) >> 6;
+@@ -314,8 +314,8 @@
+   return 0;
+ }
+ 
+-	
+-      
++
++
+ 
+ 
+ 
+@@ -405,7 +405,7 @@
+ 	lbufB[j] += ((int)((bmap[*cptr]*pct0[j])+(bmap[*cptr1]*pct1[j]))) >> 6;
+       }
+     }
+-   
++
+     linecnt++;
+   }
+ 
+@@ -421,13 +421,13 @@
+   return retval;
+ }
+ 
+-	
+-      
++
++
+ 
+ 
+ 
+ /***************************************************/
+-static int smoothXY(pic24, pic824, is24, swide, shigh, dwide, dhigh, 
++static int smoothXY(pic24, pic824, is24, swide, shigh, dwide, dhigh,
+ 		    rmap, gmap, bmap)
+ byte *pic24, *pic824, *rmap, *gmap, *bmap;
+ int   is24, swide, shigh, dwide, dhigh;
+@@ -462,7 +462,7 @@
+ 
+   bperpix = (is24) ? 3 : 1;
+ 
+-  for (j=0; j<=swide; j++) 
++  for (j=0; j<=swide; j++)
+     pixarr[j] = (j*dwide + (15*swide)/16) / swide;
+ 
+   lastline = linecnt = pixR = pixG = pixB = 0;
+@@ -526,20 +526,20 @@
+   return 0;
+ }
+ 
+-	
+-      
++
++
+ 
+ /********************************************/
+-byte *DoColorDither(pic24, pic8, w, h, rmap, gmap, bmap, 
++byte *DoColorDither(pic24, pic8, w, h, rmap, gmap, bmap,
+ 		    rdisp, gdisp, bdisp, maplen)
+      byte *pic24, *pic8, *rmap, *gmap, *bmap, *rdisp, *gdisp, *bdisp;
+      int   w, h, maplen;
+ {
+   /* takes a 24 bit picture, of size w*h, dithers with the colors in
+      rdisp, gdisp, bdisp (which have already been allocated),
+-     and generates an 8-bit w*h image, which it returns.  
++     and generates an 8-bit w*h image, which it returns.
+      ignores input value 'pic8'
+-     returns NULL on error 
++     returns NULL on error
+ 
+      note: the rdisp,gdisp,bdisp arrays should be the 'displayed' colors,
+      not the 'desired' colors
+@@ -547,7 +547,7 @@
+      if pic24 is NULL, uses the passed-in pic8 (an 8-bit image) as
+      the source, and the rmap,gmap,bmap arrays as the desired colors */
+ 
+-  byte *np, *ep, *newpic; 
++  byte *np, *ep, *newpic;
+   short *cache;
+   int r2, g2, b2;
+   int *thisline, *nextline, *thisptr, *nextptr, *tmpptr;
+@@ -558,11 +558,11 @@
+   int fserrmap[512];   /* -255 .. 0 .. +255 */
+ 
+   /* compute somewhat non-linear floyd-steinberg error mapping table */
+-  for (i=j=0; i<=0x40; i++,j++) 
++  for (i=j=0; i<=0x40; i++,j++)
+     { fserrmap[256+i] = j;  fserrmap[256-i] = -j; }
+-  for (     ; i<0x80; i++, j += !(i&1) ? 1 : 0) 
++  for (     ; i<0x80; i++, j += !(i&1) ? 1 : 0)
+     { fserrmap[256+i] = j;  fserrmap[256-i] = -j; }
+-  for (     ; i<=0xff; i++) 
++  for (     ; i<=0xff; i++)
+     { fserrmap[256+i] = j;  fserrmap[256-i] = -j; }
+ 
+ 
+@@ -575,7 +575,7 @@
+   cache  = (short *) calloc((size_t) (2<<14), sizeof(short));
+   thisline = (int *) malloc(pwide3 * sizeof(int));
+   nextline = (int *) malloc(pwide3 * sizeof(int));
+-  if (!cache || !newpic || !thisline || !nextline) { 
++  if (!cache || !newpic || !thisline || !nextline) {
+     if (newpic)   free(newpic);
+     if (cache)    free(cache);
+     if (thisline) free(thisline);
+@@ -624,30 +624,30 @@
+ 
+       r2 = *thisptr++;  g2 = *thisptr++;  b2 = *thisptr++;
+ 
+-      /* map r2,g2,b2 components (could be outside 0..255 range) 
++      /* map r2,g2,b2 components (could be outside 0..255 range)
+ 	 into 0..255 range */
+-      
++
+       if (r2<0 || g2<0 || b2<0) {   /* are there any negatives in RGB? */
+ 	if (r2<g2) { if (r2<b2) k = 0; else k = 2; }
+ 	else { if (g2<b2) k = 1; else k = 2; }
+ 
+ 	switch (k) {
+ 	case 0:  g2 -= r2;  b2 -= r2;  d = (abs(r2) * 3) / 2;    /* RED */
+-	         r2 = 0;  
++	         r2 = 0;
+ 	         g2 = (g2>d) ? g2 - d : 0;
+ 	         b2 = (b2>d) ? b2 - d : 0;
+ 	         break;
+ 
+ 	case 1:  r2 -= g2;  b2 -= g2;  d = (abs(g2) * 3) / 2;    /* GREEN */
+ 	         r2 = (r2>d) ? r2 - d : 0;
+-	         g2 = 0;  
++	         g2 = 0;
+ 	         b2 = (b2>d) ? b2 - d : 0;
+ 	         break;
+ 
+ 	case 2:  r2 -= b2;  g2 -= b2;  d = (abs(b2) * 3) / 2;    /* BLUE */
+ 	         r2 = (r2>d) ? r2 - d : 0;
+ 	         g2 = (g2>d) ? g2 - d : 0;
+-	         b2 = 0;  
++	         b2 = 0;
+ 	         break;
+ 	}
+       }
+@@ -674,7 +674,7 @@
+         mind = 10000;
+ 	for (k=closest=0; k<maplen && mind>7; k++) {
+ 	  d = abs(r2 - rdisp[k])
+-	    + abs(g2 - gdisp[k]) 
++	    + abs(g2 - gdisp[k])
+ 	    + abs(b2 - bdisp[k]);
+ 	  if (d<mind) { mind = d;  closest = k; }
+ 	}
+@@ -703,7 +703,7 @@
+ 	thisptr[1] += (gerr*7)/16;
+ 	thisptr[2] += (berr*7)/16;
+       }
+-      
++
+       if (i!=imax) {	/* do BOTTOM pixel */
+ 	nextptr[0] += (rerr*5)/16;
+ 	nextptr[1] += (gerr*5)/16;
+@@ -735,7 +735,7 @@
+ 
+ 
+ /********************************************/
+-byte *Do332ColorDither(pic24, pic8, w, h, rmap, gmap, bmap, 
++byte *Do332ColorDither(pic24, pic8, w, h, rmap, gmap, bmap,
+ 		    rdisp, gdisp, bdisp, maplen)
+      byte *pic24, *pic8, *rmap, *gmap, *bmap, *rdisp, *gdisp, *bdisp;
+      int   w, h, maplen;
+@@ -744,9 +744,9 @@
+ 
+   /* takes a 24 bit picture, of size w*h, dithers with the colors in
+      rdisp, gdisp, bdisp (which have already been allocated),
+-     and generates an 8-bit w*h image, which it returns.  
++     and generates an 8-bit w*h image, which it returns.
+      ignores input value 'pic8'
+-     returns NULL on error 
++     returns NULL on error
+ 
+      note: the rdisp,gdisp,bdisp arrays should be the 'displayed' colors,
+      not the 'desired' colors
+@@ -754,7 +754,7 @@
+      if pic24 is NULL, uses the passed-in pic8 (an 8-bit image) as
+      the source, and the rmap,gmap,bmap arrays as the desired colors */
+ 
+-  byte *np, *ep, *newpic; 
++  byte *np, *ep, *newpic;
+   int r2, g2, b2;
+   int *thisline, *nextline, *thisptr, *nextptr, *tmpptr;
+   int  i, j, rerr, gerr, berr, pwide3;
+@@ -763,11 +763,11 @@
+   int  fserrmap[512];   /* -255 .. 0 .. +255 */
+ 
+   /* compute somewhat non-linear floyd-steinberg error mapping table */
+-  for (i=j=0; i<=0x40; i++,j++) 
++  for (i=j=0; i<=0x40; i++,j++)
+     { fserrmap[256+i] = j;  fserrmap[256-i] = -j; }
+-  for (     ; i<0x80; i++, j += !(i&1) ? 1 : 0) 
++  for (     ; i<0x80; i++, j += !(i&1) ? 1 : 0)
+     { fserrmap[256+i] = j;  fserrmap[256-i] = -j; }
+-  for (     ; i<=0xff; i++) 
++  for (     ; i<=0xff; i++)
+     { fserrmap[256+i] = j;  fserrmap[256-i] = -j; }
+ 
+ 
+@@ -778,7 +778,7 @@
+   newpic   = (byte *) malloc((size_t) (w * h));
+   thisline = (int *)  malloc(pwide3 * sizeof(int));
+   nextline = (int *)  malloc(pwide3 * sizeof(int));
+-  if (!newpic || !thisline || !nextline) { 
++  if (!newpic || !thisline || !nextline) {
+     if (newpic)   free(newpic);
+     if (thisline) free(thisline);
+     if (nextline) free(nextline);
+@@ -830,7 +830,7 @@
+ 
+ 
+     for (j=0; j<w; j++) {
+-      int k, d, mind, closest, rb,gb,bb;
++      int rb,gb,bb;
+ 
+       r2 = *thisptr++;  g2 = *thisptr++;  b2 = *thisptr++;
+       if (i&1) thisptr -= 6;  /* move left */
+@@ -846,7 +846,7 @@
+       bb = (b2 + 0x20);    /* round 2 bits */
+       RANGE(bb,0,255);
+       bb = bb & 0xc0;
+-      
++
+ 
+       *np = rb | (gb>>3) | (bb>>6);
+ 
+diff -ru xv-3.10a/xvsunras.c xv-3.10a-enhancements/xvsunras.c
+--- xv-3.10a/xvsunras.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvsunras.c	2007-05-13 17:46:42.000000000 -0700
+@@ -39,7 +39,7 @@
+ #define RAS_RLE 0x80
+ 
+ 
+-static int  sunRasError    PARM((char *, char *));
++static int  sunRasError    PARM((const char *, const char *));
+ static int  rle_read       PARM((byte *, int, int, FILE *, int));
+ static void sunRas1to8     PARM((byte *, byte *, int));
+ static void sunRas8to1     PARM((byte *, byte *, int, int));
+@@ -54,10 +54,10 @@
+      PICINFO *pinfo;
+ {
+   FILE	*fp;
+-  int	 linesize,lsize,csize,isize,i,w,h,d;
+-  byte	 *image, *line, *pic8;
++  int	 linesize,lsize,csize,isize,i,w,h,d,npixels,nbytes;
++  byte	 *image, *line;
+   struct rasterfile sunheader;
+-  char   *bname;
++  const char *bname;
+ 
+   bname = BaseName(fname);
+ 
+@@ -85,7 +85,7 @@
+       sunheader.ras_depth != 8 &&
+       sunheader.ras_depth != 24 &&
+       sunheader.ras_depth != 32) {
+-    fprintf (stderr, "Sun rasterfile image has depth %d\n", 
++    fprintf (stderr, "Sun rasterfile image has depth %d\n",
+ 	     sunheader.ras_depth);
+     fprintf (stderr, "Depths supported are 1, 8, 24, and 32\n");
+     fclose(fp);
+@@ -115,26 +115,59 @@
+ 
+   w = sunheader.ras_width;
+   h = sunheader.ras_height;
+-  d = sunheader.ras_depth;
+-  isize = sunheader.ras_length ?
+-	  sunheader.ras_length :
+-	  (w * h * d) / 8;
++  d = sunheader.ras_depth;  /* 1, 8, 24, or 32 (above) */
++  npixels = w * h;
++  if (w <= 0 || h <= 0 || npixels/w != h) {
++    fprintf (stderr, "Sun rasterfile image has invalid dimensions (%dx%d)\n",
++	     w, h);
++    fclose(fp);
++    return 0;
++  }
++  if (d == 1)
++    nbytes = npixels/8;     /* should round up here, but used only for printf */
++  else {
++    nbytes = npixels * (d/8);
++/*
++    [nbytes (isize) used only in printfs; don't really care about overflows]
++    if (nbytes/npixels != (d/8)) {
++      fprintf (stderr, "Sun rasterfile has invalid dimensions (%dx%dx%d)\n",
++	       w, h, d);
++      fclose(fp);
++      return 0;
++    }
++ */
++  }
++  isize = sunheader.ras_length ? sunheader.ras_length : nbytes;
+   csize = (sunheader.ras_maptype == RMT_NONE) ? 0 : sunheader.ras_maplength;
+ 
+ 
+-  /* compute length of the output (xv-format) image */
+-  lsize = w * h;     
+-  if (d == 24 || d == 32) lsize = lsize * 3;
++  /* length of the output (xv-format) image */
++  lsize = npixels;
++  if (d == 24 || d == 32) {
++    lsize *= 3;
++    if (lsize/3 != npixels) {
++      fprintf (stderr, "Sun rasterfile has invalid dimensions (%dx%dx%d)\n",
++	       w, h, d);
++      fclose(fp);
++      return 0;
++    }
++  }
+ 
+ 
+   linesize = w * d;
++  if (linesize/w != d || linesize + 15 < linesize) {
++    fprintf (stderr, "Sun rasterfile has invalid dimensions (%dx%dx%d)\n",
++	     w, h, d);
++    fclose(fp);
++    return 0;
++  }
+   if (linesize % 16) linesize += (16 - (linesize % 16));
+   linesize /= 8;
+ 
+   if (DEBUG) {
+     fprintf(stderr,"%s: LoadSunRas() - loading a %dx%d pic, %d planes\n",
+ 	    cmd, w, h, d);
+-    fprintf (stderr, 
++    fprintf (stderr,
+ 	  "type %d, maptype %d, isize %d, csize %d, lsize %d, linesize %d\n",
+ 	     sunheader.ras_type, sunheader.ras_maptype,
+ 	     isize, csize, lsize, linesize);
+@@ -188,13 +221,13 @@
+     }
+ 
+     switch (d) {
+-    case 1:  sunRas1to8 (image + w * i, line, w);	                
++    case 1:  sunRas1to8 (image + w * i, line, w);
+              break;
+     case 8:  xvbcopy((char *) line, (char *) image + w * i, (size_t) w);
+              break;
+     case 24: xvbcopy((char *) line, (char *) image + w * i * 3, (size_t) w*3);
+              break;
+-      
++
+     case 32:
+       {
+ 	int k;
+@@ -202,7 +235,7 @@
+ 	ip = line;
+ 	op = (byte *) (image + w * i * 3);
+ 	for (k = 0; k<w; k++) {
+-	  *ip++;           /* skip 'alpha' */
++	  ip++;            /* skip 'alpha' */
+ 	  *op++ = *ip++;   /* red   */
+ 	  *op++ = *ip++;   /* green */
+ 	  *op++ = *ip++;   /* blue  */
+@@ -210,9 +243,9 @@
+       }
+     }
+   }
+-  
++
+   free(line);
+-  
++
+   if (DEBUG) fprintf(stderr,"Sun ras: image loaded!\n");
+ 
+ 
+@@ -224,7 +257,7 @@
+   else pinfo->type = PIC8;
+ 
+   pinfo->pic = image;
+-  pinfo->w = w;  
++  pinfo->w = w;
+   pinfo->h = h;
+   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
+   pinfo->frmType = F_SUNRAS;
+@@ -285,7 +318,7 @@
+ 
+ /*****************************/
+ static int sunRasError(fname, st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+@@ -364,10 +397,15 @@
+ 
+   /* special case: if PIC24 and writing GREYSCALE, write 8-bit file */
+   if (ptype == PIC24  && colorstyle == F_GREYSCALE) {
+-    graypic = (byte *) malloc((size_t) w*h);
++    int npixels = w * h;
++    if (w <= 0 || h <= 0 || npixels/w != h) {
++      SetISTR(ISTR_WARNING, "Image is too large (%dx%d)", w, h);
++      return (2);
++    }
++    graypic = (byte *) malloc((size_t) npixels);
+     if (!graypic) FatalError("unable to malloc in WriteSunRas()");
+-    
+-    for (i=0,sp=pic,dp=graypic; i<w*h; i++,sp+=3,dp++) {
++
++    for (i=0,sp=pic,dp=graypic; i<npixels; i++,sp+=3,dp++) {
+       *dp = MONO(sp[0],sp[1],sp[2]);
+     }
+ 
+@@ -379,9 +417,18 @@
+   }
+ 
+ 
+-  if      (ptype==PIC24)    { d = 24;  linesize = w * 3; }
+-  else if (colorstyle != F_BWDITHER) { d = 8;   linesize = w;     }
+-  else { 
++  if (ptype==PIC24) {
++    d = 24;
++    linesize = w * 3;
++    if (linesize/w != 3) {
++      SetISTR(ISTR_WARNING, "Image is too wide (%d)", w);
++      if (graypic) free(graypic);
++      return (2);
++    }
++  } else if (colorstyle != F_BWDITHER) {
++    d = 8;
++    linesize = w;
++  } else {
+     d = 1;
+     linesize = w;
+     if (linesize % 8) linesize += (8 - linesize % 8);
+@@ -391,6 +438,11 @@
+ 
+ 
+   if (linesize % 2) linesize++;
++  if (linesize == 0) {
++    SetISTR(ISTR_WARNING, "Image is too wide (%d)", w);
++    if (graypic) free(graypic);
++    return (2);
++  }
+   line = (byte *) malloc((size_t) linesize);
+   if (!line) {
+     SetISTR(ISTR_WARNING, "Can't allocate memory for save!\n");
+@@ -428,7 +480,7 @@
+   write_sun_long (sunheader.ras_maplength, fp);
+ 
+   /* write the colormap */
+-  if (d == 8)
++  if (d == 8) {
+     if (colorstyle == 1)  /* grayscale */
+       for (color=0; color<3; color++)
+ 	for (i=0; i<numcols; i++)
+@@ -438,6 +490,7 @@
+       fwrite (gmap, sizeof(byte), (size_t) numcols, fp);
+       fwrite (bmap, sizeof(byte), (size_t) numcols, fp);
+     }
++  }
+ 
+ 
+   /* write the image */
+diff -ru xv-3.10a/xvtarga.c xv-3.10a-enhancements/xvtarga.c
+--- xv-3.10a/xvtarga.c	1994-12-22 14:34:55.000000000 -0800
++++ xv-3.10a-enhancements/xvtarga.c	2007-05-13 17:51:18.000000000 -0700
+@@ -17,8 +17,8 @@
+  *   0:
+  *   1: colormap type
+  *   2: image type  (1=colmap RGB, 2=uncomp RGB, 3=uncomp gray)
+- *   3: 
+- *   4: 
++ *   3:
++ *   4:
+  *   5: colormap_length, low byte
+  *   6: colormap_length, high byte
+  *   7: bits per cmap entry     (8, 24, 32)
+@@ -28,7 +28,7 @@
+  *  14: height, low byte
+  *  15: height, high byte
+  *  16: bits per pixel (8, 24)
+- *  17: flags  
++ *  17: flags
+  */
+ 
+ 
+@@ -36,7 +36,7 @@
+ #include "xv.h"
+ 
+ static long filesize;
+-static char *bname;
++static const char *bname;
+ 
+ 
+ /*******************************************/
+@@ -48,7 +48,7 @@
+   /* returns '1' on success */
+ 
+   FILE  *fp;
+-  int    i, row, c, c1, w, h, r, g, b, flags, intlace, topleft, trunc;
++  int    i, row, c, c1, w, h, npixels, bufsize, flags, intlace, topleft, trunc;
+   byte *pic24, *pp;
+ 
+   bname = BaseName(fname);
+@@ -88,7 +88,9 @@
+   c=getc(fp); c1=getc(fp);
+   h = c1*256 + c;
+ 
+-  if (w<1 || h<1) {
++  npixels = w * h;
++  bufsize = 3 * npixels;
++  if (w <= 0 || h <= 0 || npixels/w != h || bufsize/3 != npixels) {
+     fclose(fp);
+     SetISTR(ISTR_WARNING,"%s:  error in Targa header (bad image size)", bname);
+     return 0;
+@@ -115,7 +117,7 @@
+ #endif
+ 
+ 
+-  pic24 = (byte *) calloc((size_t) w*h*3, (size_t) 1);
++  pic24 = (byte *) calloc((size_t) bufsize, (size_t) 1);
+   if (!pic24) FatalError("couldn't malloc 'pic24'");
+ 
+ 
+@@ -134,7 +136,7 @@
+       if      (i < h / 2) row = 2 * i;
+       else                row = 2 * (i - h/2) + 1;
+     }
+-    
++
+     else row = i;              /* no interlace */
+ 
+ 
+@@ -150,7 +152,7 @@
+ 
+ 
+   /* swap R,B values (file is in BGR, pic24 should be in RGB) */
+-  for (i=0, pp=pic24; i<w*h; i++, pp+=3) {
++  for (i=0, pp=pic24; i<npixels; i++, pp+=3) {
+     c = pp[0];  pp[0] = pp[2];  pp[2] = c;
+   }
+ 
+@@ -185,7 +187,7 @@
+ 
+   /* write the header */
+   for (i=0; i<12; i++) putc( (i==2) ? 2 : 0, fp);
+-  
++
+   putc(w&0xff,     fp);
+   putc((w>>8)&0xff,fp);
+   putc(h&0xff,     fp);
+diff -ru xv-3.10a/xvtext.c xv-3.10a-enhancements/xvtext.c
+--- xv-3.10a/xvtext.c	1995-01-13 15:46:28.000000000 -0800
++++ xv-3.10a-enhancements/xvtext.c	2007-05-13 14:25:59.000000000 -0700
+@@ -1,6 +1,6 @@
+ /*
+  *  xvtext.c  -  text file display window routines
+- * 
++ *
+  *  includes:
+  *      void CreateTextWins(geom, cmtgeom);
+  *      void OpenTextView(text, textlen, title, freeonclose);
+@@ -19,9 +19,13 @@
+ #include "copyright.h"
+ 
+ #include "xv.h"
++#ifdef TV_MULTILINGUAL
++#include "xvml.h"
++#endif
+ 
+-
+-#define BUTTW 80
++#define BUTTW1 80
++#define BUTTW2 60
++#define BUTTW3 110
+ #define BUTTH 24
+ 
+ #define TOPMARGIN 30       /* from top of window to top of text window */
+@@ -36,19 +40,36 @@
+ #define TV_ASCII    0
+ #define TV_HEX      1
+ #define TV_CLOSE    2
+-#define TV_NBUTTS   3
+ 
++#define TV_E_NBUTTS 3
++
++#ifdef TV_L10N
++#  define TV_RESCAN   3
++#  define TV_USASCII  4
++#  define TV_JIS      5
++#  define TV_EUCJ     6
++#  define TV_MSCODE   7
++
++#  define TV_J_NBUTTS 8
++#endif
+ 
+ #define TITLELEN 128
+ 
++#ifdef TV_MULTILINGUAL
++struct coding_spec {
++    struct coding_system coding_system;
++    char *(*converter)PARM((char *, int, int *));
++};
++#endif
++
+ /* data needed per text window */
+ typedef struct {  Window win, textW;
+ 		  int    vis, wasvis;
+-		  char  *text;             /* text to be displayed */
++		  const char  *text;       /* text to be displayed */
+ 		  int    freeonclose;      /* free text when closing win */
+ 		  int    textlen;          /* length of text */
+ 		  char   title[TITLELEN];  /* name of file being displayed */
+-		  char **lines;            /* ptr to array of line ptrs */
++		  const char **lines;     /* ptr to array of line ptrs */
+ 		  int    numlines;         /* # of lines in text */
+ 		  int    hexlines;         /* # of lines in HEX mode */
+ 		  int    maxwide;          /* length of longest line (ascii) */
+@@ -57,16 +78,89 @@
+ 		  int    chwide, chhigh;   /* size of textW, in chars */
+ 		  int    hexmode;          /* true if disp Hex, else Ascii */
+ 		  SCRL   vscrl, hscrl;
+-		  BUTT   but[TV_NBUTTS], nopBut;
++#ifdef TV_L10N
++		  int    code;         /* current character code */
++		  BUTT   but[TV_J_NBUTTS], nopBut;
++#else
++		  BUTT   but[TV_E_NBUTTS], nopBut;
++#endif
++#ifdef TV_MULTILINGUAL
++/*		  int    codeset; */
++		  struct coding_spec ccs;	/* current coding_spec */
++		  BUTT   csbut;
++		  char *cv_text;
++		  int cv_len;
++		  struct context *ctx;
++		  struct ml_text *txt;
++		  struct csinfo_t *cs;
++#endif
+ 		} TVINFO;
+ 
+ 
+ static TVINFO   tinfo[MAXTVWIN];
+ static int      hasBeenSized = 0;
+ static int      haveWindows  = 0;
++static int      nbutts;		/* # of buttons */
+ static int      mfwide, mfhigh, mfascent;   /* size of chars in mono font */
+ static int     *event_retP, *event_doneP;   /* used in tvChkEvent() */
+-
++#ifdef TV_MULTILINGUAL
++# define TV_PLAIN          0
++# define TV_ISO_8859_1     1
++# define TV_ISO_2022_JP    2
++# define TV_EUC_JAPAN      3
++# define TV_ISO_2022_INT_1 4
++# define TV_ISO_2022_KR    5
++# define TV_EUC_KOREA      6
++# define TV_ISO_2022_SS2_8 7
++# define TV_ISO_2022_SS2_7 8
++# define TV_SHIFT_JIS      9
++# define TV_NCSS          10
++static char *codeSetNames[TV_NCSS] = {
++    "plain",
++    "iso-8859-1",
++    "iso-2022-jp",
++    "euc-japan",
++    "iso-2022-int-1",
++    "iso-2022-kr",
++    "euc-korea",
++    "iso-2022-ss2-8",
++    "iso-2022-ss2-7",
++    "Shift JIS",
++};
++static struct coding_spec coding_spec[TV_NCSS] = {
++    /* --- G0 ---   --- G1 ---   --- G2 ---   --- G3 ---  GL GR EOL SF LS */
++    /* plain */
++    {{{{ 1,94,'B'}, { 1,94,'B'}, { 1,94,'B'}, { 1,94,'B'}}, 0, 0,  0, 1, 1},
++     NULL},
++    /* iso-8859-1 */
++    {{{{ 1,94,'B'}, { 1,96,'A'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1,  0, 0, 0},
++     NULL},
++    /* iso-2022-jp */
++    {{{{ 1,94,'B'}, {-1,94,'B'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 0,  0, 1, 0},
++     NULL},
++    /* euc-japan */
++    {{{{ 1,94,'B'}, { 2,94,'B'}, { 1,94,'J'}, { 2,94,'D'}}, 0, 1,  0, 1, 0},
++     NULL},
++    /* iso-2022-int-1 */
++    {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1,  0, 1, 1},
++     NULL},
++    /* iso-2022-kr */
++    {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1,  0, 0, 1},
++     NULL},
++    /* euc-korea */
++    {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1,  0, 0, 0},
++     NULL},
++    /* iso-2022-ss2-8 */
++    {{{{ 1,94,'B'}, {-1,94,'C'}, { 0,94,'B'}, {-1,94,'B'}}, 0, 1,  0, 0, 0},
++     NULL},
++    /* iso-2022-ss2-7 */
++    {{{{ 1,94,'B'}, {-1,94,'C'}, { 0,94,'B'}, {-1,94,'B'}}, 0, 1,  0, 1, 0},
++     NULL},
++    /* shift jis */
++    {{{{ 1,94,'B'}, { 2,94,'B'}, { 1,94,'J'}, { 2,94,'D'}}, 0, 1,  1, 1, 0},
++     sjis_to_jis},
++};
++#endif
+ 
+ static void closeText       PARM((TVINFO *));
+ static int  tvChkEvent      PARM((TVINFO *, XEvent *));
+@@ -82,7 +176,15 @@
+ static void textKey         PARM((TVINFO *, int));
+ static void doHexAsciiCmd   PARM((TVINFO *, int));
+ static void computeText     PARM((TVINFO *));
+-
++#ifdef TV_L10N
++static int  selectCodeset         PARM((TVINFO *));
++#endif
++#ifdef TV_MULTILINGUAL
++static void setCodingSpec   PARM((TVINFO *, struct coding_spec *));
++static void createCsWins    PARM((char *));
++static void openCsWin       PARM((TVINFO *));
++static void closeCsWin      PARM((TVINFO *));
++#endif
+ 
+ /* HEXMODE output looks like this:
+ 0x00000000: 00 11 22 33 44 55 66 77 - 88 99 aa bb cc dd ee ff  0123456789abcdef
+@@ -92,19 +194,57 @@
+ 
+ /***************************************************************/
+ void CreateTextWins(geom, cmtgeom)
+-     char *geom, *cmtgeom;
++     const char *geom, *cmtgeom;
+ {
+   int                   i, defwide, defhigh, cmthigh;
+   XSizeHints            hints;
+   XSetWindowAttributes  xswa;
+   TVINFO               *tv;
+-  int                   gx,gy,gw,gh,gset,gx1,gy1;
+-  
++#ifdef TV_MULTILINGUAL
++  int			default_codeset;
++#endif
++
++#ifdef TV_L10N
++  if (!xlocale) {
++#endif
++      mfwide = monofinfo->max_bounds.width;
++      mfhigh = monofinfo->ascent + monofinfo->descent;
++      mfascent = monofinfo->ascent;
++
++      nbutts = TV_E_NBUTTS;	/* # of buttons */
++#ifdef TV_L10N
++  }
++  else {
++      mfwide = monofsetinfo->max_logical_extent.width / 2;	/* shit! */
++      mfhigh = monofsetinfo->max_logical_extent.height + 1;
++      mfascent = mfhigh;
+ 
+-  mfwide = monofinfo->max_bounds.width;
+-  mfhigh = monofinfo->ascent + monofinfo->descent;
+-  mfascent = monofinfo->ascent;
++      nbutts = TV_J_NBUTTS;	/* # of buttons */
++  }
++#endif
+ 
++#ifdef TV_MULTILINGUAL
++  {
++    char *dc = XGetDefault(theDisp, "xv", "codeSet");
++    if (dc == NULL)
++      default_codeset = TV_DEFAULT_CODESET;
++    else {
++      for (i = 0; i < TV_NCSS; i++) {
++	if (strcmp(dc, codeSetNames[i]) == 0)
++	  break;
++      }
++      if (i >= TV_NCSS) {
++        if (strcmp(dc, "iso-2022") == 0)
++	  default_codeset = TV_PLAIN;
++	else {
++	  SetISTR(ISTR_WARNING, "%s: unknown codeset.", dc);
++	  default_codeset = TV_PLAIN;
++	}
++      } else
++	default_codeset = i;
++    }
++  }
++#endif
+   /* compute default size of textview windows.  should be big enough to
+      hold an 80x24 text window */
+ 
+@@ -119,11 +259,19 @@
+   for (i=0; i<MAXTVWIN; i++) {
+     tv = &tinfo[i];
+ 
++#ifdef TV_MULTILINGUAL
++    tv->ctx = ml_create_context(ScreenOfDisplay(theDisp, theScreen));
++    tv->txt = NULL;
++    tv->cv_text = NULL;
++    tv->cv_len = 0;
++    ml_set_charsets(tv->ctx, &coding_spec[TV_PLAIN].coding_system);
++#endif
++
+     tv->win = CreateWindow((i<CMTWIN) ? "xv text viewer" : "xv image comments",
+-			   "XVtextview", 
+-			   (i<CMTWIN) ? geom : cmtgeom, 
+-			   defwide, 
+-			   (i<CMTWIN) ? defhigh : cmthigh, 
++			   "XVtextview",
++			   (i<CMTWIN) ? geom : cmtgeom,
++			   defwide,
++			   (i<CMTWIN) ? defhigh : cmthigh,
+ 			   infofg, infobg, 1);
+     if (!tv->win) FatalError("can't create textview window!");
+ 
+@@ -135,17 +283,17 @@
+ 
+     /* note: everything is sized and positioned in resizeText() */
+ 
+-    tv->textW = XCreateSimpleWindow(theDisp, tv->win, 1,1, 100,100, 
++    tv->textW = XCreateSimpleWindow(theDisp, tv->win, 1,1, 100,100,
+ 				     1,infofg,infobg);
+     if (!tv->textW) FatalError("can't create textview text window!");
+ 
+-    SCCreate(&(tv->vscrl), tv->win, 0,0, 1,100, 0,0,0,0, 
++    SCCreate(&(tv->vscrl), tv->win, 0,0, 1,100, 0,0,0,0,
+ 	     infofg, infobg, hicol, locol, drawTextW);
+ 
+-    SCCreate(&(tv->hscrl), tv->win, 0,0, 0,100, 0,0,0,0, 
++    SCCreate(&(tv->hscrl), tv->win, 0,0, 0,100, 0,0,0,0,
+ 	     infofg, infobg, hicol, locol, drawTextW);
+ 
+-    if (XGetNormalHints(theDisp, tv->win, &hints)) 
++    if (XGetNormalHints(theDisp, tv->win, &hints))
+       hints.flags |= PMinSize;
+     else
+       hints.flags = PMinSize;
+@@ -162,74 +310,115 @@
+ 
+     XSelectInput(theDisp, tv->textW, ExposureMask | ButtonPressMask);
+ 
+-    
+-    BTCreate(&(tv->but[TV_ASCII]), tv->win, 0,0,BUTTW,BUTTH,
++
++    BTCreate(&(tv->but[TV_ASCII]), tv->win, 0,0,BUTTW1,BUTTH,
+ 	     "Ascii",infofg,infobg,hicol,locol);
+-    BTCreate(&(tv->but[TV_HEX]), tv->win, 0,0,BUTTW,BUTTH,
++    BTCreate(&(tv->but[TV_HEX]), tv->win, 0,0,BUTTW1,BUTTH,
+ 	     "Hex",infofg,infobg,hicol,locol);
+-    BTCreate(&(tv->but[TV_CLOSE]), tv->win, 0,0,BUTTW,BUTTH,
++    BTCreate(&(tv->but[TV_CLOSE]), tv->win, 0,0,BUTTW1,BUTTH,
+ 	     "Close",infofg,infobg,hicol,locol);
+ 
++#ifdef TV_L10N
++    if (xlocale) {
++	BTCreate(&(tv->but[TV_RESCAN]), tv->win, 0,0,BUTTW2,BUTTH,
++		 "RESCAN",infofg,infobg,hicol,locol);
++	BTCreate(&(tv->but[TV_USASCII]), tv->win, 0,0,BUTTW2,BUTTH,
++		 "ASCII",infofg,infobg,hicol,locol);
++	BTCreate(&(tv->but[TV_JIS]), tv->win, 0,0,BUTTW2,BUTTH,
++		 "JIS",infofg,infobg,hicol,locol);
++	BTCreate(&(tv->but[TV_EUCJ]), tv->win, 0,0,BUTTW2,BUTTH,
++		 "EUC-j",infofg,infobg,hicol,locol);
++	BTCreate(&(tv->but[TV_MSCODE]), tv->win, 0,0,BUTTW2,BUTTH,
++		 "MS Kanji",infofg,infobg,hicol,locol);
++    }
++#endif
++
+     BTCreate(&(tv->nopBut), tv->win, 0,0, (u_int) tv->vscrl.tsize+1,
+ 	     (u_int) tv->vscrl.tsize+1, "", infofg, infobg, hicol, locol);
+     tv->nopBut.active = 0;
+ 
+     XMapSubwindows(theDisp, tv->win);
+ 
++#ifdef TV_MULTILINGUAL
++    BTCreate(&tv->csbut, tv->win, 0, 0, BUTTW1, BUTTH, "Code Sets",
++	     infofg, infobg, hicol, locol);
++#endif
++
+     tv->text = (char *) NULL;
+     tv->textlen = 0;
+     tv->title[0] = '\0';
++#ifdef TV_L10N
++    tv->code = (xlocale ? LOCALE_DEFAULT : 0);
++#endif
++#ifdef TV_MULTILINGUAL
++    tv->ccs = coding_spec[default_codeset];
++#endif
+   }
+-
++#ifdef TV_MULTILINGUAL
++  get_monofont_size(&mfwide, &mfhigh);
++  /* recalculate sizes. */
++  defwide = 80 * mfwide + 2*LRMARGINS + 8 + 20;   /* -ish */
++  defhigh = 24 * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20;   /* ish */
++  cmthigh = 6  * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20;   /* ish */
++#endif
+ 
+   for (i=0; i<MAXTVWIN; i++) {
+     resizeText(&tinfo[i], defwide, (i<CMTWIN) ? defhigh : cmthigh);
+ 
+-    XSelectInput(theDisp, tinfo[i].win, ExposureMask | ButtonPressMask | 
++    XSelectInput(theDisp, tinfo[i].win, ExposureMask | ButtonPressMask |
+ 		 KeyPressMask | StructureNotifyMask);
+   }
+ 
+   hasBeenSized = 1;  /* we can now start looking at textview events */
+ 
++#ifdef TV_MULTILINGUAL
++  createCsWins("+100+100");
++#endif
+ }
+ 
+ 
+ /***************************************************************/
+-void TextView(fname)
+-     char *fname;
++int TextView(fname)
++     const char *fname;
+ {
+   /* given a filename, attempts to read in the file and open a textview win */
+ 
+-  int   i;
++  int   filetype;
+   long  textlen;
+   char *text, buf[512], title[128], rfname[MAXPATHLEN+1];
+   char *basefname[128];  /* just current fname, no path */
+   FILE *fp;
++  char filename[MAXPATHLEN+1];
++
++  strncpy(filename, fname, sizeof(filename) - 1);
++#ifdef AUTO_EXPAND
++  Mkvdir(filename);
++  Dirtovd(filename);
++#endif
+ 
+   basefname[0] = '\0';
+-  strcpy(rfname, fname);
++  strncpy(rfname, filename, sizeof(rfname) - 1);
+ 
+   /* see if this file is compressed.  if it is, uncompress it, and view
+      the uncompressed version */
+ 
+-  if (ReadFileType(fname) == RFT_COMPRESS) {
++  filetype = ReadFileType(filename);
++  if ((filetype == RFT_COMPRESS) || (filetype == RFT_BZIP2)) {
+ #ifndef VMS
+-    if (!UncompressFile(fname, rfname)) return;    /* failed to uncompress */
++    if (!UncompressFile(filename, rfname, filetype)) return FALSE;
+ #else
+     /* chop off trailing '.Z' from friendly displayed basefname, if any */
+-    strcpy (basefname, fname);
++    strncpy (basefname, filename, 128 - 1);
+     *rindex (basefname, '.') = '\0';
+-    if (!UncompressFile(basefname, rfname)) return;/* failed to uncompress */
++    if (!UncompressFile(basefname, rfname, filetype)) return FALSE;
+ #endif
+   }
+-      
+-
+ 
+   fp = fopen(rfname, "r");
+   if (!fp) {
+     sprintf(buf,"Couldn't open '%s':  %s", rfname, ERRSTR(errno));
+     ErrPopUp(buf,"\nOh well");
+-    return;
++    return FALSE;
+   }
+ 
+ 
+@@ -241,16 +430,16 @@
+     sprintf(buf, "File '%s' contains no data.  (Zero length file.)", rfname);
+     ErrPopUp(buf, "\nOk");
+     fclose(fp);
+-    return;
++    return FALSE;
+   }
+ 
+-  text = (char *) malloc((size_t) textlen);
++  text = (char *) malloc((size_t) textlen + 1);
+   if (!text) {
+-    sprintf(buf, "Couldn't malloc %ld bytes to read file '%s'", 
++    sprintf(buf, "Couldn't malloc %ld bytes to read file '%s'",
+ 	    textlen, rfname);
+     ErrPopUp(buf, "\nSo what!");
+     fclose(fp);
+-    return;
++    return FALSE;
+   }
+ 
+   if (fread(text, (size_t) 1, (size_t) textlen, fp) != textlen) {
+@@ -258,6 +447,9 @@
+ 	    rfname);
+     ErrPopUp(buf, "\nHmm...");
+   }
++#ifdef TV_MULTILINGUAL
++  text[textlen] = '\0';
++#endif
+ 
+   fclose(fp);
+ 
+@@ -265,27 +457,28 @@
+   OpenTextView(text, (int) textlen, title, 1);
+ 
+   /* note:  text gets freed when window gets closed */
++  return TRUE;
+ }
+ 
+-    
+-    
++
++
+ /***************************************************************/
+ void OpenTextView(text, len, title, freeonclose)
+-     char *text, *title;
+-     int   len,   freeonclose;
++     const char *text, *title;
++     int   len, freeonclose;
+ {
+   /* opens up a textview window */
+ 
+-  int     i, oldone;
+   TVINFO *tv;
+ 
+   tv = &tinfo[0];
+ 
+   /* kill off old text info */
+-  if (tv->freeonclose && tv->text) free(tv->text);
++  if (tv->freeonclose && tv->text) free((void *)tv->text);
+   if (tv->lines) free(tv->lines);
+-  tv->text = (char *) NULL;
+-  tv->lines = (char **) NULL;
++
++  tv->text = (const char *) NULL;
++  tv->lines = (const char **) NULL;
+   tv->numlines = tv->textlen = tv->hexmode = 0;
+ 
+ 
+@@ -293,6 +486,7 @@
+   tv->textlen     = len;
+   tv->freeonclose = freeonclose;
+   strncpy(tv->title, title, (size_t) TITLELEN-1);
++  tv->title[TITLELEN-1] = '\0';
+ 
+   computeText(tv);      /* compute # lines and linestarts array */
+ 
+@@ -316,7 +510,6 @@
+ {
+   /* opens up the reserved 'comment' textview window */
+ 
+-  int     i;
+   TVINFO *tv;
+ 
+   tv = &tinfo[CMTWIN];
+@@ -351,9 +544,9 @@
+   tv->textlen     = (tv->text) ? strlen(tv->text) : 0;
+   tv->freeonclose = 0;
+ 
+-  if (strlen(fullfname)) 
++  if (strlen(fullfname))
+     sprintf(tv->title, "File: '%s'", BaseName(fullfname));
+-  else 
++  else
+     sprintf(tv->title, "<no file loaded>");
+ 
+   computeText(tv);      /* compute # lines and linestarts array */
+@@ -501,12 +694,16 @@
+   if (i==MAXTEXTWIN) anyTextUp = 0;
+ 
+   /* free all info for this textview window */
+-  if (tv->freeonclose && tv->text)  free(tv->text);
++  if (tv->freeonclose && tv->text)  free((void *)tv->text);
+   if (tv->lines) free(tv->lines);
+ 
+-  tv->text  = (char *) NULL;  
+-  tv->lines = (char **) NULL;
++  tv->text  = (const char *) NULL;
++  tv->lines = (const char **) NULL;
+   tv->numlines = tv->textlen = tv->hexmode = 0;
++
++#ifdef TV_MULTILINGUAL
++  closeCsWin(tv);
++#endif
+ }
+ 
+ 
+@@ -518,7 +715,7 @@
+   /* checks event to see if it's a text-window related thing.  If it
+      is, it eats the event and returns '1', otherwise '0'. */
+ 
+-  int i, rv;
++  int rv;
+ 
+   rv = 1;
+ 
+@@ -560,7 +757,7 @@
+ 	count++;
+       } while (XCheckWindowEvent(theDisp, evt.xexpose.window,
+ 				 ExposureMask, &evt));
+-      
++
+       XClipBox(reg, &rect);  /* bounding box of region */
+       XSetRegion(theDisp, theGC, reg);
+ 
+@@ -570,7 +767,7 @@
+ 	fprintf(stderr,"grouped %d expose events into %d,%d %dx%d rect\n",
+ 		count, rect.x, rect.y, rect.width, rect.height);
+       }
+-      
++
+       if      (e->window == tv->win)   drawTextView(tv);
+       else if (e->window == tv->textW) drawTextW(0, &(tv->vscrl));
+ 
+@@ -584,7 +781,7 @@
+ 
+   else if (xev->type == ButtonPress) {
+     XButtonEvent *e = (XButtonEvent *) xev;
+-    int i,x,y;
++    int x,y;
+     x = e->x;  y = e->y;
+ 
+     if (e->button == Button1) {
+@@ -594,6 +791,40 @@
+       else if (e->window == tv->textW) { }
+       else rv = 0;
+     }
++    else if (e->button == Button4) {   /* note min vs. max, + vs. - */
++      /* scroll regardless of where we are in the text window */
++      if (e->window == tv->win ||
++	 e->window == tv->vscrl.win ||
++	 e->window == tv->hscrl.win ||
++	 e->window == tv->textW)
++      {
++	SCRL *sp=&(tv->vscrl);
++	int  halfpage=sp->page/2;
++
++	if (sp->val > sp->min+halfpage)
++	  SCSetVal(sp,sp->val-halfpage);
++	else
++	  SCSetVal(sp,sp->min);
++      }
++      else rv = 0;
++    }
++    else if (e->button == Button5) {   /* note max vs. min, - vs. + */
++      /* scroll regardless of where we are in the text window */
++      if (e->window == tv->win ||
++	 e->window == tv->vscrl.win ||
++	 e->window == tv->hscrl.win ||
++	 e->window == tv->textW)
++      {
++	SCRL *sp=&(tv->vscrl);
++	int  halfpage=sp->page/2;
++
++	if (sp->val < sp->max-halfpage)
++	  SCSetVal(sp,sp->val+halfpage);
++	else
++	  SCSetVal(sp,sp->max);
++      }
++      else rv = 0;
++    }
+     else rv = 0;
+   }
+ 
+@@ -615,7 +846,7 @@
+ 
+       if (tv->wide != e->width || tv->high != e->height) {
+ 	if (DEBUG) fprintf(stderr,"Forcing a redraw!  (from configure)\n");
+-	XClearArea(theDisp, tv->win, 0, 0, 
++	XClearArea(theDisp, tv->win, 0, 0,
+ 		   (u_int) e->width, (u_int) e->height, True);
+ 	resizeText(tv, e->width, e->height);
+       }
+@@ -633,10 +864,12 @@
+      TVINFO *tv;
+      int     w,h;
+ {
+-  int        i, maxw, maxh, hmax, hpage, vmax, vpage;
++  int        i, maxw, maxh;
+   XSizeHints hints;
+ 
++#ifndef TV_MULTILINGUAL
+   if (tv->wide == w && tv->high == h) return;  /* no change in size */
++#endif
+ 
+   if (XGetNormalHints(theDisp, tv->win, &hints)) {
+     hints.width  = w;
+@@ -657,13 +890,26 @@
+   tv->twWide = tv->chwide * mfwide + 6;
+   tv->twHigh = tv->chhigh * mfhigh + 6;
+ 
+-  XMoveResizeWindow(theDisp, tv->textW, LRMARGINS, TOPMARGIN, 
++  XMoveResizeWindow(theDisp, tv->textW, LRMARGINS, TOPMARGIN,
+ 		    (u_int) tv->twWide, (u_int) tv->twHigh);
+ 
+-  for (i=0; i<TV_NBUTTS; i++) {
+-    tv->but[i].x = tv->wide - (TV_NBUTTS-i) * (BUTTW+5);
++  for (i=0; i<TV_E_NBUTTS; i++) {
++    tv->but[i].x = tv->wide - (TV_E_NBUTTS-i) * (BUTTW1+5);
+     tv->but[i].y = tv->high - BUTTH - 5;
+   }
++#ifdef TV_MULTILINGUAL
++  tv->csbut.x = 5;
++  tv->csbut.y = tv->high - BUTTH - 5;
++#endif
++
++#ifdef TV_L10N
++  if (xlocale) {
++    for (; i<TV_J_NBUTTS; i++) {
++      tv->but[i].x = 5 + (i-TV_E_NBUTTS) * (BUTTW2+5);
++      tv->but[i].y = tv->high - BUTTH - 5;
++    }
++  }
++#endif
+ 
+   computeScrlVals(tv);
+ 
+@@ -692,8 +938,8 @@
+   hpag = tv->chwide / 4;
+   vpag = tv->chhigh - 1;
+ 
+-  
+-  SCChange(&tv->vscrl, LRMARGINS + tv->twWide+1, TOPMARGIN, 
++
++  SCChange(&tv->vscrl, LRMARGINS + tv->twWide+1, TOPMARGIN,
+ 	   1, tv->twHigh, 0, vmax, tv->vscrl.val, vpag);
+ 
+   SCChange(&tv->hscrl, LRMARGINS, TOPMARGIN + tv->twHigh + 1,
+@@ -714,6 +960,29 @@
+   case TV_CLOSE:   if (tv == &tinfo[CMTWIN]) CloseCommentText();
+                    else closeText(tv);
+                    break;
++
++#ifdef TV_L10N
++  case TV_RESCAN:
++    tv->code = selectCodeset(tv);
++    drawTextW(0, &tv->vscrl);
++    break;
++  case TV_USASCII:
++    tv->code = LOCALE_USASCII;
++    drawTextW(0, &tv->vscrl);
++    break;
++  case TV_JIS:
++    tv->code = LOCALE_JIS;
++    drawTextW(0, &tv->vscrl);
++    break;
++  case TV_EUCJ:
++    tv->code = LOCALE_EUCJ;
++    drawTextW(0, &tv->vscrl);
++    break;
++  case TV_MSCODE:
++    tv->code = LOCALE_MSCODE;
++    drawTextW(0, &tv->vscrl);
++    break;
++#endif	/* TV_L10N */
+   }
+ }
+ 
+@@ -731,11 +1000,11 @@
+     y = 5;
+ 
+     XSetForeground(theDisp, theGC, infobg);
+-    XFillRectangle(theDisp, tv->win, theGC, 5+1, y+1, 
++    XFillRectangle(theDisp, tv->win, theGC, 5+1, y+1,
+ 		   (u_int) StringWidth(tv->title)+6, (u_int) CHIGH+4);
+ 
+     XSetForeground(theDisp, theGC, infofg);
+-    XDrawRectangle(theDisp, tv->win, theGC, 5, y, 
++    XDrawRectangle(theDisp, tv->win, theGC, 5, y,
+ 		   (u_int) StringWidth(tv->title)+7, (u_int) CHIGH+5);
+ 
+     Draw3dRect(tv->win, 5+1, y+1, (u_int) StringWidth(tv->title)+5,
+@@ -748,8 +1017,10 @@
+   drawNumLines(tv);
+ 
+   /* draw the buttons */
+-  for (i=0; i<TV_NBUTTS; i++) BTRedraw(&(tv->but[i]));
+-
++  for (i=0; i<nbutts; i++) BTRedraw(&(tv->but[i]));
++#ifdef TV_MULTILINGUAL
++  BTRedraw(&tv->csbut);
++#endif
+   BTRedraw(&tv->nopBut);
+ }
+ 
+@@ -763,15 +1034,15 @@
+ 
+   if (tv->hexmode) nl = tv->hexlines;
+   else {
+-    if (tv->numlines>0 && 
+-	tv->lines[tv->numlines-1] - tv->lines[tv->numlines-2] == 1) 
++    if (tv->numlines>0 &&
++	tv->lines[tv->numlines-1] - tv->lines[tv->numlines-2] == 1)
+       nl = tv->numlines - 2;      /* line after last \n has zero length */
+     else nl = tv->numlines - 1;
+   }
+   if (nl<0) nl = 0;
+ 
+-  sprintf(tmpstr, "%d byte%s, %d line%s", 
+-	  tv->textlen, (tv->textlen!=1) ? "s" : "", 
++  sprintf(tmpstr, "%d byte%s, %d line%s",
++	  tv->textlen, (tv->textlen!=1) ? "s" : "",
+ 	  nl, (nl!=1) ? "s" : "");
+ 
+   w = StringWidth(tmpstr) + 7;  /* width of frame */
+@@ -779,13 +1050,13 @@
+   y = 6;
+ 
+   XSetForeground(theDisp, theGC, infobg);
+-  XFillRectangle(theDisp, tv->win, theGC, (x-w)+1, y+1, 
++  XFillRectangle(theDisp, tv->win, theGC, (x-w)+1, y+1,
+ 		 (u_int) (w-1), (u_int) CHIGH+4);
+ 
+   XSetForeground(theDisp, theGC, infofg);
+   XDrawRectangle(theDisp, tv->win, theGC, x-w, y, (u_int) w, (u_int) CHIGH+5);
+ 
+-  Draw3dRect(tv->win, (x-w)+1, y+1, (u_int) (w-2), (u_int) CHIGH+3, 
++  Draw3dRect(tv->win, (x-w)+1, y+1, (u_int) (w-2), (u_int) CHIGH+3,
+ 	     R3D_IN,2,hicol,locol,infobg);
+ 
+   XSetForeground(theDisp, theGC, infofg);
+@@ -800,10 +1071,10 @@
+   int x, y, w, nl;
+   char tmpstr[64];
+ 
+-  nl = (tv->hexmode) ? tv->hexlines : tv->numlines-1;                 
++  nl = (tv->hexmode) ? tv->hexlines : tv->numlines-1;
+ 
+-  sprintf(tmpstr, "%d byte%s, %d line%s", 
+-	  tv->textlen, (tv->textlen>1) ? "s" : "", 
++  sprintf(tmpstr, "%d byte%s, %d line%s",
++	  tv->textlen, (tv->textlen>1) ? "s" : "",
+ 	  nl, (nl>1) ? "s" : "");
+ 
+   w = StringWidth(tmpstr) + 7;  /* width of frame */
+@@ -819,20 +1090,28 @@
+      int   delta;
+      SCRL *sptr;
+ {
+-  int     i, j, lnum, hpos, cpos, extrach, lwide;
++  int     i, j, lnum, hpos, vpos, cpos, lwide;
++#ifndef TV_MULTILINGUAL
++  int     extrach;
++#endif
++#ifdef TV_L10N
++  int     desig_stat;	/* for ISO 2022-JP */
++	      /* 0: ASCII,  1: JIS X 0208,  2: GL is JIS X 0201 kana */
++#endif
+   TVINFO *tv;
+   char    linestr[512];
+-  u_char  *sp, *ep, *lp;
++  byte   *lp;
++  const byte  *sp, *ep;
+ 
+   /* figure out TVINFO pointer from SCRL pointer */
+-  for (i=0; i<MAXTVWIN && sptr != &tinfo[i].vscrl 
++  for (i=0; i<MAXTVWIN && sptr != &tinfo[i].vscrl
+        && sptr != &tinfo[i].hscrl; i++);
+   if (i==MAXTVWIN) return;   /* didn't find one */
+ 
+   tv = &tinfo[i];
+ 
+   /* make sure we've been sized.  Necessary, as creating/modifying the
+-     scrollbar calls this routine directly, rather than through 
++     scrollbar calls this routine directly, rather than through
+      TextCheckEvent() */
+ 
+   if (!hasBeenSized) return;
+@@ -842,14 +1121,40 @@
+   XSetFont(theDisp, theGC, monofont);
+ 
+   hpos = tv->hscrl.val;
++  vpos = tv->vscrl.val;
+   lwide = (tv->chwide < 500) ? tv->chwide : 500;
+ 
+   /* draw text */
+   if (!tv->hexmode) {     /* ASCII mode */
++#ifdef TV_MULTILINGUAL
++    XClearArea(theDisp, tv->textW, 0, 0,
++	       (u_int) tv->twWide, (u_int) tv->twHigh, False);
++    if(tv->txt == NULL)
++      return;
++    else {
++	int i;
++	int y;
++	struct ml_text *tp = tv->txt;
++	struct ml_line *lp2;
++
++	XSetFunction(theDisp, theGC, GXcopy);
++	XSetClipMask(theDisp, theGC, None);
++	y = 3;
++	for (lp2 = &tp->lines[vpos], i = tp->nlines - vpos;
++		i > 0; lp2++, i--) {
++	    XDrawText16(theDisp, tv->textW, theGC,
++			-mfwide * hpos + 3, y + lp2->ascent,
++			lp2->items, lp2->nitems);
++	    y += lp2->ascent + lp2->descent;
++	    if (y > tv->twHigh)
++		break;
++	}
++    }
++#else
+     for (i=0; i<tv->chhigh; i++) {    /* draw each line */
+-      lnum = i + tv->vscrl.val;
++      lnum = i + vpos;
+       if (lnum < tv->numlines-1) {
+-	
++
+ 	/* find start of displayed portion of line.  This is *wildly*
+ 	   complicated by the ctrl-character and tab expansion... */
+ 
+@@ -868,7 +1173,13 @@
+ 	      cpos--;  sp++;
+ 	    }
+ 	    else if (*sp < 32) extrach = 1;
++
++#ifdef TV_L10N
++	    else if (!tv->code && *sp > 127) extrach = 3;
++#else
+ 	    else if (*sp > 127) extrach = 3;
++#endif
++
+ 	    else sp++;
+ 	  }
+ 	  else {
+@@ -884,6 +1195,10 @@
+ 
+ 	/* build up the linestr buffer, which is the current line, padded
+ 	   with blanks to a width of exactly tv->chwide chars */
++#ifdef TV_L10N
++	desig_stat = 0;		/* for ISO 2022-JP */
++	      /* 0: ASCII,  1: JIS X 0208,  2: GL is JIS X 0201 kana */
++#endif
+ 	for (cpos=0, lp=(byte *) linestr; cpos<lwide; cpos++, lp++) {
+ 	  if (sp>=ep) *lp = ' ';
+ 	  else {
+@@ -897,13 +1212,117 @@
+ 	      cpos--;  lp--;  sp++;
+ 	    }
+ 
++#ifdef TV_L10N
++	    else if (*sp < 32 && !(tv->code == LOCALE_JIS && *sp == 0x1b)) {
++#else
+ 	    else if (*sp < 32) {
++#endif
+ 	      if (!extrach) extrach = 2;
+ 	      if      (extrach == 2) *lp = '^';
+ 	      else if (extrach == 1) *lp = *sp + 64;
+ 	    }
+-      
++
++#ifdef TV_L10N
++	    /* convert to EUC-Japan */
++	    else if (tv->code == LOCALE_JIS) {
++	      if (*sp == 0x1b) {	/* ESC */
++		if (*(sp+1) == '$') {
++		  if (*(sp+2) == 'B' || *(sp+2) == 'A' || *(sp+2) == '@') {
++		    /* ESC $ B,  ESC $ A,  ESC $ @ */
++		    desig_stat = 1;
++		    sp += 3;  cpos--;  lp--;
++		  }
++		  else if (*(sp+2) == '(' && *(sp+3) == 'B') {
++		    /* ESC $ ( B */
++		    desig_stat = 1;
++		    sp += 4;  cpos--;  lp--;
++		  }
++		}
++		else if (*(sp+1) == '(') {
++		  if (*(sp+2) == 'B' || *(sp+2) == 'J' || *(sp+2) == 'H') {
++		    /* ESC ( B,  ESC ( J,  ESC ( H */
++		    desig_stat = 0;
++		    sp += 3;  cpos--;  lp--;
++		  }
++		  else if (*(sp+2) == 'I') {
++		    /* ESC ( I */
++		    desig_stat = 2;
++		    sp += 3;  cpos--;  lp--;
++		  }
++		}
++		else if (*(sp+1) == ')' && *(sp+2) == 'I') {
++		  /* ESC ) I */
++		  desig_stat = 2;
++		  sp += 3;  cpos--;  lp--;
++		}
++		else {	/* error */
++		  *lp = ' ';  sp++;
++		}
++	      }
++
++	      else {
++		switch (desig_stat) {
++		case 0:		/* ASCII */
++		  *lp = *sp++;
++		  break;
++		case 1:		/* JIS X 0208 */
++		  *lp++ = *sp++ | 0x80;
++		  *lp   = *sp++ | 0x80;
++		  cpos++;
++		  break;
++		case 2:		/* JIS X 0201 kana */
++#if defined(__osf__) && !defined(X_LOCALE)
++		  *lp   = '=';  sp++;
++#else
++		  *lp++ = 0x8e;	/* ^N | 0x80 */
++		  *lp   = *sp++ | 0x80;
++#endif
++		  break;
++		default:	/* error */
++		  *lp = *sp++;
++		  break;
++		}
++	      }
++	    }
++
++	    else if (tv->code == LOCALE_MSCODE) {
++	      if ((*sp >= 0x81 && *sp <= 0x9f)
++			 || (*sp >= 0xe0 && *sp <= 0xef)) {
++		static u_char c1, c2;
++
++/*fprintf(stderr, "(%x,%x)->", *sp, *(sp+1));*/
++		c1 = ((*sp - ((*sp>=0xe0) ? 0xb0 : 0x70)) << 1)
++			- ((*(sp+1)<=0x9e) ? 1 : 0);
++		c2 = *(sp+1);
++		if      (c2 >= 0x9f)  c2 -= 0x7e;	/* 0x9F - 0xFC */
++		else if (c2 >= 0x80)  c2 -= 0x20;	/* 0x80 - 0x9E */
++		else		      c2 -= 0x1f;	/* 0x40 - 0x7E */
++
++		*lp++ = c1 | 0x80;
++		*lp   = c2 | 0x80;
++		sp += 2;
++/*fprintf(stderr, "(%x %x) ", c1 | 0x80, c2 | 0x80);*/
++		cpos++;
++	      }
++
++	      else if (*sp >= 0xa1 && *sp <= 0xdf) {	/* JIS X 0201 kana */
++#if defined(__osf__) && !defined(X_LOCALE)
++		*lp   = '=';  sp++;
++#else
++		*lp++ = 0x8e;	/* ^N | 0x80 */
++		*lp   = *sp++;
++#endif
++	      }
++
++	      else *lp = *sp++;
++	    }
++#endif	/* TV_L10N */
++
++#ifdef TV_L10N
++	    else if (!tv->code && *sp > 127) {
++#else
+ 	    else if (*sp > 127) {
++#endif
+ 	      if (!extrach) extrach = 4;
+ 	      if      (extrach == 4) *lp = '\\';
+ 	      else if (extrach == 3) *lp = ((u_char)(*sp & 0700) >> 6) + '0';
+@@ -919,6 +1338,9 @@
+ 	    }
+ 	  }
+ 	}
++#ifdef TV_L10N
++	*lp = '\0';	/* terminate linestr */
++#endif
+       }
+ 
+       else {  /* below bottom of file.  Just build a blank str */
+@@ -926,24 +1348,31 @@
+       }
+ 
+       /* draw the line */
+-      XDrawImageString(theDisp, tv->textW, theGC, 
+-		       3, i*mfhigh + 3 + mfascent, linestr, lwide);
++#ifdef TV_L10N
++      if (xlocale)
++	XmbDrawImageString(theDisp, tv->textW, monofset, theGC,
++		3, i*mfhigh + 1 + mfascent, linestr, strlen(linestr));
++      else
++#endif
++	XDrawImageString(theDisp, tv->textW, theGC,
++		3, i*mfhigh + 3 + mfascent, linestr, lwide);
+     }  /* for i ... */
++#endif /* TV_MULTILINGUAL */
+   }  /* if hexmode */
+ 
+ 
+   else { /* HEX MODE */
+     for (i=0; i<tv->chhigh; i++) {    /* draw each line */
+-      lnum = i + tv->vscrl.val;
++      lnum = i + vpos;
+       if (lnum < tv->hexlines) {
+-	
++
+ 	char hexstr[80], tmpstr[16];
+ 
+ 	/* generate hex for this line */
+ 	sprintf(hexstr, "0x%08x: ", lnum * 0x10);
+ 
+-	sp = (byte *) tv->text + lnum * 0x10;
+-	ep = (byte *) tv->text + tv->textlen;      /* ptr to end of buffer */
++	sp = (const byte *) tv->text + lnum * 0x10;
++	ep = (const byte *) tv->text + tv->textlen;      /* ptr to end of buffer */
+ 
+ 	for (j=0; j<16; j++) {
+ 	  if (sp+j < ep) sprintf(tmpstr,"%02x ", sp[j]);
+@@ -960,7 +1389,11 @@
+ 
+ 	for (j=0; j<16; j++) {
+ 	  if (sp+j < ep) {
++#ifdef TV_L10N
++	    if (sp[j] >= 32 && (sp[j] <= 127 || tv->code)) *lp++ = sp[j];
++#else
+ 	    if (sp[j] >= 32 && sp[j] <= 127) *lp++ = sp[j];
++#endif
+ 	    else *lp++ = '.';
+ 	  }
+ 	  else *lp++ = ' ';
+@@ -972,7 +1405,7 @@
+ 	   now build 'linestr', which is going to have hexstr shifted
+ 	   and/or padded with blanks  (ie, the displayed portion or hexstr) */
+ 
+-	/* skip obscured beginning of line, if any */ 
++	/* skip obscured beginning of line, if any */
+ 	for (cpos=0, sp=(byte *) hexstr; cpos<hpos && *sp;  cpos++, sp++);
+ 
+ 	for (cpos=0, lp=(byte *)linestr;  cpos<lwide; cpos++, lp++) {
+@@ -985,16 +1418,16 @@
+       }
+ 
+       /* draw the line */
+-      XDrawImageString(theDisp, tv->textW, theGC, 
++      XDrawImageString(theDisp, tv->textW, theGC,
+ 		       3, i*mfhigh + 3 + mfascent, linestr, lwide);
+     }  /* for i ... */
+   }  /* else hexmode */
+-    
++
+ 
+ 
+   XSetFont(theDisp, theGC, mfont);
+ 
+-  Draw3dRect(tv->textW, 0, 0, (u_int) (tv->twWide-1), (u_int) (tv->twHigh-1), 
++  Draw3dRect(tv->textW, 0, 0, (u_int) (tv->twWide-1), (u_int) (tv->twHigh-1),
+ 	     R3D_IN, 2, hicol, locol, infobg);
+ }
+ 
+@@ -1008,14 +1441,21 @@
+   int   i;
+   BUTT *bp;
+ 
+-  for (i=0, bp=tv->but; i<TV_NBUTTS; i++, bp++) {
++  for (i=0, bp=tv->but; i<nbutts; i++, bp++) {
+     if (PTINRECT(x,y,bp->x,bp->y,bp->w,bp->h)) break;
+   }
+ 
+-  if (i<TV_NBUTTS) {
++  if (i<nbutts) {
+     if (BTTrack(bp)) doCmd(tv, i);
+     return;
+   }
++
++#ifdef TV_MULTILINGUAL
++  if (PTINRECT(x, y, tv->csbut.x, tv->csbut.y, tv->csbut.w, tv->csbut.h)) {
++    if (BTTrack(&tv->csbut))
++      openCsWin(tv);
++  }
++#endif
+ }
+ 
+ 
+@@ -1033,7 +1473,7 @@
+   stlen = XLookupString(kevt, buf, 128, &ks, (XComposeStatus *) NULL);
+   shift = kevt->state & ShiftMask;
+   ck    = CursorKey(ks, shift, 1);
+-  dealt = 1;  
++  dealt = 1;
+ 
+   RemapKeyCheck(ks, buf, &stlen);
+ 
+@@ -1045,13 +1485,38 @@
+ 
+   /* keyboard equivalents */
+   switch (buf[0]) {
+-  case '\001': doCmd(tv, TV_ASCII);   break;      /* ^A = Ascii */
+-  case '\010': doCmd(tv, TV_HEX);     break;      /* ^H = Hex   */
+-
+-  case '\033': doCmd(tv, TV_CLOSE);   break;      /* ESC = Close window */
++  case '\001':  case 'a':  case 'A':
++    doCmd(tv, TV_ASCII);   break;      /* ^A = Ascii */
++  case '\010':  case 'h':  case 'H':
++    doCmd(tv, TV_HEX);     break;      /* ^H = Hex   */
++
++  case '\021':  case 'q':  case 'Q':
++  case '\003':  case 'c':  case 'C':
++  case '\033':
++    doCmd(tv, TV_CLOSE);   break;      /* ESC = Close window */
+ 
+   default:     break;
+   }
++
++#ifdef TV_L10N
++  if (xlocale) {
++    switch (buf[0]) {
++    case '\022':  case 'r':  case 'R':
++      doCmd(tv, TV_RESCAN);   break;
++    case '\012':  case 'j':  case 'J':
++      doCmd(tv, TV_JIS);      break;
++    case '\005':  case 'e':  case 'E':
++    case '\025':  case 'u':  case 'U':
++      doCmd(tv, TV_EUCJ);     break;
++    case '\015':  case 'm':  case 'M':
++    case '\023':  case 's':  case 'S':
++      doCmd(tv, TV_MSCODE);  break;
++
++    default:  break;
++    }
++  }
++#endif	/* TV_L10N */
++
+ }
+ 
+ 
+@@ -1060,8 +1525,6 @@
+      TVINFO *tv;
+      int     key;
+ {
+-  int i,j;
+-
+   if (!tv->textlen) return;
+ 
+   /* an arrow key (or something like that) was pressed in icon window.
+@@ -1108,13 +1571,26 @@
+   else {  /* switch to ascii mode */
+     pos = oldvscrl * 16;
+     for (i=0; i<tv->numlines-1; i++) {
+-      if (tv->lines[i+1] - tv->text > pos && 
++      if (tv->lines[i+1] - tv->text > pos &&
+ 	  tv->lines[i]   - tv->text <= pos) break;
+     }
+     if (i<tv->numlines-1) SCSetVal(&tv->vscrl, i);
+   }
+ 
++#ifdef TV_L10N
++  /* redraw text */
++  if (xlocale) {
++    XClearArea(theDisp, tv->textW, 0, 0,
++	       (u_int) tv->twWide, (u_int) tv->twHigh, False);
++
++    drawTextW(0, &tv->vscrl);
++  }
++#endif
++#ifdef TV_MULTILINGUAL
++  XClearArea(theDisp, tv->textW, 0, 0,
++	     (u_int) tv->twWide, (u_int) tv->twHigh, False);
+   drawTextW(0, &tv->vscrl);
++#endif
+ }
+ 
+ 
+@@ -1125,16 +1601,29 @@
+   /* compute # of lines and linestarts array for given text */
+ 
+   int   i,j,wide,maxwide,space;
+-  byte *sp;
++  const byte *sp;
+ 
+-  if (!tv->text) { 
+-    tv->numlines = tv->hexlines = 0;  
+-    tv->lines = (char **) NULL; 
++#ifdef TV_L10N
++  /* select code-set */
++  if (xlocale)
++    tv->code = selectCodeset(tv);
++#endif	/* TV_L10N */
++
++  if (!tv->text) {
++    tv->numlines = tv->hexlines = 0;
++    tv->lines = (const char **) NULL;
++#ifdef TV_MULTILINGUAL
++    if (tv->cv_text != NULL) {
++	free(tv->cv_text);
++	tv->cv_text = NULL;
++    }
++    tv->txt = NULL;
++#endif
+     return;
+   }
+ 
+   /* count the # of newline characters in text */
+-  for (i=0, sp=(byte *) tv->text, tv->numlines=0; i<tv->textlen; i++, sp++) {
++  for (i=0, sp=(const byte *) tv->text, tv->numlines=0; i<tv->textlen; i++, sp++) {
+     if (*sp == '\n') tv->numlines++;
+   }
+ 
+@@ -1142,19 +1631,19 @@
+   tv->numlines += 2;
+ 
+   /* build lines array */
+-  tv->lines = (char **) malloc(tv->numlines * sizeof(char *));
++  tv->lines = (const char **) malloc(tv->numlines * sizeof(char *));
+   if (!tv->lines) FatalError("out of memory in computeText()");
+ 
+   j = 0;
+   tv->lines[j++] = tv->text;
+-  for (i=0, sp=(byte *) tv->text; i<tv->textlen; i++, sp++) {
++  for (i=0, sp=(const byte *) tv->text; i<tv->textlen; i++, sp++) {
+     if (*sp == '\n') tv->lines[j++] = (char *) (sp + 1);
+   }
+ 
+   tv->lines[tv->numlines - 1] = tv->text + tv->textlen + 1;
+ 
+-  /* each line has a trailing '\n' character, except for the last line, 
+-     which has a trailing '\0' character.  In any case, all lines can 
++  /* each line has a trailing '\n' character, except for the last line,
++     which has a trailing '\0' character.  In any case, all lines can
+      be printed by printing ((lines[n+1] - lines[n]) - 1) characters,
+      starting with lines[n].
+ 
+@@ -1164,30 +1653,142 @@
+ 
+   /* compute length of longest line, when shown in 'ascii' mode.  Takes
+      into account the fact that non-printing chars (<32 or >127) will be
+-     shown in an 'expanded' form.  (<32 chars will be shown as '^A' 
++     shown in an 'expanded' form.  (<32 chars will be shown as '^A'
+      (or whatever), and >127 chars will be shown as octal '\275') */
+ 
+   maxwide = 0;
+   for (i=0; i<tv->numlines-1; i++) {
+     /* compute displayed width of line #i */
+-    for (sp=(byte *) tv->lines[i], wide=0; sp<(byte *) tv->lines[i+1]-1; 
++    for (sp=(const byte *) tv->lines[i], wide=0; sp<(const byte *) tv->lines[i+1]-1;
+ 	 sp++) {
+       if (*sp == '\011') {   /* tab to next multiple of 8 */
+ 	space = ((wide+8) & (~7)) - wide;
+ 	wide += space;
+       }
+       else if (*sp <  32) wide += 2;
++#ifdef TV_L10N
++      else if (*sp > 127 && !tv->code) wide += 4;
++#else
+       else if (*sp > 127) wide += 4;
++#endif
+       else wide++;
+     }
+     if (wide > maxwide) maxwide = wide;
+   }
+   tv->maxwide = maxwide;
+ 
++#ifdef TV_MULTILINGUAL
++  ml_set_charsets(tv->ctx, &tv->ccs.coding_system);
++  if (tv->cv_text != NULL) {
++      free(tv->cv_text);
++      tv->cv_text = NULL;
++  }
++  if (tv->ccs.converter == NULL) {
++      tv->txt = ml_draw_text(tv->ctx, tv->text, tv->textlen);
++  } else {
++      tv->cv_text = (*tv->ccs.converter)(tv->text, tv->textlen, &tv->cv_len);
++      tv->txt = ml_draw_text(tv->ctx, tv->cv_text, tv->cv_len);
++  }
++  tv->maxwide = tv->txt->width / mfwide;
++  tv->numlines = tv->txt->height / mfhigh + 1;
++#endif
++
+   tv->hexlines = (tv->textlen + 15) / 16;
+ }
+ 
+ 
++/***************************************************/
++#ifdef TV_L10N
++static int selectCodeset(tv)
++     TVINFO *tv;
++{
++  const byte *sp;
++  int i, len;
++  int code = LOCALE_USASCII;	/* == 0 */
++
++
++  len = tv->textlen;
++
++  /* select code-set */
++  if (xlocale) {
++    sp = (const byte *) tv->text;  i = 0;
++    while (i < len - 1) {
++      if (*sp == 0x1b &&
++	  (*(sp+1) == '$' || *(sp+1) == '(' || *(sp+1) == ')')) {
++	code = LOCALE_JIS;
++	break;
++      }
++
++      else if (*sp >= 0xa1 && *sp <= 0xdf) {
++	if (*(sp+1) >= 0xf0 && *(sp+1) <= 0xfe) {
++	  code = LOCALE_EUCJ;
++	  break;
++	}
++#  if (LOCALE_DEFAULT == LOCALE_EUCJ)
++	else {
++	  sp++;  i++;
++	}
++#  endif
++      }
++
++      else if ((*sp >= 0x81 && *sp <= 0x9f) || (*sp >= 0xe0 && *sp <= 0xef)) {
++	if ((*(sp+1) >= 0x40 && *(sp+1) <= 0x7e) || *(sp+1) == 0x80) {
++	  code = LOCALE_MSCODE;
++	  break;
++	}
++	else if (*(sp+1) == 0xfd || *(sp+1) == 0xfe) {
++	  code = LOCALE_EUCJ;
++	  break;
++	}
++	else {
++	  sp++;  i++;
++	}
++      }
++
++      else if (*sp >= 0xf0 && *sp <= 0xfe) {
++	code = LOCALE_EUCJ;
++	break;
++      }
++
++      sp++;  i++;
++    }
++    if (!code)  code = LOCALE_DEFAULT;
++  }
++
++  return code;
++}
++#endif	/* TV_L10N */
++
++#ifdef TV_MULTILINGUAL
++static void setCodingSpec(tv, cs)
++    TVINFO *tv;
++    struct coding_spec *cs;
++{
++  if (xvbcmp((char *) &tv->ccs, (char *) cs, sizeof *cs) == 0)
++    return;
++
++  tv->ccs = *cs;
++#if 0
++  ml_set_charsets(tv->ctx, &tv->ccs.coding_system);
++  if (tv->cv_text != NULL) {
++      free(tv->cv_text);
++      tv->cv_text = NULL;
++  }
++  if (tv->ccs.converter == NULL) {
++      tv->txt = ml_draw_text(tv->ctx, tv->text, tv->textlen);
++  } else {
++      tv->cv_text = (*tv->ccs.converter)(tv->text, tv->textlen, &tv->cv_len);
++      tv->txt = ml_draw_text(tv->ctx, tv->cv_text, tv->cv_len);
++  }
++#else
++  computeText(tv);
++  computeScrlVals(tv);
++#endif
++  /* drawTextW(0, &tv->vscrl); */
++}
++#endif
++
++
+ /**********************************************************************/
+ /* BUILT-IN TEXT FILES ************************************************/
+ /**********************************************************************/
+@@ -1203,9 +1804,13 @@
+ 
+   /* build the license text */
+ #ifdef LC
+-#undef LC
++#  undef LC
++#endif
++#ifdef __STDC__  /* since "x" is always a static string, this works: */
++#  define LC(x) (strcat(license, x "\n"))
++#else
++#  define LC(x) (strcat(license, x), strcat(license, "\n"))
+ #endif
+-#define LC(x) (strcat(license, x), strcat(license, "\n"))
+ 
+   LC("(Note: This has been changed, and hopefully clarified, from the 3.00");
+   LC("version of this info.  Please read it.)");
+@@ -1220,7 +1825,12 @@
+   LC("the xv distribution.  Do *not* send mail unless absolutely necessary");
+   LC("(ie, you don't have ftp capability).");
+   LC("");
+-  LC("Note:  The docs (xvdocs.ps) may be installed in '/usr/local/lib'.");
++  LC("Note:  The documentation (README.jumbo, xvdocs.ps, and/or xvdocs.pdf)");
++#ifdef __STDC__
++  LC("may be installed in '" DOCDIR "'.");
++#else
++  LC("may be installed in '/usr/local/share/doc/xv'.");
++#endif
+   LC("");
+   LC("If you're viewing this information via the 'About XV' command, and");
+   LC("you'd like to print it out, a copy of this info can be found in the ");
+@@ -1230,7 +1840,7 @@
+   LC("");
+   LC("XV Licensing Information");
+   LC("------------------------");
+-  LC("XV IS SHAREWARE FOR PERSONAL USE ONLY.  ");
++  LC("XV IS SHAREWARE FOR PERSONAL USE ONLY.");
+   LC("");
+   LC("You may use XV for your own amusement, and if you find it nifty,");
+   LC("useful, generally cool, or of some value to you, your registration fee");
+@@ -1279,7 +1889,7 @@
+   LC("are not.  All forms of payment must be payable in US Funds.  Checks");
+   LC("must be payable through a US bank (or a US branch of a non-US bank).");
+   LC("Purchase orders for less than $50, while still accepted, are not");
+-  LC("encouraged. ");
++  LC("encouraged.");
+   LC("");
+   LC("All payments should be payable to 'John Bradley', and mailed to:");
+   LC("        John Bradley");
+@@ -1382,7 +1992,11 @@
+   keyhelp[0] = '\0';
+ 
+ #undef LC
+-#define LC(x) (strcat(keyhelp, x), strcat(keyhelp, "\n"))
++#ifdef __STDC__  /* since "x" is always a static string, this works: */
++#  define LC(x) (strcat(keyhelp, x "\n"))
++#else
++#  define LC(x) (strcat(keyhelp, x), strcat(keyhelp, "\n"))
++#endif
+ 
+   LC("XV Mouse and Keyboard Usage");
+   LC("===========================");
+@@ -1415,16 +2029,16 @@
+   LC("");
+   LC("Part 2:  Normal Keyboard Equivalents");
+   LC("------------------------------------");
+-  LC("The following keys can be used in most xv windows, including the ");
+-  LC("image, controls, and color editor windows, but *not* in the visual");
+-  LC("schnauzer windows.");
++  LC("The following keys can be used in most xv windows, including the");
++  LC("image, controls, and color editor windows, but *not* in the Visual");
++  LC("Schnauzer windows.");
+   LC("");
+-  LC("  Tab or ");
++  LC("  Tab or");
+   LC("  Space         - 'Next' command");
+   LC("");
+   LC("  Return        - reload currently displayed image file");
+   LC("");
+-  LC("  Del or ");
++  LC("  Del or");
+   LC("  Backspace     - 'Prev' command");
+   LC("");
+   LC("  ctrl+'l'      - 'Load' command");
+@@ -1432,7 +2046,7 @@
+   LC("  ctrl+'p'      - 'Print' command");
+   LC("  ctrl+'d'      - 'Delete' command");
+   LC("");
+-  LC("  'q' or ");
++  LC("  'q' or");
+   LC("  ctrl+'q'      - 'Quit' command");
+   LC("");
+   LC("  meta+'x'      - 'cut' command");
+@@ -1468,7 +2082,7 @@
+   LC("  's'           - smooth mode");
+   LC("  meta+'8'      - toggle 8/24 bit mode");
+   LC("");
+-  LC("  'V' or ");
++  LC("  'V' or");
+   LC("  ctrl+'v'      - Visual Schnauzer");
+   LC("  'e'           - Color Editor");
+   LC("  'i'           - Image Info");
+@@ -1490,7 +2104,7 @@
+   LC("  meta+'S'      - Spread algorithm");
+   LC("");
+   LC("  'R' or");
+-  LC("  meta+'r' or ");
++  LC("  meta+'r' or");
+   LC("  meta+'0'      - 'Reset' command in color editor");
+   LC("");
+   LC("  meta+'1'      - select preset 1 in color editor");
+@@ -1503,7 +2117,7 @@
+   LC("");
+   LC("Part 2a:  Image Window Keys");
+   LC("---------------------------");
+-  LC("The following keys can *only* be used inside the image window.");
++  LC("The following keys can be used *only* inside the image window.");
+   LC("");
+   LC("  ctrl + Up     - crops 1 pixel off the bottom of the image");
+   LC("  ctrl + Down   - crops 1 pixel off the top of the image");
+@@ -1514,11 +2128,11 @@
+   LC("  'p'           -  opens a 'go to page #' dialog box");
+   LC("");
+   LC("  PageUp, or");
+-  LC("  Prev, or ");
++  LC("  Prev, or");
+   LC("  shift+Up      - previous page");
+   LC("");
+   LC("  PageDown, or");
+-  LC("  Next, or ");
++  LC("  Next, or");
+   LC("  shift+Down    - next page");
+   LC("");
+   LC("");
+@@ -1535,7 +2149,7 @@
+   LC("");
+   LC("Part 2b:  Visual Schnauzer Keys");
+   LC("-------------------------------");
+-  LC("The following keys can only be used in the visual schnauzer windows.");
++  LC("The following keys can be used only in the Visual Schnauzer windows.");
+   LC("");
+   LC("  ctrl+'d'      - delete file(s)");
+   LC("  ctrl+'n'      - create new directory");
+@@ -1560,8 +2174,509 @@
+   OpenTextView(keyhelp, (int) strlen(keyhelp), "XV Help", 0);
+ }
+ 
++#ifdef TV_MULTILINGUAL
+ 
++#define TV_ML_ACCEPT TV_NCSS
++#define TV_ML_CLOSE  (TV_ML_ACCEPT + 1)
++#define TV_ML_NBUTTS (TV_ML_CLOSE + 1)
++
++#define TV_ML_RETCODE	0
++#	define TV_ML_RET_LF	0
++#	define TV_ML_RET_CRLF	1
++#	define TV_ML_RET_CR	2
++#	define TV_ML_RET_ANY	3
++#define TV_ML_GL	1
++#define TV_ML_GR	2
++#define TV_ML_CVTR	3
++#define TV_ML_NRBUTTS	4
++
++#define TV_ML_SHORT	0
++#define TV_ML_LOCK	1
++#define TV_ML_NCBUTTS	2
++
++#define TV_ML_NLISTS	4
++
++#define CSWIDE (BUTTW3 * 5 + 5 * 6)
++#define CSHIGH 450
++
++typedef struct csinfo_t {
++    TVINFO *tv;
++    RBUTT *rbt[TV_ML_NRBUTTS];
++    CBUTT cbt[TV_ML_NCBUTTS];
++    LIST ls[TV_ML_NLISTS];
++    BUTT bt[TV_ML_NBUTTS];
++    int up;
++    Window win;
++    struct coding_spec tcs;	/* temporary coding_spec */
++} CSINFO;
++CSINFO csinfo[MAXTVWIN];
++static char **regs;
++static int nregs;
++
++static int  csCheckEvent           PARM((CSINFO *, XEvent *));
++static void csReflect              PARM((CSINFO *));
++static void csRedraw               PARM((CSINFO *));
++static void csListRedraw           PARM((LIST *));
++static void csLsRedraw             PARM((int, SCRL *));
++static void create_registry_list   PARM((void));
++
++static char *(*cvtrtab[])PARM((char *, int, int *)) = {
++    NULL,
++    sjis_to_jis,
++};
+ 
++static void createCsWins(geom)
++    const char *geom;
++{
++    XSetWindowAttributes xswa;
++    int i, j;
++
++    create_registry_list();
++
++    xswa.backing_store = WhenMapped;
++    for (i = 0; i < MAXTVWIN; i++) {
++	char nam[8];
++	TVINFO *tv = &tinfo[i];
++	CSINFO *cs = &csinfo[i];
++	tv->cs = cs;
++	cs->tv = tv;
++	sprintf(nam, "XVcs%d", i);
++	cs->win = CreateWindow("xv codeset", nam, geom,
++			       CSWIDE, CSHIGH, infofg, infobg, 0);
++	if (!cs->win) FatalError("couldn't create 'charset' window!");
++#ifdef BACKING_STORE
++	XChangeWindowAttributes(theDisp, cs->win, CWBackingStore, &xswa);
++#endif
++	XSelectInput(theDisp, cs->win, ExposureMask | ButtonPressMask);
++
++	DrawString(cs->win, 5, 5 + ASCENT, "Initial States");
++	for (i = 0; i < TV_ML_NLISTS; i++) {
++	    int x, y;
++	    char buf[80];
++
++	    if (i / 2 == 0)
++		x = 15;
++	    else
++		x = 280;
++	    if (i % 2 == 0)
++		y = 5 + LINEHIGH * 1;
++	    else
++		y = 5 + LINEHIGH * 7 + SPACING * 3;
++
++	    sprintf(buf, "Designation for G%d:", i + 1);
++	    DrawString(cs->win, x, y + ASCENT, buf);
++
++	    LSCreate(&cs->ls[i], cs->win, x + 15, y + LINEHIGH,
++			200, LINEHIGH * 5, 5,
++			regs, nregs + 2,
++			infofg, infobg, hicol, locol, csLsRedraw, 0, 0);
++	    cs->ls[i].selected = 0;
++	}
+ 
++	for (i = 0; i < 2; i++) {
++	    char *p;
++	    int n;
++	    int x, y;
++
++	    if ((p = (char *) malloc(3 * 4)) == NULL)
++		FatalError("out of memory in createCsWins().");
++	    strcpy(p, "G1 G2 G3 G4");
++	    p[2] = p[5] = p[8] = '\0';
++	    n = (i == 0 ? TV_ML_GL : TV_ML_GR);
++	    x = (i == 0 ? 15 : 280);
++	    y = 235;
++	    DrawString(cs->win, x, y + ASCENT, "Assignment for GL:");
++	    x += 15;
++	    y += LINEHIGH;
++	    cs->rbt[n] = RBCreate(NULL, cs->win,
++				  x, y, p, infofg, infobg, hicol, locol);
++	    for (j = 1; j < 4; j++) {
++		p += 3;
++		x += 50;
++		RBCreate(cs->rbt[n], cs->win,
++			 x, y, p, infofg, infobg, hicol, locol);
++	    }
++	}
++
++	DrawString(cs->win, 5, 280 + ASCENT, "Ret Code:");
++	cs->rbt[TV_ML_RETCODE] =
++	    RBCreate(NULL, cs->win, 20, 300, "LF", infofg,infobg, hicol,locol);
++	RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 20, 300 + 20, "CR+LF",
++		 infofg, infobg, hicol, locol);
++	RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 90, 300, "CR",
++		 infofg, infobg, hicol, locol);
++	RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 90, 300 + 20, "Any",
++		 infofg, infobg, hicol, locol);
++
++	DrawString(cs->win, 350, 280 + ASCENT, "Converter:");
++	cs->rbt[TV_ML_CVTR] =
++	    RBCreate(NULL, cs->win, 365, 300, "Nothing",
++		     infofg, infobg, hicol, locol);
++	RBCreate(cs->rbt[TV_ML_CVTR], cs->win, 365, 300 + 20, "Shift JIS",
++		 infofg, infobg, hicol, locol);
++
++	CBCreate(&cs->cbt[TV_ML_SHORT], cs->win, 200, 300, "Short Form",
++		 infofg, infobg, hicol, locol);
++	CBCreate(&cs->cbt[TV_ML_LOCK], cs->win, 200, 320, "Locking Shift",
++		 infofg, infobg, hicol, locol);
++
++	for (j = 0; j < TV_NCSS; j++) {
++	    BTCreate(&cs->bt[j], cs->win,
++		     5 + (BUTTW3 + 5) * (j % 5),
++		     350 + 5 + (BUTTH + 5) * (j / 5),
++		     BUTTW3, BUTTH, codeSetNames[j],
++		     infofg, infobg, hicol, locol);
++	}
++	BTCreate(&cs->bt[TV_ML_ACCEPT], cs->win,
++		 CSWIDE - 10 - BUTTW3 * 2, CSHIGH - 5 - BUTTH, BUTTW3, BUTTH,
++		 "Accept", infofg, infobg, hicol, locol);
++	BTCreate(&cs->bt[TV_ML_CLOSE], cs->win,
++		 CSWIDE - 5 - BUTTW3, CSHIGH - 5 - BUTTH, BUTTW3, BUTTH,
++		 "Close", infofg, infobg, hicol, locol);
++
++	XMapSubwindows(theDisp, cs->win);
++	cs->up = 0;
++    }
++}
+ 
++static void openCsWin(tv)
++    TVINFO *tv;
++{
++    CSINFO *cs = tv->cs;
++    if (cs->up)
++	return;
++
++    XMapRaised(theDisp, cs->win);
++    cs->up = 1;
++    cs->tcs = cs->tv->ccs;
++    csReflect(cs);
++}
++
++static void closeCsWin(tv)
++    TVINFO *tv;
++{
++    CSINFO *cs = tv->cs;
++    if (!cs->up)
++	return;
++    cs->up = 0;
++    XUnmapWindow(theDisp, cs->win);
++}
++
++int CharsetCheckEvent(xev)
++    XEvent *xev;
++{
++    int i;
++    CSINFO *cs;
++
++    for (cs = csinfo, i = 0; i < MAXTVWIN; cs++, i++) {
++	if (!cs->up)
++	    continue;
++	if (csCheckEvent(cs, xev))
++	    break;
++    }
++    if (i < MAXTVWIN)
++	return 1;
++    return 0;
++}
++
++static int csCheckEvent(cs, xev)
++    CSINFO *cs;
++    XEvent *xev;
++{
++    RBUTT **rbp;
++    CBUTT *cbp;
++    LIST *ls;
++    BUTT *bp;
++    int i, n;
++
++    if (xev->type == Expose) {
++	int x, y, w, h;
++	XExposeEvent *e = (XExposeEvent *) xev;
++	x = e->x; y = e->y; w = e->width; h = e->height;
++
++	if (cs->win == e->window){
++	    csRedraw(cs);
++	    return 1;
++	} else {
++	    for (i = 0; i < TV_ML_NLISTS; i++) {
++		if (cs->ls[i].win == e->window) {
++		    LSRedraw(&cs->ls[i], 0);
++		    return 1;
++		}
++	    }
++	   for (i = 0; i < TV_ML_NLISTS; i++) {
++		if (cs->ls[i].scrl.win == e->window) {
++		    SCRedraw(&cs->ls[i].scrl);
++		    return 1;
++		}
++	   }
++	}
++    } else if (xev->type == ButtonPress) {
++	int x, y;
++	XButtonEvent *e = (XButtonEvent *) xev;
++	x = e->x; y = e->y;
++	if (cs->win == e->window) {
++	    for (bp = cs->bt, i = 0; i < TV_ML_NBUTTS; bp++, i++) {
++		if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h))
++		    break;
++	    }
++	    if (i < TV_ML_NBUTTS) {
++		if (BTTrack(bp)) {
++		    if (i < TV_NCSS) {
++			cs->tcs = coding_spec[i];
++			csReflect(cs);
++		    } else {
++			switch (i) {
++			case TV_ML_ACCEPT:
++			    setCodingSpec(cs->tv, &cs->tcs);
++			    break;
++			case TV_ML_CLOSE:
++			    closeCsWin(cs->tv);
++			    break;
++			}
++		    }
++		}
++		return 1;
++	    }
++	    for (cbp = cs->cbt, i = 0; i < TV_ML_NCBUTTS; cbp++, i++) {
++		if (CBClick(cbp, x, y) && CBTrack(cbp))
++		    break;
++	    }
++	    if (i < TV_ML_NCBUTTS) {
++		switch (i) {
++		case TV_ML_SHORT:
++		    cs->tcs.coding_system.short_form = cbp->val;
++		    break;
++		case TV_ML_LOCK:
++		    cs->tcs.coding_system.lock_shift = cbp->val;
++		    break;
++		}
++		return 1;
++	    }
++	    for (rbp = cs->rbt, i = 0; i < TV_ML_NRBUTTS; rbp++, i++) {
++		if ((n = RBClick(*rbp, x, y)) >= 0 && RBTrack(*rbp, n)) {
++		    break;
++		}
++	    }
++	    if (i < TV_ML_NRBUTTS) {
++		switch (i) {
++		case TV_ML_RETCODE:
++		    cs->tcs.coding_system.eol = n;
++		    break;
++		case TV_ML_GL:
++		    cs->tcs.coding_system.gl = n;
++		    break;
++		case TV_ML_GR:
++		    cs->tcs.coding_system.gr = n;
++		    break;
++		case TV_ML_CVTR:
++		    cs->tcs.converter = cvtrtab[n];
++		    break;
++		}
++		return 1;
++	    }
++	} else {
++	    for (ls = cs->ls, i = 0; i < TV_ML_NLISTS; ls++, i++) {
++		if (ls->win == e->window) {
++		    LSClick(ls, e);
++		    n = ls->selected;
++		    if (n < nregs) {
++			char r[32], *p = r;
++			int b7;
++			strcpy(r, regs[n]);
++			if ((p = strrchr(r, '/')) != NULL) {
++			    *p = '\0';
++			    b7 = (*(p + 1) == 'R' ? 1 : 0);
++			} else
++			    b7 = 0;	/* shouldn't occur */
++			cs->tcs.coding_system.design[i] = lookup_design(r, b7);
++		    } else if (n == nregs)    /* initially none is designed. */
++			cs->tcs.coding_system.design[i].bpc = 0;
++		    else
++			cs->tcs.coding_system.design[i].bpc = -1;
++		    return 1;
++		}
++	    }
++	    for (ls = cs->ls, i = 0; i < TV_ML_NLISTS; ls++, i++) {
++		if (ls->scrl.win == e->window) {
++		    SCTrack(&ls->scrl, x, y);
++		    return 1;
++		}
++	    }
++	}
++    }
++    return 0;
++}
++
++static void csReflect(cs)
++    CSINFO *cs;
++{
++    int i;
++
++    RBSelect(cs->rbt[TV_ML_RETCODE], cs->tcs.coding_system.eol);
++    RBSelect(cs->rbt[TV_ML_GL], cs->tcs.coding_system.gl);
++    RBSelect(cs->rbt[TV_ML_GR], cs->tcs.coding_system.gr);
++    for (i = 0; i < sizeof cvtrtab / sizeof cvtrtab[0]; i++) {
++	if (cs->tcs.converter == cvtrtab[i])
++	    break;
++    }
++    if (i >= sizeof cvtrtab / sizeof cvtrtab[0])
++	FatalError("program error in csReflect().");
++    RBSelect(cs->rbt[TV_ML_CVTR], i);
++
++    cs->cbt[TV_ML_SHORT].val = cs->tcs.coding_system.short_form;
++    cs->cbt[TV_ML_LOCK].val = cs->tcs.coding_system.lock_shift;
++    for (i = 0; i < TV_ML_NLISTS; i++) {
++	struct design design = cs->tcs.coding_system.design[i];
++	char *reg, r[32];
++	int b7;
++	int n = 0;
++	switch (design.bpc) {
++	case -1:
++	    n = nregs + 1;
++	    break;
++	case 0:
++	    n = nregs;
++	    break;
++	case 1:
++	case 2:
++	    if ((reg = lookup_registry(design, &b7)) == NULL)
++		FatalError("internal error in csReflect.");
++	    sprintf(r, "%s/%s", reg, b7 ? "Right" : "Left");
++	    for (n = 0; n < nregs; n++) {
++		if (strcmp(regs[n], r) == 0)
++		    break;
++	    }
++	}
++	cs->ls[i].selected = n;
++	ScrollToCurrent(&cs->ls[i]);
++    }
++    csRedraw(cs);
++    for (i = 0; i < TV_ML_NLISTS; i++)
++	csListRedraw(&cs->ls[i]);
++}
++
++static void csRedraw(cs)
++    CSINFO *cs;
++{
++    int i;
++
++    XSetForeground(theDisp, theGC, infofg);
++    DrawString(cs->win,  5,5 + ASCENT, "Initial States");
++    for (i = 0; i < TV_ML_NLISTS; i++) {
++	int x, y;
++	char buf[80];
++
++	if (i / 2 == 0)
++	    x = 15;
++	else
++	    x = 280;
++	if (i % 2 == 0)
++	    y = 5 + LINEHIGH * 1;
++	else
++	    y = 5 + LINEHIGH * 7 + SPACING * 3;
++
++	sprintf(buf, "Designation for G%d:", i);
++	DrawString(cs->win, x, y + ASCENT, buf);
++    }
++
++    DrawString(cs->win,  15, 235 + ASCENT, "Invocation for GL:");
++    DrawString(cs->win, 280, 235 + ASCENT, "Invocation for GR:");
++    DrawString(cs->win,   5, 280 + ASCENT, "Ret Code:");
++    DrawString(cs->win, 350, 280 + ASCENT, "Converter:");
++
++    for (i = 0; i < TV_ML_NBUTTS; i++)
++	BTRedraw(&cs->bt[i]);
++    for (i = 0; i < TV_ML_NCBUTTS; i++)
++	CBRedraw(&cs->cbt[i]);
++    for (i = 0; i < TV_ML_NRBUTTS; i++)
++	RBRedraw(cs->rbt[i], -1);
++}
++
++static void csListRedraw(ls)
++    LIST *ls;
++{
++    int i;
++    for (i = 0; i < TV_ML_NLISTS; i++) {
++	LSRedraw(ls, 0);
++	SCRedraw(&ls->scrl);
++    }
++}
++
++static void csLsRedraw(delta, sptr)
++    int delta;
++    SCRL *sptr;
++{
++    int i, j;
++    for (i = 0; i < MAXTVWIN; i++) {
++	for (j = 0; j < TV_ML_NLISTS; j++) {
++	    if (sptr == &csinfo[i].ls[j].scrl) {
++		LSRedraw(&csinfo[i].ls[j], delta);
++		return;
++	    }
++	}
++    }
++}
++
++int CharsetDelWin(win)
++    Window win;
++{
++    CSINFO *cs;
++    int i;
++
++    for (cs = csinfo, i = 0; i < TV_NCSS; cs++, i++) {
++	if (cs->win == win) {
++	    if (cs->up) {
++		XUnmapWindow(theDisp, cs->win);
++		cs->up = 0;
++	    }
++	    return 1;
++	}
++    }
++    return 0;
++}
++
++static int reg_comp PARM((const void *, const void *));
++static void create_registry_list()
++{
++    struct design d;
++    char *names, *p;
++    int i;
++
++    if ((p = names = (char *) malloc(32 * 0x80 * 2 * 2)) == NULL)
++	FatalError("out of memory in create_name_list#1.");
++    nregs = 0;
++    for (d.bpc = 1; d.bpc <=2; d.bpc++) {
++	for (d.noc = 94; d.noc <= 96; d.noc += 2) {
++	    for (d.des = ' '; (unsigned char) d.des < 0x80; d.des++) {
++		int b7;
++		char *r;
++		if ((r = lookup_registry(d, &b7)) != NULL) {
++		    sprintf(p, "%s/%s", r, b7 ? "Right" : "Left");
++		    p += strlen(p) + 1;
++		    nregs++;
++		}
++	    }
++	}
++    }
++    if ((names = (char *) realloc(names, (size_t) (p - names))) == NULL)
++	FatalError("out of memory in create_name_list#2.");
++    if ((regs = (char **) malloc(sizeof(char *) * (nregs + 3))) == NULL)
++	FatalError("out of memory in create_name_list#3.");
++    p = names;
++    for (i = 0; i < nregs; i++) {
++	regs[i] = p;
++	p += strlen(p) + 1;
++    }
++    qsort(regs, (size_t) nregs, sizeof(char *), reg_comp);
++    regs[i++] = "nothing";
++    regs[i++] = "unused";
++    regs[i++] = NULL;
++}
++static int reg_comp(dst, src)
++    const void *dst, *src;
++{
++    return strcmp(*(char **) dst, *(char **) src);
++}
+ 
++#endif /* TV_MULTILINGUAL */
+diff -ru xv-3.10a/xvtiff.c xv-3.10a-enhancements/xvtiff.c
+--- xv-3.10a/xvtiff.c	1995-01-13 11:53:34.000000000 -0800
++++ xv-3.10a-enhancements/xvtiff.c	2007-05-20 10:32:31.000000000 -0700
+@@ -1,11 +1,11 @@
+ /*
+  * xvtiff.c - load routine for 'TIFF' format pictures
+  *
+- * LoadTIFF(fname, numcols)  -  load a TIFF file
++ * LoadTIFF(fname, numcols, quick)  -  load a TIFF file
+  */
+ 
+ #ifndef va_start
+-# define NEEDSARGS
++#  define NEEDSARGS
+ #endif
+ 
+ #include "xv.h"
+@@ -15,6 +15,35 @@
+ #include "tiffio.h"     /* has to be after xv.h, as it needs varargs/stdarg */
+ 
+ 
++/* Portions fall under the following copyright:
++ *
++ * Copyright (c) 1992, 1993, 1994 Sam Leffler
++ * Copyright (c) 1992, 1993, 1994 Silicon Graphics, Inc.
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and
++ * its documentation for any purpose is hereby granted without fee, provided
++ * that (i) the above copyright notices and this permission notice appear in
++ * all copies of the software and related documentation, and (ii) the names of
++ * Sam Leffler and Silicon Graphics may not be used in any advertising or
++ * publicity relating to the software without the specific, prior written
++ * permission of Sam Leffler and Silicon Graphics.
++ *
++ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
++ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
++ *
++ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
++ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
++ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
++ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
++ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++
++static int   copyTiff    PARM((TIFF *, char *));
++static int   cpStrips    PARM((TIFF *, TIFF *));
++static int   cpTiles     PARM((TIFF *, TIFF *));
+ static byte *loadPalette PARM((TIFF *, uint32, uint32, int, int, PICINFO *));
+ static byte *loadColor   PARM((TIFF *, uint32, uint32, int, int, PICINFO *));
+ static int   loadImage   PARM((TIFF *, uint32, uint32, byte *, int));
+@@ -23,24 +52,29 @@
+ 
+ static long  filesize;
+ static byte *rmap, *gmap, *bmap;
+-static char *filename;
++static const char *filename;
+ 
+ static int   error_occurred;
+ 
++
+ /*******************************************/
+-int LoadTIFF(fname, pinfo)
+-     char *fname;
++int LoadTIFF(fname, pinfo, quick)
++     char    *fname;
+      PICINFO *pinfo;
++     int      quick;
+ /*******************************************/
+ {
+   /* returns '1' on success, '0' on failure */
+ 
+   TIFF  *tif;
+   uint32 w, h;
++  float  xres, yres;
+   short	 bps, spp, photo, orient;
+   FILE  *fp;
+   byte  *pic8;
+   char  *desc, oldpath[MAXPATHLEN+1], tmppath[MAXPATHLEN+1], *sp;
++  char   tmp[256], tmpname[256];
++  int    i, nump;
+ 
+   error_occurred = 0;
+ 
+@@ -60,6 +94,8 @@
+   filesize = ftell(fp);
+   fclose(fp);
+ 
++
++
+   rmap = pinfo->r;  gmap = pinfo->g;  bmap = pinfo->b;
+ 
+   /* a kludge:  temporarily cd to the directory that the file is in (if
+@@ -71,7 +107,7 @@
+   if (fname[0] == '/') {
+     xv_getwd(oldpath, sizeof(oldpath));
+     strcpy(tmppath, fname);
+-    sp = BaseName(tmppath);
++    sp = (char *) BaseName(tmppath);  /* intentionally losing constness */
+     if (sp != tmppath) {
+       sp[-1] = '\0';     /* truncate before last '/' char */
+       if (chdir(tmppath)) {
+@@ -80,10 +116,65 @@
+       else filename = BaseName(fname);
+     }
+   }
+-      
+-    
+ 
+-  tif=TIFFOpen(filename,"r");
++
++  nump = 1;
++
++  if (!quick) {
++    /* see if there's more than 1 image in tiff file, to determine if we
++       should do multi-page thing... */
++
++    tif = TIFFOpen(filename, "r");
++    if (!tif) return 0;
++    while (TIFFReadDirectory(tif)) ++nump;
++    TIFFClose(tif);
++    if (DEBUG)
++      fprintf(stderr,"LoadTIFF: %d page%s found\n", nump, nump==1 ? "" : "s");
++
++
++    /* if there are multiple images, copy them out to multiple tmp files,
++       and load the first one... */
++
++    if (nump>1) {
++      TIFF *in;
++
++      /* GRR 20050320:  converted this fake mktemp() to use mktemp()/mkstemp()
++         internally (formerly it simply prepended tmpdir to the string and
++         returned immediately) */
++      xv_mktemp(tmpname, "xvpgXXXXXX");
++
++      if (tmpname[0] == '\0') {   /* mktemp() or mkstemp() blew up */
++        sprintf(dummystr,"LoadTIFF: Unable to create temporary filename???");
++        ErrPopUp(dummystr, "\nHow unlikely!");
++        return 0;
++      }
++
++      /* GRR 20070506:  could clean up unappended tmpname-file here (Linux
++         bug?), but "cleaner" (more general) to do so in KillPageFiles() */
++
++      in = TIFFOpen(filename, "r");
++      if (!in) return 0;
++      for (i=1; i<=nump; i++) {
++	sprintf(tmp, "%s%d", tmpname, i);
++	if (!copyTiff(in, tmp)) {
++	  SetISTR(ISTR_WARNING, "LoadTIFF:  Error writing page files!");
++	  break;
++	}
++
++	if (!TIFFReadDirectory(in)) break;
++      }
++      TIFFClose(in);
++      if (DEBUG)
++	fprintf(stderr,"LoadTIFF: %d page%s written\n",
++		i-1, (i-1)==1 ? "" : "s");
++
++      sprintf(tmp, "%s%d", tmpname, 1);           /* start with page #1 */
++      filename = tmp;
++    }
++  }  /* if (!quick) ... */
++
++
++  tif = TIFFOpen(filename, "r");
+   if (!tif) return 0;
+ 
+   /* flip orientation so that image comes in X order */
+@@ -107,6 +198,11 @@
+   TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps);
+   TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photo);
+   TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
++  if ((TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) == 1) &&
++      (TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) == 1)) {
++    normaspect = yres / xres;
++    if (DEBUG) fprintf(stderr,"TIFF aspect = %f\n", normaspect);
++  }
+ 
+   if (spp == 1) {
+       pic8 = loadPalette(tif, w, h, photo, bps, pinfo);
+@@ -116,19 +212,19 @@
+ 
+   /* try to get comments, if any */
+   pinfo->comment = (char *) NULL;
+-  
++
+   desc = (char *) NULL;
+ 
+   TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &desc);
+   if (desc && strlen(desc) > (size_t) 0) {
+     /* kludge:  tiff library seems to return bizarre comments */
+-    if (strlen(desc)==4 && strcmp(desc, "\367\377\353\370")==0) {} 
++    if (strlen(desc)==4 && strcmp(desc, "\367\377\353\370")==0) {}
+     else {
+       pinfo->comment = (char *) malloc(strlen(desc) + 1);
+       if (pinfo->comment) strcpy(pinfo->comment, desc);
+     }
+   }
+-    
++
+   TIFFClose(tif);
+ 
+   /* un-kludge */
+@@ -139,6 +235,8 @@
+     if (pic8) free(pic8);
+     if (pinfo->comment) free(pinfo->comment);
+     pinfo->comment = (char *) NULL;
++    if (!quick && nump>1) KillPageFiles(tmpname, nump);
++    SetCursors(-1);
+     return 0;
+   }
+ 
+@@ -148,15 +246,178 @@
+   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
+   pinfo->frmType = F_TIFF;
+ 
++  if (nump>1) strcpy(pinfo->pagebname, tmpname);
++  pinfo->numpages = nump;
+ 
+   if (pinfo->pic) return 1;
+ 
++
+   /* failed.  if we malloc'd a comment, free it */
+   if (pinfo->comment) free(pinfo->comment);
+   pinfo->comment = (char *) NULL;
+ 
++  if (!quick && nump>1) KillPageFiles(tmpname, nump);
++  SetCursors(-1);
++
+   return 0;
+-}  
++}
++
++
++
++
++/*******************************************/
++
++#define CopyField(tag, v) \
++  if (TIFFGetField(in, tag, &v))            TIFFSetField(out, tag, v)
++#define CopyField2(tag, v1, v2) \
++  if (TIFFGetField(in, tag, &v1, &v2))      TIFFSetField(out, tag, v1, v2)
++#define CopyField3(tag, v1, v2, v3) \
++  if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
++
++
++/*******************************************/
++static int copyTiff(in, fname)
++     TIFF *in;
++     char *fname;
++{
++  /* copies tiff (sub)image to given filename.  (Used only for multipage
++     images.)  Returns 0 on error */
++
++  TIFF   *out;
++  short   bitspersample, samplesperpixel, shortv, *shortav;
++  uint32  w, l;
++  float   floatv, *floatav;
++  char   *stringv;
++  uint32  longv;
++  uint16 *red, *green, *blue, shortv2;
++  int     rv;
++
++  out = TIFFOpen(fname, "w");
++  if (!out) return 0;
++
++  if (TIFFGetField(in, TIFFTAG_COMPRESSION, &shortv)){
++    /* Currently, the TIFF Library cannot correctly copy TIFF version 6.0 (or
++     * earlier) files that use "old" JPEG compression, so don't even try. */
++    if (shortv == COMPRESSION_OJPEG) return 0;
++    TIFFSetField(out, TIFFTAG_COMPRESSION, shortv);
++  }
++  CopyField (TIFFTAG_SUBFILETYPE,         longv);
++  CopyField (TIFFTAG_TILEWIDTH,           w);
++  CopyField (TIFFTAG_TILELENGTH,          l);
++  CopyField (TIFFTAG_IMAGEWIDTH,          w);
++  CopyField (TIFFTAG_IMAGELENGTH,         l);
++  CopyField (TIFFTAG_BITSPERSAMPLE,       bitspersample);
++  CopyField (TIFFTAG_PREDICTOR,           shortv);
++  CopyField (TIFFTAG_PHOTOMETRIC,         shortv);
++  CopyField (TIFFTAG_THRESHHOLDING,       shortv);
++  CopyField (TIFFTAG_FILLORDER,           shortv);
++  CopyField (TIFFTAG_ORIENTATION,         shortv);
++  CopyField (TIFFTAG_SAMPLESPERPIXEL,     samplesperpixel);
++  CopyField (TIFFTAG_MINSAMPLEVALUE,      shortv);
++  CopyField (TIFFTAG_MAXSAMPLEVALUE,      shortv);
++  CopyField (TIFFTAG_XRESOLUTION,         floatv);
++  CopyField (TIFFTAG_YRESOLUTION,         floatv);
++  CopyField (TIFFTAG_GROUP3OPTIONS,       longv);
++  CopyField (TIFFTAG_GROUP4OPTIONS,       longv);
++  CopyField (TIFFTAG_RESOLUTIONUNIT,      shortv);
++  CopyField (TIFFTAG_PLANARCONFIG,        shortv);
++  CopyField (TIFFTAG_ROWSPERSTRIP,        longv);
++  CopyField (TIFFTAG_XPOSITION,           floatv);
++  CopyField (TIFFTAG_YPOSITION,           floatv);
++  CopyField (TIFFTAG_IMAGEDEPTH,          longv);
++  CopyField (TIFFTAG_TILEDEPTH,           longv);
++  CopyField2(TIFFTAG_EXTRASAMPLES,        shortv, shortav);
++  CopyField3(TIFFTAG_COLORMAP,            red, green, blue);
++  CopyField2(TIFFTAG_PAGENUMBER,          shortv, shortv2);
++  CopyField (TIFFTAG_ARTIST,              stringv);
++  CopyField (TIFFTAG_IMAGEDESCRIPTION,    stringv);
++  CopyField (TIFFTAG_MAKE,                stringv);
++  CopyField (TIFFTAG_MODEL,               stringv);
++  CopyField (TIFFTAG_SOFTWARE,            stringv);
++  CopyField (TIFFTAG_DATETIME,            stringv);
++  CopyField (TIFFTAG_HOSTCOMPUTER,        stringv);
++  CopyField (TIFFTAG_PAGENAME,            stringv);
++  CopyField (TIFFTAG_DOCUMENTNAME,        stringv);
++  CopyField2(TIFFTAG_JPEGTABLES,          longv, stringv);
++  CopyField (TIFFTAG_YCBCRCOEFFICIENTS,   floatav);
++  CopyField2(TIFFTAG_YCBCRSUBSAMPLING,    shortv,shortv2);
++  CopyField (TIFFTAG_YCBCRPOSITIONING,    shortv);
++  CopyField (TIFFTAG_REFERENCEBLACKWHITE, floatav);
++
++  if (TIFFIsTiled(in)) rv = cpTiles (in, out);
++                  else rv = cpStrips(in, out);
++
++  TIFFClose(out);
++  return rv;
++}
++
++
++/*******************************************/
++static int cpStrips(in, out)
++     TIFF *in, *out;
++{
++  tsize_t bufsize;
++  byte *buf;
++
++  bufsize = TIFFStripSize(in);
++  if (bufsize <= 0) return 0;  /* tsize_t is signed */
++  buf = (byte *) malloc((size_t) bufsize);
++  if (buf) {
++    tstrip_t s, ns = TIFFNumberOfStrips(in);
++    uint32 *bytecounts;
++
++    TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts);
++    for (s = 0; s < ns; s++) {
++      if (bytecounts[s] > bufsize) {
++	buf = (unsigned char *) realloc(buf, (size_t) bytecounts[s]);
++	if (!buf) return (0);
++	bufsize = bytecounts[s];
++      }
++      if (TIFFReadRawStrip (in,  s, buf, (tsize_t) bytecounts[s]) < 0 ||
++	  TIFFWriteRawStrip(out, s, buf, (tsize_t) bytecounts[s]) < 0) {
++	free(buf);
++	return 0;
++      }
++    }
++    free(buf);
++    return 1;
++  }
++  return 0;
++}
++
++
++/*******************************/
++static int cpTiles(in, out)
++     TIFF *in, *out;
++{
++  tsize_t bufsize;
++  byte   *buf;
++
++  bufsize = TIFFTileSize(in);
++  if (bufsize <= 0) return 0;  /* tsize_t is signed */
++  buf = (unsigned char *) malloc((size_t) bufsize);
++  if (buf) {
++    ttile_t t, nt = TIFFNumberOfTiles(in);
++    uint32 *bytecounts;
++
++    TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts);
++    for (t = 0; t < nt; t++) {
++      if (bytecounts[t] > bufsize) {
++	buf = (unsigned char *)realloc(buf, (size_t) bytecounts[t]);
++	if (!buf) return (0);
++	bufsize = bytecounts[t];
++      }
++      if (TIFFReadRawTile (in,  t, buf, (tsize_t) bytecounts[t]) < 0 ||
++	  TIFFWriteRawTile(out, t, buf, (tsize_t) bytecounts[t]) < 0) {
++	free(buf);
++	return 0;
++      }
++    }
++    free(buf);
++    return 1;
++  }
++  return 0;
++}
+ 
+ 
+ /*******************************************/
+@@ -167,6 +428,7 @@
+      PICINFO *pinfo;
+ {
+   byte *pic8;
++  uint32 npixels;
+ 
+   switch (photo) {
+   case PHOTOMETRIC_PALETTE:
+@@ -178,7 +440,7 @@
+   case PHOTOMETRIC_MINISWHITE:
+   case PHOTOMETRIC_MINISBLACK:
+     pinfo->colType = (bps==1) ? F_BWDITHER : F_GREYSCALE;
+-    sprintf(pinfo->fullInfo,"TIFF, %u-bit, %s format.  (%ld bytes)", 
++    sprintf(pinfo->fullInfo,"TIFF, %u-bit, %s format.  (%ld bytes)",
+ 	    bps,
+ 	    photo == PHOTOMETRIC_MINISWHITE ? "min-is-white" :
+ 	    "min-is-black",
+@@ -186,9 +448,16 @@
+     break;
+   }
+ 
+-  sprintf(pinfo->shrtInfo, "%ux%u TIFF.",w,h);
++  sprintf(pinfo->shrtInfo, "%ux%u TIFF.",(u_int) w, (u_int) h);
++
++  npixels = w*h;
++  if (npixels/w != h) {
++    /* SetISTR(ISTR_WARNING, "loadPalette() - image dimensions too large"); */
++    TIFFError(filename, "Image dimensions too large");
++    return (byte *) NULL;
++  }
+ 
+-  pic8 = (byte *) malloc((size_t) w*h);
++  pic8 = (byte *) malloc((size_t) npixels);
+   if (!pic8) FatalError("loadPalette() - couldn't malloc 'pic8'");
+ 
+   if (loadImage(tif, w, h, pic8, 0)) return pic8;
+@@ -205,19 +474,28 @@
+      PICINFO *pinfo;
+ {
+   byte *pic24, *pic8;
++  uint32 npixels, count;
+ 
+   pinfo->colType = F_FULLCOLOR;
+-  sprintf(pinfo->fullInfo, "TIFF, %u-bit, %s format.  (%ld bytes)", 
++  sprintf(pinfo->fullInfo, "TIFF, %u-bit, %s format.  (%ld bytes)",
+ 	  bps,
+ 	  (photo == PHOTOMETRIC_RGB ?	"RGB" :
+ 	   photo == PHOTOMETRIC_YCBCR ?	"YCbCr" :
+ 	   "???"),
+ 	  filesize);
+ 
+-  sprintf(pinfo->shrtInfo, "%ux%u TIFF.",w,h);
++  sprintf(pinfo->shrtInfo, "%ux%u TIFF.",(u_int) w, (u_int) h);
++
++  npixels = w*h;
++  count = 3*npixels;
++  if (npixels/w != h || count/3 != npixels) {
++    /* SetISTR(ISTR_WARNING, "loadPalette() - image dimensions too large"); */
++    TIFFError(filename, "Image dimensions too large");
++    return (byte *) NULL;
++  }
+ 
+   /* allocate 24-bit image */
+-  pic24 = (byte *) malloc((size_t) w*h*3);
++  pic24 = (byte *) malloc((size_t) count);
+   if (!pic24) FatalError("loadColor() - couldn't malloc 'pic24'");
+ 
+   pic8 = (byte *) NULL;
+@@ -249,7 +527,7 @@
+   vsprintf(cp, fmt, ap);
+   strcat(cp, ".");
+ 
+-  SetISTR(ISTR_WARNING,buf);
++  SetISTR(ISTR_WARNING, "%s", buf);
+ 
+   error_occurred = 1;
+ }
+@@ -273,7 +551,7 @@
+   vsprintf(cp, fmt, ap);
+   strcat(cp, ".");
+ 
+-  SetISTR(ISTR_WARNING,buf);
++  SetISTR(ISTR_WARNING, "%s", buf);
+ }
+ 
+ 
+@@ -301,10 +579,14 @@
+ static	byte **BWmap;
+ static	byte **PALmap;
+ 
+-typedef void (*tileContigRoutine)   PARM((byte*, u_char*, RGBvalue*, 
++/* XXX Work around some collisions with the new library. */
++#define tileContigRoutine _tileContigRoutine
++#define tileSeparateRoutine _tileSeparateRoutine
++
++typedef void (*tileContigRoutine)   PARM((byte*, u_char*, RGBvalue*,
+ 					  uint32, uint32, int, int));
+ 
+-typedef void (*tileSeparateRoutine) PARM((byte*, u_char*, u_char*, u_char*, 
++typedef void (*tileSeparateRoutine) PARM((byte*, u_char*, u_char*, u_char*,
+                                          RGBvalue*, uint32, uint32, int, int));
+ 
+ 
+@@ -312,13 +594,13 @@
+ 
+ static int    gt                       PARM((TIFF *, uint32, uint32, byte *));
+ static uint32 setorientation           PARM((TIFF *, uint32));
+-static int    gtTileContig             PARM((TIFF *, byte *, RGBvalue *, 
++static int    gtTileContig             PARM((TIFF *, byte *, RGBvalue *,
+ 					     uint32, uint32, int));
+-static int    gtTileSeparate           PARM((TIFF *, byte *, RGBvalue *, 
++static int    gtTileSeparate           PARM((TIFF *, byte *, RGBvalue *,
+ 					     uint32, uint32, int));
+-static int    gtStripContig            PARM((TIFF *, byte *, RGBvalue *, 
++static int    gtStripContig            PARM((TIFF *, byte *, RGBvalue *,
+ 					     uint32, uint32, int));
+-static int    gtStripSeparate          PARM((TIFF *, byte *, RGBvalue *, 
++static int    gtStripSeparate          PARM((TIFF *, byte *, RGBvalue *,
+ 					     uint32, uint32, int));
+ 
+ static int    makebwmap                PARM((void));
+@@ -340,7 +622,7 @@
+ 					     uint32, uint32, int, int));
+ static void   put4bitbwtile            PARM((byte *, u_char *, RGBvalue *,
+ 					     uint32, uint32, int, int));
+-static void   put16bitbwtile           PARM((byte *, u_char *, RGBvalue *,
++static void   put16bitbwtile           PARM((byte *, u_short *, RGBvalue *,
+ 					     uint32, uint32, int, int));
+ 
+ static void   putRGBcontig8bittile     PARM((byte *, u_char *, RGBvalue *,
+@@ -349,22 +631,38 @@
+ static void   putRGBcontig16bittile    PARM((byte *, u_short *, RGBvalue *,
+ 					     uint32, uint32, int, int));
+ 
+-static void   putRGBseparate8bittile   PARM((byte *, u_char *, u_char *, 
+-					     u_char *, RGBvalue *, 
++static void   putRGBseparate8bittile   PARM((byte *, u_char *, u_char *,
++					     u_char *, RGBvalue *,
+ 					     uint32, uint32, int, int));
+ 
+-static void   putRGBseparate16bittile  PARM((byte *, u_short *, u_short *, 
+-					    u_short *, RGBvalue *, 
++static void   putRGBseparate16bittile  PARM((byte *, u_short *, u_short *,
++					    u_short *, RGBvalue *,
+ 					    uint32, uint32, int, int));
+ 
+ 
+-static void   initYCbCrConversion     PARM((void));
++static void   initYCbCrConversion      PARM((void));
+ 
+-static void   putRGBContigYCbCrClump  PARM((byte *, u_char *, int, int, 
+-					    uint32, int, int, int));
++static void   putRGBContigYCbCrClump   PARM((byte *, u_char *, int, int,
++					     uint32, int, int, int));
+ 
+-static void   putcontig8bitYCbCrtile  PARM((byte *, u_char *, RGBvalue *,
+-					  uint32, uint32, int, int));
++static void   putRGBSeparateYCbCrClump PARM((byte *, u_char *, u_char *,
++					     u_char *, int, int, uint32, int,
++					     int, int));
++  
++static void   putRGBSeparate16bitYCbCrClump PARM((byte *, u_short *, u_short *,
++						  u_short *, int, int, uint32,
++						  int, int, int));
++
++static void   putcontig8bitYCbCrtile   PARM((byte *, u_char *, RGBvalue *,
++					     uint32, uint32, int, int));
++
++static void   putYCbCrseparate8bittile PARM((byte *, u_char *, u_char *, 
++					     u_char *, RGBvalue *, 
++					     uint32, uint32, int, int));
++
++static void   putYCbCrseparate16bittile PARM((byte *, u_short *, u_short *, 
++					      u_short *, RGBvalue *, 
++					      uint32, uint32, int, int));
+ 
+ static tileContigRoutine   pickTileContigCase   PARM((RGBvalue *));
+ static tileSeparateRoutine pickTileSeparateCase PARM((RGBvalue *));
+@@ -382,28 +680,28 @@
+ 
+   TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
+   switch (bitspersample) {
+-  case 1: 
+-  case 2: 
++  case 1:
++  case 2:
+   case 4:
+-  case 8: 
++  case 8:
+   case 16:  break;
+ 
+   default:
+     TIFFError(TIFFFileName(tif),
+-	      "Sorry, can not handle %d-bit pictures", bitspersample);
++	      "Sorry, cannot handle %d-bit pictures", bitspersample);
+     return (0);
+   }
+ 
+ 
+   TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
+   switch (samplesperpixel) {
+-  case 1: 
+-  case 3: 
++  case 1:
++  case 3:
+   case 4:  break;
+ 
+   default:
+     TIFFError(TIFFFileName(tif),
+-	      "Sorry, can not handle %d-channel images", samplesperpixel);
++	      "Sorry, cannot handle %d-channel images", samplesperpixel);
+     return (0);
+   }
+ 
+@@ -462,39 +760,81 @@
+      uint32 w, h;
+      byte   *raster;
+ {
++#ifdef USE_LIBJPEG_FOR_TIFF_YCbCr_RGB_CONVERSION
++  u_short compression;
++#endif
+   u_short minsamplevalue, maxsamplevalue, planarconfig;
+   RGBvalue *Map;
+   int bpp = 1, e;
+   int x, range;
+ 
++#ifdef USE_LIBJPEG_FOR_TIFF_YCbCr_RGB_CONVERSION
++  TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
++#endif
++  TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
+   TIFFGetFieldDefaulted(tif, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue);
+   TIFFGetFieldDefaulted(tif, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue);
+   Map = NULL;
+-  
++
+   switch (photometric) {
+   case PHOTOMETRIC_YCBCR:
+-    TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS,
+-			  &YCbCrCoeffs);
+-    TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
+-			  &YCbCrHorizSampling, &YCbCrVertSampling);
+-    TIFFGetFieldDefaulted(tif, TIFFTAG_REFERENCEBLACKWHITE,
+-			  &refBlackWhite);
+-    initYCbCrConversion();
++#ifdef USE_LIBJPEG_FOR_TIFF_YCbCr_RGB_CONVERSION
++    if (compression == COMPRESSION_JPEG
++#ifdef LIBTIFF_HAS_OLDJPEG_SUPPORT
++                                        || compression == COMPRESSION_OJPEG
++#endif
++                                                                            ) {
++      /* FIXME:  Remove the following test as soon as TIFF Library is fixed!
++       *   (Currently [June 2002] this requires supporting patches in both
++       *   tif_ojpeg.c and tif_jpeg.c in order to support subsampled YCbCr
++       *   images having separated color planes.) */
++      if (planarconfig == PLANARCONFIG_CONTIG) {
++        /* can rely on libjpeg to convert to RGB (assuming newer libtiff,
++         * compiled with appropriate forms of JPEG support) */
++        TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
++        photometric = PHOTOMETRIC_RGB;
++      } else {
++        TIFFError(filename, "Cannot handle format");
++        return (0);
++      }
++    } else
++#endif // USE_LIBJPEG_FOR_TIFF_YCbCr_RGB_CONVERSION
++    {
++      TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS, &YCbCrCoeffs);
++      TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
++			    &YCbCrHorizSampling, &YCbCrVertSampling);
++
++      /* According to the TIFF specification, if no "ReferenceBlackWhite"
++       * tag is present in the input file, "TIFFGetFieldDefaulted()" returns
++       * default reference black and white levels suitable for PHOTOMETRIC_RGB;
++       * namely:  <0,255,0,255,0,255>.  But for PHOTOMETRIC_YCBCR in JPEG
++       * images, the usual default (e.g., corresponding to the behavior of the
++       * IJG libjpeg) is:  <0,255,128,255,128,255>.  Since libtiff doesn't have
++       * a clean, standard interface for making this repair, the following
++       * slightly dirty code installs the default.  --Scott Marovich,
++       * Hewlett-Packard Labs, 9/2001.
++       */
++      if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, &refBlackWhite)) {
++        TIFFGetFieldDefaulted(tif, TIFFTAG_REFERENCEBLACKWHITE, &refBlackWhite);
++        refBlackWhite[4] = refBlackWhite[2] = 1 << (bitspersample - 1);
++      }
++      TIFFGetFieldDefaulted(tif, TIFFTAG_REFERENCEBLACKWHITE, &refBlackWhite);
++      initYCbCrConversion();
++    }
+     /* fall thru... */
+-	
++
+   case PHOTOMETRIC_RGB:
+     bpp *= 3;
+     if (minsamplevalue == 0 && maxsamplevalue == 255)
+       break;
+-	
++
+     /* fall thru... */
+   case PHOTOMETRIC_MINISBLACK:
+   case PHOTOMETRIC_MINISWHITE:
+     range = maxsamplevalue - minsamplevalue;
+     Map = (RGBvalue *)malloc((range + 1) * sizeof (RGBvalue));
+     if (Map == NULL) {
+-      TIFFError(filename,
+-		"No space for photometric conversion table");
++      TIFFError(filename, "No space for photometric conversion table");
+       return (0);
+     }
+ 
+@@ -509,7 +849,7 @@
+     if (range<256) {
+       for (x=0; x<=range; x++) rmap[x] = gmap[x] = bmap[x] = Map[x];
+     } else {
+-      for (x=0; x<256; x++) 
++      for (x=0; x<256; x++)
+ 	rmap[x] = gmap[x] = bmap[x] = Map[(range*x)/255];
+     }
+ 
+@@ -529,8 +869,7 @@
+   case PHOTOMETRIC_PALETTE:
+     if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
+ 		      &redcmap, &greencmap, &bluecmap)) {
+-      TIFFError(filename,
+-		"Missing required \"Colormap\" tag");
++      TIFFError(filename, "Missing required \"Colormap\" tag");
+       return (0);
+     }
+ 
+@@ -571,7 +910,6 @@
+     return (0);
+   }
+ 
+-  TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
+   if (planarconfig == PLANARCONFIG_SEPARATE && samplesperpixel > 1) {
+     e = TIFFIsTiled(tif) ? gtTileSeparate (tif, raster, Map, h, w, bpp) :
+                            gtStripSeparate(tif, raster, Map, h, w, bpp);
+@@ -590,6 +928,8 @@
+      TIFF *tif;
+      uint32 h;
+ {
++  /* note that orientation was flipped in LoadTIFF() (near line 175) */
++
+   uint32 y;
+ 
+   TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation);
+@@ -613,6 +953,11 @@
+     orientation = ORIENTATION_TOPLEFT;
+     /* fall thru... */
+   case ORIENTATION_TOPLEFT:
++    /* GRR 20050319:  This may be wrong for tiled images (also stripped?);
++     *   looks like we want to return th-1 instead of h-1 in at least some
++     *   cases.  For now, just added quick hack (USE_TILED_TIFF_BOTLEFT_FIX)
++     *   to gtTileContig().  (Note that, as of libtiff 3.7.1, tiffcp still
++     *   has exactly the same bug.) */
+     y = h-1;
+     break;
+   }
+@@ -623,11 +968,11 @@
+ 
+ 
+ /*
+- * Get an tile-organized image that has
++ * Get a tile-organized image that has
+  *	PlanarConfiguration contiguous if SamplesPerPixel > 1
+  * or
+  *	SamplesPerPixel == 1
+- */	
++ */
+ /*******************************************/
+ static int gtTileContig(tif, raster, Map, h, w, bpp)
+      TIFF *tif;
+@@ -642,11 +987,14 @@
+   int fromskew, toskew;
+   u_int nrow;
+   tileContigRoutine put;
++  tsize_t bufsize;
+ 
+   put = pickTileContigCase(Map);
+   if (put == 0) return (0);
+ 
+-  buf = (u_char *) malloc((size_t) TIFFTileSize(tif));
++  bufsize = TIFFTileSize(tif);
++  if (bufsize <= 0) return 0;  /* tsize_t is signed */
++  buf = (u_char *) malloc((size_t) bufsize);
+   if (buf == 0) {
+     TIFFError(filename, "No space for tile buffer");
+     return (0);
+@@ -655,12 +1003,27 @@
+   TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
+   TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
+   y = setorientation(tif, h);
++#ifdef USE_TILED_TIFF_BOTLEFT_FIX  /* image _originally_ ORIENTATION_BOTLEFT */
++  /* this fix causes tiles as a whole to be placed starting at the top,
++   * regardless of orientation; the only difference is what happens within
++   * a given tile (see toskew, below) */
++  /* GRR FIXME:  apply globally in setorientation()? */
++  if (orientation == ORIENTATION_TOPLEFT)
++    y = th-1;
++#endif
++  /* toskew causes individual tiles to copy from bottom to top for
++   * ORIENTATION_TOPLEFT and from top to bottom otherwise */
+   toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w);
+ 
+   for (row = 0; row < h; row += th) {
+     nrow = (row + th > h ? h - row : th);
+     for (col = 0; col < w; col += tw) {
+-      if (TIFFReadTile(tif,buf,(uint32)col, (uint32)row, 0, 0) < 0
++      /*
++       * This reads the tile at (col,row) into buf.  "The data placed in buf
++       * are returned decompressed and, typically, in the native byte- and
++       * bit-ordering, but are otherwise packed."
++       */
++      if (TIFFReadTile(tif, buf, (uint32)col, (uint32)row, 0, 0) < 0
+ 	  && stoponerr) break;
+ 
+       if (col + tw > w) {
+@@ -670,14 +1033,18 @@
+ 	 */
+ 	uint32 npix = w - col;
+ 	fromskew = tw - npix;
+-	(*put)(raster + (y*w + col)*bpp, buf, Map,   npix, (uint32) nrow,
+-	       fromskew, (int) ((toskew + fromskew)*bpp));
++	(*put)(raster + (y*w + col)*bpp, buf, Map, npix, (uint32) nrow,
++	       fromskew, (int) ((toskew + fromskew)*bpp) );
+       } else
+-	(*put)(raster + (y*w + col)*bpp, buf, Map,   tw,   (uint32) nrow,
++	(*put)(raster + (y*w + col)*bpp, buf, Map, tw,   (uint32) nrow,
+ 	       0, (int) (toskew*bpp));
+     }
+ 
++#ifdef USE_TILED_TIFF_BOTLEFT_FIX  /* image _originally_ ORIENTATION_BOTLEFT */
++    y += nrow;
++#else
+     y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
++#endif
+   }
+   free(buf);
+   return (1);
+@@ -687,11 +1054,11 @@
+ 
+ 
+ /*
+- * Get an tile-organized image that has
++ * Get a tile-organized image that has
+  *	 SamplesPerPixel > 1
+  *	 PlanarConfiguration separated
+  * We assume that all such images are RGB.
+- */	
++ */
+ 
+ /*******************************************/
+ static int gtTileSeparate(tif, raster, Map, h, w, bpp)
+@@ -701,20 +1068,26 @@
+      uint32 h, w;
+      int bpp;
+ {
+-  uint32 col, row, y;
+   uint32 tw, th;
++  uint32 col, row, y;
+   u_char *buf;
+   u_char *r, *g, *b;
+-  int tilesize;
++  tsize_t tilesize;
++  uint32 bufsize;
+   int fromskew, toskew;
+   u_int nrow;
+   tileSeparateRoutine put;
+-  
++
+   put = pickTileSeparateCase(Map);
+   if (put == 0) return (0);
+ 
+   tilesize = TIFFTileSize(tif);
+-  buf = (u_char *)malloc((size_t) (3*tilesize));
++  bufsize = 3*tilesize;
++  if (tilesize <= 0 || bufsize/3 != tilesize) {  /* tsize_t is signed */
++    TIFFError(filename, "Image dimensions too large");
++    return 0;
++  }
++  buf = (u_char *) malloc((size_t) bufsize);
+   if (buf == 0) {
+     TIFFError(filename, "No space for tile buffer");
+     return (0);
+@@ -751,10 +1124,10 @@
+ 	 */
+ 	uint32 npix = w - col;
+ 	fromskew = tw - npix;
+-	(*put)(raster + (y*w + col)*bpp, r, g, b, Map, npix, (uint32) nrow, 
++	(*put)(raster + (y*w + col)*bpp, r, g, b, Map, npix, (uint32) nrow,
+ 	       fromskew, (int) ((toskew + fromskew)*bpp));
+       } else
+-	(*put)(raster + (y*w + col)*bpp, r, g, b, Map, tw, (uint32) nrow, 
++	(*put)(raster + (y*w + col)*bpp, r, g, b, Map, tw, (uint32) nrow,
+ 	       0, (int) (toskew*bpp));
+     }
+     y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
+@@ -768,7 +1141,7 @@
+  *	PlanarConfiguration contiguous if SamplesPerPixel > 1
+  * or
+  *	SamplesPerPixel == 1
+- */	
++ */
+ /*******************************************/
+ static int gtStripContig(tif, raster, Map, h, w, bpp)
+      TIFF *tif;
+@@ -784,11 +1157,15 @@
+   uint32 imagewidth;
+   int scanline;
+   int fromskew, toskew;
+-  
++  tsize_t bufsize;
++
+   put = pickTileContigCase(Map);
+   if (put == 0)
+     return (0);
+-  buf = (u_char *) malloc((size_t) TIFFStripSize(tif));
++
++  bufsize = TIFFStripSize(tif);
++  if (bufsize <= 0) return 0;  /* tsize_t is signed */
++  buf = (u_char *) malloc((size_t) bufsize);
+   if (buf == 0) {
+     TIFFError(filename, "No space for strip buffer");
+     return (0);
+@@ -828,25 +1205,34 @@
+      uint32 h, w;
+      int bpp;
+ {
++  uint32 nrow, row, y;
+   u_char *buf;
+   u_char *r, *g, *b;
+-  uint32 row, y, nrow;
++  tsize_t stripsize;
++  uint32 bufsize;
++  int fromskew, toskew;
+   int scanline;
+   tileSeparateRoutine put;
+   uint32 rowsperstrip;
+   uint32 imagewidth;
+-  u_int stripsize;
+-  int fromskew, toskew;
+-  
++
+   stripsize = TIFFStripSize(tif);
+-  r = buf = (u_char *) malloc((size_t) 3*stripsize);
+-  if (buf == 0)
++  bufsize = 3*stripsize;
++  if (stripsize <= 0 || bufsize/3 != stripsize) {  /* tsize_t is signed */
++    TIFFError(filename, "Image dimensions too large");
++    return 0;
++  }
++  buf = (u_char *) malloc((size_t) bufsize);
++  if (buf == 0) {
++    TIFFError(filename, "No space for strip buffer");
+     return (0);
++  }
++  r = buf;
+   g = r + stripsize;
+   b = g + stripsize;
+   put = pickTileSeparateCase(Map);
+   if (put == 0) {
+-    TIFFError(filename, "Can not handle format");
++    TIFFError(filename, "Cannot handle format");
+     return (0);
+   }
+   y = setorientation(tif, h);
+@@ -861,7 +1247,7 @@
+     nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
+     band = 0;
+     if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, (uint32) row, band),
+-			     (tdata_t) r, (tsize_t)(nrow*scanline)) < 0 
++			     (tdata_t) r, (tsize_t)(nrow*scanline)) < 0
+ 	&& stoponerr) break;
+ 
+     band = 1;
+@@ -871,7 +1257,7 @@
+ 
+     band = 2;
+     if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, (uint32) row, band),
+-			     (tdata_t) b, (tsize_t)(nrow*scanline)) < 0 
++			     (tdata_t) b, (tsize_t)(nrow*scanline)) < 0
+ 	&& stoponerr) break;
+ 
+     (*put)(raster + y*w*bpp, r, g, b, Map, w, nrow, fromskew, toskew*bpp);
+@@ -886,7 +1272,7 @@
+ /*
+  * Greyscale images with less than 8 bits/sample are handled
+  * with a table to avoid lots of shifts and masks.  The table
+- * is setup so that put*bwtile (below) can retrieve 8/bitspersample
++ * is set up so that put*bwtile (below) can retrieve 8/bitspersample
+  * pixel values simply by indexing into the table with one
+  * number.
+  */
+@@ -895,7 +1281,7 @@
+   register int i;
+   int nsamples = 8 / bitspersample;
+   register byte *p;
+-  
++
+   BWmap = (byte **)malloc(
+ 			  256*sizeof (byte *)+(256*nsamples*sizeof(byte)));
+   if (BWmap == NULL) {
+@@ -938,18 +1324,18 @@
+ 
+ 
+ /*
+- * Palette images with <= 8 bits/sample are handled
+- * with a table to avoid lots of shifts and masks.  The table
+- * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
+- * pixel values simply by indexing into the table with one
+- * number.
++ * Palette images with <= 8 bits/sample are handled with
++ * a table to avoid lots of shifts and masks.  The table
++ * is set up so that put*cmaptile (below) can retrieve
++ * (8/bitspersample) pixel-values simply by indexing into
++ * the table with one number.
+  */
+ static int makecmap()
+ {
+   register int i;
+   int nsamples = 8 / bitspersample;
+   register byte *p;
+-  
++
+   PALmap = (byte **)malloc(
+ 			   256*sizeof (byte *)+(256*nsamples*sizeof(byte)));
+   if (PALmap == NULL) {
+@@ -994,7 +1380,7 @@
+ /*
+  * The following routines move decoded data returned
+  * from the TIFF library into rasters filled with packed
+- * ABGR pixels (i.e. suitable for passing to lrecwrite.)
++ * ABGR pixels (i.e., suitable for passing to lrecwrite.)
+  *
+  * The routines have been created according to the most
+  * important cases and optimized.  pickTileContigCase and
+@@ -1014,7 +1400,7 @@
+ #define	CASE4(x,op)	switch (x) { case 3: op; case 2: op; case 1: op; }
+ 
+ #define	UNROLL8(w, op1, op2) {		\
+-	uint32 x;		        \
++	uint32 x;	                \
+ 	for (x = w; x >= 8; x -= 8) {	\
+ 		op1;			\
+ 		REPEAT8(op2);		\
+@@ -1026,7 +1412,7 @@
+ }
+ 
+ #define	UNROLL4(w, op1, op2) {		\
+-	register uint32 x;		\
++	uint32 x;		        \
+ 	for (x = w; x >= 4; x -= 4) {	\
+ 		op1;			\
+ 		REPEAT4(op2);		\
+@@ -1038,7 +1424,7 @@
+ }
+ 
+ #define	UNROLL2(w, op1, op2) {		\
+-	register uint32 x;		\
++	uint32 x;		        \
+ 	for (x = w; x >= 2; x -= 2) {	\
+ 		op1;			\
+ 		REPEAT2(op2);		\
+@@ -1048,7 +1434,7 @@
+ 		op2;			\
+ 	}				\
+ }
+-			
++
+ 
+ #define	SKEW(r,g,b,skew)	{ r += skew; g += skew; b += skew; }
+ 
+@@ -1065,7 +1451,7 @@
+      int fromskew, toskew;
+ {
+   while (h-- > 0) {
+-    UNROLL8(w,0, *cp++ = PALmap[*pp++][0]);
++    UNROLL8(w, , *cp++ = PALmap[*pp++][0]);
+     cp += toskew;
+     pp += fromskew;
+   }
+@@ -1082,7 +1468,7 @@
+      int       fromskew, toskew;
+ {
+   register byte *bw;
+-  
++
+   fromskew /= 2;
+   while (h-- > 0) {
+     UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
+@@ -1103,7 +1489,7 @@
+      int       fromskew, toskew;
+ {
+   register byte *bw;
+-  
++
+   fromskew /= 4;
+   while (h-- > 0) {
+     UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
+@@ -1123,10 +1509,10 @@
+ 	int       fromskew, toskew;
+ {
+   register byte *bw;
+-  
++
+   fromskew /= 8;
+   while (h-- > 0) {
+-    UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
++    UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++)
+     cp += toskew;
+     pp += fromskew;
+   }
+@@ -1164,10 +1550,10 @@
+      int fromskew, toskew;
+ {
+   register byte *bw;
+-  
++
+   fromskew /= 8;
+   while (h-- > 0) {
+-    UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
++    UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++)
+     cp += toskew;
+     pp += fromskew;
+   }
+@@ -1184,7 +1570,7 @@
+      int fromskew, toskew;
+ {
+   register byte *bw;
+-  
++
+   fromskew /= 4;
+   while (h-- > 0) {
+     UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
+@@ -1204,7 +1590,7 @@
+      int fromskew, toskew;
+ {
+   register byte *bw;
+-  
++
+   fromskew /= 2;
+   while (h-- > 0) {
+     UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
+@@ -1218,17 +1604,16 @@
+  */
+ static void put16bitbwtile(cp, pp, Map, w, h, fromskew, toskew)
+      byte  *cp;
+-     u_char *pp;
++     u_short *pp;
+      RGBvalue *Map;
+      uint32 w, h;
+      int fromskew, toskew;
+ {
+   register uint32   x;
+-  
++
+   while (h-- > 0) {
+     for (x=w; x>0; x--) {
+-      *cp++ = Map[(pp[0] << 8) + pp[1]];
+-      pp += 2;
++      *cp++ = Map[*pp++];
+     }
+     cp += toskew;
+     pp += fromskew;
+@@ -1262,7 +1647,7 @@
+     }
+   } else {
+     while (h-- > 0) {
+-      UNROLL8(w,0,
++      UNROLL8(w, ,
+ 	      *cp++ = pp[0];
+ 	      *cp++ = pp[1];
+ 	      *cp++ = pp[2];
+@@ -1284,7 +1669,7 @@
+      int fromskew, toskew;
+ {
+   register u_int x;
+-  
++
+   fromskew *= samplesperpixel;
+   if (Map) {
+     while (h-- > 0) {
+@@ -1320,7 +1705,7 @@
+      RGBvalue *Map;
+      uint32 w, h;
+      int fromskew, toskew;
+-     
++
+ {
+   if (Map) {
+     while (h-- > 0) {
+@@ -1335,7 +1720,7 @@
+     }
+   } else {
+     while (h-- > 0) {
+-      UNROLL8(w,0,
++      UNROLL8(w, ,
+ 	      *cp++ = *r++;
+ 	      *cp++ = *g++;
+ 	      *cp++ = *b++;
+@@ -1357,7 +1742,7 @@
+      int fromskew, toskew;
+ {
+   uint32 x;
+-  
++
+   if (Map) {
+     while (h-- > 0) {
+       for (x = w; x > 0; x--) {
+@@ -1381,7 +1766,7 @@
+   }
+ }
+ 
+-#define Code2V(c, RB, RW, CR)  ((((c)-(int)RB)*(float)CR)/(float)(RW-RB))
++#define Code2V(c, RB, RW, CR)  (((((int)c)-(int)RB)*(float)CR)/(float)(RW-RB))
+ 
+ #define	CLAMP(f,min,max) \
+     (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
+@@ -1390,17 +1775,32 @@
+ #define	LumaGreen	YCbCrCoeffs[1]
+ #define	LumaBlue	YCbCrCoeffs[2]
+ 
+-static	float D1, D2;
+-static	float D3, D4, D5;
++static	float D1, D2, D3, D4 /*, D5 */;
+ 
+ 
+ static void initYCbCrConversion()
+ {
++  /*
++   * Old, broken version (goes back at least to 19920426; made worse 19941222):
++   *   YCbCrCoeffs[] = {0.299, 0.587, 0.114}
++   *     D1 = 1.402
++   *     D2 = 0.714136
++   *     D3 = 1.772
++   *     D4 = 0.138691  <-- bogus
++   *     D5 = 1.70358   <-- unnecessary
++   *
++   * New, fixed version (GRR 20050319):
++   *   YCbCrCoeffs[] = {0.299, 0.587, 0.114}
++   *     D1 = 1.402
++   *     D2 = 0.714136
++   *     D3 = 1.772
++   *     D4 = 0.344136
++   */
+   D1 = 2 - 2*LumaRed;
+   D2 = D1*LumaRed / LumaGreen;
+   D3 = 2 - 2*LumaBlue;
+-  D4 = D2*LumaBlue / LumaGreen;
+-  D5 = 1.0 / LumaGreen;
++  D4 = D3*LumaBlue / LumaGreen;  /* ARGH, used to be D2*LumaBlue/LumaGreen ! */
++/* D5 = 1.0 / LumaGreen; */      /* unnecessary */
+ }
+ 
+ static void putRGBContigYCbCrClump(cp, pp, cw, ch, w, n, fromskew, toskew)
+@@ -1412,7 +1812,7 @@
+ {
+   float Cb, Cr;
+   int j, k;
+-  
++
+   Cb = Code2V(pp[n],   refBlackWhite[2], refBlackWhite[3], 127);
+   Cr = Code2V(pp[n+1], refBlackWhite[4], refBlackWhite[5], 127);
+   for (j = 0; j < ch; j++) {
+@@ -1421,8 +1821,24 @@
+       Y = Code2V(*pp++,
+ 		 refBlackWhite[0], refBlackWhite[1], 255);
+       R = Y + Cr*D1;
++/*    G = Y*D5 - Cb*D4 - Cr*D2;  highly bogus! */
++      G = Y - Cb*D4 - Cr*D2;
+       B = Y + Cb*D3;
+-      G = Y*D5 - Cb*D4 - Cr*D2;
++      /*
++       * These are what the JPEG/JFIF equations--which aren't _necessarily_
++       * what JPEG/TIFF uses but which seem close enough--are supposed to be,
++       * according to Avery Lee (e.g., see http://www.fourcc.org/fccyvrgb.php):
++       *
++       *     R = Y + 1.402 (Cr-128)
++       *     G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
++       *     B = Y + 1.772 (Cb-128)
++       *
++       * Translated into xvtiff.c notation:
++       *
++       *     R = Y + Cr*D1
++       *     G = Y - Cb*D4' - Cr*D2   (i.e., omit D5 and fix D4)
++       *     B = Y + Cb*D3
++       */
+       cp[3*k+0] = CLAMP(R,0,255);
+       cp[3*k+1] = CLAMP(G,0,255);
+       cp[3*k+2] = CLAMP(B,0,255);
+@@ -1432,6 +1848,62 @@
+   }
+ }
+ 
++static void putRGBSeparateYCbCrClump(cp, y, cb, cr, cw, ch, w, n, fromskew, toskew)
++     byte *cp;
++     u_char *y, *cb, *cr;
++     int cw, ch;
++     uint32 w;
++     int n, fromskew, toskew;
++{
++  float Cb, Cr;
++  int j, k;
++  
++  Cb = Code2V(cb[0], refBlackWhite[2], refBlackWhite[3], 127);
++  Cr = Code2V(cr[0], refBlackWhite[4], refBlackWhite[5], 127);
++  for (j = 0; j < ch; j++) {
++    for (k = 0; k < cw; k++) {
++      float Y, R, G, B;
++      Y = Code2V(y[k], refBlackWhite[0], refBlackWhite[1], 255);
++      R = Y + Cr*D1;
++      G = Y - Cb*D4 - Cr*D2;
++      B = Y + Cb*D3;
++      cp[3*k+0] = CLAMP(R,0,255);
++      cp[3*k+1] = CLAMP(G,0,255);
++      cp[3*k+2] = CLAMP(B,0,255);
++    }
++    cp += w*3 + toskew;
++    y  += w + ch*fromskew;
++  }
++}
++
++static void putRGBSeparate16bitYCbCrClump(cp, y, cb, cr, cw, ch, w, n, fromskew, toskew)
++     byte *cp;
++     u_short *y, *cb, *cr;
++     int cw, ch;
++     uint32 w;
++     int n, fromskew, toskew;
++{
++  float Cb, Cr;
++  int j, k;
++  
++  Cb = Code2V(cb[0], refBlackWhite[2], refBlackWhite[3], 127);
++  Cr = Code2V(cr[0], refBlackWhite[4], refBlackWhite[5], 127);
++  for (j = 0; j < ch; j++) {
++    for (k = 0; k < cw; k++) {
++      float Y, R, G, B;
++      Y = Code2V(y[k], refBlackWhite[0], refBlackWhite[1], 255);
++      R = Y + Cr*D1;
++      G = Y - Cb*D4 - Cr*D2;
++      B = Y + Cb*D3;
++      cp[3*k+0] = CLAMP(R,0,255);
++      cp[3*k+1] = CLAMP(G,0,255);
++      cp[3*k+2] = CLAMP(B,0,255);
++    }
++    cp += w*3 + toskew;
++    y  += w + ch*fromskew;
++  }
++}
++
+ #undef LumaBlue
+ #undef LumaGreen
+ #undef LumaRed
+@@ -1452,7 +1924,7 @@
+   u_int Coff = YCbCrVertSampling * YCbCrHorizSampling;
+   byte *tp;
+   uint32 x;
+-  
++
+   /* XXX adjust fromskew */
+   while (h >= YCbCrVertSampling) {
+     tp = cp;
+@@ -1481,19 +1953,122 @@
+       pp += Coff+2;
+     }
+     if (x > 0)
+-      putRGBContigYCbCrClump(tp, pp, (int) x, (int) h, w, 
++      putRGBContigYCbCrClump(tp, pp, (int) x, (int) h, w,
+ 			     (int)Coff, (int)(YCbCrHorizSampling-x),toskew);
+   }
+ }
+ 
+ /*
++ * 8-bit unpacked YCbCr samples => RGB
++ */
++static void putYCbCrseparate8bittile(cp, y, cb, cr, Map, w, h, fromskew, toskew)
++     byte *cp;
++     u_char *y, *cb, *cr;
++     RGBvalue *Map;
++     uint32 w, h;
++     int fromskew, toskew;
++{
++  uint32 x;
++  int fromskew2 = fromskew/YCbCrHorizSampling;
++  
++  while (h >= YCbCrVertSampling) {
++    for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
++      putRGBSeparateYCbCrClump(cp, y, cb, cr, YCbCrHorizSampling,
++			       YCbCrVertSampling, w, 0, 0, toskew);
++      cp += 3*YCbCrHorizSampling;
++      y += YCbCrHorizSampling;
++      ++cb;
++      ++cr;
++    }
++    if (x > 0) {
++      putRGBSeparateYCbCrClump(cp, y, cb, cr, (int) x, YCbCrVertSampling,
++			       w, 0, (int)(YCbCrHorizSampling - x), toskew);
++      cp += x*3;
++      y += YCbCrHorizSampling;
++      ++cb;
++      ++cr;
++    }
++    cp += (YCbCrVertSampling - 1)*w*3 + YCbCrVertSampling*toskew;
++    y  += (YCbCrVertSampling - 1)*w + YCbCrVertSampling*fromskew;
++    cb += fromskew2;
++    cr += fromskew2;
++    h -= YCbCrVertSampling;
++  }
++  if (h > 0) {
++    for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
++      putRGBSeparateYCbCrClump(cp, y, cb, cr, YCbCrHorizSampling, (int) h,
++			       w, 0, 0, toskew);
++      cp += 3*YCbCrHorizSampling;
++      y += YCbCrHorizSampling;
++      ++cb;
++      ++cr;
++    }
++    if (x > 0)
++      putRGBSeparateYCbCrClump(cp, y, cb, cr, (int) x, (int) h, w, 
++			       0, (int)(YCbCrHorizSampling-x),toskew);
++  }
++}
++
++/*
++ * 16-bit unpacked YCbCr samples => RGB
++ */
++static void putYCbCrseparate16bittile(cp, y, cb, cr, Map, w, h, fromskew, toskew)
++     byte *cp;
++     u_short *y, *cb, *cr;
++     RGBvalue *Map;
++     uint32 w, h;
++     int fromskew, toskew;
++{
++  uint32 x;
++  int fromskew2 = fromskew/YCbCrHorizSampling;
++  
++  while (h >= YCbCrVertSampling) {
++    for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
++      putRGBSeparate16bitYCbCrClump(cp, y, cb, cr, YCbCrHorizSampling,
++		 		    YCbCrVertSampling, w, 0, 0, toskew);
++      cp += 3*YCbCrHorizSampling;
++      y += YCbCrHorizSampling;
++      ++cb;
++      ++cr;
++    }
++    if (x > 0) {
++      putRGBSeparate16bitYCbCrClump(cp, y, cb, cr, (int) x, YCbCrVertSampling,
++				    w, 0, (int)(YCbCrHorizSampling - x),
++				    toskew);
++      cp += x*3;
++      y += YCbCrHorizSampling;
++      ++cb;
++      ++cr;
++    }
++    cp += (YCbCrVertSampling - 1)*w*3 + YCbCrVertSampling*toskew;
++    y  += (YCbCrVertSampling - 1)*w + YCbCrVertSampling*fromskew;
++    cb += fromskew2;
++    cr += fromskew2;
++    h -= YCbCrVertSampling;
++  }
++  if (h > 0) {
++    for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
++      putRGBSeparate16bitYCbCrClump(cp, y, cb, cr, YCbCrHorizSampling, (int) h,
++				    w, 0, 0, toskew);
++      cp += 3*YCbCrHorizSampling;
++      y += YCbCrHorizSampling;
++      ++cb;
++      ++cr;
++    }
++    if (x > 0)
++      putRGBSeparate16bitYCbCrClump(cp, y, cb, cr, (int) x, (int) h, w, 
++			 	    0, (int)(YCbCrHorizSampling-x),toskew);
++  }
++}
++
++/*
+  * Select the appropriate conversion routine for packed data.
+  */
+ static tileContigRoutine pickTileContigCase(Map)
+      RGBvalue* Map;
+ {
+   tileContigRoutine put = 0;
+-  
++
+   switch (photometric) {
+   case PHOTOMETRIC_RGB:
+     switch (bitspersample) {
+@@ -1501,7 +2076,7 @@
+     case 16: put = (tileContigRoutine) putRGBcontig16bittile;  break;
+     }
+     break;
+-    
++
+   case PHOTOMETRIC_PALETTE:
+     switch (bitspersample) {
+     case 8: put = put8bitcmaptile; break;
+@@ -1514,7 +2089,7 @@
+   case PHOTOMETRIC_MINISWHITE:
+   case PHOTOMETRIC_MINISBLACK:
+     switch (bitspersample) {
+-    case 16: put = put16bitbwtile; break;
++    case 16: put = (tileContigRoutine) put16bitbwtile; break;
+     case 8:  put = putgreytile;    break;
+     case 4:  put = put4bitbwtile;  break;
+     case 2:  put = put2bitbwtile;  break;
+@@ -1529,7 +2104,7 @@
+     break;
+   }
+ 
+-  if (put==0) TIFFError(filename, "Can not handle format");
++  if (put==0) TIFFError(filename, "Cannot handle format");
+   return (put);
+ }
+ 
+@@ -1537,14 +2112,14 @@
+ /*
+  * Select the appropriate conversion routine for unpacked data.
+  *
+- * NB: we assume that unpacked single channel data is directed
+- *	 to the "packed routines.
++ * NB: we assume that unpacked single-channel data is directed
++ *	 to the "packed" routines.
+  */
+ static tileSeparateRoutine pickTileSeparateCase(Map)
+      RGBvalue* Map;
+ {
+   tileSeparateRoutine put = 0;
+-  
++
+   switch (photometric) {
+   case PHOTOMETRIC_RGB:
+     switch (bitspersample) {
+@@ -1552,12 +2127,41 @@
+     case 16: put = (tileSeparateRoutine) putRGBseparate16bittile; break;
+     }
+     break;
++
++  case PHOTOMETRIC_YCBCR:
++    switch (bitspersample) {
++    case  8: put = (tileSeparateRoutine) putYCbCrseparate8bittile;  break;
++    case 16: put = (tileSeparateRoutine) putYCbCrseparate16bittile; break;
++    }
++    break;
+   }
+ 
+-  if (put==0) TIFFError(filename, "Can not handle format");
++  if (put==0) TIFFError(filename, "Cannot handle format");
+   return (put);
+ }
+ 
+ 
+ 
++/*******************************************/
++void
++VersionInfoTIFF()      /* GRR 19980605 */
++{
++  char temp[1024], *p, *q;
++
++  strcpy(temp, TIFFGetVersion());
++  p = temp;
++  while (!isdigit(*p))
++    ++p;
++  if ((q = strchr(p, '\n')) != NULL)
++    *q = '\0';
++
++  fprintf(stderr, "   Compiled with libtiff %s", p);
++#ifdef TIFFLIB_VERSION
++  fprintf(stderr, " of %d", TIFFLIB_VERSION);    /* e.g., 19960307 */
++#endif
++  fprintf(stderr, ".\n");
++}
++
++
++
+ #endif /* HAVE_TIFF */
+diff -ru xv-3.10a/xvtiffwr.c xv-3.10a-enhancements/xvtiffwr.c
+--- xv-3.10a/xvtiffwr.c	1995-01-03 13:28:13.000000000 -0800
++++ xv-3.10a-enhancements/xvtiffwr.c	2007-05-12 14:07:58.000000000 -0700
+@@ -9,15 +9,15 @@
+ 
+ #ifdef HAVE_TIFF
+ 
+-#include "tiffio.h"    /* has to be after xv.h, as it needs varargs/stdarg */
++#include <tiffio.h>    /* has to be after xv.h, as it needs varargs/stdarg */
+ 
+ 
+ #define ALLOW_JPEG 0  /* set to '1' to allow 'JPEG' choice in dialog box */
+ 
+ 
+ static void setupColormap   PARM((TIFF *, byte *, byte *, byte *));
+-static int  WriteTIFF       PARM((FILE *, byte *, int, int, int, 
+-				  byte *, byte *, byte *, int, int, 
++static int  WriteTIFF       PARM((FILE *, byte *, int, int, int,
++				  byte *, byte *, byte *, int, int,
+ 				  char *, int, char *));
+ 
+ 
+@@ -29,7 +29,7 @@
+ {
+   short red[256], green[256], blue[256];
+   int i;
+-  
++
+   /* convert 8-bit colormap to 16-bit */
+   for (i=0; i<256; i++) {
+ #define	SCALE(x)	((((int)x)*((1L<<16)-1))/255)
+@@ -43,6 +43,7 @@
+ 
+ 
+ /*******************************************/
++/* Returns '0' if successful. */
+ static int WriteTIFF(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,
+ 		     fname,comp,comment)
+      FILE *fp;
+@@ -55,6 +56,13 @@
+   TIFF *tif;
+   byte *pix;
+   int   i,j;
++  int   npixels = w*h;
++
++  if (w <= 0 || h <= 0 || npixels/w != h) {
++    SetISTR(ISTR_WARNING, "%s: image dimensions too large", fname);
++    /* TIFFError(fname, "Image dimensions too large"); */
++    return -1;
++  }
+ 
+ #ifndef VMS
+   tif = TIFFOpen(fname, "w");
+@@ -62,7 +70,7 @@
+   tif = TIFFFdOpen(dup(fileno(fp)), fname, "w");
+ #endif
+ 
+-  if (!tif) return 0;
++  if (!tif) return -1;   /* GRR:  was 0 */
+ 
+   WaitCursor();
+ 
+@@ -78,25 +86,36 @@
+       TIFFSetField(tif, TIFFTAG_GROUP3OPTIONS,
+ 	  GROUP3OPT_2DENCODING+GROUP3OPT_FILLBITS);
+ 
++  if (comp == COMPRESSION_LZW)
++      TIFFSetField(tif, TIFFTAG_PREDICTOR, 2);
++
+   TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+   TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
+   TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
+   TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, h);
+ 
+   TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (int)2);
+-  TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)1200.0);
+-  TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)1200.0);
++  TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float) 72.0);
++  TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float) 72.0);
+ 
+ 
+   /* write the image data */
+ 
+   if (ptype == PIC24) {  /* only have to deal with FULLCOLOR or GREYSCALE */
+     if (colorstyle == F_FULLCOLOR) {
++      int count = 3*npixels;
++
++      if (count/3 != npixels) {  /* already know w, h, npixels > 0 */
++        /* SetISTR(ISTR_WARNING, "%s: image dimensions too large", fname); */
++        TIFFError(fname, "Image dimensions too large");
++        return -1;
++      }
++
+       TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
+       TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE,   8);
+       TIFFSetField(tif, TIFFTAG_PHOTOMETRIC,     PHOTOMETRIC_RGB);
+-      
+-      TIFFWriteEncodedStrip(tif, 0, pic, w*h*3);
++
++      TIFFWriteEncodedStrip(tif, 0, pic, count);
+     }
+ 
+     else {  /* colorstyle == F_GREYSCALE */
+@@ -106,13 +125,13 @@
+       TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE,   8);
+       TIFFSetField(tif, TIFFTAG_PHOTOMETRIC,    PHOTOMETRIC_MINISBLACK);
+ 
+-      tpic = (byte *) malloc((size_t) w*h);
++      tpic = (byte *) malloc((size_t) npixels);
+       if (!tpic) FatalError("unable to malloc in WriteTIFF()");
+ 
+-      for (i=0, tp=tpic, sp=pic; i<w*h; i++, sp+=3) 
++      for (i=0, tp=tpic, sp=pic; i<npixels; i++, sp+=3)
+ 	*tp++ = MONO(sp[0],sp[1],sp[2]);
+-      
+-      TIFFWriteEncodedStrip(tif, 0, tpic, w*h);
++
++      TIFFWriteEncodedStrip(tif, 0, tpic, npixels);
+ 
+       free(tpic);
+     }
+@@ -123,32 +142,42 @@
+       TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+       TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
+       setupColormap(tif, rmap, gmap, bmap);
+-      TIFFWriteEncodedStrip(tif, 0, pic, w*h);
++      TIFFWriteEncodedStrip(tif, 0, pic, npixels);
+     }
+ 
+     else if (colorstyle == F_GREYSCALE) {             /* 8-bit greyscale */
+       byte rgb[256];
+-      byte *tpic = (byte *) malloc((size_t) w*h);
++      byte *tpic = (byte *) malloc((size_t) npixels);
+       byte *tp = tpic;
+       TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+       TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
+       for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
+-      for (i=0, pix=pic; i<w*h; i++,pix++) {
++      for (i=0, pix=pic; i<npixels; i++,pix++) {
+ 	if ((i&0x7fff)==0) WaitCursor();
+ 	*tp++ = rgb[*pix];
+       }
+-      TIFFWriteEncodedStrip(tif, 0, tpic, w*h);
++      TIFFWriteEncodedStrip(tif, 0, tpic, npixels);
+       free(tpic);
+     }
+ 
+     else if (colorstyle == F_BWDITHER) {             /* 1-bit B/W stipple */
+       int bit,k,flipbw;
+       byte *tpic, *tp;
++      tsize_t stripsize;  /* signed */
+ 
+       flipbw = (MONO(rmap[0],gmap[0],bmap[0]) > MONO(rmap[1],gmap[1],bmap[1]));
+       TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1);
+       TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
+-      tpic = (byte *) malloc((size_t) TIFFStripSize(tif));
++      stripsize = TIFFStripSize(tif);
++      if (stripsize <= 0) {
++        TIFFError(fname, "Image dimensions too large");
++        return -1;
++      }
++      tpic = (byte *) malloc((size_t) stripsize);
++      if (tpic == 0) {
++        TIFFError(fname, "No space for strip buffer");
++        return -1;
++      }
+       tp = tpic;
+       for (i=0, pix=pic; i<h; i++) {
+ 	if ((i&15)==0) WaitCursor();
+@@ -167,7 +196,7 @@
+ 	  *tp++ = (byte) (k & 0xff);
+ 	}
+       }
+-      TIFFWriteEncodedStrip(tif, 0, tpic, TIFFStripSize(tif));
++      TIFFWriteEncodedStrip(tif, 0, tpic, stripsize);
+       free(tpic);
+     }
+   }
+@@ -209,16 +238,16 @@
+ {
+   int	     y;
+ 
+-  tiffW = CreateWindow("xv tiff", "XVtiff", NULL, 
++  tiffW = CreateWindow("xv tiff", "XVtiff", NULL,
+ 		       TWIDE, THIGH, infofg, infobg, 0);
+   if (!tiffW) FatalError("can't create tiff window!");
+ 
+   XSelectInput(theDisp, tiffW, ExposureMask | ButtonPressMask | KeyPressMask);
+ 
+-  BTCreate(&tbut[T_BOK], tiffW, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH, 
++  BTCreate(&tbut[T_BOK], tiffW, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH,
+ 	   "Ok", infofg, infobg, hicol, locol);
+ 
+-  BTCreate(&tbut[T_BCANC], tiffW, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH, 
++  BTCreate(&tbut[T_BCANC], tiffW, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH,
+ 	   "Cancel", infofg, infobg, hicol, locol);
+ 
+   y = 55;
+@@ -237,7 +266,7 @@
+ 
+   XMapSubwindows(theDisp, tiffW);
+ }
+-  
++
+ 
+ /***************************************************/
+ void TIFFDialog(vis)
+@@ -288,9 +317,9 @@
+ 
+   else if (xev->type == KeyPress) {
+     XKeyEvent *e = (XKeyEvent *) xev;
+-    char buf[128];  KeySym ks;  XComposeStatus status;  
++    char buf[128];  KeySym ks;  XComposeStatus status;
+     int stlen;
+-	
++
+     stlen = XLookupString(e,buf,128,&ks,&status);
+     buf[stlen] = '\0';
+ 
+@@ -350,7 +379,7 @@
+ static void drawTD(x,y,w,h)
+ int x,y,w,h;
+ {
+-  char *title  = "Save TIFF file...";
++  const char *title  = "Save TIFF file...";
+   int  i;
+   XRectangle xr;
+ 
+@@ -381,7 +410,7 @@
+   /* check BUTTs */
+ 
+   /* check the RBUTTS first, since they don't DO anything */
+-  if ( (i=RBClick(compRB, x,y)) >= 0) { 
++  if ( (i=RBClick(compRB, x,y)) >= 0) {
+     (void) RBTrack(compRB, i);
+     return;
+   }
+@@ -417,7 +446,7 @@
+     }
+   }
+     break;
+-    
++
+   case T_BCANC:	TIFFDialog(0);   break;
+ 
+   default:	break;
+diff -ru xv-3.10a/xvxbm.c xv-3.10a-enhancements/xvxbm.c
+--- xv-3.10a/xvxbm.c	1994-12-22 14:34:41.000000000 -0800
++++ xv-3.10a-enhancements/xvxbm.c	2007-05-13 17:45:48.000000000 -0700
+@@ -25,9 +25,9 @@
+  *   move forward to next occurence of '0x'
+  *   repeat
+  */
+- 
+ 
+-static int xbmError PARM((char *, char *));
++
++static int xbmError PARM((const char *, const char *));
+ 
+ 
+ /*******************************************/
+@@ -44,7 +44,7 @@
+   long   filesize;
+   char   line[256], name[256];
+   byte   hex[256];
+-  char  *bname;
++  const char  *bname;
+ 
+   k = 0;
+ 
+@@ -59,7 +59,7 @@
+ 
+   /* read width:  skip lines until we hit a #define */
+   while (1) {
+-    if (!fgets(line,256,fp)) 
++    if (!fgets(line,256,fp))
+       return(xbmError(bname, "EOF reached in header info."));
+ 
+     if (strncmp(line,"#define",    (size_t) 7)==0 &&
+@@ -70,9 +70,9 @@
+ 
+   /* read height:  skip lines until we hit another #define */
+   while (1) {
+-    if (!fgets(line,256,fp)) 
++    if (!fgets(line,256,fp))
+       return(xbmError(bname, "EOF reached in header info."));
+-    
++
+     if (strncmp(line,"#define",    (size_t) 7)==0 &&
+ 	sscanf(line,"#define %s %d", name, &h)==2 &&
+ 	xv_strstr(name, "_height") != NULL) break;
+@@ -84,18 +84,18 @@
+   c = getc(fp);  c1 = getc(fp);
+   while (c1!=EOF && !(c=='0' && c1=='x') ) { c = c1;  c1 = getc(fp); }
+ 
+-  if (c1==EOF) 
++  if (c1==EOF)
+     return(xbmError(bname, "No bitmap data found"));
+ 
+-  if (w<1 || h<1 || w>10000 || h>10000) 
++  if (w<1 || h<1 || w>10000 || h>10000)
+     return(xbmError(bname, "not an XBM file"));
+-  
+-  pic8 = (byte *) calloc((size_t) w*h, (size_t) 1);
++
++  pic8 = (byte *) calloc((size_t) w*h, (size_t) 1);  /* safe (10^8 max) */
+   if (!pic8) return(xbmError(bname, "couldn't malloc 'pic8'"));
+ 
+   /* load up the pinfo structure */
+   pinfo->pic = pic8;
+-  pinfo->w = w;     
++  pinfo->w = w;
+   pinfo->h = h;
+   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
+   pinfo->type = PIC8;
+@@ -120,18 +120,18 @@
+   /* read/convert the image data */
+ 
+   for (i=0, pix=pic8; i<h; i++)
+-    for (j=0,bit=0; j<w; j++, pix++, bit = (++bit)&7) {
++    for (j=0,bit=0; j<w; j++, pix++, bit = (bit+1)&7) {
+ 
+       if (!bit) {
+ 	/* get next byte from file.  we're already positioned at it */
+ 	c = getc(fp);  c1 = getc(fp);
+-	if (c<0 || c1<0) { 
+-	  /* EOF: break out of loop */	  
++	if (c<0 || c1<0) {
++	  /* EOF: break out of loop */
+ 	  c=c1='0'; i=h; j=w;
+ 	  xbmError(bname, "The file would appear to be truncated.");
+ 	}
+ 
+-	if (hex[c1] == 255) {  
++	if (hex[c1] == 255) {
+ 	  if (hex[c] == 255) k = 0;   /* no digits after the '0x' ... */
+ 	  else k = hex[c];
+ 	}
+@@ -149,13 +149,13 @@
+   fclose(fp);
+ 
+   return 1;
+-}  
++}
+ 
+ 
+ 
+ /*******************************************/
+ static int xbmError(fname, st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
+   return 0;
+@@ -172,7 +172,7 @@
+ {
+   /* pic is expected to be an array of w*h bytes, each of which is either
+      '0' or '1'.
+-     The 'darker' of {rmap,gmap,bmap}[0] and {rmap,gmap,bmap}[1] is 
++     The 'darker' of {rmap,gmap,bmap}[0] and {rmap,gmap,bmap}[1] is
+      considered black, and the other one, white.
+      Some sort of stippling algorithm should've
+      been called already to produce pic, otherwise the output won't be at all
+@@ -182,13 +182,12 @@
+   byte *pix;
+   char name[256], *foo;
+ 
+-  foo = BaseName(fname);
+-  strcpy(name, foo);
++  strcpy(name, BaseName(fname));
+ 
+   foo = (char *) index(name,'.');
+   if (foo) *foo='\0';                 /* truncated name at first '.' */
+ 
+-  fprintf(fp,"#define %s_width %d\n",name,w);  
++  fprintf(fp,"#define %s_width %d\n",name,w);
+   fprintf(fp,"#define %s_height %d\n",name,h);
+   fprintf(fp,"static char %s_bits[] = {\n",name);
+ 
+diff -ru xv-3.10a/xvxpm.c xv-3.10a-enhancements/xvxpm.c
+--- xv-3.10a/xvxpm.c	1994-12-22 14:34:42.000000000 -0800
++++ xv-3.10a-enhancements/xvxpm.c	2007-05-13 17:52:21.000000000 -0700
+@@ -10,7 +10,7 @@
+  * format images.
+  *
+  * Thanks go to Sam Yates (syates at spam.maths.adelaide.edu.au) for
+- * provideing inspiration.
++ * providing inspiration.
+  */
+ 
+ #define VALUES_LEN	80	/* Max length of values line */
+@@ -48,8 +48,8 @@
+                                 /*  a quoted string? */
+ 
+ /* Local Functions */
+-static int     XpmLoadError  PARM((char*, char*));
+-static int     XpmGetc	     PARM((FILE*));
++static int     XpmLoadError  PARM((const char *, const char *));
++static int     XpmGetc	     PARM((FILE *));
+ static int     hash          PARM((char *));
+ static int     hash_init     PARM((int));
+ static int     hash_insert   PARM((hentry *));
+@@ -63,110 +63,128 @@
+      PICINFO *pinfo;
+ {
+   /* returns '1' on success */
+-  
++
+   FILE    *fp;
+   hentry   item;
+   int      c;
+-  char    *bname;
++  const char *bname;
+   char     values[VALUES_LEN];
+   byte    *pic;
+   byte    *i_sptr;		/* image search pointer */
+   long     filesize;
+   int      w, h, nc, cpp, line_pos;
++  int      npixels;
+   short    i, j, k;		/* for() loop indexes */
+   hentry  *clmp;		/* colormap hash-table */
+   hentry  *c_sptr;		/* cmap hash-table search pointer*/
+   XColor   col;
+-  
++
+   bname = BaseName(fname);
+   fp = fopen(fname, "r");
+   if (!fp)
+     return (XpmLoadError(bname, "couldn't open file"));
+-  
++
+   if (DEBUG)
+     printf("LoadXPM(): Loading xpm from %s\n", fname);
+-  
++
+   fseek(fp, 0L, 2);
+   filesize = ftell(fp);
+   fseek(fp, 0L, 0);
+-  
++
+   bufchar = -2;
+   in_quote = FALSE;
+-  
++
+   /* Read in the values line.  It is the first string in the
+    * xpm, and contains four numbers.  w, h, num_colors, and
+    * chars_per_pixel. */
+-  
++
+   /* First, get to the first string */
+   while (((c = XpmGetc(fp))!=EOF) && (c != '"')) ;
+   line_pos = 0;
+-  
++
+   /* Now, read in the string */
+   while (((c = XpmGetc(fp))!=EOF) && (line_pos < VALUES_LEN) && (c != '"')) {
+     values[line_pos++] = c;
+   }
+   if (c != '"')
+     return (XpmLoadError(bname, "error parsing values line"));
+-  
++
+   values[line_pos] = '\0';
+   sscanf(values, "%d%d%d%d", &w, &h, &nc, &cpp);
+   if (nc <= 0 || cpp <= 0)
+     return (XpmLoadError(bname, "No colours in Xpm?"));
+-  
++
++  npixels = w * h;
++  if (w <= 0 || h <= 0 || npixels/w != h)
++    return (XpmLoadError(bname, "Image dimensions out of range"));
++
+   if (nc > 256)
+     pinfo->type = PIC24;
+   else
+     pinfo->type = PIC8;
+-  
++
+   if (DEBUG)
+     printf("LoadXPM(): reading a %dx%d image (%d colors)\n", w, h, nc);
+-  
++
+   /* We got this far... */
+   WaitCursor();
+-  
++
+   if (!hash_init(nc))
+     return (XpmLoadError(bname, "Not enough memory to hash colormap"));
+-  
++
+   clmp = (hentry *) malloc(nc * sizeof(hentry)); /* Holds the colormap */
+-  if (pinfo->type == PIC8) pic = (byte *) malloc((size_t) (w*h));
+-                      else pic = (byte *) malloc((size_t) (w*h*3));
+-  
++  if (pinfo->type == PIC8)
++    pic = (byte *) malloc((size_t) npixels);
++  else {
++    int bufsize = 3*npixels;
++    if (bufsize/3 != npixels)
++      return (XpmLoadError(bname, "Image dimensions out of range"));
++    pic = (byte *) malloc((size_t) bufsize);
++  }
++
+   if (!clmp || !pic)
+     return (XpmLoadError(bname, "Not enough memory to load pixmap"));
+-  
++
+   c_sptr = clmp;
+   i_sptr = pic;
+-  
++
+   /* initialize the 'hex' array for zippy ASCII-hex -> int conversion */
+-  
++
+   for (i = 0 ; i < 256 ; i++)   hex[i] = 0;
+   for (i = '0'; i <= '9' ; i++) hex[i] = i - '0';
+   for (i = 'a'; i <= 'f' ; i++) hex[i] = i - 'a' + 10;
+   for (i = 'A'; i <= 'F' ; i++) hex[i] = i - 'A' + 10;
+-  
++
+   /* Again, we've made progress. */
+   WaitCursor();
+-  
++
+   /* Now, we need to read the colormap. */
+   pinfo->colType = F_BWDITHER;
+   for (i = 0 ; i < nc ; i++) {
+     while (((c = XpmGetc(fp))!=EOF) && (c != '"')) ;
+     if (c != '"')
+       return (XpmLoadError(bname, "Error reading colormap"));
+-    
++
+     for (j = 0 ; j < cpp ; j++)
+       c_sptr->token[j] = XpmGetc(fp);
+     c_sptr->token[j] = '\0';
+-    
++
+     while (((c = XpmGetc(fp))!=EOF) && ((c == ' ') || (c == '\t'))) ;
+     if (c == EOF)		/* The failure condition of getc() */
+       return (XpmLoadError(bname, "Error parsing colormap line"));
+-    
++
+     do {
+       char  key[3];
+-      char  color[40];	/* Need to figure a good size for this... */
+-      short hd;		/* Hex digits per R, G, or B */
+-      
++      char  color[80];	/* Need to figure a good size for this... */
++
++/*
++ *  Problem with spaces in color names
++ *
++ *    X s Color Name m Other Name c Last Name
++ *
++ *  ... this parser doesn't find `Any Name'
++ */
++
+       for (j=0; j<2 && (c != ' ') && (c != '\t') && (c != EOF); j++) {
+ 	key[j] = c;
+ 	c = XpmGetc(fp);
+@@ -177,7 +195,7 @@
+       if (c == EOF)	/* The failure condition of getc() */
+ 	return (XpmLoadError(bname, "Error parsing colormap line"));
+ 
+-      for (j=0; j<39 && (c!=' ') && (c!='\t') && (c!='"') && c!=EOF; j++) {
++      for (j=0; j<79 && (c!=' ') && (c!='\t') && (c!='"') && c!=EOF; j++) {
+ 	color[j] = c;
+ 	c = XpmGetc(fp);
+       }
+@@ -185,14 +203,14 @@
+ 
+       while ((c == ' ') || (c == '\t'))
+ 	c = XpmGetc(fp);
+-      
++
+       if (DEBUG > 1)
+ 	printf("LoadXPM(): Got color key '%s', color '%s'\n",
+ 	       key, color);
+-      
++
+       if (key[0] == 's')	/* Don't find a color for a symbolic name */
+ 	continue;
+-      
++
+       if (XParseColor(theDisp,theCmap,color,&col)) {
+ 	if (pinfo->type == PIC8) {
+ 	  pinfo->r[i] = col.red >> 8;
+@@ -201,8 +219,8 @@
+ 	  c_sptr->cv_index = i;
+ 
+ 	  /* Is there a better way to do this? */
+-	  if (pinfo->colType != F_FULLCOLOR)
+-	    if (pinfo->colType == F_GREYSCALE)
++	  if (pinfo->colType != F_FULLCOLOR) {
++	    if (pinfo->colType == F_GREYSCALE) {
+ 	      if (pinfo->r[i] == pinfo->g[i] &&
+ 		  pinfo->g[i] == pinfo->b[i])
+ 		/* Still greyscale... */
+@@ -210,9 +228,9 @@
+ 	      else
+ 		/* It's color */
+ 		pinfo->colType = F_FULLCOLOR;
+-	    else
++	    } else {
+ 	      if (pinfo->r[i] == pinfo->g[i] &&
+-		  pinfo->g[i] == pinfo->b[i])
++		  pinfo->g[i] == pinfo->b[i]) {
+ 		if ((pinfo->r[i] == 0 || pinfo->r[i] == 0xff) &&
+ 		    (pinfo->g[i] == 0 || pinfo->g[i] == 0xff) &&
+ 		    (pinfo->b[i] == 0 || pinfo->b[i] == 0xff))
+@@ -221,10 +239,12 @@
+ 		else
+ 		  /* It's greyscale */
+ 		  pinfo->colType = F_GREYSCALE;
+-	      else
++	      } else
+ 		/* It's color */
+ 		pinfo->colType = F_FULLCOLOR;
+-	  
++	    }
++	  }
++
+ 	}
+ 	else {   /* PIC24 */
+ 	  c_sptr->cv_rgb[0] = col.red >> 8;
+@@ -236,13 +256,13 @@
+       else {      /* 'None' or unrecognized color spec */
+ 	int rgb;
+ 
+-	if (strcmp(color, "None") == 0) rgb = 0xb2c0dc;  /* infobg */
++	if (strcasecmp(color, "None") == 0) rgb = 0xb2c0dc;  /* infobg */
+ 	else {
+ 	  SetISTR(ISTR_INFO, "%s:  unknown color spec '%s'", bname, color);
+ 	  Timer(1000);
+ 	  rgb = 0x808080;
+ 	}
+-	
++
+ 	if (pinfo->type == PIC8) {
+ 	  pinfo->r[i] = (rgb>>16) & 0xff;
+ 	  pinfo->g[i] = (rgb>> 8) & 0xff;
+@@ -256,39 +276,39 @@
+ 	}
+       }
+ 
+-      
++
+       xvbcopy((char *) c_sptr, (char *) &item, sizeof(item));
+       hash_insert(&item);
+-      
+-      if (DEBUG > 1) 
++
++      if (DEBUG > 1)
+ 	printf("LoadXPM():  Cmap entry %d, 0x%02x 0x%02x 0x%02x, token '%s'\n",
+ 	       i, pinfo->r[i], pinfo->g[i], pinfo->b[i], c_sptr->token);
+-      
++
+       if (*key == 'c') {	/* This is the color entry, keep it. */
+ 	while (c!='"' && c!=EOF) c = XpmGetc(fp);
+ 	break;
+       }
+-      
++
+     } while (c != '"');
+     c_sptr++;
+ 
+     if (!(i%13)) WaitCursor();
+   } /* for */
+-  
++
+ 
+   if (DEBUG)
+     printf("LoadXPM(): Read and stored colormap.\n");
+-  
++
+   /* Now, read the pixmap. */
+   for (i = 0 ; i < h ; i++) {
+     while (((c = XpmGetc(fp))!=EOF) && (c != '"')) ;
+     if (c != '"')
+       return (XpmLoadError(bname, "Error reading colormap"));
+-    
++
+     for (j = 0 ; j < w ; j++) {
+       char pixel[TOKEN_LEN];
+       hentry *mapentry;
+-      
++
+       for (k = 0 ; k < cpp ; k++)
+ 	pixel[k] = XpmGetc(fp);
+       pixel[k] = '\0';
+@@ -300,7 +320,7 @@
+ 		 pixel);
+ 	return (XpmLoadError(bname, "Can't map resolve into colormap"));
+       }
+-      
++
+       if (pinfo->type == PIC8)
+ 	*i_sptr++ = mapentry->cv_index;
+       else {
+@@ -309,35 +329,36 @@
+ 	*i_sptr++ = mapentry->cv_rgb[2];
+       }
+     }  /* for ( j < w ) */
+-    (void)XpmGetc(fp);		/* Throw away the close " */
+-  
++    while (((c = XpmGetc(fp))!=EOF) &&		/* Throw away the close " and */
++	(c != '"'));				/* erase all remaining pixels */
++
+     if (!(i%7)) WaitCursor();
+   }  /* for ( i < h ) */
+-  
++
+   pinfo->pic = pic;
+   pinfo->normw = pinfo->w = w;
+   pinfo->normh = pinfo->h = h;
+   pinfo->frmType = F_XPM;
+ 
+   if (DEBUG) printf("LoadXPM(): pinfo->colType is %d\n", pinfo->colType);
+-  
++
+   sprintf(pinfo->fullInfo, "Xpm v3 Pixmap (%ld bytes)", filesize);
+   sprintf(pinfo->shrtInfo, "%dx%d Xpm.", w, h);
+   pinfo->comment = (char *)NULL;
+-  
++
+   hash_destroy();
+   free(clmp);
+-  
++
+   if (fp != stdin)
+     fclose(fp);
+-  
++
+   return(1);
+ }
+ 
+ 
+ /***************************************/
+ static int XpmLoadError(fname, st)
+-     char *fname, *st;
++     const char *fname, *st;
+ {
+   SetISTR(ISTR_WARNING, "%s:  %s", fname, st);
+   return 0;
+@@ -349,17 +370,17 @@
+      FILE *f;
+ {
+   int	c, d, lastc;
+-  
++
+   if (bufchar != -2) {
+     /* The last invocation of this routine read the character... */
+     c = bufchar;
+     bufchar = -2;
+     return(c);
+   }
+-  
++
+   if ((c = getc(f)) == EOF)
+     return(EOF);
+-  
++
+   if (c == '"')
+     in_quote = !in_quote;
+   else if (!in_quote && c == '/') {	/* might be a C-style comment */
+@@ -389,14 +410,14 @@
+ 
+ 
+ /***************************************/
+-static int hash(token) 
++static int hash(token)
+      char *token;
+ {
+   int i, sum;
+ 
+   for (i=sum=0; token[i] != '\0'; i++)
+     sum += token[i];
+-  
++
+   sum = sum % hash_len;
+   return (sum);
+ }
+@@ -414,7 +435,7 @@
+    */
+ 
+   int i;
+-  
++
+   hash_len = 257;
+ 
+   hashtab = (hentry **) malloc(sizeof(hentry *) * hash_len);
+@@ -425,7 +446,7 @@
+ 
+   for (i = 0 ; i < hash_len ; i++)
+     hashtab[i] = NULL;
+-  
++
+   return 1;
+ }
+ 
+@@ -436,22 +457,22 @@
+ {
+   int     key;
+   hentry *tmp;
+-  
++
+   key = hash(entry->token);
+-  
++
+   tmp = (hentry *) malloc(sizeof(hentry));
+   if (!tmp) {
+     SetISTR(ISTR_WARNING, "Couldn't malloc hash entry in LoadXPM()!\n");
+     return 0;
+   }
+-  
++
+   xvbcopy((char *)entry, (char *)tmp, sizeof(hentry));
+-  
++
+   if (hashtab[key]) tmp->next = hashtab[key];
+                else tmp->next = NULL;
+-  
++
+   hashtab[key] = tmp;
+-  
++
+   return 1;
+ }
+ 
+@@ -462,9 +483,9 @@
+ {
+   int     key;
+   hentry *tmp;
+-  
++
+   key = hash(token);
+-  
++
+   tmp = hashtab[key];
+   while (tmp && strcmp(token, tmp->token)) {
+     tmp = tmp->next;
+@@ -479,7 +500,7 @@
+ {
+   int     i;
+   hentry *tmp;
+-  
++
+   for (i=0; i<hash_len; i++) {
+     while (hashtab[i]) {
+       tmp = hashtab[i]->next;
+@@ -487,7 +508,7 @@
+       hashtab[i] = tmp;
+     }
+   }
+-  
++
+   free(hashtab);
+   return;
+ }
+@@ -508,10 +529,10 @@
+   /* Note here, that tokenchars is assumed to contain 64 valid token */
+   /* characters.  It's hardcoded to assume this for benefit of generating */
+   /* tokens, when there are more than 64^2 colors. */
+-  
++
+   short	i, imax, j;	/* for() loop indices */
+   short	cpp = 0;
+-  char	*tokenchars = 
++  const char *tokenchars =
+             ".#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+   char	*tokens;
+   char	image_name[256], *foo;
+@@ -523,20 +544,20 @@
+   long	li;		/* for() loop index */
+   int	numcol;
+ #endif
+-  
+-  if (DEBUG)
++
++  if (DEBUG) {
+     if (ptype == PIC8)
+       printf("WriteXPM(): Write a %d color, colortype %d, PIC8 image.\n",
+ 	     nc, col);
+     else
+       printf("WriteXPM(): Write a colortype %d, PIC24 image.\n", col);
+-  
+-  foo = BaseName(name);
+-  strcpy(image_name, foo);
++  }
++
++  strcpy(image_name, BaseName(name));
+   foo = (char *)strchr(image_name, '.');
+   if (foo)
+     *foo = '\0';		/* Truncate name at first '.' */
+-  
++
+ #ifdef USE_UNFINISHED_24BIT_WRITING_CODE
+   if (ptype == PIC24)
+     return -1;
+@@ -547,15 +568,15 @@
+   /* 'packed'.  Code in here to do that should be removed if       */
+   /* Conv24to8 is "fixed" to do this...                            */
+   /*    Chris P. Ross (cross at eng.umd.edu)  28-Sept-94              */
+-  
++
+   numcol = 0;
+-  
++
+   if (ptype == PIC24) {
+     /* Reduce to an 8-bit image.  Would be nice to actually write */
+     /* the 24-bit image.  I'll have to code that someday...       */
+     pic8 = Conv24to8(pic, w, h, 256, rtemp, gtemp, btemp);
+     if (!pic8) {
+-      SetISTR(ISTR_WARNING, 
++      SetISTR(ISTR_WARNING,
+ 	      "%s:  Unable to convert to 8-bit image in WriteXPM()",
+ 	      image_name);
+       return 1;
+@@ -594,7 +615,7 @@
+   }
+ #endif
+ 
+-  
++
+ #ifdef USE_UNFINISHED_24BIT_WRITING_CODE
+   if (ptype == PIC24) cpp = 4;
+   else if (numcol > 64) cpp = 2;
+@@ -609,7 +630,7 @@
+   fprintf(fp, "/* width height num_colors chars_per_pixel */\n");
+   fprintf(fp, "\"   %3d   %3d   %6d            %1d\",\n", w, h, numcol, cpp);
+   fprintf(fp, "/* colors */\n");
+-  
++
+   switch (cpp) {
+ 
+   case 1:			/* <= 64 colors; index into tokenchars */
+@@ -681,12 +702,12 @@
+ 
+   case 4:
+     /* Generate a colormap */
+-    
++
+     break;
+   default:
+     break;
+   }
+-  
++
+   if (fprintf(fp, "\"\n};\n") == EOF) {
+     return 1;
+   } else
+diff -ru xv-3.10a/xvxwd.c xv-3.10a-enhancements/xvxwd.c
+--- xv-3.10a/xvxwd.c	1994-12-22 14:34:40.000000000 -0800
++++ xv-3.10a-enhancements/xvxwd.c	2007-05-13 17:52:35.000000000 -0700
+@@ -1,10 +1,10 @@
+-/* 
++/*
+  ** Based on xwdtopnm.c - read and write an X11 or X10 window dump file
+  **
+  ** Modified heavily by Markus Baur (mbaur at ira.uka.de) for use as a part
+  ** of xv-2.21, 12/30/92
+  **
+- ** Hacked up again to support xv-3.00 and XWDs from 64bit machines 
++ ** Hacked up again to support xv-3.00 and XWDs from 64bit machines
+  ** (e.g. DEC Alphas), 04/10/94
+  **
+  ** Copyright (C) 1989, 1991 by Jef Poskanzer.
+@@ -24,42 +24,42 @@
+ /***************************** x11wd.h *****************************/
+ #define X11WD_FILE_VERSION 7
+ typedef struct {
+-    CARD32 header_size;         /* Size of the entire file header (bytes). */
+-    CARD32 file_version;        /* X11WD_FILE_VERSION */
+-    CARD32 pixmap_format;       /* Pixmap format */
+-    CARD32 pixmap_depth;        /* Pixmap depth */
+-    CARD32 pixmap_width;        /* Pixmap width */
+-    CARD32 pixmap_height;       /* Pixmap height */
+-    CARD32 xoffset;             /* Bitmap x offset */
+-    CARD32 byte_order;          /* MSBFirst, LSBFirst */
+-    CARD32 bitmap_unit;         /* Bitmap unit */
+-    CARD32 bitmap_bit_order;    /* MSBFirst, LSBFirst */
+-    CARD32 bitmap_pad;          /* Bitmap scanline pad */
+-    CARD32 bits_per_pixel;      /* Bits per pixel */
+-    CARD32 bytes_per_line;      /* Bytes per scanline */
+-    CARD32 visual_class;        /* Class of colormap */
+-    CARD32 red_mask;            /* Z red mask */
+-    CARD32 green_mask;          /* Z green mask */
+-    CARD32 blue_mask;           /* Z blue mask */
+-    CARD32 bits_per_rgb;        /* Log base 2 of distinct color values */
+-    CARD32 colormap_entries;    /* Number of entries in colormap */
+-    CARD32 ncolors;             /* Number of Color structures */
+-    CARD32 window_width;        /* Window width */
+-    CARD32 window_height;       /* Window height */
+-    CARD32 window_x;            /* Window upper left X coordinate */
+-    CARD32 window_y;            /* Window upper left Y coordinate */
+-    CARD32 window_bdrwidth;     /* Window border width */
++  CARD32 header_size;         /* Size of the entire file header (bytes). */
++  CARD32 file_version;        /* X11WD_FILE_VERSION */
++  CARD32 pixmap_format;       /* Pixmap format */
++  CARD32 pixmap_depth;        /* Pixmap depth */
++  CARD32 pixmap_width;        /* Pixmap width */
++  CARD32 pixmap_height;       /* Pixmap height */
++  CARD32 xoffset;             /* Bitmap x offset */
++  CARD32 byte_order;          /* MSBFirst, LSBFirst */
++  CARD32 bitmap_unit;         /* Bitmap unit */
++  CARD32 bitmap_bit_order;    /* MSBFirst, LSBFirst */
++  CARD32 bitmap_pad;          /* Bitmap scanline pad */
++  CARD32 bits_per_pixel;      /* Bits per pixel */
++  CARD32 bytes_per_line;      /* Bytes per scanline */
++  CARD32 visual_class;        /* Class of colormap */
++  CARD32 red_mask;            /* Z red mask */
++  CARD32 grn_mask;            /* Z green mask */
++  CARD32 blu_mask;            /* Z blue mask */
++  CARD32 bits_per_rgb;        /* Log base 2 of distinct color values */
++  CARD32 colormap_entries;    /* Number of entries in colormap */
++  CARD32 ncolors;             /* Number of Color structures */
++  CARD32 window_width;        /* Window width */
++  CARD32 window_height;       /* Window height */
++  CARD32 window_x;            /* Window upper left X coordinate */
++  CARD32 window_y;            /* Window upper left Y coordinate */
++  CARD32 window_bdrwidth;     /* Window border width */
+ #ifdef WORD64
+-    CARD32 header_pad;
++  CARD32 header_pad;
+ #endif
+-  } X11WDFileHeader;
++} X11WDFileHeader;
+ 
+ typedef struct {
+   CARD32 num;
+   CARD16 red, green, blue;
+-  CARD8  flags;                 /* do_red, do_green, do_blue */
++  CARD8  flags;               /* do_red, do_green, do_blue */
+   CARD8  pad;
+-  } X11XColor;
++} X11XColor;
+ 
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -67,32 +67,35 @@
+ typedef byte pixel;
+ 
+ /* local functions */
+-static int    getinit         PARM((FILE *, int*, int*, int*, CARD32 *, 
++static int    getinit         PARM((FILE *, int*, int*, int*, CARD32 *,
+ 			                          CARD32, PICINFO *));
+ static CARD32 getpixnum       PARM((FILE *));
+-static int    xwdError        PARM((char *));
+-static void   xwdWarning      PARM((char *));
++static int    xwdError        PARM((const char *));
++static void   xwdWarning      PARM((const char *));
+ static int    bs_short        PARM((int));
+ static CARD32 bs_long         PARM((CARD32));
+ static int    readbigshort    PARM((FILE *, CARD16 *));
+ static int    readbiglong     PARM((FILE *, CARD32 *));
+ static int    readlittleshort PARM((FILE *, CARD16 *));
+ static int    readlittlelong  PARM((FILE *, CARD32 *));
++#if 0 /* NOTUSED */
+ static int    writebigshort   PARM((FILE *, int));
+ static int    writebiglong    PARM((FILE *, CARD32));
++#endif
+ 
+ static byte  *pic8, *pic24;
+ static CARD32 red_mask, green_mask, blue_mask;
+-static int    bits_per_item, bits_used, bit_shift, bits_per_pixel;
++static int    red_shift, green_shift, blue_shift;
++static int    bits_per_item, bits_used, bit_shift,
++              bits_per_pixel, bits_per_rgb;
+ static char   buf[4];
+ static char   *byteP;
+ static CARD16 *shortP;
+ static CARD32 *longP;
+ static CARD32 pixel_mask;
+ static int    byte_swap, byte_order, bit_order, filesize;
+-static byte   bw[2] = {0, 0xff};
+ 
+-static char  *bname;
++static const char  *bname;
+ 
+ 
+ 
+@@ -105,33 +108,38 @@
+ 
+   pixel *xP;
+   int    col;
+-  int    rows, cols, padright, row;
+-  CARD32 maxval, visualclass;
++  int    rows=0, cols=0, padright=0, row, npixels, bufsize;
++  CARD32 maxval=0, visualclass=0;
+   FILE  *ifp;
+ 
+   bname          = BaseName(fname);
+   pinfo->pic     = (byte *) NULL;
+   pinfo->comment = (char *) NULL;
+-  maxval         = 0;
+ 
+   ifp = xv_fopen(fname, "r");
+   if (!ifp) return (xwdError("can't open file"));
+-  
++
+   /* figure out the file size (used to check colormap size) */
+   fseek(ifp, 0L, 2);
+   filesize = ftell(ifp);
+   fseek(ifp, 0L, 0);
+-  
++
+ 
+   if (getinit(ifp, &cols, &rows, &padright, &visualclass, maxval, pinfo))
+     return 0;
+ 
++  npixels = cols * rows;
++  if (cols <= 0 || rows <= 0 || npixels/cols != rows) {
++    xwdError("Image dimensions out of range");
++    return 0;
++  }
++
+ 
+   switch (visualclass) {
+   case StaticGray:
+   case GrayScale:
+     pinfo->colType = F_GREYSCALE;
+-    pic8 = (byte *) calloc((size_t) cols*rows, (size_t) 1);
++    pic8 = (byte *) calloc((size_t) npixels, (size_t) 1);
+     if (!pic8) {
+       xwdError("couldn't malloc 'pic'");
+       return 0;
+@@ -140,18 +148,18 @@
+     for (row=0; row<rows; row++) {
+       for (col=0, xP=pic8+(row*cols); col<cols; col++, xP++)
+ 	*xP = getpixnum(ifp);
+-      
++
+       for (col=0; col<padright; col++) getpixnum(ifp);
+     }
+ 
+     pinfo->type = PIC8;
+     pinfo->pic  = pic8;
+-    break;      
++    break;
+ 
+   case StaticColor:
+   case PseudoColor:
+     pinfo->colType = F_FULLCOLOR;
+-    pic8 = (byte *) calloc((size_t) cols*rows, (size_t) 1);
++    pic8 = (byte *) calloc((size_t) npixels, (size_t) 1);
+     if (!pic8) {
+       xwdError("couldn't malloc 'pic'");
+       return 0;
+@@ -162,59 +170,70 @@
+ 	*xP = getpixnum(ifp);
+       for (col=0; col<padright; col++) getpixnum(ifp);
+     }
+-    
++
+     pinfo->type = PIC8;
+     pinfo->pic  = pic8;
+-    break;      
++    break;
+ 
+   case TrueColor:
+   case DirectColor:
+     pinfo->colType = F_FULLCOLOR;
+-    pic24 = (byte *) calloc((size_t) cols*rows*3, (size_t) 1);
++    bufsize = 3*npixels;
++    if (bufsize/3 != npixels) {
++      xwdError("Image dimensions out of range");
++      return 0;
++    }
++    pic24 = (byte *) calloc((size_t) bufsize, (size_t) 1);
+     if (!pic24) {
+       xwdError("couldn't malloc 'pic24'");
+       return 0;
+     }
+ 
+-    for (row=0; row<rows; row++) {
+-      for (col=0, xP=pic24+(row*cols*3); col<cols; col++) {
+-	CARD32 ul;
+-	
+-	ul = getpixnum(ifp);
+-	switch (bits_per_pixel) {
+-	case 16:
+-	  *xP++ = ((ul & red_mask)   >> 0);
+-	  *xP++ = ((ul & green_mask) >> 5);
+-	  *xP++ = ((ul & blue_mask)  >> 10);
+-	  break;
+-	  
+-	case 24:
+-	case 32:
+-	  *xP++ = (ul    ) & 0xff;
+-	  *xP++ = (ul>> 8) & 0xff;
+-	  *xP++ = (ul>>16) & 0xff;
+-	  break;
+-	  
+-	default:
+-	  xwdError("True/Direct only supports 16, 24, and 32 bits");
+-	  return 0;
+-	}
+-      }
++    switch (bits_per_pixel) {
++    case 16:
++    case 24:
++    case 32:
++      ;
++    default:
++      xwdError("True/Direct supports only 16, 24, and 32 bits");
++      return 0;
++    }
+ 
+-      for (col=0; col<padright; col++) getpixnum(ifp);
++    if (byte_order == MSBFirst) {
++      for (row=0; row<rows; row++) {
++        for (col=0, xP=pic24+(row*cols*3); col<cols; col++) {
++          register CARD32 ul = getpixnum(ifp);
++
++          *xP++ = ul >> red_shift   & red_mask  ;
++          *xP++ = ul >> green_shift & green_mask;
++          *xP++ = ul >> blue_shift  & blue_mask ;
++        };
++        for (col=0; col<padright; col++) getpixnum(ifp);
++      }
++    } else {
++      for (row=0; row<rows; row++) {
++        for (col=0, xP=pic24+(row*cols*3); col<cols; col++) {
++          register CARD32 ul = getpixnum(ifp);
++
++          *xP++ = ul >> blue_shift  & blue_mask ;
++          *xP++ = ul >> green_shift & green_mask;
++          *xP++ = ul >> red_shift   & red_mask  ;
++        };
++        for (col=0; col<padright; col++) getpixnum(ifp);
++      }
+     }
+-    
++
+     pinfo->type = PIC24;
+     pinfo->pic  = pic24;
+     break;
+-    
++
+   default:
+     xwdError("unknown visual class");
+     return 0;
+   }
+ 
+   sprintf(pinfo->fullInfo, "XWD, %d-bit %s.  (%d bytes)",
+-	  bits_per_pixel, 
++	  bits_per_pixel,
+ 	  ((visualclass == StaticGray ) ? "StaticGray"  :
+ 	   (visualclass == GrayScale  ) ? "GrayScale"   :
+ 	   (visualclass == StaticColor) ? "StaticColor" :
+@@ -258,10 +277,10 @@
+   maxv = 255L;
+ 
+   h11P = (X11WDFileHeader*) header;
+-  
++
+   if (fread(&header[0], sizeof(*h11P), (size_t) 1, file) != 1)
+     return(xwdError("couldn't read X11 XWD file header"));
+-  
++
+   if (h11P->file_version != X11WD_FILE_VERSION) {
+     byte_swap = 1;
+     h11P->header_size      = bs_long(h11P->header_size);
+@@ -279,8 +298,8 @@
+     h11P->bytes_per_line   = bs_long(h11P->bytes_per_line);
+     h11P->visual_class     = bs_long(h11P->visual_class);
+     h11P->red_mask         = bs_long(h11P->red_mask);
+-    h11P->green_mask       = bs_long(h11P->green_mask);
+-    h11P->blue_mask        = bs_long(h11P->blue_mask);
++    h11P->grn_mask         = bs_long(h11P->grn_mask);
++    h11P->blu_mask         = bs_long(h11P->blu_mask);
+     h11P->bits_per_rgb     = bs_long(h11P->bits_per_rgb);
+     h11P->colormap_entries = bs_long(h11P->colormap_entries);
+     h11P->ncolors          = bs_long(h11P->ncolors);
+@@ -294,7 +313,7 @@
+   for (i=0; i<h11P->header_size - sizeof(*h11P); i++)
+     if (getc(file) == EOF)
+       return(xwdError("couldn't read rest of X11 XWD file header"));
+-      
++
+   /* Check whether we can handle this dump. */
+   if (h11P->pixmap_depth > 24)
+     return(xwdError("can't handle X11 pixmap_depth > 24"));
+@@ -303,27 +322,31 @@
+     return(xwdError("can't handle X11 bits_per_rgb > 24"));
+ 
+   if (h11P->pixmap_format != ZPixmap && h11P->pixmap_depth != 1)  {
+-    sprintf(errstr, "can't handle X11 pixmap_format %d with depth != 1",
+-	    h11P->pixmap_format);
++    sprintf(errstr, "can't handle X11 pixmap_format %ld with depth != 1",
++	    (long)h11P->pixmap_format);
+     return(xwdError(errstr));
+   }
+ 
+   if (h11P->bitmap_unit != 8 && h11P->bitmap_unit != 16 &&
+       h11P->bitmap_unit != 32)  {
+-    sprintf(errstr, "X11 bitmap_unit (%d) is non-standard - can't handle",
+-	    h11P->bitmap_unit);
++    sprintf(errstr, "X11 bitmap_unit (%ld) is non-standard - can't handle",
++	    (long)h11P->bitmap_unit);
+     return(xwdError(errstr));
+   }
+-  
++
+   grayscale = 1;
+   if (h11P->ncolors > 0) {      /* Read X11 colormap. */
+-    x11colors = (X11XColor*) malloc(h11P->ncolors * sizeof(X11XColor));
++    int bufsize = h11P->ncolors * sizeof(X11XColor);
++
++    if (bufsize/sizeof(X11XColor) != h11P->ncolors)
++      return(xwdError("too many colors"));
++    x11colors = (X11XColor*) malloc(bufsize);
+     if (!x11colors) return(xwdError("out of memory"));
+-    
+-    if (h11P->header_size + h11P->ncolors * sizeof(X11XColor) 
++
++    if (h11P->header_size + bufsize
+ 	+ h11P->pixmap_height * h11P->bytes_per_line + h11P->ncolors * 4
+ 	== filesize ) word64 = 1;
+-    
++
+     if (word64) {
+       for (i = 0; i < h11P->ncolors; ++i) {
+ 	if (fread(&pad, sizeof(pad), (size_t) 1, file ) != 1)
+@@ -334,11 +357,11 @@
+       }
+     }
+     else {
+-      if (fread(x11colors, sizeof(X11XColor), (size_t) h11P->ncolors, file) 
++      if (fread(x11colors, sizeof(X11XColor), (size_t) h11P->ncolors, file)
+ 	  != h11P->ncolors)
+ 	return(xwdError("couldn't read X11 XWD colormap"));
+     }
+-    
++
+     for (i = 0; i < h11P->ncolors; ++i) {
+       if (byte_swap) {
+ 	x11colors[i].red   = (CARD16) bs_short(x11colors[i].red);
+@@ -356,8 +379,11 @@
+ 	grayscale = 0;
+     }
+   }
+-  
++
+   *visualclassP = h11P->visual_class;
++  /* SJT: FIXME. If bits_per_pixel == 16, maxv could be either 31 or 63.
++     It doesn't matter, though, because maxv is never used beyond here.
++   */
+   if (*visualclassP == TrueColor || *visualclassP == DirectColor) {
+     if (h11P->bits_per_pixel == 16) maxv = 31;
+     else maxv = 255;
+@@ -389,24 +415,58 @@
+       }
+     }
+   }
+-      
++
+   *colsP = h11P->pixmap_width;
+   *rowsP = h11P->pixmap_height;
+   *padrightP = h11P->bytes_per_line * 8 / h11P->bits_per_pixel -
+     h11P->pixmap_width;
+-  
++
+   bits_per_item  = h11P->bitmap_unit;
+-  bits_used      = bits_per_item;
+   bits_per_pixel = h11P->bits_per_pixel;
+   byte_order     = h11P->byte_order;
+   bit_order      = h11P->bitmap_bit_order;
+-  
++  bits_per_rgb   = h11P->bits_per_rgb;
++
++
++  /* add sanity-code for freako 'exceed' server, where bitmapunit = 8
++     and bitsperpix = 32 (and depth=24)... */
++
++  if (bits_per_item < bits_per_pixel) {
++    bits_per_item = bits_per_pixel;
++
++    /* round bits_per_item up to next legal value, if necc */
++    if      (bits_per_item <  8) bits_per_item = 8;
++    else if (bits_per_item < 16) bits_per_item = 16;
++    else                         bits_per_item = 32;
++  }
++
++
++  /* which raises the question:  how (can?) you ever have a 24 bits per pix,
++     (i.e., 3 bytes, no alpha/padding) */
++
++
++  bits_used      = bits_per_item;
++
+   if (bits_per_pixel == sizeof(pixel_mask) * 8)  pixel_mask = (CARD32) -1;
+   else pixel_mask = (1 << bits_per_pixel) - 1;
+-  
++
+   red_mask   = h11P->red_mask;
+-  green_mask = h11P->green_mask;
+-  blue_mask  = h11P->blue_mask;
++  green_mask = h11P->grn_mask;
++  blue_mask  = h11P->blu_mask;
++
++  red_shift = blue_shift = green_shift = 0;
++  while (!(red_mask & 1)) {
++    red_mask >>= 1;
++    ++red_shift;
++  }
++  while (!(blue_mask & 1)) {
++    blue_mask >>= 1;
++    ++blue_shift;
++  }
++  while (!(green_mask & 1)) {
++    green_mask >>= 1;
++    ++green_shift;
++  }
+ 
+   byteP  = (char   *) buf;
+   shortP = (CARD16 *) buf;
+@@ -421,13 +481,13 @@
+      FILE* file;
+ {
+   int n;
+-  
++
+   if (bits_used == bits_per_item) {
+     switch (bits_per_item) {
+     case 8:
+       *byteP = getc(file);
+       break;
+-      
++
+     case 16:
+       if (byte_order == MSBFirst) {
+ 	if (readbigshort(file, shortP) == -1)
+@@ -438,7 +498,7 @@
+ 	  xwdWarning("unexpected EOF");
+       }
+       break;
+-      
++
+     case 32:
+       if (byte_order == MSBFirst) {
+ 	if (readbiglong(file, longP) == -1)
+@@ -449,48 +509,48 @@
+ 	  xwdWarning("unexpected EOF");
+       }
+       break;
+-      
++
+     default:
+       xwdWarning("can't happen");
+     }
+     bits_used = 0;
+-    
++
+     if (bit_order == MSBFirst)
+       bit_shift = bits_per_item - bits_per_pixel;
+     else
+       bit_shift = 0;
+   }
+-  
++
+   switch (bits_per_item) {
+   case 8:
+     n = (*byteP >> bit_shift) & pixel_mask;
+     break;
+-    
++
+   case 16:
+     n = (*shortP >> bit_shift) & pixel_mask;
+     break;
+-    
++
+   case 32:
+     n = (*longP >> bit_shift) & pixel_mask;
+     break;
+-    
++
+   default:
+     n = 0;
+     xwdWarning("can't happen");
+   }
+-  
++
+   if (bit_order == MSBFirst) bit_shift -= bits_per_pixel;
+                         else bit_shift += bits_per_pixel;
+ 
+   bits_used += bits_per_pixel;
+-  
++
+   return n;
+ }
+ 
+ 
+ /***************************/
+ static int xwdError(st)
+-     char *st;
++     const char *st;
+ {
+   if (pic8  != NULL) free(pic8);
+   if (pic24 != NULL) free(pic24);
+@@ -502,7 +562,7 @@
+ 
+ /***************************/
+ static void xwdWarning(st)
+-     char *st;
++     const char *st;
+ {
+   SetISTR(ISTR_WARNING,"%s:  %s", bname, st);
+ }
+@@ -511,7 +571,7 @@
+ 
+ 
+ 
+-/* 
++/*
+  * Byte-swapping junk.
+  */
+ 
+@@ -537,7 +597,7 @@
+ {
+   union cheat u;
+   unsigned char t;
+-  
++
+   u.l = l;
+   t = u.c[0];  u.c[0] = u.c[3];  u.c[3] = t;
+   t = u.c[1];  u.c[1] = u.c[2];  u.c[2] = t;
+@@ -549,7 +609,7 @@
+ 
+ 
+ 
+-/* 
++/*
+  * Endian I/O.
+  */
+ 
+@@ -584,7 +644,7 @@
+ {
+   *sP  =  getc(in) & 0xff;
+   *sP |= (getc(in) & 0xff) << 8;
+-  
++
+   if (ferror(in)) return -1;
+   return 0;
+ }
+@@ -604,6 +664,7 @@
+ }
+ 
+ 
++#if 0 /* NOTUSED */
+ static int writebiglong(out, l)
+      FILE* out;
+      CARD32 l;
+@@ -624,3 +685,4 @@
+   putc(s&0xff, out);
+   return 0;
+ }
++#endif /* 0 (NOTUSED) */


Property changes on: dists/trunk/xv/debian/patches/01-xv-3.10a-jumbo-fix-enh-patch-20070520.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: dists/trunk/xv/debian/patches/02-xv-3.10a-jumbo-files-20070520.dpatch
===================================================================
--- dists/trunk/xv/debian/patches/02-xv-3.10a-jumbo-files-20070520.dpatch	                        (rev 0)
+++ dists/trunk/xv/debian/patches/02-xv-3.10a-jumbo-files-20070520.dpatch	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,18751 @@
+#!/bin/sh /usr/share/dpatch/dpatch-run
+## xv-3.10a-jumbo-patches-20070520.tar.gz by Greg Roelofs <newt at pobox.com>
+## It was downloaded from <http://www.sonic.net/~roelofs/greg_xv.html>.
+##
+## DP: XV Jumbo Patches (supplementary files).
+
+ at DPATCH@
+
+diff -Naru xv-3.10a/bits/br_bzip2 xv-3.10a.jumbo/bits/br_bzip2
+--- xv-3.10a/bits/br_bzip2	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_bzip2	1998-04-13 04:23:39.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_bzip2_width 48
++#define br_bzip2_height 48
++static unsigned char br_bzip2_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x7c, 0xbe, 0x3d, 0x0e, 0x02, 0x20, 0xfc, 0xbe, 0x7d, 0x1f, 0x02,
++   0x20, 0xcc, 0xb0, 0x6d, 0x1b, 0x02, 0x20, 0xcc, 0x98, 0x6d, 0x1b, 0x02,
++   0x20, 0xfc, 0x98, 0x6d, 0x18, 0x02, 0x20, 0x7c, 0x8c, 0x7d, 0x0c, 0x02,
++   0x20, 0xcc, 0x8c, 0x3d, 0x0e, 0x02, 0x20, 0xcc, 0x84, 0x0d, 0x06, 0x02,
++   0x20, 0xcc, 0x86, 0x0d, 0x03, 0x02, 0x20, 0xfc, 0xbe, 0x0d, 0x1f, 0x02,
++   0x20, 0x7c, 0xbe, 0x0d, 0x1f, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_jp2 xv-3.10a.jumbo/bits/br_jp2
+--- xv-3.10a/bits/br_jp2	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_jp2	2005-05-09 07:00:27.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_jp2_width 48
++#define br_jp2_height 48
++static unsigned char br_jp2_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0xfb, 0xf1, 0x01, 0x02,
++   0x20, 0x00, 0xfb, 0xfb, 0x03, 0x02, 0x20, 0x00, 0x1b, 0x1b, 0x03, 0x02,
++   0x20, 0x00, 0x1b, 0x1b, 0x00, 0x02, 0x20, 0x00, 0x1b, 0x1b, 0x00, 0x02,
++   0x20, 0x00, 0x9b, 0x1b, 0x00, 0x02, 0x20, 0x00, 0xfb, 0x19, 0x00, 0x02,
++   0x20, 0x00, 0xfb, 0x18, 0x00, 0x02, 0x20, 0x18, 0x1b, 0x18, 0x00, 0x02,
++   0x20, 0x18, 0x1b, 0x18, 0x00, 0x02, 0x20, 0xb8, 0x1b, 0x18, 0x03, 0x02,
++   0x20, 0xf0, 0x19, 0xf8, 0x03, 0x02, 0x20, 0xe0, 0x18, 0xf0, 0x01, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_jpc xv-3.10a.jumbo/bits/br_jpc
+--- xv-3.10a/bits/br_jpc	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_jpc	2005-05-09 07:00:27.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_jpc_width 48
++#define br_jpc_height 48
++static unsigned char br_jpc_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0xfb, 0xf1, 0x01, 0x02,
++   0x20, 0x00, 0xfb, 0xfb, 0x03, 0x02, 0x20, 0x00, 0x1b, 0x1b, 0x03, 0x02,
++   0x20, 0x00, 0x1b, 0x03, 0x03, 0x02, 0x20, 0x00, 0x1b, 0x03, 0x03, 0x02,
++   0x20, 0x00, 0x9b, 0x83, 0x01, 0x02, 0x20, 0x00, 0xfb, 0xc1, 0x01, 0x02,
++   0x20, 0x00, 0xfb, 0xe0, 0x00, 0x02, 0x20, 0x18, 0x1b, 0x70, 0x00, 0x02,
++   0x20, 0x18, 0x1b, 0x38, 0x00, 0x02, 0x20, 0xb8, 0x1b, 0x18, 0x00, 0x02,
++   0x20, 0xf0, 0x19, 0xf8, 0x03, 0x02, 0x20, 0xe0, 0x18, 0xf8, 0x03, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_mag xv-3.10a.jumbo/bits/br_mag
+--- xv-3.10a/bits/br_mag	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_mag	2005-04-17 23:04:22.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_mag_width 48
++#define br_mag_height 48
++static unsigned char br_mag_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x0c, 0x86, 0xc1, 0x0f, 0x02,
++   0x20, 0x0c, 0xc6, 0xe3, 0x1f, 0x02, 0x20, 0x1c, 0xe7, 0x67, 0x18, 0x02,
++   0x20, 0x1c, 0x77, 0x6e, 0x18, 0x02, 0x20, 0xbc, 0x37, 0x6c, 0x00, 0x02,
++   0x20, 0xbc, 0x37, 0x6c, 0x00, 0x02, 0x20, 0xec, 0x36, 0x6c, 0x1e, 0x02,
++   0x20, 0xec, 0xf6, 0x6f, 0x1e, 0x02, 0x20, 0x4c, 0xf6, 0x6f, 0x18, 0x02,
++   0x20, 0x4c, 0x36, 0x6c, 0x18, 0x02, 0x20, 0x0c, 0x36, 0x6c, 0x18, 0x02,
++   0x20, 0x0c, 0x36, 0xec, 0x1f, 0x02, 0x20, 0x0c, 0x36, 0xcc, 0x0f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_maki xv-3.10a.jumbo/bits/br_maki
+--- xv-3.10a/bits/br_maki	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_maki	2005-04-17 23:04:22.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_maki_width 48
++#define br_maki_height 48
++static unsigned char br_maki_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x83, 0x61, 0x18, 0x33, 0x02,
++   0x20, 0x83, 0xf1, 0x98, 0x33, 0x02, 0x20, 0xc7, 0xf9, 0x99, 0x31, 0x02,
++   0x20, 0xc7, 0x9d, 0xdb, 0x30, 0x02, 0x20, 0xef, 0x0d, 0xfb, 0x30, 0x02,
++   0x20, 0xef, 0x0d, 0x7b, 0x30, 0x02, 0x20, 0xbb, 0x0d, 0x7b, 0x30, 0x02,
++   0x20, 0xbb, 0xfd, 0xdb, 0x30, 0x02, 0x20, 0x93, 0xfd, 0xdb, 0x30, 0x02,
++   0x20, 0x93, 0x0d, 0x9b, 0x31, 0x02, 0x20, 0x83, 0x0d, 0x9b, 0x31, 0x02,
++   0x20, 0x83, 0x0d, 0x1b, 0x33, 0x02, 0x20, 0x83, 0x0d, 0x1b, 0x33, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_mgcsfx xv-3.10a.jumbo/bits/br_mgcsfx
+--- xv-3.10a/bits/br_mgcsfx	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_mgcsfx	2005-04-17 23:04:22.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_mgcsfx_width 48
++#define br_mgcsfx_height 48
++static unsigned char br_mgcsfx_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x3c, 0xcf, 0x71, 0x00, 0x02,
++   0x20, 0x6c, 0x61, 0xda, 0x00, 0x02, 0x20, 0x6c, 0x67, 0xd8, 0x1e, 0x02,
++   0x20, 0x3c, 0x61, 0xd8, 0x1e, 0x02, 0x20, 0x6c, 0x61, 0xda, 0x00, 0x02,
++   0x20, 0x6c, 0xcf, 0x71, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x4e, 0x7a, 0xef, 0x3d, 0x02, 0x20, 0xd3, 0x32, 0x68, 0x6c, 0x02,
++   0x20, 0xc3, 0x32, 0xe4, 0x6c, 0x02, 0x20, 0x5b, 0x33, 0x62, 0x6c, 0x02,
++   0x20, 0x53, 0x33, 0x61, 0x6c, 0x02, 0x20, 0x4e, 0x7a, 0xef, 0x3d, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_pcd xv-3.10a.jumbo/bits/br_pcd
+--- xv-3.10a/bits/br_pcd	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_pcd	1995-06-16 06:31:53.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_pcd_width 48
++#define br_pcd_height 48
++static unsigned char br_pcd_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x67, 0x00, 0xe0, 0x1c, 0x02,
++   0x20, 0x6f, 0x00, 0xf0, 0x3d, 0x02, 0x20, 0x6b, 0x00, 0xb0, 0x2d, 0x02,
++   0x20, 0x6b, 0x00, 0x33, 0x2c, 0x02, 0x20, 0x6b, 0x00, 0x33, 0x2c, 0x02,
++   0x20, 0xeb, 0x98, 0x37, 0x2c, 0x02, 0x20, 0xef, 0xbd, 0x37, 0x2c, 0x02,
++   0x20, 0x67, 0x2d, 0x33, 0x2c, 0x02, 0x20, 0x63, 0x2d, 0x33, 0x2c, 0x02,
++   0x20, 0x63, 0x2d, 0x33, 0x2c, 0x02, 0x20, 0x63, 0x2d, 0xb3, 0x2d, 0x02,
++   0x20, 0x63, 0x3d, 0xf7, 0x3d, 0x02, 0x20, 0x63, 0x19, 0xe6, 0x1c, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_pi xv-3.10a.jumbo/bits/br_pi
+--- xv-3.10a/bits/br_pi	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_pi	2005-04-17 23:04:22.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_pi_width 48
++#define br_pi_height 48
++static unsigned char br_pi_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x80, 0x1f, 0x7e, 0x00, 0x02,
++   0x20, 0x80, 0x3f, 0x7e, 0x00, 0x02, 0x20, 0x80, 0x31, 0x18, 0x00, 0x02,
++   0x20, 0x80, 0x31, 0x18, 0x00, 0x02, 0x20, 0x80, 0x31, 0x18, 0x00, 0x02,
++   0x20, 0x80, 0x39, 0x18, 0x00, 0x02, 0x20, 0x80, 0x1f, 0x18, 0x00, 0x02,
++   0x20, 0x80, 0x0f, 0x18, 0x00, 0x02, 0x20, 0x80, 0x01, 0x18, 0x00, 0x02,
++   0x20, 0x80, 0x01, 0x18, 0x00, 0x02, 0x20, 0x80, 0x01, 0x18, 0x00, 0x02,
++   0x20, 0x80, 0x01, 0x7e, 0x00, 0x02, 0x20, 0x80, 0x01, 0x7e, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_pic xv-3.10a.jumbo/bits/br_pic
+--- xv-3.10a/bits/br_pic	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_pic	2005-04-17 23:04:22.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_pic_width 48
++#define br_pic_height 48
++static unsigned char br_pic_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xf0, 0xf3, 0xf3, 0x01, 0x02,
++   0x20, 0xf0, 0xf7, 0xfb, 0x03, 0x02, 0x20, 0x30, 0xc6, 0x18, 0x03, 0x02,
++   0x20, 0x30, 0xc6, 0x18, 0x00, 0x02, 0x20, 0x30, 0xc6, 0x18, 0x00, 0x02,
++   0x20, 0x30, 0xc7, 0x18, 0x00, 0x02, 0x20, 0xf0, 0xc3, 0x18, 0x00, 0x02,
++   0x20, 0xf0, 0xc1, 0x18, 0x00, 0x02, 0x20, 0x30, 0xc0, 0x18, 0x00, 0x02,
++   0x20, 0x30, 0xc0, 0x18, 0x00, 0x02, 0x20, 0x30, 0xc0, 0x18, 0x03, 0x02,
++   0x20, 0x30, 0xf0, 0xfb, 0x03, 0x02, 0x20, 0x30, 0xf0, 0xf3, 0x01, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_pic2 xv-3.10a.jumbo/bits/br_pic2
+--- xv-3.10a/bits/br_pic2	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_pic2	2005-04-17 23:04:22.000000000 +0200
+@@ -0,0 +1,27 @@
++#define br_pic2_width 48
++#define br_pic2_height 48
++static unsigned char br_pic2_bits[] = {
++   0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++   0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x3f, 0x3f, 0x1f, 0x1f, 0x02,
++   0x20, 0x7f, 0xbf, 0xbf, 0x3f, 0x02, 0x20, 0x63, 0x8c, 0xb1, 0x31, 0x02,
++   0x20, 0x63, 0x8c, 0x01, 0x30, 0x02, 0x20, 0x63, 0x8c, 0x01, 0x30, 0x02,
++   0x20, 0x73, 0x8c, 0x01, 0x30, 0x02, 0x20, 0x3f, 0x8c, 0x01, 0x18, 0x02,
++   0x20, 0x1f, 0x8c, 0x01, 0x0c, 0x02, 0x20, 0x03, 0x8c, 0x01, 0x06, 0x02,
++   0x20, 0x03, 0x8c, 0x01, 0x03, 0x02, 0x20, 0x03, 0x8c, 0xb1, 0x01, 0x02,
++   0x20, 0x03, 0xbf, 0xbf, 0x3f, 0x02, 0x20, 0x03, 0x3f, 0x9f, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++   0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03};
+diff -Naru xv-3.10a/bits/br_png xv-3.10a.jumbo/bits/br_png
+--- xv-3.10a/bits/br_png	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_png	1996-06-13 23:32:08.000000000 +0200
+@@ -0,0 +1,28 @@
++#define br_png_width 48
++#define br_png_height 48
++static unsigned char br_png_bits[] = {
++  0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0xf8, 0x19, 0xc3, 0x07, 0x02, 0x20, 0x18, 0x3b, 0x63, 0x0c, 0x02,
++  0x20, 0x18, 0x3b, 0x33, 0x00, 0x02, 0x20, 0x18, 0x5b, 0x33, 0x00, 0x02,
++  0x20, 0xf8, 0x59, 0x33, 0x0f, 0x02, 0x20, 0x18, 0x98, 0x33, 0x0c, 0x02,
++  0x20, 0x18, 0x98, 0x33, 0x0c, 0x02, 0x20, 0x18, 0x18, 0x63, 0x0c, 0x02,
++  0x20, 0x18, 0x18, 0xc3, 0x0b, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03,
++  };
+diff -Naru xv-3.10a/bits/br_zx xv-3.10a.jumbo/bits/br_zx
+--- xv-3.10a/bits/br_zx	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/bits/br_zx	1998-08-06 22:00:03.000000000 +0200
+@@ -0,0 +1,28 @@
++#define br_zx_width 48
++#define br_zx_height 48
++static unsigned char br_zx_bits[] = {
++  0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00,
++  0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x7f, 0xce, 0x01, 0x0e, 0x02, 0x20, 0x61, 0x84, 0x00, 0x11, 0x02,
++  0x20, 0x30, 0x48, 0x00, 0x10, 0x02, 0x20, 0x18, 0x38, 0x10, 0x08, 0x02,
++  0x20, 0x0c, 0x30, 0x10, 0x0e, 0x02, 0x20, 0x06, 0x68, 0x7c, 0x10, 0x02,
++  0x20, 0x03, 0x48, 0x10, 0x10, 0x02, 0x20, 0x41, 0x84, 0x10, 0x11, 0x02,
++  0x20, 0x7f, 0xce, 0x01, 0x0e, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0xff, 0xff, 0xff, 0xff, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x40, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02,
++  0x20, 0x00, 0x00, 0x00, 0x10, 0x02, 0x20, 0x00, 0x00, 0x00, 0x08, 0x03,
++  0x20, 0x00, 0x00, 0x00, 0x84, 0x03, 0x20, 0x00, 0x00, 0x00, 0xc2, 0x03,
++  0x20, 0x00, 0x00, 0x00, 0xe1, 0x03, 0x20, 0x00, 0x00, 0x80, 0xf0, 0x02,
++  0x20, 0x00, 0x00, 0x40, 0x78, 0x02, 0x20, 0x00, 0x00, 0x20, 0x3c, 0x02,
++  0x20, 0x00, 0x00, 0x10, 0x1e, 0x02, 0x20, 0x00, 0x00, 0x08, 0x0f, 0x03,
++  0x20, 0x00, 0x00, 0x84, 0x87, 0x03, 0x20, 0x00, 0x00, 0xc2, 0xc3, 0x03,
++  0x20, 0x00, 0x00, 0xe1, 0xe1, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03,
++  };
+diff -Naru xv-3.10a/contrib/fedora/Build-FC5 xv-3.10a.jumbo/contrib/fedora/Build-FC5
+--- xv-3.10a/contrib/fedora/Build-FC5	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fedora/Build-FC5	2006-06-01 17:12:47.000000000 +0200
+@@ -0,0 +1,56 @@
++#!/bin/bash
++#
++# prep and build XV for FC5
++#
++# adapted from Slackware 10.2 -- john.cooper at third-harmonic.com
++#
++
++if [ ${1}foo == "__LOGGED__foo" ]; then
++	shift
++else
++	for i in `seq 0 9`
++		do
++		if [ -e ${0}.log.$((9-i)) ]; then
++			mv ${0}.log.$((9-i)) ${0}.log.$((9-i+1))
++		fi
++		done
++
++	exec $0 __LOGGED__ $@ 2>&1 | tee $BUILDDIR/$0.log.0
++	exit $?
++fi
++
++SOURCE=`pwd`
++if [ "$BUILD" = "" ]; then
++  BUILD=./build
++fi
++
++if [ ! -d $BUILD ]; then
++  mkdir -p $BUILD
++fi
++
++PFLAGS="--verbose --backup --suffix=.orig"
++
++function bail()
++	{
++	echo "$0: failed $1"
++	exit 1
++	}
++
++cd $BUILD
++rm -rf xv-3.10
++tar xzvf $SOURCE/xv-3.10.tar.gz
++cd xv-3.10
++zcat $SOURCE/xv-3.10a.patch.gz | patch -p0 $PFLAGS || \
++	bail $SOURCE/xv-3.10a.patch.gz
++bzcat $SOURCE/xv-3.10a-jumbo-fix-patch-20050410.txt.bz2 | patch -p1 $PFLAGS || \
++	bail $SOURCE/xv-3.10a-jumbo-fix-patch-20050410.txt.bz2
++bzcat $SOURCE/xv-3.10a-jumbo-enh-patch-20050501.txt.bz2 | patch -p1 $PFLAGS || \
++	bail $SOURCE/xv-3.10a-jumbo-enh-patch-20050501.txt.bz2
++zcat $SOURCE/xv.prefix.diff.gz | patch -p1 $PFLAGS || \
++	bail $SOURCE/xv.prefix.diff.gz
++make -f Makefile.std || bail make
++strip --strip-unneeded bggen vdcomp xcmap xv xvpictoppm || bail strip
++
++exit $?
++
++# vi:set ts=4:
+diff -Naru xv-3.10a/contrib/fedora/README xv-3.10a.jumbo/contrib/fedora/README
+--- xv-3.10a/contrib/fedora/README	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fedora/README	2006-06-01 17:12:47.000000000 +0200
+@@ -0,0 +1,16 @@
++Greg,
++     After winding up in dark lonely places trying to
++get xv-3.10a to build on FC5 I suspected I was missing
++something.  Then I happened on your patch manifest
++in Slackware 10.2.
++
++I bandsawed the script a bit to use in propagating XV
++to a handful of personal FC5 machines.  Attached for
++reference.
++
++Thanks for your effort!
++
++-john
++
++-- 
++john.cooper at third-harmonic.com
+diff -Naru xv-3.10a/contrib/fnkey-scripts/jpegcrop.sh xv-3.10a.jumbo/contrib/fnkey-scripts/jpegcrop.sh
+--- xv-3.10a/contrib/fnkey-scripts/jpegcrop.sh	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fnkey-scripts/jpegcrop.sh	2006-03-12 04:30:03.000000000 +0100
+@@ -0,0 +1,33 @@
++#!/bin/bash
++FILE=$1
++WIDTH=$4
++HEIGHT=$5
++XPOS=$2
++YPOS=$3
++if [[ $XPOS -lt 0 ]]; then
++	echo "Negative x position $XPOS converted to zero, width adjusted."
++	WIDTH=$((WIDTH+XPOS))
++	XPOS=0
++fi
++if [[ $YPOS -lt 0 ]]; then
++	echo "Negative y position $YPOS converted to zero, height adjusted."
++	HEIGHT=$((HEIGHT+YPOS))
++	YPOS=0
++fi
++if [[ $(($WIDTH+$HEIGHT)) == 0 ]]; then
++	echo "Refusing to crop $FILE with an empty rectangle."
++	exit 1
++fi
++
++TMPFILE=`mktemp $FILE.tmp-jpeg-rot-XXXXXXXX`
++if jpegtran -optimize -progressive -crop ${WIDTH}x${HEIGHT}+${XPOS}+${YPOS} \
++   -copy all $FILE > $TMPFILE; then
++	COUNT=`echo $FILE-uncropped | wc -c`
++	NEXT=$((`ls $FILE-uncropped* | cut -b $COUNT- | grep '^[0-9]*$' \
++	         | sed 's/^0*/'/ | sort -n | tail -n 1`+1))
++	# the targets shouldn't exist, but -i just in case
++	mv -i $FILE $FILE-uncropped$NEXT 
++	mv -i $TMPFILE $FILE
++else
++	rm $TMPFILE
++fi
+diff -Naru xv-3.10a/contrib/fnkey-scripts/jpegeditcom.sh xv-3.10a.jumbo/contrib/fnkey-scripts/jpegeditcom.sh
+--- xv-3.10a/contrib/fnkey-scripts/jpegeditcom.sh	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fnkey-scripts/jpegeditcom.sh	2007-01-16 07:23:04.000000000 +0100
+@@ -0,0 +1,12 @@
++#!/bin/bash
++CFILE=`mktemp $1.tmp-jpeg-comments-XXXXXXXX`
++TMPFILE=`mktemp $1.tmp-jpeg-XXXXXXXX`
++rdjpgcom $1 > $CFILE
++INITIAL=`md5sum $CFILE`
++xterm -e "$EDITOR" "$CFILE" # customize your editor here
++MODIFIED=`md5sum $CFILE`
++if [[ "$INITIAL" != "$MODIFIED" ]]; then
++	mv $1 $TMPFILE
++	wrjpgcom -replace -cfile $CFILE $TMPFILE > $1
++fi
++rm $TMPFILE $CFILE $CFILE~
+diff -Naru xv-3.10a/contrib/fnkey-scripts/jpeglogrot.sh xv-3.10a.jumbo/contrib/fnkey-scripts/jpeglogrot.sh
+--- xv-3.10a/contrib/fnkey-scripts/jpeglogrot.sh	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fnkey-scripts/jpeglogrot.sh	2007-01-16 07:55:18.000000000 +0100
+@@ -0,0 +1,10 @@
++#!/bin/bash
++curdir="`pwd`"
++LOG=~/photos/bin/rotscript # customize your install dir here
++if [[ ! -e "$LOG" ]]; then
++	echo '#!/bin/bash' >> "$LOG"
++	chmod u+x "$LOG"
++fi
++echo "# following entry made on `date`" >> "$LOG"
++# also customize the following line
++echo ~/photos/bin/jpegrot \""$1"\" \""$curdir/$2"\" >> "$LOG"
+diff -Naru xv-3.10a/contrib/fnkey-scripts/jpegrot.sh xv-3.10a.jumbo/contrib/fnkey-scripts/jpegrot.sh
+--- xv-3.10a/contrib/fnkey-scripts/jpegrot.sh	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fnkey-scripts/jpegrot.sh	2006-07-19 06:10:43.000000000 +0200
+@@ -0,0 +1,7 @@
++#!/bin/bash
++TMPFILE="`mktemp "$2".tmp-jpeg-rot-XXXXXXXX`"
++if jpegtran -perfect -optimize -progressive -rotate "$1" -copy all "$2" > "$TMPFILE"; then
++	mv "$TMPFILE" "$2"
++else
++	rm "$TMPFILE"
++fi
+diff -Naru xv-3.10a/contrib/fnkey-scripts/jpegundocrop.sh xv-3.10a.jumbo/contrib/fnkey-scripts/jpegundocrop.sh
+--- xv-3.10a/contrib/fnkey-scripts/jpegundocrop.sh	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fnkey-scripts/jpegundocrop.sh	2006-03-12 04:30:04.000000000 +0100
+@@ -0,0 +1,8 @@
++#!/bin/bash
++FILE=$1
++COUNT=`echo $FILE-uncropped | wc -c`
++LATEST=$((`ls $FILE-uncropped* | cut -b $COUNT- | grep '^[0-9]*$' \
++         | sed 's/^0*/'/ | sort -n | tail -n 1`))
++if [[ -f $FILE-uncropped$LATEST ]]; then
++	mv $FILE-uncropped$LATEST $FILE
++fi
+diff -Naru xv-3.10a/contrib/fnkey-scripts/README xv-3.10a.jumbo/contrib/fnkey-scripts/README
+--- xv-3.10a/contrib/fnkey-scripts/README	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/contrib/fnkey-scripts/README	2007-01-16 09:41:51.000000000 +0100
+@@ -0,0 +1,111 @@
++-- License and Disclaimer --
++
++This patch & script package was written by Alexey Spiridonov, and is
++licensed under the GNU GPLv2. There is NO WARRANTY.
++
++XV is copyrighted by John Bradley.
++
++-- What is this? --
++
++This is a small patch for XV that allows you to run scripts by pressing 
++a key from F1 through F12 (or more, just change 12 to your number in the
++patch file). 
++
++The patch enables a number of useful features. Here is a my set-up:
++
++F1: Losslessly rotate JPEG 90 degrees to the right.
++F2: Losslessly rotate JPEG 90 degrees to the left.
++
++F3: Print the current selection rectangle (on the terminal where xv was 
++    launched). This is useful for quickly recording a bunch of positions in
++    an image. Use case: 
++      I'm annotating face positions.
++        1) Select Joe in picture, hit F3, type "Joe" in the terminal.
++        2) Select Jane in the picture, ... 
++        ...
++        n) Copy the text visible in the terminal, and paste it into the
++           JPEG comment.
++    Of course, i would write a more convenient script if I annotated faces 
++    with any any frequency.
++
++F4: Edit JPEG comment (I use it for annotations/tags).
++
++F5: Log a 'losslessly rotate right' command for batch processing.  This
++    writes the rotation command for the current file into a shell script
++    somewhere ("~/photos/bin/rotscript" by default). This is great for 
++    slower computers because you don't have to wait for each image to 
++    rotate; instead, you just rotate them all at once by running the 
++    resulting script.
++F6: Log a 'losslessly rotate left' batch command.
++
++F8: Crop image on disk, but back-up the uncropped version. You can make 
++    a succession of crops this way, with a backup made at every step.
++    This wastes disk space, so be sure to clean up once you get a crop you
++    like.
++F7: Undo the last crop done on this image. This can be repeated until you're
++    back at the original.
++
++-- Installation --
++
++I'll tell you how to get the set-up I described above. Of course, you can
++customize it to your heart's content.
++
++(( 1 ))
++
++Go to:
++
++  http://www.sonic.net/~roelofs/greg_xv.html
++
++and follow the XV install instructions there. If you are okay with
++reading shell scripts, you might also give this a shot:
++
++  http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo-x86/media-gfx/xv/xv-3.10a-r12.ebuild
++
++When you're ready to type "make install", do the following to apply my patch:
++
++  $ cd WHEREVER_YOU_COMPILED_XV
++  $ patch -p1 --dry-run < PATH/TO/xv-3.10a-fkey-command-patch.greg-xv
++
++Hopefully, the above command won't complain; if it does, Greg Roelofs
++probably changed his patchset, and my patch has become out of date -- let me
++know. If that went well, run:
++
++  $ patch -p1 < PATH/TO/xv-3.10a-fkey-command-patch.greg-xv
++  
++Now, simply recompile and install as described in the other instructions.
++  
++(( 2 ))
++
++Copy 'jpegcrop.sh', 'jpegeditcom.sh', 'jpegundocrop.sh', 'jpegrot.sh',
++'jpeglogrot.sh' to some convenient directory.
++
++Suggestions: ~/photos/bin, /usr/local/bin, etc...
++
++Edit 'jpeglogrot.sh' and 'jpegeditcom.sh'. In the former, you need to
++customize the path to 'jpegrot.sh'. In the latter, you should make set 
++your favorite editor. The spots to customize are marked as such.
++
++(( 3 ))
++
++Open .Xdefaults in your favorite text editor, and paste the following lines
++there:
++
++xv.F1command: ~/photos/bin/jpegrot.sh 90 %s
++xv.F2command: ~/photos/bin/jpegrot.sh 270 %s
++xv.F3command: @echo "The selection rect for '%s' is at (%d, %d) of size %dx%d."
++xv.F4command: @~/photos/bin/jpegeditcom.sh %s &
++xv.F5command: @~/photos/bin/jpeglogrot.sh 90 %s
++xv.F6command: @~/photos/bin/jpeglogrot.sh 270 %s
++xv.F7command: ~/photos/bin/jpegundocrop.sh %s
++xv.F8command: ~/photos/bin/jpegcrop.sh %s %d %d %d %d
++
++Change '~/photos/bin/' to the directory you chose in (( 2 )). In case you're
++wondering what the '@' symbol means, it tells XV not to reload the file
++after running this command. The default is to reload the file.
++
++-- Apologies --
++
++I didn't get a chance to run through the above instructions and check
++that they work. I know they're right in spirit, but I might've made a typo
++or two. Even if it's obvious to you, would you please let me know by writing
++to lesha at mit dot edu?
+diff -Naru xv-3.10a/README.jumbo xv-3.10a.jumbo/README.jumbo
+--- xv-3.10a/README.jumbo	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/README.jumbo	2007-05-21 07:19:20.000000000 +0200
+@@ -0,0 +1,559 @@
++This is the latest version of the XV jumbo patches I originally created in
++February 2000 (but never distributed) and eventually updated and released in
++May 2004, prompted by a discussion on LWN (http://lwn.net/Articles/76391/).
++Information about the patches, updates to the patches, and the patches
++themselves can all be found here:
++
++	http://pobox.com/~newt/greg_xv.html
++	http://freshmeat.net/projects/xvjumbopatches/
++
++(Use the "Subscribe to new releases" link on the latter page if you want to
++be notified of new versions automatically; trivial registration required.)
++
++These patches incorporate all of the fix- and enhancement-patches available
++from John's XV site (http://www.trilon.com/xv/downloads.html and
++ftp://ftp.trilon.com/pub/xv/patches/), plus a number of my own fixes and
++additions (security-related and otherwise), plus quite a few from other
++people.  They're still not fully complete, and it's probable they never
++will be, but I do plan to continue tinkering with them whenever the mood
++strikes--and I may even release them publicly on rare occasions.  (At the
++current rate, once every few years may be the best we can hope for....)
++
++Also be aware that several other people have had the same idea over the
++years.  Ones I've found, more or less by accident, include:
++
++ - Landon Curt "chongo" Noll (http://www.isthe.com/chongo/)
++   http://www.isthe.com/chongo/src/xv-patch/
++ - Mark Ashley <mark ibiblio.org>
++   http://www.ibiblio.org/pub/packages/solaris/sparc/html/xv.3.10a.p19.html
++ - Peter Jordan <pete dc.seflin.org>
++   http://www.ibiblio.org/pub/Linux/apps/graphics/viewers/X/xv-3.10a.patch.*
++ - Uwe F. Mayer (http://www.tux.org/~mayer/)
++   http://www.tux.org/~mayer/linux/book/node311.html
++ - Kurt Wall <kwall kurtwerks.com>
++   http://www.kurtwerks.com/software/xv.html
++ - Chisato Yamauchi (http://phe.phyas.aichi-edu.ac.jp/~cyamauch/index_en.html)
++   http://phe.phyas.aichi-edu.ac.jp/~cyamauch/xv.html
++ - Daisuke Yabuki <dxy optix.org>
++   http://www.optix.org/~dxy/solaris/xv/
++ - Pekoe (http://pekoe.lair.net/)
++   http://pekoe.lair.net/diary/xv.html
++ - FreeBSD FreshPorts
++   http://www.freshports.org/graphics/xv/
++ - Kyoichiro Suda <sudakyo fat.coara.or.jp>
++   http://www.coara.or.jp/~sudakyo/XV_jp.html
++
++This is not an exhaustive list (e.g., Jörgen Grahn also had one).  So far,
++most of the other patch-sets appear not to be as extensive or as up-to-date
++as my own, particularly now that the (very large) "Japanese extension" patches
++are incorporated--big thanks to Werner Fink of SuSE for that!
++
++Below I summarize the component patches that are encompassed by my jumbo
++bugfixes and jumbo enhancements patches, circa 2005.  (As of 2007, they're
++distributed as a single monster-patch, and the "component patches" are now
++listed in the changelog section at the bottom of this file.)  Unfortunately,
++some of my own additions never saw the light of day as standalone patches,
++but considering the number of overlaps (collisions) already implicit in the
++list, that would have been difficult to accomplish even if I'd had the time.
++
++Here's a quick guide to the "third-party" credits in the lists and changelog
++below:
++
++  AAC = Andrey A. Chernov [ache]
++        (http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-ab)
++  AD  = Andreas Dilger (adilger clusterfs.com)
++  AL  = Alexander Lehmann (lehmann usa.net)
++  AS  = Alexey Spiridonov (http://www-math.mit.edu/~lesha/)
++  AT  = Anthony Thyssen (http://www.cit.gu.edu.au/~anthony/)
++  BR  = Bruno Rohee (http://bruno.rohee.com/)
++  DAC = David A. Clunie (http://www.dclunie.com/xv-pcd.html)
++  EAJ = Erling A. Jacobsen (linuxcub email.dk)
++  EK  = Egmont Koblinger (egmont users.sourceforge.net)
++  FG  = Fabian Greffrath (fabian debian-unofficial.org)
++  GRR = Greg Roelofs (http://pobox.com/~newt/greg_contact.html)
++  GV  = Guido Vollbeding (http://sylvana.net/guido/)
++  IM  = IKEMOTO Masahiro (ikeyan airlab.cs.ritsumei.ac.jp)
++  JC  = John Cooper (john.cooper third-harmonic.com)
++  JCE = John C. Elliott (http://www.seasip.demon.co.uk/ZX/zxdload.html)
++  JDB = John D. Baker (http://mylinuxisp.com/~jdbaker/)
++  JG  = Jörgen Grahn (jgrahn algonet.se)
++  JHB = John H. Bradley, of course (http://www.trilon.com/xv/)
++  JPD = Jean-Pierre Demailly (http://www-fourier.ujf-grenoble.fr/~demailly/)
++  JR  = John Rochester (http://www.freebsd.org/cgi/query-pr.cgi?pr=2920)
++        (also http://cvsweb.freebsd.org/ports/graphics/xv/files/patch-af, -ag)
++  JRK = James Roberts Kirkpatrick (uwyo.edu)
++  JZ  = Joe Zbiciak (http://spatula-city.org/~im14u2c/)
++  KS  = Kyoichiro Suda (http://www.coara.or.jp/~sudakyo/XV_jp.html)
++  LCN = Landon Curt "chongo" Noll (http://www.isthe.com/chongo/)
++  LJ  = Larry Jones (lawrence.jones ugs.com)
++  PBJ = Peter Jordan (http://www.ibiblio.org/pub/Linux/apps/graphics/viewers/X/)
++  PSV = Pawel S. Veselov (http://manticore.2y.net/wbmp.html)
++  RAC = Ross Combs (rocombs cs.nmsu.edu)
++  RJH = Robin Humble (http://www.cita.utoronto.ca/~rjh/)
++  SB  = Sean Borman (http://www.nd.edu/~sborman/software/xvwheelmouse.html)
++  SJT = TenThumbs (tenthumbs cybernex.net)
++  SBM = Scott B. Marovich (formerly marovich hpl.hp.com)
++  TA  = Tim Adye (http://hepwww.rl.ac.uk/Adye/xv-psnewstyle.html)
++  TAR = Tim Ramsey (tar pobox.com)
++  TI  = Tetsuya INOUE (tin329 chino.it.okayama-u.ac.jp)
++  TO  = Tavis Ormandy (taviso gentoo.org)
++  WF  = Werner Fink (http://www.suse.de/~werner/)
++
++Other credits are as listed on the XV Downloads page or in the respective
++patches (e.g., the jp-extension patches or within the PNG patch).
++
++Finally, please note that these patches have not been blessed by John Bradley
++in any way (although I copied him on the May 2004 announcement and wrote to
++him again in May 2005), unless you count Debian's redistribution permission
++(Daniel Kirchheimer, 5 Dec 2005).  Nor have I personally tested every change
++and feature!  (See the BIG SCARY WARNING below for further caveats.)  In other
++words, they're both completely unofficial and completely unguaranteed.  But
++they seem to work for me.  (And when they don't, I try to fix 'em--eventually,
++anyway... ;-) )
++
++Greg Roelofs, 20070520
++http://pobox.com/~newt/greg_contact.html
++
++
++How to build
++------------
++
++The following assumes you, the user, already have the libtiff,[1] libjpeg,[2]
++libpng,[3] zlib,[4] and JasPer[5] libraries downloaded, patched (if necessary),
++compiled, and installed, not to mention a C compiler and the bzip2,[6] tar,[7]
++patch,[8] and make[9] utilities.  You should also have downloaded the original
++XV 3.10a source distribution from the XV Downloads page[10] and be able to edit
++its Makefile and config.h files as indicated in the INSTALL file.  (Editing
++the Makefile will also allow you to disable some of the third-party libraries
++if you wish.)  Finally, you should know what a Unix(-style) command line is,
++where to find one, and how to wield it with abandon (or at least with adult
++supervision)--and preferably not as the root user until the "make install"
++step.  (A filesystem is a terrible thing to waste.)
++
++   [1] http://www.remotesensing.org/libtiff/
++   [2] http://www.ijg.org/
++   [3] http://www.libpng.org/pub/png/libpng.html
++   [4] http://www.zlib.net/
++   [5] http://www.ece.uvic.ca/~mdadams/jasper/
++   [6] http://sources.redhat.com/bzip2/
++   [7] http://www.gnu.org/directory/devel/specific/tar.html
++   [8] http://www.gnu.org/directory/devel/specific/patch.html
++   [9] http://www.gnu.org/directory/devel/specific/make.html
++  [10] http://www.trilon.com/xv/downloads.html#src-distrib
++
+++-------------------------------------------------------------------------+
++|                                                                         |
++|                            BIG SCARY WARNING                            |
++|                                                                         |
++|  These patches work for Greg (and parts of them reportedly work for     |
++|  various other people), and so far Greg's CPU still computes and his    |
++|  hard disks haven't been wiped.  But there's no guarantee that this     |
++|  will be the case for you! In particular, not every incorporated patch  |
++|  has been explicitly tested, nor has every possible subcase of the      |
++|  explicitly tested subset. (Read that again; it's grammatical.)  Nor    |
++|  are these patches officially blessed by John Bradley in any way. In    |
++|  other words, if you use these patches, you do so at your own risk.     |
++|  (Greg doesn't believe there are any serious problems remaining, but    |
++|  then, what programmer ever does? Bugs happen.)                         |
++|                                                                         |
+++-------------------------------------------------------------------------+
++
++Assuming you have the prerequisites out of the way and aren't scared
++off by the Big Scary Warning, here's the build procedure:
++
++      tar xvzf xv-3.10a-jumbo-patches-20070520.tar.gz
++      (or:  gzip -dc xv-3.10a-jumbo-patches-20070520.tar.gz | tar xvf - )
++
++      tar xvzf xv-3.10a.tar.gz 
++
++      cd xv-3.10a 
++
++      patch -p1 < ../xv-3.10a-jumbo-fix-enh-patch-20070520.txt 
++
++      edit Makefile and config.h as directed in INSTALL file (in particular,
++      ensure paths to external libraries and header files are correct)
++
++      make 
++
++      ./xv  your_favorite_image  your_other_favorite_image  etc.
++
++If everything seems to be working to your satisfaction, go ahead and install: 
++
++      make -n install (and double-check that things will be installed
++      where you want them to be)
++
++      become root if necessary (e.g., type su)
++
++      make install 
++      (or:  sudo make install)
++
++That wasn't so hard, was it? 
++
++
++Summary of incorporated and unincorporated patches (through 20050501)
++---------------------------------------------------------------------
++(See the ChangeLog at the bottom for more recent incorporated patches.)
++
++fixes ((*) = listed on XV Downloads page, (f) = on ftp site only):
++
++20040516:
++ - grabpatch (*)		[obsoleted by new-xvgrab.c below]
++ - vispatch (*)
++ - mp-tiff-patch (*)		[technically an enhancement, but JHB says...]
++ - longname.patch (*)		[*SECURITY*]
++ - xpm.patch (*)
++ - deepcolor.patch (*)		[slightly modified for language conformance]
++ - gifpatch (*)
++ - exceed_grab.patch (*)
++ - xv-redhat6-readme.txt (*)	[slightly modified for portability]
++ - beos.patch (*)		[modified for portability]
++ - croppad.patch (f)
++ - epsfpatch (f)
++ - tiff1200.patch (*)
++ - gssafer.patch (*)		[*SECURITY*]
++ - new-xvgrab.c (f)		[includes grabpatch but not exceed_grab.patch]
++ - xcmap.diff (AD)		[part of xv-3.10a-png-1.2d.tar.gz]
++ - fixes for huge number gcc -Wall warnings--including two bugs (GRR)
++ - fix for cleandir script when no makefile exists (GRR)
++ - *SECURITY* fix for gets() in vdcomp.c (GRR, LCN vdcomp-security.patch)
++ - *SECURITY* fix for getwd() on Linux (GRR, LCN Linux-compile.patch)
++ - fix for "no fuss" Linux compiles (LCN Linux-compile.patch)
++ - partial *SECURITY* fix for mktemp() in xv.c and xvdir.c (GRR)
++   (remaining instances in xv.c (2), xvimage.c, xvfits.c, xvpds.c, xvps.c, and
++   possibly xvtiff.c--most involve system())
++ - freebsd-vdcomp-newline.patch (AAC)
++ - xv-3.10a.patch.linux (PBJ)	[/bin/sh versions of cleandir, RANLIB.sh only]
++ - removed trailing white space (GRR)  [purely cosmetic]
++20040523:
++ - fixed compilation error in registered versions (GRR)
++20050410:
++ - fix for YCbCr oversaturated-green bug(s) in TIFF decoder (GRR)
++ - provisional fix for contiguous tiled TIFFs with bottom-* orientation (GRR)
++ - fixes for gcc 3.3 -Wall warnings (GRR)
++ - fix for incorrect 16/24-bit display of xwd dumps (SJT)
++ - *SECURITY* fix for multiple input-validation bugs (OpenBSD/SuSE, Gentoo, GRR)
++   (this also completes the partial mktemp() security fix listed above)
++ - fix for (probable) 24-bit endianness bug in fixpix code (GRR)
++
++
++enhancements ((*) = listed on XV Downloads page, (<who>) = third-party):
++
++20040516:
++ - xv-3.10a.JPEG-patch (*)
++   (xv-3.10a.JPEG-patch.old differs only in ftp site listed in comments at top)
++ - xv-3.10a.TIFF-patch (*)
++ - xv-3.10a-png-1.2d.tar.gz (AL, AD) (*)
++   (xvjpeg.diff and xvtiff.diff ignored; xcmap.diff included in fixes)
++ - xvpng-1.2d-fix3.patch (GRR, SJT) (*)
++ - pdf.patch (*)
++ - windowid.patch + windowid.patch.readme (*)
++ - bmp32.patch (*)
++ - fixpix-20000610.tar.gz (GV)
++   (identical to 19961127 version except for README updates and new Win32 file)
++   [modified to be runtime-selectable via -/+fixpix option]
++ - browse-remember.patch (JZ)
++ - faster-smooth.patch (JZ)
++ - PAM support (GRR)
++ - PNG/GIF -ibg ("image background") transparency option (GRR)
++   (does not yet support TIFF, XPM or TGA)
++ - VersionInfo* in help screen (GRR)
++ - minor grammar/spelling fixes (GRR)
++ - floating-point support for -wait when USE_TICKS enabled (GRR)
++ - wheelmouse.patch (SB)
++ - freebsd-gravity-hints-patch (JR)
++ - xv-zx.patch (JCE)
++ - xv3.10a.wapbmp.patch (PSV)
++ - xv-3.10a-pcd.patch.20010708 (DAC)
++ - jp-ext-bzip2-1.1.patch
++   (from ftp://ftp.freebsd.org/pub/FreeBSD/ports/local-distfiles/shige/xv/)
++20050410:
++ - boosted maximum number of files from 4096 to 32768 (GRR)
++   (note that OS kernel limits may also apply; for example, in Linux see
++   MAX_ARG_PAGES in linux-<version>/include/linux/binfmts.h)
++ - xv-3.10a-bmp16.patch (KS)
++ - final-image delay (e.g., "-wait 0.2,3" : pause 3 secs on final image) (GRR)
++ - xv-numpad.patch (EK)
++ - xv-delete-is-not-backspace.patch (EK)
++ - made browser window (schnauzer) and icons configurable (AT, GRR)
++20050501:
++ - xv-3.10a-bmpfix.patch (WF)		[*SECURITY*]
++ - xv310a-jp-extension-rev5.3.3.tar.gz (TI, IM, ..., WF)
++   (adds support for MAG, MAKI, Pi, PIC, and PIC2 formats[!]; "magic suffix"
++   detection/conversion; MacBinary prefixes; archives as virtual filesystems;
++   multilingual text viewer [though not Unicode]; etc.)
++ - xv-3.10a-yaos.dif (WF, TO)		[*SECURITY*]
++   (fixes a number of format-string issues and system() calls)
++ - xv-3.10a.dif (WF)			[*SECURITY*]
++   (fixes more format-string issues, mktemp() and open() calls, and compilation
++   warnings [mostly from jp-extension patch])
++ - xv-3.10a-jumbo-jpd_startgrab-patch-20050420.txt (JPD)
++ - PATCH.alwaysnever (LJ)
++ - PATCH.bsd (LJ)
++ - PATCH.linedraw (LJ)
++ - PATCH.multipage (LJ)
++ - PATCH.multipageGIF (LJ)
++ - PATCH.random (LJ)
++ - PATCH.stat (LJ)
++ - PATCH.thumbs (LJ)
++ - xv-startgrab-imake-hips.patch (JPD)
++   ("hips" portion only; adds support for HIPS image format[!])
++ - xv-3.10a-formatstr.patch (KS)
++ - xv-3.10a-shortsleep.patch (KS)
++ - xv-3.10a-locale-linux.patch (KS)
++ - xv-3.10a-printkey.patch (KS)
++ - xv-3.10a-sysconfdir.patch (KS)
++ - added PREFIX and DESTDIR support to Makefile (KS, GRR)
++ - xv-3.10a-xvexecpath.patch (but disabled pending fixes) (KS)
++ - xv-3.10a-zeroquit.patch (KS, GRR)
++
++[!] Note that all six of these formats may still suffer from exploitable heap
++    overflows [*SECURITY*] when decoding images with large (possibly invalid)
++    dimensions; as a result, they are DISABLED by default.  (Search for "GRR
++    POSSIBLE OVERFLOW / FIXME" comments in xvmag.c, xvmaki.c, xvpi.c, xvpic.c,
++    xvpic2.c, and xvhips.c, but keep in mind that these may not be exhaustive.)
++    Users who choose to overlook these security issues can enable any or all
++    of them by editing config.h.
++
++
++not (yet?) included:
++
++ - others from http://www.coara.or.jp/~sudakyo/XV_jp.html (some are duplicates):
++	-rw-r--r--      4644 Mar 11  2004 xv-3.10a-directory.patch
++	-rw-r--r--       462 Mar 11  2004 xv-3.10a-dirwkey.patch
++	-rw-r--r--       688 Mar 11  2004 xv-3.10a-docdir.patch
++	-rw-r--r--     11952 Mar 11  2004 xv-3.10a-download-test0.patch
++	-rw-r--r--     41786 Mar 11  2004 xv-3.10a-download-test1.patch
++	-rw-r--r--     42397 Mar 11  2004 xv-3.10a-download-test2.patch
++	-rw-r--r--     47679 Mar 11  2004 xv-3.10a-download-test3.patch
++	-rw-r--r--     52745 Mar 11  2004 xv-3.10a-download-test4.patch
++	-rw-r--r--      3423 Apr 24  2004 xv-3.10a-keyzoom.patch
++	-rw-r--r--     12387 Mar 15  2004 xv-3.10a-menubutton.patch
++	-rw-r--r--      1178 Apr 24  2004 xv-3.10a-noblink.patch
++	-rw-r--r--     57092 Jul  9  2004 xv-3.10a-resolution.patch
++	-rw-r--r--      4645 Apr 24  2004 xv-3.10a-selall.patch
++	-rw-r--r--       702 Apr 24  2004 xv-3.10a-showlongname.patch
++	-rw-r--r--      1205 Apr 24  2004 xv-3.10a-staytoppdir.patch
++	-rw-r--r--      4228 Apr 24  2004 xv-3.10a-wheelmouse.patch
++	-rw-r--r--       744 Apr 24  2004 xv-3.10a-xvbutt_wait.patch
++	-rw-r--r--      3757 Jul  9  2004 xv-3.10a-xvscrl_button2.patch
++	-rw-r--r--      1494 Jul  9  2004 xv-3.10a-xvscrl_wait.patch
++	-rw-r--r--     19352 Jul  9  2004 xv-3.10a-xvzoom.patch
++
++ - xv-3.10a+jp-extension-rev5.3.3+FLmask.v2.1+png+misc.patch	["mask" support]
++
++ - xv-psnewstyle.patch (TA)			[coming "soon"?]
++ - xv-3.10a.patch.linux (PBJ)			[maybe use vdcomp.c changes?]
++ - xvxpm-anthony-thyssen.c (AT)			["slate grey" bug already gone?]
++ - xv-geoff-kuenning-iconsize-slideshow.patch	[var. icons; full-screen slides]
++ - xv-scott-marovich-20070214-xvtiff.c.patch6.unified	[TIFF CMYK support]
++
++ - stuff in xv/unsupt:
++	-rw-r--r--     30527 Dec 22  1994 FITS.rite
++	-rw-r--r--     49152 Dec 22  1994 FITS.tar
++	-rw-r--r--      3753 Dec 22  1994 G3.patch1
++	-rw-r--r--     24576 Dec 22  1994 G3.tar
++	-rw-r--r--      1098 Dec 22  1994 INFO.cgm
++	-rw-r--r--      1941 Dec 22  1994 README
++	-rwxr-xr-x      1059 Dec 22  1994 getweather
++	-rwxr-xr-x      2186 Dec 22  1994 getweather.ksh
++	-rw-r--r--       856 Dec 22  1994 twm.fix
++	-rw-r--r--       844 Dec 22  1994 vargs.c
++	-rw-r--r--     47626 Dec 22  1994 vis
++	-rw-r--r--     21097 Dec 22  1994 xscm
++
++
++
++not finished (and/or even started ;-) ):
++
++ - fix xvpng.c not to use direct struct access
++ - (better) fix for never-ending pile of SLOW popups when viewing TIFFs with
++   unknown tags (or truncated/corrupted images)
++ - fix for minor .Z inefficiency in xv.c ("FIXME")
++ - fix for filename entry-field mouse/cursor deficiencies
++   (positioning fixed 20070104 by Ross Combs; would like select/cut/paste, too)
++ - fix for .ppm.gz "disk leak" [can't reproduce...already fixed?]
++   (maybe occurs only if filesystem is already nearly full?  bad .gz?)
++
++ - transparency support for TIFF, XPM and TGA images
++ - support for tiled background image (with transparent foreground image)
++ - MNG/JNG support
++ - SVG support
++
++
++ChangeLog
++---------
++
++  20000220
++    original pair of jumbo patches, comprising perhaps 16 fix-patches and a
++    dozen enhancement-patches; never publicly released 
++
++  20040516
++    first public release, incorporating 25 fix-patches and 21 enhancement-
++    patches
++
++  20040523
++    minor fix to xvctrl.c to support registered versions (GRR warnings-patch
++    was slightly overzealous); switched to tarball packaging
++
++  20040531
++    fixed undefined CLK_TCK with gcc -ansi (enh/USE_TICKS option); made
++    libjpeg, libtiff, libpng and zlib sections of makefile more consistent
++    (enh)
++
++  20040606
++    added freshmeat link, build instructions, and changelog to jumbo README
++    (this file)
++
++  20050213
++    increased max number of files from 4096 to 32768 (enh)
++
++  20050320-20050410
++    fixed two very long-standing YCbCr bugs in TIFF decoder (fix);
++    provisionally fixed bug in TIFF decoder for contiguous tiled TIFFs with
++    bottom-* orientation (fix/USE_TILED_TIFF_BOTLEFT_FIX option); fixed new
++    gcc 3.3 warnings (fix); fixed incorrect 16/24-bit display of xwd dumps
++    (fix); fixed multiple input-validation bugs (potential heap overflows)
++    and mktemp() dependencies (*SECURITY* fixes:  CAN-2004-1725, CAN-2004-
++    1726, CAN-2005-0665, CERT VU#622622, and others); added support for 16-
++    and 32-bit BMPs using bitfields "compression" (enh); fixed probable byte-
++    sex bug in 24-bit FixPix display code (enh/USE_24BIT_ENDIAN_FIX option);
++    fixed numerical-keypad NumLock behavior and delete-key behavior in file-
++    load/save window (enh); made schnauzer window and icons configurable (enh)
++
++  20050417
++    incorporated "Japanese extension" patches, revision 5.3.3 (enh); fixed
++    additional *SECURITY* issues (format-string vulnerabilities, system()
++    and mktemp() calls, etc., but NOT heap overflows in new decoders) both
++    in existing code and in jp-extension additions (enh)
++
++  20050425
++    added support for -startgrab option (enh); added support for a "Never"
++    button to file-overwrite popups (enh); added NetBSD and BSDI to list of
++    mkstemp()-supporting systems (enh); improved line-drawing code to set the
++    correct pixels for lines of all slopes (enh); added "Page n of m" to Info
++    window for multipage images (enh); added support for multipage (animated)
++    GIFs (enh); fixed -random support so randomized file list can be traversed
++    normally in forward or backward direction (enh); added typecasts to stat()
++    printfs for portability (enh); fixed erroneous use of "creation" time and
++    forced unlink prior to overwrite in schnauzer thumbnail code (enh); added
++    HIPS support (enh/HAVE_HIPS option)
++
++  20050501
++    extended multipage keyboard support (PgUp/PgDn) to all windows except
++    control ("console") and directory (enh); fixed minor (non-security)
++    format-string issue in xv.c (enh); shortened delay on popup error windows
++    from 3 seconds to 1 second (enh); tweaked text-viewer localization support
++    (TV_L10N) for Linux (enh); added keyboard short cuts for Color and
++    Grayscale buttons in print dialog (enh); added support for separate "magic
++    suffix" (xv_mgcsfx) config dir (enh); added PREFIX and DESTDIR support to
++    Makefile (enh); fixed handling of zero-length files and other text-viewer
++    failures (enh)
++
++  20050528
++    conditionally added missing alloca.h to xvpcd.c (required if alloca() is
++    a macro and alloca.h not included in stdlib.h, for example); fixed bogus
++    __S_IWRITE introduced in 20050501 release; fixed Makefile "install" target
++    (mkdir, chmod); fixed bug in MUST macro in xvwbmp.c; fixed prototype
++    warnings in xvevent.c, xvpcd.c (JRK, GRR)
++	- xv-3.10a-jimkirk-fixes.patch
++
++  20050630
++    fixed broken mkdir(.xvpics) introduced in 20050501 release (RJH, GRR);
++    tweaked GUNZIP config for OpenBSD (GRR)
++	- xv-3.10a-xvpics-mkdir-fix.patch
++
++  20051014
++    fixed longstanding xvevent.c typo (wasJpegUp -> wasPngUp) that caused build
++    failure if no JPEG support (TAR)
++
++  20051019
++    fixed Darwin (Mac OS X) build error in xv.h and vdcomp.c due to lack of
++    malloc.h (JDB)
++
++  20070210
++    fixed minor grammos (GRR); promoted PNG to first position, demoted GIF to
++    third (GRR); changed internal type of default image to PNG (GRR); increased
++    max files again, to 65536 (GRR)
++
++  20070310
++    incorporated JPEG-2000 patch (SBM, GRR); added manual fax options for
++    unrecognized G3 images (SBM); relaxed 30-byte minimum file size (SBM)
++	- http://www.ece.uvic.ca/~mdadams/jasper/software/xv-patches
++
++  20070318
++    incorporated 16bps raw (binary) PPM patch (define ASSUME_RAW_PPM_LSB_FIRST
++    for old behavior) (RAC, GRR); updated format list, web sites in xv man page
++    (GRR); fixed Makefile "install" target to create any necessary directories
++    (RAC, GRR); fixed GIF decoder bug (sizes of global, local color tables
++    different) (GRR)
++	- xv-ross-combs-ppm-16bps-rawbits.patch
++
++  20070325
++    fixed invalid gamma assumption in PNG decoder (=> progressive color changes
++    over load/save cycles) (GRR)
++
++  20070328
++    fixed animated-GIF /tmp/xvpgXXXXXX droppings (GRR)
++
++  20070331
++    fixed PNG duplicate-palette-entries bug (GRR)
++
++  20070415
++    incorporated EXIF-preserve patch (GHK); added missing JP2/JPC VS bits code
++    (GRR); added extended-warning options to CCOPTS (RAC); added "const" to
++    huge number of function args (RAC, GRR); made more effectively static
++    functions officially static (RAC); added mouse-clickability (but not
++    selectability) to text-entry fields (RAC); fixed window positioning (race
++    conditions?) under some virtual window managers (e.g., tvtwm) (RAC);
++    removed explicit paths for external (de)compressors (GRR, RAC)
++	- xv-geoff-kuenning-jpeg-exif-preserve.patch
++	- xv-ross-combs-20070104.diff
++
++  20070422
++    incorporated function-key-scripts patch (see contrib/fnkey-scripts) (AS);
++    fixed man-page-section extensions ("1", not "l" or "1X") (FG); switched to
++    more sensible install paths for docs (FG); added Fedora Core build script
++    (see contrib/fedora) (JC); fixed VS to switch from move-mode to copy-mode
++    if source dir is read-only (EAJ); extended VS incremental-search mode (EAJ)
++	- xv-alexey-spiridonov-20070116-fnkey-scripts.tar.bz2
++	- xv-fabian-greffrath-20070215-debian-04-manpages.dpatch
++	- xv-fabian-greffrath-20070215-debian-03-makefiles.dpatch
++	- xv-john-cooper-Build-FC5-script.sh
++	- xv-erling-jacobsen-20060617-incr-search.patch
++
++  20070428
++    modified install to include README.jumbo in docs (GRR); incorporated PNG
++    no-stdio patch (SBM); fixed XWD endianness support, improved performance
++    (replaces SJT 16/24-bit fix) (SBM)
++	- xv-scott-marovich-20070214-xvpng.diff
++	- xv-scott-marovich-20070214-xvxwd.c.patch
++
++  20070506
++    added JPEG CMYK support (SBM); fixed TIFF (and others?) /tmp/xvpgXXXXXX
++    droppings (GRR); added VS clipboard support (JG)
++	- xv-scott-marovich-20070214-xvjpeg.c.patch
++	- xv-jurgen-grahn-20051127-schnauzer-clip.patch
++
++  20070512
++    inverted handling of malloc.h header file to require NEED_MALLOC_H macro
++    for those few systems that actually need it (GRR)
++
++  20070513
++    fixed GCC 4.1.x warnings (GRR); next round of const cleanup (GRR); fixed
++    minor TIFF memleak (GRR)
++
++  20070514
++    fixed TIFF YCbCr reference black/white levels (SBM); added option to use
++    libjpeg YCbCr-to-RGB conversion for TIFF images (SBM, GRR)
++	- xv-scott-marovich-20070214-xvtiff.c.patch2.unified
++	- xv-scott-marovich-20070214-xvtiff.c.patch3.unified
++
++  20070519
++    fixed handling of multi-page JPEG-compressed TIFFs (old or new) (SBM);
++    added TIFF YCbCr separated-color-plane support (may require libtiff
++    patch(es) to tif_ojpeg.c and/or tif_jpeg.c) (SBM)
++	- xv-scott-marovich-20070214-xvtiff.c.patch4.unified
++	- xv-scott-marovich-20070214-xvtiff.c.patch5.unified
++
++  20070520
++    updated README.jumbo
+diff -Naru xv-3.10a/README.pcd xv-3.10a.jumbo/README.pcd
+--- xv-3.10a/README.pcd	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/README.pcd	2001-07-08 20:21:19.000000000 +0200
+@@ -0,0 +1,159 @@
++Copyright 1993-2001 David Clunie.
++
++PCD patch for XV 3.10a Release Notes 2001/07/08.
++
++See also the progress notes at the end of this file. Thanks to all those
++contributors who have substantially improved this patch.
++
++These patches allow xv to read Kodak photocd files and choose which of the
++5 available resolutions one wants to view.
++
++When a photocd file is loaded, a dialog box asks which resolution you
++would like. The visual schnauzer builds thumbnails by reading the lowest
++resolution image. The selected resolution can be selected from the
++command line with the -pcd option:
++
++	[-pcd 0|1|2|3|4]
++
++where:
++
++	0=192*128,	base/16 resolution
++	1=384*256,	base/4 resolution
++	2=768*512,	base resolution
++	3=1536*1024,	4base resolution
++	4=3072*2048	16base resolution.
++
++Note that the Pro format is not supported.
++
++The command line option allows loops without the dialog box popping up, eg.:
++
++	xv -pcd 1 -wloop -wait 10 *.pcd
++
++The code is pretty crude and was written quickly for a specific purpose and
++has not really been cleaned up. It is poorly structured, full of debugging
++codes and verbose comments, and there is very little attempt at optimizing
++things. No profiling has been done.
++
++There is not yet support for overview files, nor is there a facility to
++use the higher resolution chroma planes from when viewing lower resolution
++images.
++
++It's only claim to fame is that it works and produces reasonable looking
++images.
++
++The outline of this is shamelessly derived from xvpbm.c to read the
++file, and xvtiffwr.c to handle the popup window and X stuff (X never
++has been my forte !), and the PhotoCD format information (though not
++the code) was found in Hadmut Danisch's (danisch at ira.uka.de) hpcdtoppm
++program in which he has reverse engineered the format by studying
++hex dumps of PhotoCDs ! The color stuff and Huffman decding were
++extensively revised by Matthew Francey.
++
++Feel free to send me comments or improvements, or even better, more
++information about the photo CD format ... hopefully someone who really
++knows what they are doing will tidy it up or do a neater job.
++
++david (dclunie at dclunie.com)
++
++---------
++
++The trace #define in xvpcd.c is now in the right place, and the ansi
++prototype for the magnify function has been fixed. Colin made me switch to
++xvbcopy() which seems like a good idea for System V victims.
++
++---------
++
++Date: Wed, 22 Dec 1993 16:09:52 --1000
++From: colinc at fitmail.fit.qut.edu.au (Colin Canfield )
++
++I have done some more work using your patch I thought you might be intested in.
++The major change was adding a size parameter to the LoadPCD; either -1 to mean
++the popup or else the size you desired. This allows batch mode processing,
++specifically xv -pcd <size> <filename>, and the visual schnauzer can work in 
++quick mode (ie. you don't have to select each image size when it is building 
++the icons)
++
++I have added an xbm file for the file type but haven't drawn an icon for it,
++this is in bitmaps/br_pcd.xbm. I will just send you the new files.
++
++---------
++
++From: andrew at andrew.triumf.ca (Andrew Daviel)
++Date: 16 Feb 1995 23:32:21 GMT
++
++This is David Clunie's patch for xv-3.00 tuned a bit to work
++on xv-3.10. The code's all the same except for replacing 
++"trace" with "fprintf" in xvpcd.c and adding an "unsigned" qualifier to 
++keep my compiler (gcc) happy. Oh yes, changed RFT_PCD to 20 as
++John Bradley has now used 15 through 19.
++
++---------
++
++From: dclunie at flash.us.com (David A. Clunie)
++Date: Thu Jun 15 14:43:46 GMT+0300 1995
++
++Andrew's patch didn't include Colin's browser changes, so I redid the
++xv-3.10 update from scratch ... it seems pretty much the same as
++Andrew's changes. I also edited the Imakefile and Makefiles in order
++to support the PCD changes, as well as make the install process a
++little more flexible, with options to strip and set modes and so on.
++Also made RFT_PCD 25 so as not to conflict with magpic patch from Japan
++by Ikemoto Masahiro <ikeyan at airlab.cs.ritsumei.ac.jp>, and used his
++bitmap icon for pcd files.
++
++Now there are two versions of the patch, one which should be applied
++to the xv-3.10 distribution.
++
++The other should be applied to xv-3.10 AFTER Ikemoto Masahiro's 
++Patch.magpic2.PhotoCD.XV319a, in order to add the browser features to
++the latter, as well as fixing a Makefile typo (was xcpcd.c not xvpcd.c)
++and including unistd.h for the SEEK_xxx constants in the magicpic
++stuff.
++
++---------
++
++Subject: Re: photo-cd patch for xv 
++From: Matthew Francey <mdf at angoss.com>
++Date: Mon, 26 Mar 2001 15:37:55 +0000
++
++Attached is a revised version of xvpcd.c;  the areas that I have
++re-written or changed are in a different coding style so you can tell
++what has changed.  The GNU 'indent' program can be run against the file
++to enforce a consistent style ..
++
++Here is what I've done though:
++
++a) huffman table reader re-written, because it would fail on some
++   photocd files with "unusual" huffman codes.
++
++b) the huffman-coded corrections are now properly applied
++
++c) the corrections can sometimes over or underflow;  clipping has been
++   introduced and effectively fixes the problem, but I suspect that
++   there is something deeper going on.
++
++d) the "official" YCC->sRGB transform is done.  a "beyond 100% white"
++   mapping table was snarfed from ImageMagick.  an option for using a
++   flat linear LUT was added -- this can make somewhat over-exposed images
++   look alot nicer.
++
++e) there were strange problems where the code wouldn't be able to find
++   the huffman tables and data for the 16base image (the bit-buffering
++   code was starting mid-sector, instead of at a sector boundary).  Looking
++   at a pcd file with a hex editor suggests to me that it is possible to
++   just skip directly to these huffman tables -- no special "+12" and such
++   constants necessary.  But I haven't tried this yet.
++
++The results:  I've been able to read about 50 or 60 .pcd files [scattered
++in age from 6 years old to scans done last week] with this code without
++incident.  Image quality at the high resolution is excellent.  Even the
++trivial amount of LUT control is useful when dealing with over-exposed
++images.
++
++If I get around to it:  finer LUT control to take advantage of the
++slightly extended dynamic range of PhotoCD scans, especially in regards to
++dark or somewhat underexposed scenes.
++
++
++
++
+diff -Naru xv-3.10a/tiff/RANLIB.sh xv-3.10a.jumbo/tiff/RANLIB.sh
+--- xv-3.10a/tiff/RANLIB.sh	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/tiff/RANLIB.sh	2004-05-11 08:31:38.000000000 +0200
+@@ -0,0 +1,22 @@
++#!/bin/sh -f
++#
++# tests to see if the program 'ranlib' exists.  If it does, runs ranlib on
++# the first argument (a library name).  Otherwise, does nothing, and returns
++#
++# written by John Bradley for the XV 3.00 release
++# thanks to John Hagan for shell-script hackery
++#
++
++echo "executing 'ranlib $1'..."
++
++# Is there a ranlib?  Let's try and then suffer the consequences...
++ranlib $1 >& /dev/null
++
++if [ $? -ne 0  ]; then
++	echo "There doesn't seem to be a ranlib on this system..."
++	echo "Don't worry about it."
++fi
++
++echo ""
++echo ""
++
+diff -Naru xv-3.10a/xvhips.c xv-3.10a.jumbo/xvhips.c
+--- xv-3.10a/xvhips.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvhips.c	2005-05-01 08:49:14.000000000 +0200
+@@ -0,0 +1,406 @@
++/*
++ * xvhips.c - load routine for 'HIPS' format pictures
++ *
++ * LoadHIPS(fname, numcols)
++ */
++
++/*
++ * Copyright 1989, 1990 by the University of Pennsylvania
++ *
++ * Permission to use, copy, and distribute for non-commercial purposes,
++ * is hereby granted without fee, providing that the above copyright
++ * notice appear in all copies and that both the copyright notice and this
++ * permission notice appear in supporting documentation.
++ *
++ * The software may be modified for your own purposes, but modified versions
++ * may not be distributed.
++ *
++ * This software is provided "as is" without any express or implied warranty.
++ */
++
++#include "xv.h"
++
++#ifdef HAVE_HIPS
++
++#define Boolean FREDDIE
++#include "xvhips.h"
++#undef Boolean
++
++#include <alloca.h>
++
++#define LINES 100
++#define LINELENGTH 132
++
++static int   fread_header(int fd, struct header *hd);
++static char  *getline(int fd, char **s, int *l);
++static int   dfscanf(int fd);
++static void  make_grayscale(char *r, char *g, char *b);
++static float hls_value (float n1, float n2, float hue);
++static void  hls_to_rgb(float h, float l, float s,
++                        float *r, float *g, float *b);
++static void  make_huescale(char *r, char *g, char *b);
++static void  make_heatscale(char *r, char *g, char *b);
++static int   load_colourmap(char *filestem, int max_colours,
++                            char *r, char *g, char *b);
++
++/************************************************************************
++ *
++ * Read Header routines
++ *
++ ************************************************************************/
++
++static char *ssave[LINES];
++static int slmax[LINES];
++static int lalloc = 0;
++//extern char *calloc();
++
++
++
++static int fread_header(fd, hd)
++  int fd;
++  struct header *hd;
++{
++  int lineno, len, i;
++  char *s;
++
++/*fprintf(stderr,"fread_header: entered\n");*/
++  if(lalloc<1) {
++    ssave[0] = calloc(LINELENGTH, sizeof (char));
++    slmax[0] = LINELENGTH;
++    lalloc = 1;
++  }
++/*fprintf(stderr,"fread_header: ssave allocated\n");*/
++  getline(fd,&ssave[0],&slmax[0]);
++  hd->orig_name = calloc(strlen(ssave[0])+1, sizeof (char));
++  strcpy(hd->orig_name,ssave[0]);
++  getline(fd,&ssave[0],&slmax[0]);
++  hd->seq_name = calloc(strlen(ssave[0])+1, sizeof (char));
++  strcpy(hd->seq_name,ssave[0]);
++  hd->num_frame = dfscanf(fd);
++  getline(fd,&ssave[0],&slmax[0]);
++  hd->orig_date = calloc(strlen(ssave[0])+1, sizeof (char));
++  strcpy(hd->orig_date,ssave[0]);
++  hd->rows = dfscanf(fd);
++  hd->cols = dfscanf(fd);
++  hd->bits_per_pixel = dfscanf(fd);
++  hd->bit_packing = dfscanf(fd);
++  hd->pixel_format = dfscanf(fd);
++  lineno = 0;
++  len = 1;
++  getline(fd,&ssave[0],&slmax[0]);
++  s = ssave[0];
++  while(*(s += strlen(s)-3) == '|') {
++    len += strlen(ssave[lineno]);
++    lineno++;
++    if (lineno >= LINES)
++      fprintf(stderr, "Too many lines in header history");
++    if(lineno >= lalloc) {
++      ssave[lineno] = calloc(LINELENGTH, sizeof (char));
++      slmax[lineno] = LINELENGTH;
++      lalloc++;
++    }
++    getline(fd,&ssave[lineno],&slmax[lineno]);
++    s = ssave[lineno];
++  }
++  len += strlen(ssave[lineno]);
++  hd->seq_history = calloc(len, sizeof (char));
++  hd->seq_history[0] = '\0';
++  for (i=0;i<=lineno;i++)
++    strcat(hd->seq_history,ssave[i]);
++  lineno = 0;
++  len = 1;
++  while(strcmp(getline(fd,&ssave[lineno],&slmax[lineno]),".\n")) {
++    len += strlen(ssave[lineno]);
++    lineno++;
++    if (lineno >= LINES)
++      fprintf(stderr, "Too many lines in header desc.");
++    if(lineno >= lalloc) {
++      ssave[lineno] = calloc(LINELENGTH, sizeof (char));
++      slmax[lineno] = LINELENGTH;
++      lalloc++;
++    }
++  }
++  hd->seq_desc = calloc(len, sizeof (char));
++  *hd->seq_desc = '\0';
++  for (i=0;i<lineno;i++)
++    strcat(hd->seq_desc,ssave[i]);
++/*fprintf(stderr,"fread_header: exiting\n");*/
++  return 0;
++}
++
++
++
++static char *getline(fd,s,l)
++  int fd;
++  char **s;
++  int *l;
++{
++  int i,m;
++  char c,*s1,*s2;
++
++  i = 0;
++  s1 = *s;
++  m = *l;
++  while(read(fd,&c,1) == 1 && c != '\n') {
++    if (m-- <= 2) {
++      s2 = calloc(LINELENGTH+*l,sizeof (char));
++      strcpy(s2,*s);
++      *s = s2;
++      *l += LINELENGTH;
++      m = LINELENGTH;
++      s1 = s2 + strlen(s2);
++    }
++    *s1++ = c;
++  }
++  if (c == '\n') {
++    *s1++ = '\n';
++    *s1 = '\0';
++    return *s;
++  }
++  fprintf(stderr, "Unexpected EOF while reading header.");
++  return NULL;
++}
++
++
++
++static int dfscanf(fd)
++  int fd;
++{
++  int i;
++
++  getline(fd,&ssave[0],&slmax[0]);
++  sscanf(ssave[0],"%d",&i);
++  return(i);
++}
++
++
++
++/*******************************************/
++int LoadHIPS(fname,pinfo)
++     char *fname;
++     PICINFO * pinfo;
++/*******************************************/
++{
++  FILE  *fp;
++  struct header h;
++  char * pic;
++
++  /* open the stream, if necesary */
++  fp=fopen(fname,"r");
++  if (!fp) return 0;
++
++  if (!fread_header(fileno(fp), &h)) {
++    SetISTR(ISTR_WARNING,"Can't read HIPS header");
++    return 0;
++  }
++
++  pinfo->w = h.cols;
++  pinfo->h = h.rows;
++  pic = pinfo->pic = (byte *) malloc(h.rows * h.cols);   // GRR POSSIBLE OVERFLOW / FIXME
++  if (!pic) FatalError("couldn't malloc HIPS file");
++
++  if (!fread(pic, 1, h.cols*h.rows, fp)) {
++    SetISTR(ISTR_WARNING,"Error reading HIPS data.\n");
++    return 0;
++  }
++  fclose (fp);
++
++  pinfo->frmType = F_SUNRAS;
++  pinfo->colType = F_FULLCOLOR;
++  sprintf(pinfo->fullInfo, "HIPS file (%d bytes)", h.cols*h.rows);
++  sprintf(pinfo->shrtInfo, "HIPS file.");
++  pinfo->comment = (char *) NULL;
++
++  {
++    char cmapname[256];
++    /* Check header for colormap spec */
++    char * s = h.seq_desc - 1;
++    char * cmaptag = "+COLORMAP";
++    int sl = strlen(cmaptag);
++    cmapname[0] = 0;
++    while (*++s)
++      if (*s == '+')
++	if (strncmp(s, cmaptag, sl) == 0) {
++	  char * p = s + sl;
++	  while (*p && (*p == ' ' || *p == '\n' || *p == '\t')) p++;
++	  sscanf(p, "%s", cmapname);
++	  SetISTR(ISTR_INFO, cmapname);
++	  fprintf(stderr, "Colormap = [%s]\n", cmapname);
++	}
++
++    if (strcmp(cmapname, "gray") == 0 || strcmp(cmapname, "grey") == 0)
++      make_grayscale(pinfo->r, pinfo->g, pinfo->b);
++    else if (strcmp(cmapname, "heat") == 0)
++      make_heatscale(pinfo->r, pinfo->g, pinfo->b);
++    else if (strcmp(cmapname, "hues") == 0)
++      make_huescale(pinfo->r, pinfo->g, pinfo->b);
++    else if (!cmapname[0] || !load_colourmap(cmapname, 256, pinfo->r, pinfo->g, pinfo->b))
++      make_grayscale(pinfo->r, pinfo->g, pinfo->b);
++    sprintf(pinfo->fullInfo, "HIPS file (%d x %d), Colormap = [%s]", h.cols, h.rows, cmapname);
++  }
++
++  return 1;
++}
++
++
++
++static void make_grayscale(char * r, char * g, char * b)
++{
++  int i;
++  /* default grayscale colors */
++  r[0] = 40; g[0] = 150; b[0] = 100; /* "green4" background */
++  for(i = 1; i < 256; i++)
++    r[i] = g[i] = b[i] = i;
++}
++
++
++
++static float hls_value (n1, n2, hue)
++  float n1,n2,hue;
++{
++	if (hue>360.0)
++	  hue-=360.0 ;
++	else if (hue<0.0)
++	  hue+=360.0 ;
++
++	if (hue<60.0)
++	  return( n1+(n2-n1)*hue/60.0 ) ;
++	else if (hue<180.0)
++	  return ( n2 ) ;
++	else if (hue<240.0)
++	  return ( n1+(n2-n1)*(240.0-hue)/60.0 ) ;
++	else
++	  return (n1) ;
++}
++
++
++
++static void hls_to_rgb(h,l,s,  r,g,b)
++  float h, l, s;
++  float *r, *g, *b;
++{
++	static float m1, m2 ;
++
++	if (l<=0.5)
++		m2=l*(1+s) ;
++	else
++		m2=l+s-l*s ;
++	m1=2.0*l-m2 ;
++	if (s==0.0) *r=*g=*b=l ;
++	else {
++		*r=hls_value(m1,m2,h+120.0) ;
++		*g=hls_value(m1,m2,h) ;
++		*b=hls_value(m1,m2,h-120.0) ;
++	}
++
++}
++
++
++
++static void make_huescale(char * r, char * g, char * b)
++{
++  int j;
++  r[0] = g[0] = b[0] = 0;
++  for (j = 1; j<256; j++)
++    {
++      float fr, fg, fb;
++      hls_to_rgb((double)(256.0-j)*360.0/256.0, 0.5, 1.0, &fr, &fg, &fb);
++      r[j] = rint(255*fr);
++      g[j] = rint(255*fg);
++      b[j] = rint(255*fb);
++    }
++}
++
++
++
++static void make_heatscale(char * r, char * g, char * b)
++{
++  int j;
++  r[0] = g[0] = b[0] = 0;
++  for (j = 1; j<256; j++)
++    {
++      if(j<255/2)
++	r[j] = j*255/(255/2-1);
++      else
++	r[j]=255;
++      if (j>=255/2+255/3)
++	g[j] = 255;
++      else if (j>255/3)
++	g[j] = (j-255/3)*255/(255/2-1);
++      else
++	g[j] = 0;
++      if (j>255/2)
++	b[j] = (j-255/2)*255/(255-255/2-1);
++      else
++	b[j] = 0;
++    }
++}
++
++
++
++static int load_colourmap(char *filestem, int max_colours,
++                          char *r, char *g, char *b)
++{
++  FILE * fp;
++  int numread=0;
++  char * filename;
++  char str[200];
++  int num_colors;
++  /*
++   * Look for palette file in local directory
++   */
++
++  filename = (char*)alloca(strlen(filestem) + 5);
++  strcpy(filename, filestem);
++  strcat(filename, ".PAL"); /* Add the PAL suffix to the name specified */
++  fp = fopen(filename,"r");
++  if (!fp) {
++    /*
++     * If not found, try in $IM2HOME/etc/palettes
++     */
++    char * im2home = (char*)getenv("IM2HOME");
++    char * palette_subdirectory = "etc/palettes";
++    char * fullfilename;
++    if (!im2home)
++      {
++	im2home = "/home/jewel/imagine2";
++	fprintf(stderr,"IM2HOME environment variable not set -- using [%s]\n",im2home);
++      }
++    fullfilename = alloca(strlen(im2home)+strlen(palette_subdirectory)+strlen(filename)+5);
++    sprintf(fullfilename, "%s/%s/%s",im2home,palette_subdirectory,filename);
++    fp = fopen(fullfilename,"r");
++    if (!fp)
++      {
++	fprintf(stderr,"Couldn't find any palette file -- looked for [%s] and [%s].\n",
++		filename,fullfilename);
++	perror("Last system error message was");
++	return 0;
++      }
++  }
++
++  strcpy(str,"(null)");
++  if (!fscanf(fp,"%s\n",str) || strncmp(str,"Palette",7) != 0) {
++    fprintf(stderr,"error: First line of palette file should be `Palette', not [%s]\n", str);
++    return 0;
++  }
++
++  fscanf(fp,"%[^\n]",str) ; /* Scan to end of line */
++  fscanf (fp,"%d",&num_colors);/* Read the number of colours in the file */
++  fgets(str,120,fp) ; /* Skip the text description, and general info lines */
++  fgets(str,120,fp) ;
++
++  while ((numread<max_colours)&&(numread<num_colors)) {
++    int rc, gc, bc;
++    fscanf (fp,"%d %d %d -", &rc, &gc, &bc) ; /* Get the (r,g,b) tuples */
++    r[numread] = rc;
++    g[numread] = gc;
++    b[numread] = bc;
++    numread++;
++    fgets(str,120,fp) ; /* Skip the description, if present */
++  }
++
++  SetISTR(ISTR_INFO,"Read %d colors from palette file [%s]", numread, filename);
++  return (numread) ; /* Return the number of colours ACTUALLY READ */
++}
++
++#endif /* HAVE_HIPS */
+diff -Naru xv-3.10a/xvhips.h xv-3.10a.jumbo/xvhips.h
+--- xv-3.10a/xvhips.h	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvhips.h	2005-04-25 17:34:14.000000000 +0200
+@@ -0,0 +1,154 @@
++/*
++ * HIPL Picture Header Format Standard
++ *
++ * Michael Landy - 2/1/82
++ */
++
++#define XHEADER
++#ifdef XHEADER
++struct extended {
++	char *name;
++	char *vals;
++	};
++#endif
++
++struct header {
++	char	*orig_name;	/* The originator of this sequence */
++	char	*seq_name;	/* The name of this sequence */
++	int	num_frame;	/* The number of frames in this sequence */
++	char	*orig_date;	/* The date the sequence was originated */
++	int	rows;		/* The number of rows in each image */
++	int	cols;		/* The number of columns in each image */
++	int	bits_per_pixel;	/* The number of significant bits per pixel */
++	int	bit_packing;	/* Nonzero if bits were packed contiguously */
++	int	pixel_format;	/* The format of each pixel, see below */
++	char	*seq_history;	/* The sequence's history of transformations */
++	char	*seq_desc;	/* Descriptive information */
++#ifdef XHEADER
++	struct extended *xheader;
++#endif
++};
++
++/*
++ * Pixel Format Codes
++ */
++
++#define	PFBYTE	0		/* Bytes interpreted as integers (8 bits) */
++#define PFSHORT	1		/* Short integers (2 bytes) */
++#define PFINT	2		/* Integers (4 bytes) */
++#define	PFFLOAT	3		/* Float's (4 bytes)*/
++#define	PFCOMPLEX 4		/* 2 Float's interpreted as (real,imaginary) */
++#define PFASCII	5		/* ASCII rep, with linefeeds after each row */
++#define	PFDOUBLE 6		/* Double's (8 byte floats) */
++#define	PFDBLCOM 7		/* Double complex's (2 Double's) */
++#define PFQUAD	10		/* quad-tree encoding (Mimaging) */
++#define PFQUAD1	11		/* quad-tree encoding */
++#define PFBHIST	12		/* histogram of byte image (using ints) */
++#define PFSPAN	13		/* spanning tree format */
++#define PLOT3D	24		/* plot-3d format */
++#define PFINTPYR 50		/* integer pyramid */
++#define PFFLOATPYR 51		/* float pyramid */
++#define PFPOLYLINE 100		/* 2D points */
++#define PFCOLVEC 101		/* Set of RGB triplets defining colours */
++#define PFUKOOA 102		/* Data in standard UKOOA format */
++#define PFTRAINING 104		/* Set of colour vector training examples */
++#define PFTOSPACE 105		/* TOspace world model data structure */
++#define PFSTEREO 106		/* Stereo sequence (l, r, l, r, ...) */
++#define PFRGPLINE 107		/* 2D points with regions */
++#define PFRGISPLINE 108		/* 2D points with regions and interfaces */
++#define PFCHAIN	200		/* Chain code encoding (Mimaging) */
++#define PFLUT	300		/* LUT format (uses Ints) (Mimaging) */
++#define PFAHC	400		/* adaptive hierarchical encoding */
++#define PFOCT	401		/* oct-tree encoding */
++#define	PFBT	402		/* binary tree encoding */
++#define PFAHC3	403		/* 3-d adaptive hierarchical encoding */
++#define PFBQ	404		/* binquad encoding */
++#define PFRLED	500		/* run-length encoding */
++#define PFRLEB	501		/* run-length encoding, line begins black */
++#define PFRLEW	502		/* run-length encoding, line begins white */
++#define PFPOLAR	600		/* rho-theta format (Mimaging) */
++
++/*
++ * Bit packing formats
++ */
++
++#define	MSBFIRST 1		/* bit packing - most significant bit first */
++#define	LSBFIRST 2		/* bit packing - least significant bit first */
++
++#define FBUFLIMIT 30000		/* increase this if you use large PLOT3D
++					files */
++
++/*
++ * For general readability
++ */
++
++#ifndef TRUE
++# define	TRUE	1
++#endif
++
++#ifndef FALSE
++# define	FALSE	0
++#endif
++
++typedef	long	Boolean;
++extern char *strsave(), *memalloc();
++
++/*
++ * image and pyramid type declarations for the pyramid routines.
++ *
++ * The pyramid utilities are derived from code originally written by
++ * Raj Hingorani at SRI/David Sarnoff Research Institute.  The original
++ * Gaussian and Laplacian pyramid algorithms were designed by Peter Burt (also
++ * currently at SRI/DSRC).  See:  Computer Graphics and Image Processing,
++ * Volume 16, pp. 20-51, 1981, and IEEE Transactions on Communications,
++ * Volume COM-31, pp. 532-540, 1983.
++ */
++
++#define MAXLEV 12
++
++
++typedef struct {
++   float **ptr;
++   int nr;
++   int nc;
++} FIMAGE;
++
++typedef struct {
++   int **ptr;
++   int nr;
++   int nc;
++} IIMAGE;
++
++typedef FIMAGE FPYR[MAXLEV];
++typedef IIMAGE IPYR[MAXLEV];
++
++typedef struct {
++   float *k;
++   int taps2;		/* the number of taps from the center rightward,
++				total number is 2*taps2-1 */
++} FILTER;
++
++/* function definitions */
++
++float		**_read_fimgstr();
++int		**_read_iimgstr();
++float		**_alloc_fimage();
++int		**_alloc_iimage();
++
++/* image macros */
++
++#ifndef MAX
++# define MAX(A,B)  ((A) > (B) ? (A) : (B))
++#endif /* MAX */
++#ifndef MIN
++# define MIN(A,B)  ((A) < (B) ? (A) : (B))
++#endif /* MIN */
++#ifndef ABS
++# define ABS(A)    ((A) > 0 ? (A) : (-(A)))
++#endif /* ABS */
++#ifndef BETWEEN
++# define BETWEEN(A,B,C) (((A) < (B)) ? (B) : (((A) > (C)) ? (C) : (A)))
++#endif /* BETWEEN */
++#ifndef SIGN
++# define SIGN(A,B) (((B) > 0) ? (A) : (-(A)))
++#endif /* SIGN */
+diff -Naru xv-3.10a/xvjp2k.c xv-3.10a.jumbo/xvjp2k.c
+--- xv-3.10a/xvjp2k.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvjp2k.c	2007-05-14 03:04:37.000000000 +0200
+@@ -0,0 +1,1326 @@
++/*
++ * xvjp2k.c - I/O subroutines for JPEG 2000 format pictures
++ *
++ * This module is a "shim" between XV and a JPEG 2000 CODEC in the open-source
++ * JasPer Library created by Michael D. Adams; for more information, see the URL
++ * "http://www.ece.uvic.ca/~mdadams/jasper".  We don't use most of the other
++ * facilities in this library, so it's better to link XV with a UNIX "archive"
++ * representation of it, not a DLL.
++ *
++ * JPEG 2000 files can be represented in either of two general ways:  The
++ * simplest representation is a "code stream", which often has a ".jpc" file
++ * name suffix and is organized much like a classical JPEG file, except that
++ * unfortunately, JPEG 2000 code streams indicate the no. of colors in an image
++ * but no longer give any clues about its color space (e.g., RGB or YCbCr).
++ * Instead, there is now a semantically higher-level representation, which often
++ * has a ".jp2" file name suffix and encapsulates a "code stream" with (possibly
++ * a lot of) color-space information, optionally including things like ICC
++ * correction tables.
++ *
++ * Compared to the IJG JPEG Library used in file "xvjpeg.c", one must solve
++ * several problems for color images when marrying JasPer to XV.
++ *
++ * 1. JPEG 2000 files can represent a wide range of image sizes, resolutions,
++ *    and color spaces, not all of which can be easily rendered "as is" on a
++ * normal "X Windows" display, so we must carefully check a decoded image's
++ * parameters in order to reject anything that we can't handle gracefully.
++ *
++ * 2. JasPer prefers to decode/encode images using color-plane "slices", instead
++ *    of interleaved pixels needed by "X Windows", so we must (de)interleave
++ * copies of the image buffer here.
++ *
++ * XXX  Things to do:
++ *
++ * 1. In "LoadJP{2,C}()" try to handle the "quick" option, which requests
++ *    faster loading of a reduced-size image for the visual schnauzer.  The
++ * schnauzer's icon size is currently 80x60, so the old "xvjpeg.c" module tries
++ * to produce a 2X (160x120) image.  Can we do the same?
++ *
++ * 2. In "StoreJP2K()", JasPer Library Version 1.701 apparently has no API to
++ *    let the XV global "picComments" string be inserted in a JPEG 2000 comment
++ * record.  If the library ever gets fixed, enhance our code accordingly.
++ *
++ * --Scott Marovich <marovich at hpl.hp.com>, Hewlett-Packard Laboratories,
++ *   January 2005.
++ */
++#include "copyright.h"
++
++#define  NEEDSARGS
++#include "xv.h"
++
++#ifdef HAVE_JP2K
++
++#include <jasper/jasper.h>
++/* missing prototype in 1.701.0, sigh: */
++jas_stream_t *jas_stream_freopen PARM((const char *, const char *, FILE *));
++
++static const char *fbasename,  /* File's base name, for error/warning msgs */
++    bad_samp[]   = "%s:  can't read %d-plane %s file!",
++    fmode[]      = "rb",
++    full_msg[]   = "%s %s. (%ld bytes)",
++    jp2_kind[]   = "JP2",
++    jpc_kind[]   = "JPEG 2000",
++    load_msg[]   = "Loading %dx%d %s %s (%ld bytes)...",
++    no_mem[]     = "%s:  can't read %s file - out of memory",
++    pixel_size[] = "%s:  can't display %d-bit pixels!",
++    shrt_msg[]   = "%dx%d %s %s. ",
++    truncated[]  = "%s:  Unexpected end of %s file",
++    read_err[]   = "%s:  I/O error reading %s file",
++    bad_dims[]   = "%s:  error in JPEG-2000 header (bad image size)";
++
++/* We only want to override the JasPer Library's "jas_eprintf()" subroutine in
++   order to make it a "wrapper" around XV's own error-reporting subroutine, but
++   because of the way the former is currently packaged in JasPer Library Version
++   1.701, we must override everything else packaged in the "jas_debug.o" module
++   with it, otherwise we get "duplicate definition" messages from the linker.
++*/
++int jas_getdbglevel(void) {return 0;}
++int jas_setdbglevel(int n) {return 0;}
++int jas_memdump(FILE *fp,void *data,size_t len) {return 0;}
++
++int jas_eprintf(const char *fmt,...)         /* Handle JasPer Library message */
++{
++    static char error[] = "error: ", warning[]= "warning: ";
++    va_list ap;
++    int kind = ISTR_WARNING;
++    char buffer[512];
++    register char *p;
++
++ /* Unlike the IJG JPEG Library, the JasPer Library current has no graceful way
++    for an application (= us!) to intercept its diagnostic messages and output
++    them using our own subroutines, so this ugly replacement for its output
++    subroutine will have to suffice.  At Version 1.701, lthough the library's
++    own "jas_eprintf()" is a varargs subroutine, all calls currently pass just
++    1 string with a Line Feed at the end and no "printf(3C)" arguments.  Most
++    strings begin with "error: " or "warning: ", although a few have neither.
++    We try to translate these into the format preferred by XV, trimming any
++    trailing Line Feed character (ugh!).
++ */
++    va_start(ap, fmt);
++    vsnprintf(p = buffer,512,fmt,ap);
++    va_end(ap);
++    while (*p++);
++    if (p[-2] == '\n') p[-2] = '\0';
++    p = buffer;
++    if (strncmp(p,error,sizeof error) == 0) /* "error: ... " */
++      {
++        kind = ISTR_WARNING;
++        p += sizeof error;
++      }
++    else /* "warning: ... " */
++      if (strncmp(p,warning,sizeof warning) == 0)
++        {
++          kind = ISTR_INFO;
++          p += sizeof warning;
++        };
++    SetISTR(kind,"%s:  %s",fbasename,p);
++    return strlen(fmt);
++}
++
++static char *SetBuf(FILE *f)
++{
++    char *buf;
++    register char *p;
++
++ /* JPEG 2000 image files are apt to be large, but the buffer size allocated by
++    most implementations of the "C" Standard I/O Library is still ridiculously
++    small, typically 1 KB.  We want to allocate a much larger buffer for higher
++    I/O efficiency, but the details are unfortunately a bit platform-specific.
++    Under UNIX systems with virtual memory, we want to encourage its internal
++    "physio()" subroutine by making the buffer an integral number of pages,
++    aligned on a page-multiple memory address boundary.  Under HP-UX 11.1+ and
++    perhaps other operating-systems, a Standard I/O buffer is preceded by a
++    header whose size must also be taken into account.
++ */
++# ifndef IOBUFSIZ
++#   define IOBUFSIZ 65536
++# endif /* IOBUFSIZ */
++# ifdef __hpux
++#   define OVERHEAD sizeof(mbstate_t)
++# endif /* __hpux */
++# ifndef OVERHEAD
++#   define OVERHEAD 0
++# endif /* OVERHEAD */
++
++# ifdef NBPG
++    if (!(buf = p = malloc(NBPG+OVERHEAD+IOBUFSIZ))) return 0;
++    p = (char *)((unsigned long)p+NBPG-1 & ~(NBPG-1));
++    p -= OVERHEAD;
++# else /* not NBPG */
++    if (!(buf = p = malloc(OVERHEAD+IOBUFSIZ))) return 0;
++    p += OVERHEAD;
++# endif /* NBPG */
++    setvbuf(f,p,_IOFBF,OVERHEAD+IOBUFSIZ);
++    return buf;
++#   undef OVERHEAD
++#   undef IOBUFSIZ
++}
++
++int LoadJPC(char *fname,register PICINFO *pinfo,int quick)
++{
++    jas_image_t *img;
++    jas_stream_t *str;
++    FILE *fp;
++    char *iobuf;
++    const char *s;
++    unsigned long filesize;
++    long w, h, npixels, bufsize;
++    int ok = 0, vstride;
++    register int i;
++
++ /* Load a JPEG 2000 "code stream" image file into a pixel buffer for XV.
++    Unlike classical JPEG files, they have no clue about the image's color
++    space, so we check for 8-bit data samples but make no effort to check or
++    convert color spaces, and "what you see is what you get".  For now, ignore
++    the "quick" option to return a reduced-resolution or -size image.  Return 1
++    on success, or 0 on failure.
++ */
++    if (!(fp = xv_fopen(fname,fmode))) return 0;
++    fbasename = BaseName(fname); /* Input file's base name, for message(s) */
++    if (!(iobuf = SetBuf(fp)))
++      {
++        (void)fclose(fp);
++        SetISTR(ISTR_WARNING,no_mem,fbasename,jpc_kind);
++        goto L3;
++      }
++
++ /* Before telling the JasPer Library about this file, get its size for display
++    purposes.  Non-UNIX systems don't necessarily simulate "stat(2)", so do it
++    crudely but portably by seeking to the end, then back to the beginning.
++ */
++    fseek(fp,0L,2);
++    filesize = ftell(fp);
++    fseek(fp,0L,0);
++
++ /* "jas_stream_close()" will eventually close the input file, so only do it
++    explicitly if no stream can be created:
++ */
++    if (!(str = jas_stream_freopen(fname,fmode,fp))) /* nice if prototype... */
++      {
++        (void)fclose(fp);
++        goto L3;
++      }
++
++ /* It's not clear to me whether the following represents a JasPer Library "bug"
++    but it sure looks goofy:  Unless a stream buffer is marked "read only",
++    which only happens when the stream's "fillbuf" method is called, even though
++    our buffers are always "read only", the library will try to flush out buffer
++    contents when the stream is destroyed, which makes it die a horrible death.
++    So, mark the stream buffer proactively:
++ */
++    str->bufmode_ |= JAS_STREAM_RDBUF; /* We will only read the stream buffer */
++    if (!(img = jpc_decode(str,0))) goto L2;
++    if ((vstride = jas_image_numcmpts(img))) /* num. color planes */
++      {
++
++     /* After the image-component streams created, they are left in a "write"
++        state with the streams' cursors positioned at their ends, so "seek" in
++        order to "read" each stream from its beginning.
++     */
++        i = vstride;
++        while (--i >= 0)
++          if (jas_stream_seek(img->cmpts_[i]->stream_,0L,0))
++            {
++              SetISTR(ISTR_WARNING,read_err,fbasename,jpc_kind);
++              goto L1;
++            }
++      }
++    w = jas_image_width(img);
++    h = jas_image_height(img);
++
++    /* avoid buffer overflow */
++    npixels = w * h;
++    bufsize = vstride * npixels;
++    if (w <= 0 || h <= 0 || npixels/w != h || bufsize/vstride != npixels)
++      {
++        (void)fclose(fp);
++        SetISTR(ISTR_WARNING,bad_dims,fbasename);
++        goto L1;
++      }
++    pinfo->normw = pinfo->w = w;
++    pinfo->normh = pinfo->h = h;
++
++ /* Sanity-check the image's color space and no. of colors.  For now, accept
++    only "generic" color spaces, not files needing image-specific color
++    correction, but fix that someday...
++ */
++    switch (vstride)
++      {
++        default:
++          SetISTR(ISTR_WARNING,bad_samp,fbasename,vstride,jpc_kind);
++          goto L1;
++        case 1:
++          if ((i = jas_image_cmptprec(img,0)) != 8) /* not 8-bit pixels */
++            {
++              SetISTR(ISTR_WARNING,pixel_size,fbasename,i);
++              goto L1;
++            }
++          s = "Greyscale";
++          pinfo->type = PIC8;
++          pinfo->colType = F_GREYSCALE;
++          i = 256; /* Return fake indexed-color "map" */
++          while (--i >= 0) pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
++          break;
++        case 3:
++
++       /* BEWARE OF KLUDGE:  If the image's color space is RGB, assume that the
++                             data-sample precision for all color planes is the
++          same.  If the color space is YCbCr, assume the luminance (Y = 0th)
++          component has the greatest precision, although the chrominance
++          (Cr = 1st, Cb = 2nd) components are usually sub-sampled.
++       */
++          if ((i = jas_image_cmptprec(img,0)) != 8) /* not 24-bit pixels */
++            {
++              SetISTR(ISTR_WARNING,pixel_size,fbasename,i*3);
++              goto L1;
++            }
++          s = "Color";
++          pinfo->type = PIC24;
++          pinfo->colType = F_FULLCOLOR;
++
++       /* XXX  Unlike the IJG JPEG Library, the JasPer Library is apparently
++               unable to quantize colors or tell us whether the image's colors
++          were quantized by its creator, so it seems that we can't return a
++          color map for XV to potentially use 8-bit indexed color.  If there
++          *is* an easy way to do it that escapes me, put the code here someday.
++       */
++      }
++    if (!(pinfo->pic = (byte *)malloc(bufsize))) /* image buffer for XV */
++      {
++        SetISTR(ISTR_WARNING,no_mem,fbasename,jpc_kind);
++        goto L1;
++      }
++    pinfo->frmType = F_JPC;
++    sprintf(pinfo->fullInfo,full_msg,s,jpc_kind,filesize);
++    sprintf(pinfo->shrtInfo,shrt_msg,pinfo->w,pinfo->h,s,jpc_kind);
++    SetISTR(ISTR_INFO,load_msg,pinfo->normw,pinfo->normh,s,jpc_kind,filesize);
++    if (vstride == 1) /* gray-scale image */
++      { register jas_stream_t *c = img->cmpts_[0]->stream_;
++        register byte *p = pinfo->pic;
++
++     /* Since this is a 1-plane image, avoid a lot of errant nonsense in the
++        JasPer Library by sequentially reading all of the data into our buffer
++        directly.
++     */
++        do if ((i = (*c->ops_->read_)(c->obj_,(char *)p,bufsize)) <= 0)
++             {
++               SetISTR(ISTR_WARNING,i < 0 ? read_err : truncated,fbasename,
++                 jpc_kind);
++               goto L1;
++             }
++        while ((p += i),(bufsize -= i) > 0);
++      }
++    else /* RGB color image */
++      {
++
++     /* Reading color images is inefficient because JPEG 2000 wants to partition
++        file data into separate image planes (colors), while XV wants data
++        samples from each plane to be interleaved as 3-byte pixels.  Apparently
++        the fastest method consists of 3 passes through the XV image buffer,
++        into which we insert the bytes of each component.
++     */
++        i = 0;
++        do /* each color component */
++          { long npix = npixels;
++            register jas_stream_t *c = img->cmpts_[i]->stream_;
++            register byte *p = pinfo->pic + i;
++
++            do /* each pixel */
++              { register int b;
++
++                if ((b = jas_stream_getc(c)) < 0)
++                  {
++                    SetISTR(ISTR_WARNING,
++                      (c->flags_ & JAS_STREAM_EOF) ? truncated : read_err,
++                      fbasename,jpc_kind);
++                    goto L1;
++                  }
++                *p = b;
++              }
++            while ((p += 3),--npix > 0);
++          }
++        while (++i <= 2);
++      }
++    ok = 1; /* Success! */
++L1: jas_image_destroy(img);
++L2: (void)jas_stream_close(str);
++    free(iobuf);
++L3: return ok;
++}
++
++int LoadJP2(char *fname,register PICINFO *pinfo,int quick)
++{
++    jas_image_t *img;
++    jas_stream_t *str;
++    FILE *fp;
++    char *iobuf;
++    const char *s;
++    unsigned long filesize;
++    long w, h, npixels, bufsize;
++    int ok = 0, vstride;
++    register int i;
++
++ /* Load a JPEG 2000 JP2 image file into a pixel buffer for XV, doing any
++    necessary color-space conversion to end up with 8-bit gray scale or 24-bit
++    RGB.  For now, ignore the "quick" option to return a reduced-resolution
++    or -size image.  Return 1 on success, or 0 on failure.
++ */
++    if (!(fp = xv_fopen(fname,fmode))) return 0;
++    fbasename = BaseName(fname); /* Input file's base name, for message(s) */
++    if (!(iobuf = SetBuf(fp)))
++      {
++        (void)fclose(fp);
++        SetISTR(ISTR_WARNING,no_mem,fbasename,jpc_kind);
++        goto L3;
++      }
++
++ /* Before telling the JasPer Library about this file, get its size for display
++    purposes.  Non-UNIX systems don't necessarily simulate "stat(2)", so do it
++    crudely but portably by seeking to the end, then back to the beginning.
++ */
++    fseek(fp,0L,2);
++    filesize = ftell(fp);
++    fseek(fp,0L,0);
++
++ /* "jas_stream_close()" will eventually close the input file, so only do it
++    explicitly if no stream can be created:
++ */
++    if (!(str = jas_stream_freopen(fname,fmode,fp)))
++      {
++        (void)fclose(fp);
++        goto L3;
++      }
++
++ /* It's not clear to me whether the following represents a JasPer Library "bug"
++    but it sure looks goofy:  Unless a stream buffer is marked "read only",
++    which only happens when the stream's "fillbuf" method is called, even though
++    our buffers are always "read only", the library will try to flush out buffer
++    contents when the stream is destroyed, which makes it die a horrible death.
++    So, mark the stream buffer proactively:
++ */
++    str->bufmode_ |= JAS_STREAM_RDBUF; /* We will only read the stream buffer */
++    if (!(img = jp2_decode(str,0))) goto L2;
++    if ((vstride = jas_image_numcmpts(img))) /* num. color planes */
++      {
++
++     /* After the image-component streams created, they are left in a "write"
++        state with the streams' cursors positioned at their ends, so "seek" in
++        order to "read" each stream from its beginning.
++     */
++        i = vstride;
++        while (--i >= 0)
++          if (jas_stream_seek(img->cmpts_[i]->stream_,0L,0))
++            {
++              SetISTR(ISTR_WARNING,read_err,fbasename,jp2_kind);
++              goto L1;
++            }
++      }
++    w = jas_image_width(img);
++    h = jas_image_height(img);
++
++    /* avoid buffer overflow */
++    npixels = w * h;
++    bufsize = vstride * npixels;
++    if (w <= 0 || h <= 0 || npixels/w != h || bufsize/vstride != npixels)
++      {
++        (void)fclose(fp);
++        SetISTR(ISTR_WARNING,bad_dims,fbasename);
++        goto L1;
++      }
++    pinfo->normw = pinfo->w = w;
++    pinfo->normh = pinfo->h = h;
++
++ /* Sanity-check the image's color space and no. of colors.  For now, accept
++    only "generic" color spaces, not files needing image-specific color
++    correction, but fix that someday...
++ */
++    switch (vstride)
++      { static char color_space[]={"%s:  invalid color space!"};
++
++        default:
++          SetISTR(ISTR_WARNING,bad_samp,fbasename,vstride,jp2_kind);
++          goto L1;
++        case 1:
++          if (   !jas_clrspc_isunknown(i = jas_image_clrspc(img))
++              && jas_clrspc_fam(i) != JAS_CLRSPC_FAM_GRAY
++             )
++            {
++              SetISTR(ISTR_WARNING,color_space,fbasename);
++              goto L1;
++            }
++          if ((i = jas_image_cmptprec(img,0)) != 8) /* not 8-bit pixels */
++            {
++              SetISTR(ISTR_WARNING,pixel_size,fbasename,i);
++              goto L1;
++            }
++          s = "Greyscale";
++          pinfo->type = PIC8;
++          pinfo->colType = F_GREYSCALE;
++          i = 256; /* Return fake indexed-color "map" */
++          while (--i >= 0) pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
++          break;
++        case 3:
++          if (jas_clrspc_isunknown(i = jas_image_clrspc(img)))
++            {
++              SetISTR(ISTR_WARNING,color_space,fbasename);
++              goto L1;
++            }
++          if (jas_clrspc_fam(i) != JAS_CLRSPC_FAM_RGB)
++            { jas_image_t *oimg;
++              jas_cmprof_t *profile;
++
++           /* Here's where the JasPer Library really shines.  The only color
++              space that XV handles is RGB, so if that's not what our image
++              uses, then to quote Capt. Kirk:  "Make it so!"
++           */
++              if (!(profile = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)))
++                 {
++                   SetISTR(ISTR_WARNING,"%s:  can't create RGB profile",
++                     fbasename);
++                   goto L1;
++                 }
++              img = jas_image_chclrspc( oimg = img
++                                      , profile
++                                      , JAS_CMXFORM_INTENT_PER
++                                      );
++              jas_cmprof_destroy(profile);
++              if (!img) /* Oops!  We failed, so restore original image */
++                {
++                  img = oimg;
++                  SetISTR(ISTR_WARNING,"%s:  can't convert to RGB",fbasename);
++                  goto L1;
++                }
++              jas_image_destroy(oimg);
++            }
++
++       /* BEWARE OF KLUDGE:  If the image's color space is RGB, assume that the
++                             data-sample precision for all color planes is the
++          same.  If the color space is YCbCr, assume the luminance (Y = 0th)
++          component has the greatest precision, although the chrominance
++          (Cr = 1st, Cb = 2nd) components are usually sub-sampled.
++       */
++          if ((i = jas_image_cmptprec(img,0)) != 8) /* not 24-bit pixels */
++            {
++              SetISTR(ISTR_WARNING,pixel_size,fbasename,i*3);
++              goto L1;
++            }
++          s = "Color";
++          pinfo->type = PIC24;
++          pinfo->colType = F_FULLCOLOR;
++
++       /* XXX  Unlike the IJG JPEG Library, the JasPer Library is apparently
++               unable to quantize colors or tell us whether the image's colors
++          were quantized by its creator, so it seems that we can't return a
++          color map for XV to potentially use 8-bit indexed color.  If there
++          *is* an easy way to do it that escapes me, put the code here someday.
++       */
++      }
++    if (!(pinfo->pic = (byte *)malloc(bufsize))) /* image buffer for XV */
++      {
++        SetISTR(ISTR_WARNING,no_mem,fbasename,jp2_kind);
++        goto L1;
++      }
++    pinfo->frmType = F_JP2;
++    sprintf(pinfo->fullInfo,full_msg,s,jp2_kind,filesize);
++    sprintf(pinfo->shrtInfo,shrt_msg,pinfo->w,pinfo->h,s,jp2_kind);
++    SetISTR(ISTR_INFO,load_msg,pinfo->normw,pinfo->normh,s,jp2_kind,filesize);
++    if (vstride == 1) /* gray-scale image */
++      { register jas_stream_t *c = img->cmpts_[0]->stream_;
++        register byte *p = pinfo->pic;
++
++     /* Since this is a 1-plane image, avoid a lot of errant nonsense in the
++        JasPer Library by sequentially reading all of the data into our buffer
++        directly.
++     */
++        do if ((i = (*c->ops_->read_)(c->obj_,(char *)p,bufsize)) <= 0)
++             {
++               SetISTR(ISTR_WARNING,i < 0 ? read_err : truncated,fbasename,
++                 jp2_kind);
++               goto L1;
++             }
++        while ((p += i),(bufsize -= i) > 0);
++      }
++    else /* RGB color image */
++      {
++
++     /* Reading color images is inefficient because JPEG 2000 wants to partition
++        file data into separate image planes (colors), while XV wants data
++        samples from each plane to be interleaved as 3-byte pixels.  Apparently
++        the fastest method consists of 3 passes through the XV image buffer,
++        into which we insert the bytes of each component.
++     */
++        i = 0;
++        do /* each color component */
++          { long npix = npixels;
++            register jas_stream_t *c = img->cmpts_[i]->stream_;
++            register byte *p = pinfo->pic + i;
++
++            do /* each pixel */
++              { register int b;
++
++                if ((b = jas_stream_getc(c)) < 0)
++                  {
++                    SetISTR(ISTR_WARNING,
++                      (c->flags_ & JAS_STREAM_EOF) ? truncated : read_err,
++                      fbasename,jp2_kind);
++                    goto L1;
++                  }
++                *p = b;
++              }
++            while ((p += 3),--npix > 0);
++          }
++        while (++i <= 2);
++      }
++    ok = 1; /* Success! */
++L1: jas_image_destroy(img);
++L2: (void)jas_stream_close(str);
++    free(iobuf);
++L3: return ok;
++}
++
++/* The following variables and subroutines are used when writing a JPEG 2000
++   file, which is done mainly using call-backs from "X Windows" widgets.  The
++   most complicated part of this interface is: managing interactions with a
++   window to request the boat-loads of options that the JasPer Library supports.
++   Start by defining subwindow sizes, plus indices into several arrays of
++   corresponding widget-state variables.
++
++   IMPLEMENTATION NOTES:  The following dimensions create a tall, thin window
++                          which appears to have considerable empty space at the
++   bottom.  Before you complain, click the Precinct Height menu button in order
++   to the tall pop-up subwindow that it generates.  If the parent window is made
++   shorter, then this pop-up will be clipped, which is an ugly nuisance.  I
++   don't know how to make the pop-up visible outside its parent's borders; do
++   you?  If there's some way to make "X Windows" do this, then we might consider
++   making the parent shorter.
++
++   Note that there is currently no mechanism to program the no. of intermediate
++   layers used by the encoder, or their rates.  This is potentially a large and
++   complicated data-entry problem, and perhaps someday we can invent a clever
++   solution using the rest of the parent window's space.
++*/
++# define JP2KW 275 /* Window width, in pixels */
++# define JP2KH 400 /* Window height, in pixels */
++# define BUTTW 51 /* Button width, in pixels (odd for half-toning) */
++# define BUTTH 20 /* Button height, in pixels */
++# define MENUW 75 /* Menu-button width, in pixels (odd for half-toning) */
++# define MENUH 24 /* Menu-button height, in pixels */
++# define RBUTH 20 /* Radio button height, in pixels */
++# define RBUTW 51 /* Radio button width, in pixels (odd for half-toning) */
++# define TEXTH (LINEHIGH+5) /* Text subwindow height, in pixels */
++# define TEXTW 75 /* Text subwindow width, in pixels */
++
++# define J_BOK   0 /* Boolean "Ok" button */
++# define J_BCANC 1 /* Boolean "Cancel" button */
++# define J_NBUTT 2 /* No. of regular button widgets */
++
++# define J_CSOP   0 /* Boolean encoding-style option buttons */
++# define J_CEPH   1
++# define J_CLAZY  2
++# define J_CTERM  3
++# define J_CSEGS  4
++# define J_CVCAU  5
++# define J_CPTRM  6
++# define J_CRSTP  7
++# define J_NCHKB  8 /* No. of check-box button widgets */
++
++# define J_MCBXW 0 /* 1-of-N menu-selection buttons */
++# define J_MCBXH 1
++# define J_MPREW 2
++# define J_MPREH 3
++# define J_MPROG 4
++# define J_NMENU 5 /* No. of menu-button widgets */
++
++# define J_TGBIT 0 /* (Unsigned numeric) string subwindows */
++# define J_TRES  1
++# define J_TRATE 2
++# define J_NTEXT 3 /* No. of text subwindows */
++
++static BUTT button[J_NBUTT];
++static CBUTT chkbut[J_NCHKB];
++static MBUTT menu[J_NMENU];
++static RBUTT *radio;
++static Window text[J_NTEXT];
++static int colorType, format, textval[J_NTEXT];
++static const char *ProgList[]={"lrcp","rlcp","rpcl","pcrl","cprl"};
++
++void CreateJP2KW(void)
++{
++    static const char EXP2_0[] ={    "1"}, /* Successive powers of 2 */
++                      EXP2_1[] ={    "2"},
++                      EXP2_2[] ={    "4"},
++                      EXP2_3[] ={    "8"},
++                      EXP2_4[] ={   "16"},
++                      EXP2_5[] ={   "32"},
++                      EXP2_6[] ={   "64"},
++                      EXP2_7[] ={  "128"},
++                      EXP2_8[] ={  "256"},
++                      EXP2_9[] ={  "512"},
++                      EXP2_10[]={ "1024"},
++                      EXP2_11[]={ "2048"},
++                      EXP2_12[]={ "4096"},
++                      EXP2_13[]={ "8192"},
++                      EXP2_14[]={"16384"},
++                      EXP2_15[]={"32768"};
++    static const char *CBoxList[]=
++      {
++        EXP2_1 ,EXP2_2 ,EXP2_3 ,EXP2_4 ,EXP2_5,EXP2_6 ,EXP2_7 ,EXP2_8 ,EXP2_9,
++        EXP2_10,EXP2_11
++      };
++    static const char *PrecList[]=
++      {
++        EXP2_0,EXP2_1,EXP2_2 ,EXP2_3 ,EXP2_4 ,EXP2_5 ,EXP2_6 ,EXP2_7 ,
++        EXP2_8,EXP2_9,EXP2_10,EXP2_11,EXP2_12,EXP2_13,EXP2_14,EXP2_15
++      };
++    static const char hstr[]={"Height"}, wstr[]={"Width"};
++
++    if (!(jp2kW = CreateWindow( "xvjp2k"
++                              , "XVjp2k"
++                              , 0
++                              , JP2KW
++                              , JP2KH
++                              , infofg
++                              , infobg
++                              , 0
++                              )
++         )
++       ) FatalError("can't create JPEG 2000 window!");
++    XSelectInput(theDisp,jp2kW,ExposureMask|ButtonPressMask|KeyPressMask);
++
++ /* Create a row of 2 boolean-valued, regular buttons ("Ok" and "Cancel") in the
++    window's bottom right corner.
++ */
++    BTCreate(&button[J_BOK  ],jp2kW,
++      JP2KW-2*BUTTW-20,JP2KH-10-BUTTH-1,BUTTW,BUTTH,
++      "Ok"    ,infofg,infobg,hicol,locol);
++    BTCreate(&button[J_BCANC],jp2kW,
++      JP2KW-  BUTTW-10,JP2KH-10-BUTTH-1,BUTTW,BUTTH,
++      "Cancel",infofg,infobg,hicol,locol);
++
++ /* Create a vertical column of 8 boolean-valued, check-box buttons (for
++    encoding-style options) down the window's left side.
++ */
++    CBCreate(&chkbut[J_CSOP] ,jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+0*BUTTH,
++      "sop"       ,infofg,infobg,hicol,locol);
++    CBCreate(&chkbut[J_CEPH] ,jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+1*BUTTH,
++      "eph"       ,infofg,infobg,hicol,locol);
++    CBCreate(&chkbut[J_CLAZY],jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+2*BUTTH,
++      "lazy"      ,infofg,infobg,hicol,locol);
++    CBCreate(&chkbut[J_CTERM],jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+3*BUTTH,
++      "termall"   ,infofg,infobg,hicol,locol);
++    CBCreate(&chkbut[J_CSEGS],jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+4*BUTTH,
++      "segsym"   ,infofg,infobg,hicol,locol);
++    CBCreate(&chkbut[J_CVCAU],jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+5*BUTTH,
++      "vcausal"  ,infofg,infobg,hicol,locol);
++    CBCreate(&chkbut[J_CPTRM],jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+6*BUTTH,
++      "pterm"    ,infofg,infobg,hicol,locol);
++    CBCreate(&chkbut[J_CRSTP],jp2kW,
++      10,10+ASCENT+SPACING+2*LINEHIGH+7*BUTTH,
++      "resetprob",infofg,infobg,hicol,locol);
++ /* Create text subwindows for unsigned decimal integer values. */
++
++    text[J_TGBIT] = XCreateSimpleWindow(theDisp,jp2kW,
++      JP2KW-TEXTW-10,10+ASCENT+SPACING+2*LINEHIGH+3*MENUH+0*TEXTH,TEXTW,TEXTH,
++      1,infofg,infobg);
++    XSelectInput(theDisp,text[J_TGBIT],ExposureMask|KeyPressMask);
++    text[J_TRES ] = XCreateSimpleWindow(theDisp,jp2kW,
++      JP2KW-TEXTW-10,10+ASCENT+SPACING+2*LINEHIGH+3*MENUH+1*TEXTH,TEXTW,TEXTH,
++      1,infofg,infobg);
++    XSelectInput(theDisp,text[J_TRES ],ExposureMask|KeyPressMask);
++    text[J_TRATE] = XCreateSimpleWindow(theDisp,jp2kW,
++      JP2KW-TEXTW-10,10+ASCENT+SPACING+2*LINEHIGH+3*MENUH+2*TEXTH,TEXTW,TEXTH,
++      1,infofg,infobg);
++    XSelectInput(theDisp,text[J_TRATE],ExposureMask|KeyPressMask);
++
++ /* Create a row of 2 boolean-valued radio buttons (for the "Rate" subwindow
++    value's unit of measure).  The 1st button is "selected" by default.
++ */
++    radio = RBCreate(0,jp2kW,
++      JP2KW-19*RBUTW/8-10,10+ASCENT+SPACING+2*LINEHIGH+3*MENUH+3*TEXTH+4,
++      "Percent",infofg,infobg,hicol,locol);
++    (void)RBCreate(radio,jp2kW,
++      JP2KW-1*RBUTW-10  ,10+ASCENT+SPACING+2*LINEHIGH+3*MENUH+3*TEXTH+4,
++      "Bytes",infofg,infobg,hicol,locol);
++
++ /* Create pop-up menu-selection buttons after mapping the above subwindows,
++    since we don't want the pop-up menus mapped unless the corresponding button
++    is selected.
++ */
++    XMapSubwindows(theDisp,jp2kW);
++    MBCreate(&menu[J_MCBXW],jp2kW,
++      JP2KW-2*MENUW-10,10+ASCENT+SPACING+2*LINEHIGH+0*MENUH,MENUW,MENUH, 
++      wstr   ,CBoxList,sizeof CBoxList/sizeof *CBoxList,infofg,infobg,
++      hicol,locol);
++    MBCreate(&menu[J_MCBXH],jp2kW,
++      JP2KW-2*MENUW-10,10+ASCENT+SPACING+2*LINEHIGH+1*MENUH,MENUW,MENUH, 
++      hstr   ,CBoxList,sizeof CBoxList/sizeof *CBoxList,infofg,infobg,
++      hicol,locol);
++    MBCreate(&menu[J_MPREW],jp2kW,
++      JP2KW-1*MENUW-10,10+ASCENT+SPACING+2*LINEHIGH+0*MENUH,MENUW,MENUH, 
++      wstr   ,PrecList,sizeof PrecList/sizeof *PrecList,infofg,infobg,
++      hicol,locol);
++    MBCreate(&menu[J_MPREH],jp2kW,
++      JP2KW-1*MENUW-10,10+ASCENT+SPACING+2*LINEHIGH+1*MENUH,MENUW,MENUH, 
++      hstr   ,PrecList,sizeof PrecList/sizeof *PrecList,infofg,infobg,
++      hicol,locol);
++    MBCreate(&menu[J_MPROG],jp2kW,
++      JP2KW-1*MENUW-10,10+ASCENT+SPACING+2*LINEHIGH+2*MENUH,MENUW,MENUH, 
++      "Order",ProgList,sizeof ProgList/sizeof *ProgList,infofg,infobg,
++      hicol,locol);
++
++ /* Initialize values represented by widgets, which should correspond to default
++    compiled into the JasPer Library.  Unfortunately, as of Version 1.701 there
++    is no easy way for an application to extract these from the library, so the
++    following code might get out of sync over time:
++ */
++    menu[J_MCBXW].hascheck = 1; menu[J_MCBXW].flags[ 5] = 1;
++    menu[J_MCBXH].hascheck = 1; menu[J_MCBXH].flags[ 5] = 1;
++    menu[J_MPREW].hascheck = 1; menu[J_MPREW].flags[15] = 1;
++    menu[J_MPREH].hascheck = 1; menu[J_MPREH].flags[15] = 1;
++    menu[J_MPROG].hascheck = 1; menu[J_MPROG].flags[ 0] = 1;
++    textval[J_TGBIT] = 2; /* No. of guard bits */
++    textval[J_TRES ] = 6; /* Max. no. of resolution levels */
++    textval[J_TRATE] = 100; /* Rate = 100% */
++}
++
++void JP2KSaveParams(int fmt,char *fname,int col)    /* Save output-file parms */
++{
++    format = fmt;      /* Desired file format: F_JPC|F_JP2 */
++    fbasename = fname; /* ->Output file path */
++    colorType = col;   /* Desired color space: F_GREYSCALE|... */
++}
++
++static void StoreJP2K(char *options)
++{
++    static jas_image_cmptparm_t parm[3]= /* Image parameters */
++      {{0,0,1,1,0,0,8,0},{0,0,1,1,0,0,8,0},{0,0,1,1,0,0,8,0}};
++    static char nomem[]={"StoreJP2K: out of memory\n"},
++                write[]={"w"};
++    jas_image_t *img;
++    jas_stream_t *str;
++    FILE *fp, *fp2;
++    byte *pic, *r, *g, *b;
++    const char *filename;
++    char *iobuf = 0;
++    unsigned long imagesize;
++    jas_clrspc_t color_space;
++    int nc, w, h, pfree, ptype, error = 1;
++    register int i;
++
++ /* This is a generic subroutine for writing JPEG 2000 image files using the
++    JasPer Library.  Our argument is an ASCII string, containing a Space (" ")-
++    separated sequence of encoder options that currently aren't well documented.
++    Most of the work is identical for both ".jpc" and ".jp2" files.  Start by
++    verifying that the output file can be opened, then get an image buffer from
++    XV and begin crunching it into a suitable form for the JasPer Library.
++ */
++    if (!(fp = OpenOutFile(filename = fbasename))) return; /* Oops! */
++    setbuf(fp,0); /* We don't really use this file pointer for I/O; see below */
++    fbasename = BaseName(filename);
++    WaitCursor();
++    pic = GenSavePic(&ptype,&w,&h,&pfree,&nc,&r,&g,&b);
++    imagesize = w*h;
++    if (ptype == PIC24) imagesize *= 3;
++
++ /* As an optimization to save file space, even if our user didn't ask to store
++    a gray-scale image, check whether we could and, if so, do it anyway.
++ */
++    if (colorType != F_GREYSCALE) /* can we force a gray-scale image? */
++      {
++        if (ptype == PIC8)
++          {
++            i = nc;
++            while (--i >= 0 && r[i] == g[i] && r[i] == b[i]);
++          }
++        else /* PIC24 */
++          { register byte *p = pic + imagesize;
++
++            while ((p -= 3) >= pic && p[0] == p[1] && p[0] == p[2]);
++            i = p-pic;
++          };
++        if (i < 0) colorType = F_GREYSCALE; /* We made it all the way through */
++      };
++
++ /* If XV is currently color-mapping the image, make a color-mapped copy so that
++    the map needn't be transmitted in the output file.
++ */
++    if ((i = (colorType != F_GREYSCALE) << 1 | (ptype != PIC8)) != 3)
++      { byte *tmp = pic, *last = pic + imagesize;
++        register byte *from = tmp, *to = pic;
++
++        if (!(pic = (byte *)malloc(imagesize))) FatalError(nomem);
++        switch (i)
++          {
++
++         /* Color-map 8->8 bit image. */
++
++            case 0: do
++                      {
++                        i = *from;
++                        *to++ = MONO(r[i],g[i],b[i]);
++                      }
++                    while (++from < last);
++                    break;
++
++         /* Color-map 24->8 bit image. */
++
++            case 1: do *to++ = MONO(from[0],from[1],from[2]);
++                    while ((from += 3) < last);
++                    break;
++
++         /* Color-map 8->24 bit image. */
++
++            case 2: do
++                      {
++                        i = *from;
++                        *to++ = r[i]; *to++ = g[i]; *to++ = b[i];
++                      }
++                    while (++from < last);
++                    break;
++          };
++        if (pfree) free(tmp); /* Release the original image buffer if we can */
++        pfree = 1; /* Let the modified buffer be released later */
++      };
++
++ /* Initialize various image-file parameter variables. */
++
++    parm[0].width  = w;
++    parm[0].height = h;
++    if (colorType == F_GREYSCALE) /* gray-scale image */
++      {
++        ptype = 1; /* No. of color planes */
++        color_space = JAS_CLRSPC_SGRAY;
++      }
++    else /* RGB color image */
++      {
++        ptype = 3; /* No. of color planes */
++        color_space = JAS_CLRSPC_SRGB;
++        parm[2].width  = parm[1].width  = parm[0].width;
++        parm[2].height = parm[1].height = parm[0].height;
++      };
++
++ /* Now comes a egregious hack:  The JasPer Library will eventually want to
++    close the output file that it writes, but since XV opened the file, XV also
++    thinks it has the right to close the file!  In order to pacify them both,
++    we duplicate the file pointer and let the JasPer Library have it, while we
++    retain the original for XV.
++
++    XXX  This code is very UNIX-specific; what's an equivalent hack for Windows?
++ */
++    if (!(fp2 = (i = dup(fileno(fp))) >= 0 ? fdopen(i,write) : 0))
++      FatalError("StoreJP2K: can't duplicate output file pointer\n");
++    if (!(iobuf = SetBuf(fp2)))
++      {
++        (void)fclose(fp2);
++        FatalError(nomem);
++      };
++
++ /* Hand our output file to the JasPer Library and create an image object.
++    "jas_stream_close()" will eventually close our output file, so only do it
++    explicitly if no stream can be created.  If everything looks copacetic,
++    then write our buffer contents to the image components' streams.
++ */
++    if (!(str = jas_stream_freopen(filename,write,fp2)))
++      {
++        (void)fclose(fp2);
++        FatalError("StoreJP2K: can't open output stream\n");
++      };
++    if (!(img = jas_image_create(ptype,parm,color_space))) goto L2;
++    if (ptype == 1)
++      { register jas_stream_t *c = img->cmpts_[0]->stream_;
++        register byte *p = pic;
++
++     /* Since this is a 1-plane image, avoid a lot of errant nonsense in the
++        JasPer Library by sequentially writing all of the data directly from our
++        buffer.
++     */
++        jas_image_setcmpttype(img,0,JAS_IMAGE_CT_GRAY_Y);
++        img->cmpts_[0]->type_ = JAS_IMAGE_CT_GRAY_Y;
++        do if ((i = (*c->ops_->write_)(c->obj_,(char *)p,imagesize)) <= 0)
++             goto L1;
++        while ((p += i),(imagesize -= i) > 0);
++        if (jas_stream_flush(c) < 0) goto L1;
++      }
++    else /* RGB color image */
++      {
++
++     /* Writing color images is inefficient because JPEG 2000 wants to partition
++        file data into separate image planes (colors), while XV wants data
++        samples from each plane to be interleaved as 3-byte pixels.  Apparently
++        the fastest method consists of 3 passes through the XV image buffer,
++        from which we extract the bytes of each component.
++     */
++        i = 0;
++        do /* each color component */
++          { long npix = imagesize/3;
++            register jas_stream_t *c = img->cmpts_[i]->stream_;
++            register byte *p = pic + i;
++
++            jas_image_setcmpttype(img,i,i+JAS_IMAGE_CT_RGB_R);
++            do if (jas_stream_putc(c,*p) < 0) goto L1;
++            while ((p += 3),--npix > 0);
++            if (jas_stream_flush(c) < 0) goto L1;
++          }
++        while (++i <= 2);
++      };
++    if (   (*(format == F_JPC ? jpc_encode : jp2_encode))(img,str,options) >= 0
++        && jas_stream_flush(str) >= 0
++       ) error = 0; /* Success! */
++L1: jas_image_destroy(img);
++L2: (void)jas_stream_close(str);
++    if (iobuf) free(iobuf);
++    if (pfree) free(pic);
++    if (!CloseOutFile(fp,filename,error)) DirBox(0);
++    SetCursors(-1);
++}
++
++void JP2KDialog(int vis)
++{
++    if ((jp2kUp = vis)) CenterMapWindow(jp2kW,0,0,JP2KW,JP2KH);
++    else XUnmapWindow(theDisp,jp2kW);
++}
++
++static void TWRedraw(Window w,unsigned int val)
++{
++    char buf[11];
++    register int i;
++
++ /* Draw a 1-line numeric text string in the specified window, representing the
++    argument value as a left-justified unsigned decimal integer, followed by a
++    "cursor" icon.
++ */
++    sprintf(buf,"%u",val);
++    if (ctrlColor) XClearArea(theDisp,w,2,2,TEXTW-4,TEXTH-4,False);
++    else XClearWindow(theDisp,w);
++    Draw3dRect(w,0,0,TEXTW-1,TEXTH-1,R3D_IN,2,hicol,locol,infobg);
++    XSetForeground(theDisp,theGC,infofg);
++    XDrawString(theDisp,w,theGC,3,ASCENT+3,buf,i = strlen(buf));
++
++ /* Draw a "cursor" icon after the numeric string. */
++
++    i = XTextWidth(mfinfo,buf,i);
++    XDrawLine(theDisp,w,theGC,i+3,2        ,i+3,2+CHIGH+1);
++    XDrawLine(theDisp,w,theGC,i+3,2+CHIGH+1,i+5,2+CHIGH+3);
++    XDrawLine(theDisp,w,theGC,i+3,2+CHIGH+1,i+1,2+CHIGH+3);
++}
++
++int JP2KCheckEvent(register XEvent *xev)
++{
++    int ok = 0;
++
++ /* Check whether the argument "X Windows" event is for one of our subwindows.
++    If it is, handle the event and return 1; otherwise, return 0.
++ */
++    if (!jp2kUp) return 0;
++    switch (xev->type)
++      { KeySym ks;
++        int len;
++        char buf[128];
++        register int i;
++
++     /* Throw away excess "expose" events for "dumb" windows. */
++
++        case Expose     :
++#         define E ((XExposeEvent *)xev)
++          if (E->window == jp2kW)
++            { XRectangle rect;
++
++              rect.x     = E->x    ; rect.y      = E->y     ;
++              rect.width = E->width; rect.height = E->height;
++              XSetClipRectangles(theDisp,theGC,0,0,&rect,1,Unsorted);
++              XSetForeground(theDisp,theGC,infofg);
++              XSetBackground(theDisp,theGC,infobg);
++              i = sizeof button/sizeof *button;
++              while (--i >= 0) BTRedraw(&button[i]);
++              i = sizeof chkbut/sizeof *chkbut;
++              while (--i >= 0) CBRedraw(&chkbut[i]);
++              i = sizeof menu/sizeof *menu;
++              while (--i >= 0) MBRedraw(&menu[i]);
++              RBRedraw(radio,-1);
++              DrawString(jp2kW,10,10+ASCENT,"Save JPEG 2000 File...");
++              DrawString(jp2kW,10,10+ASCENT+2*LINEHIGH,"Style options:");
++              DrawString(jp2kW,JP2KW-2*MENUW-10,10+ASCENT+2*LINEHIGH,
++                "Coding Blk");
++              DrawString(jp2kW,JP2KW-1*MENUW-10,10+ASCENT+2*LINEHIGH,
++                "  Precinct");
++              DrawString(jp2kW,
++                JP2KW-2*MENUW-10,10+ASCENT+SPACING+3*LINEHIGH+2*MENUH,
++                "Progression:");
++              DrawString(jp2kW,
++                JP2KW-2*TEXTW-10,10+ASCENT+SPACING+3*LINEHIGH+3*MENUH+0*TEXTH,
++                "Guard bits:");
++              DrawString(jp2kW,
++                JP2KW-2*TEXTW-10,10+ASCENT+SPACING+3*LINEHIGH+3*MENUH+1*TEXTH,
++                "Res levels:");
++              DrawString(jp2kW,
++                JP2KW-2*TEXTW-10,10+ASCENT+SPACING+3*LINEHIGH+3*MENUH+2*TEXTH,
++                "Rate:");
++              XSetClipMask(theDisp,theGC,None);
++              ok = 1;
++              break;
++            };
++          i = sizeof text/sizeof *text;
++          while (--i >= 0 && E->window != text[i]);
++          if (i >= 0)
++            {
++              TWRedraw(E->window,textval[i]);
++              ok = 1;
++            };
++          break;
++#         undef E
++
++     /* Check whether the user pressed one of our buttons. */
++
++        case ButtonPress:
++#         define E ((XButtonEvent *)xev)
++          if (E->button == Button1 && E->window == jp2kW)
++            { register int j;
++
++              ok = 1; /* Check whether a regular button was pressed */
++              i = sizeof button/sizeof *button;
++              while (  --i >= 0
++                     && !PTINRECT(E->x,E->y,button[i].x,button[i].y,button[i].w,button[i].h)
++                    );
++              if (i >= 0) /* our button was pressed */
++                { char options[1024];
++                  register char *p;
++                  register const char *q;
++
++                  if (!BTTrack(&button[i])) break; /* Ignore it */
++                  if (i != J_BOK) /* must be "Cancel" button */
++                    {
++                      JP2KDialog(0);
++                      break;
++                    };
++
++               /* Our user hit the "Ok" button.  At this point, we have an ugly
++                  job to do:  JasPer Library encoder options must be specified
++                  as an ASCII string of Space (" ")-separated <tag>[=<value>]
++                  entries, so we must collect the values of all of our widgets
++                  and subwindows, determine whether our user has requested any
++                  non-default values, then build the string only for the JasPer
++                  Library to immediately tear it apart again.  Yechh!
++               */
++                  if ((unsigned)textval[J_TGBIT]-1 > 7)
++                    {
++                      OpenAlert("No. of guard bits must be 1-8");
++                      sleep(3);
++                      CloseAlert();
++                      break;
++                    };
++                  if ((unsigned)textval[J_TRES ] <= 0)
++                    {
++                      OpenAlert("Maximum resolution levels must be >= 1");
++                      sleep(3);
++                      CloseAlert();
++                      break;
++                    };
++
++               /* XXX  Should we check and complain if the rate is zero?
++                       JasPer Library Version 1.701 apparently accepts that
++                  value, even though it seems kinda weird.
++               */
++                  p = options;
++                  i = 0;
++                  do if ((j = MBWhich(&menu[i])) != 5)
++                       { static const char *parm[2] =
++                           {"cblkwidth=%u", "cblkheight=%u"};
++
++                         if (p > options) *p++ = ' ';
++                         sprintf(p,parm[i-J_MCBXW],++j);
++                         while (*++p);
++                       }
++                  while (++i <= J_MCBXH);
++                  do if ((j = MBWhich(&menu[i])) < 15)
++                       { static const char *parm[2] =
++                           {"prcwidth=%u", "prcheight=%u"};
++
++                         if (p > options) *p++ = ' ';
++                         sprintf(p,parm[i-J_MPREW],j);
++                         while (*++p);
++                       }
++                  while (++i <= J_MPREH);
++                  if ((j = MBWhich(&menu[i])))
++                    {
++                      if (p > options) *p++ = ' ';
++                      *p++ = 'p'; *p++ = 'r'; *p++ = 'g'; *p = '=';
++                      q = ProgList[j];
++                      while ((*++p = *q++));
++                    };
++                  if ((i = textval[J_TRES ]) != 6)
++                    {
++                      if (p > options) *p++ = ' ';
++                      sprintf(p,"numrlvls=%u",i);
++                      while (*++p);
++                    };
++                  i = 0;
++                  do if (chkbut[i].val) /* append this encoding option */
++                       {
++                         if (p > options) *p++ = ' ';
++                         q = chkbut[i].str;
++                         while ((*p++ = *q++));
++                         *--p = '\000';
++                       }
++                  while (++i < sizeof chkbut/sizeof *chkbut);
++                  if ((i = textval[J_TGBIT]) != 2)
++                    {
++                      if (p > options) *p++ = ' ';
++                      sprintf(p,"numgbits=%u",i);
++                      while (*++p);
++                    };
++                  if ((i = textval[J_TRATE]) != 100)
++                    {
++                      if (p > options) *p++ = ' ';
++                      *p++ = 'r'; *p++ = 'a'; *p++ = 't'; *p++ = 'e';
++                      *p++ = '=';
++                      if (i) /* non-zero rate */
++                        {
++                          if (RBWhich(radio)) sprintf(p,"%uB",i); /* # Bytes */
++                          else /* the value is a percentage */
++                            {
++                              if (i > 100) i = 200; /* => Raw size + 1 */
++                              sprintf(p,"%u.%.2u",i/100,i%100);
++                            }
++                          while (*++p);
++                        }
++                      else /* rate = 0 */
++                        {
++
++                       /* XXX  This is apparently valid, since JasPer Library
++                               Version 1.701 doesn't complain about it.
++                       */
++                          *p++ = '0';
++                          *p = '\000';
++                        }
++                    };
++                  StoreJP2K(options); /* Finally, do the *real* work! */
++                  JP2KDialog(0);
++                  p = GetDirFullName();
++                  if (!ISPIPE(*p))
++                    {
++                      XVCreatedFile(p);
++                      StickInCtrlList(0);
++                    };
++                  break;
++                };
++
++           /* See whether a check-box button was pressed. */
++
++              i = sizeof chkbut/sizeof *chkbut;
++              while (--i >= 0 && !CBClick(&chkbut[i],E->x,E->y));
++              if (i >= 0) /* our button was pressed */
++                {
++                  (void)CBTrack(&chkbut[i]);
++                  break;
++                };
++
++           /* See whether a menu button was pressed. */
++
++              i = sizeof menu/sizeof *menu;
++              while (--i >= 0 && !MBClick(&menu[i],E->x,E->y));
++              if (i >= 0) /* our button was pressed */
++                { register int j;
++
++                  if ((j = MBTrack(&menu[i])) >= 0)
++                    {
++                      switch (i)
++                        {
++
++                       /* The JasPer Library constrains a coding box's area
++                          (width x height) to be <= 4096 pixels, so if this
++                          button-press would violate that condition, then
++                          quietly limit the box's orthogonal dimension by just
++                          enough to compensate.
++                       */
++                          case J_MCBXH:
++                          case J_MCBXW: if (MBWhich(&menu[!i]) + j >= 10)
++                                          MBSelect(&menu[!i],10 - j);
++                        };
++                      MBSelect(&menu[i],j);
++                      MBSetActive(&menu[i],1);
++                    };
++                  break;
++                };
++
++           /* See whether a radio button was pressed. */
++
++              if (   (i = RBClick(radio,E->x,E->y)) >= 0 /* button pressed */
++                  && RBTrack(radio,i)
++                 )
++                {
++                  RBSelect(radio,i);
++                  RBSetActive(radio,i,1);
++                };
++              break;
++            };
++          XBell(theDisp,50);
++          break;
++#         undef E
++
++     /* Translate a few key-press events into simulated button events. */
++
++        case KeyPress   :
++#         define E ((XKeyEvent *)xev)
++          buf[len = XLookupString(E,buf,sizeof buf,&ks,0)] = '\000';
++          RemapKeyCheck(ks,buf,&len);
++          if (E->window == jp2kW)
++            {
++              ok = 1;
++              if (len > 0)
++                switch (buf[0])
++                  {
++                    case '\r'  :
++                    case '\n'  : FakeButtonPress(&button[J_BOK  ]);
++                                 break;
++                    case '\033': FakeButtonPress(&button[J_BCANC]);
++                  };
++              break;
++            };
++          i = sizeof text/sizeof *text;
++          while (--i >= 0 && E->window != text[i]);
++          if (i >= 0) /* a key was pressed in our text window */
++            { int oldval = textval[i]; /* Save this subwindow's old value */
++              register int c, j = 0;
++
++           /* This is a *very* simple text-input editing loop that assembles an
++              an unsigned integer from successive ASCII decimal digits, typed
++              into one of our 1-line subwindows.  For convenience, the only
++              character recognized is Backspace.
++           */
++              ok = 1;
++           L: if (j >= len) break;
++              if ((unsigned)(c = buf[j++] - '0') <= 9)
++                {
++                  TWRedraw(text[i],textval[i] = textval[i]*10 + c);
++                  goto L;
++                };
++              if ((c += '0') == '\b')
++                {
++                  TWRedraw(text[i],textval[i] = textval[i]/10);
++                  goto L;
++                };
++              textval[i] = oldval;
++            };
++          XBell(theDisp,50);
++#         undef E
++      };
++    return ok;
++}
++
++
++/*******************************************/
++void
++VersionInfoJP2K()       /* GRR 20070304 */
++{
++  fprintf(stderr, "   Compiled with libjasper %s; using libjasper %s.\n",
++    JAS_VERSION, jas_getversion());
++}
++
++#endif /* HAVE_JP2K */
+diff -Naru xv-3.10a/xvmag.c xv-3.10a.jumbo/xvmag.c
+--- xv-3.10a/xvmag.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvmag.c	2005-04-18 07:56:58.000000000 +0200
+@@ -0,0 +1,866 @@
++/*
++ *  xvmag.c - load routine for `MAG' format pictures.
++ *
++ *  The `MAG' format is used by many Japanese personal computer users.
++ *  This program is based on MAGBIBLE.DOC which is the specification
++ *  for `MAG' format written by Woody RINN.  It is written in Japanese,
++ *  and exists in some anon-ftp sites.
++ */
++
++#include "xv.h"
++#include <setjmp.h>
++
++#ifdef HAVE_MAG
++
++typedef unsigned short data16;
++
++struct mag {
++    jmp_buf jmp;
++    FILE *fp;
++    long fsize;
++    int m_256, m_dig, m_8, m_200;
++    int x1, y1, x2, y2, left_pad, right_pad;
++    int p_width, p_height, width, height;
++    long h_off, a_off, a_size, b_off, b_size, p_off, p_size;
++    byte *a, *b, *p;
++};
++
++static void mag_open_file       PARM((struct mag*, char*));
++static void mag_read_check_data PARM((struct mag*));
++static void mag_read_comment    PARM((struct mag*, char**));
++static void mag_read_header     PARM((struct mag*));
++static void mag_read_palette    PARM((struct mag*, byte*, byte*, byte*));
++static void mag_read_flags      PARM((struct mag*));
++static void mag_read_pixel_data PARM((struct mag*));
++static void mag_expand_body     PARM((struct mag*, byte**));
++
++static void mag_compress_data    PARM((struct mag*, byte*));
++static void mag_write_check_data PARM((struct mag*));
++static void mag_write_comment    PARM((struct mag*, char *));
++static void mag_write_palette    PARM((struct mag*, int,
++				       byte*, byte*, byte*, int));
++static void mag_write_flags      PARM((struct mag*));
++static void mag_write_pixel_data PARM((struct mag*));
++static void mag_write_header     PARM((struct mag*));
++static void mag_set_double_word  PARM((long, byte *));
++
++static void mag_init_info        PARM((struct mag*));
++static void mag_cleanup_mag_info PARM((struct mag*, int));
++static void mag_cleanup_pinfo    PARM((PICINFO*));
++static void mag_memory_error     PARM((char*, char*));
++static void mag_error            PARM((struct mag*, int));
++static void mag_file_error       PARM((struct mag*, int));
++static void mag_file_warning     PARM((struct mag*, int));
++static void mag_show_struct      PARM((struct mag*));
++static void *mag_malloc          PARM((size_t, char*));
++static void *mag_realloc         PARM((void*, size_t, char*));
++
++
++static char *mag_id = "MAKI02  ";
++static struct{
++    int dx, dy;
++}points[16] = {
++    { 0,  0}, { 1,  0}, { 2,  0}, { 4,  0},
++    { 0,  1}, { 1,  1},
++    { 0,  2}, { 1,  2}, { 2,  2},
++    { 0,  4}, { 1,  4}, { 2,  4},
++    { 0,  8}, { 1,  8}, { 2,  8},
++    { 0, 16},
++};
++static int try[15] = {1, 4, 5, 6, 7, 9, 10, 2, 8, 11, 12, 13, 14, 3, 15};
++
++static char *mag_msgs[] = {
++    NULL,
++#define MAG_OPEN 1
++    "can't open file",
++#define MAG_CORRUPT 2
++    "file currupted.",
++#define MAG_FORMAT 3
++    "not MAG format.",
++#define MAG_WRITE 4
++    "write failed.",
++};
++
++
++#define H4(x) (((int) (x) >> 4) & 0x0f)	/* operates on a byte */
++#define L4(x) ((x) & 0x0f)
++#define H8(x) (((x) >> 8) & 0xff)	/* operates on a data16 */
++#define L8(x) ((x) & 0xff)
++
++#define error(msgnum) longjmp(mi->jmp, msgnum)
++
++
++/* The main routine to load a MAG file. */
++int LoadMAG(fname, pinfo)
++    char *fname;
++    PICINFO *pinfo;
++{
++    struct mag mag;
++    int e;
++
++    if(DEBUG) fputs("LoadMAG:\n", stderr);
++
++    pinfo->comment = NULL;
++    mag_init_info(&mag);
++    if((e = setjmp(mag.jmp)) != 0){
++	/* When an error occurs, comes here. */
++	mag_cleanup_mag_info(&mag, 0);
++	mag_cleanup_pinfo(pinfo);
++	return 0;
++    }
++
++    mag_open_file(&mag, fname);
++    mag_read_check_data(&mag);
++    mag_read_comment(&mag, &pinfo->comment);
++    mag_read_header(&mag);
++    mag_read_palette(&mag, pinfo->r, pinfo->g, pinfo->b);
++    mag_read_flags(&mag);
++    mag_read_pixel_data(&mag);
++    mag_expand_body(&mag, &pinfo->pic);
++
++    pinfo->w = pinfo->normw = mag.width;
++    pinfo->h = pinfo->normh = mag.height;
++    pinfo->type = PIC8;
++    pinfo->frmType = F_MAG;
++    pinfo->colType = F_FULLCOLOR;
++    sprintf(pinfo->fullInfo, "MAG, %d colors%s (%ld bytes)",
++	    mag.m_256 ? 256 : (mag.m_8 ? 8 : 16),
++	    mag.m_200 ? ", aspect 0.5" : "", mag.fsize);
++    sprintf(pinfo->shrtInfo, "%dx%d MAG", mag.width, mag.height);
++    if(mag.m_200)
++	normaspect = 0.5;
++
++    mag_cleanup_mag_info(&mag, 0);
++    return 1;
++}
++
++static void mag_open_file(mi, fname)
++    struct mag *mi;
++    char *fname;
++{
++    if((mi->fp = fopen(fname, "rb")) == NULL)
++	mag_file_error(mi, MAG_OPEN);
++    fseek(mi->fp, (size_t) 0, SEEK_END);
++    mi->fsize = ftell(mi->fp);
++    fseek(mi->fp, (size_t) 0, SEEK_SET);
++}
++
++static void mag_read_check_data(mi)
++    struct mag *mi;
++{
++    char buffer[8];
++
++    if(fread(buffer, (size_t) 8, (size_t) 1, mi->fp) != 1)
++	mag_file_error(mi, MAG_CORRUPT);
++    if(strncmp(buffer, mag_id, (size_t) 8) != 0)
++	mag_error(mi, MAG_FORMAT);
++}
++
++static void mag_read_comment(mi, p)
++    struct mag *mi;
++    char **p;
++{
++    int max = -1, i = 0;
++    int c;
++
++    while((c = fgetc(mi->fp)) != EOF){
++	if(c == 0x1a)
++	    break;
++	if(max < i){
++	    max += 16;
++	    *p = mag_realloc(*p, (size_t) max + 1, "mag_read_comment#1");
++	}
++	(*p)[i++] = c;
++    }
++
++    if(c == EOF)
++	mag_file_error(mi, MAG_CORRUPT);
++
++    if(max < i){
++	*p = mag_realloc(*p, (size_t) max + 2, "mag_read_comment#2");
++    }
++    if(i > 24){
++	(*p)[i] = '\0';
++	strcpy(*p, &(*p)[24]);
++    }else{
++	(*p)[0] = '\0';
++    }
++}
++
++static void mag_read_header(mi)
++    struct mag *mi;
++{
++    byte buf[32];
++
++    mi->h_off = ftell(mi->fp);
++
++    if(fread(buf, (size_t) 32, (size_t) 1, mi->fp) != 1)
++	mag_file_error(mi, MAG_CORRUPT);
++
++    mi->m_256 = buf[3] & 0x80;
++    mi->m_dig = buf[3] & 0x04;
++    mi->m_8   = buf[3] & 0x02;
++    mi->m_200 = buf[3] & 0x01;
++
++    mi->x1 = buf[ 4] + buf[ 5] * 256;
++    mi->y1 = buf[ 6] + buf[ 7] * 256;
++    mi->x2 = buf[ 8] + buf[ 9] * 256;
++    mi->y2 = buf[10] + buf[11] * 256;
++
++#define get_dword(a, b, c, d) \
++    ((long)(a) << 24 | (long)(b) << 16 | (long)(c) << 8 | (long)(d))
++
++    mi->a_off  = get_dword(buf[15], buf[14], buf[13], buf[12]);
++    mi->b_off  = get_dword(buf[19], buf[18], buf[17], buf[16]);
++    mi->b_size = get_dword(buf[23], buf[22], buf[21], buf[20]);
++    mi->p_off  = get_dword(buf[27], buf[26], buf[25], buf[24]);
++    mi->p_size = get_dword(buf[31], buf[30], buf[29], buf[28]);
++#undef get_dword
++
++    mi->a_size = mi->b_off - mi->a_off;
++    mi->a_off += mi->h_off;
++    mi->b_off += mi->h_off;
++    mi->p_off += mi->h_off;
++
++    mi->width     = mi->x2 - mi->x1 + 1;
++    mi->height    = mi->y2 - mi->y1 + 1;
++    mi->left_pad  =       mi->x1 & 07;
++    mi->right_pad = 07 - (mi->x2 & 07);
++    mi->x1       -= mi->left_pad;		/* x1 = 8m   */
++    mi->x2       += mi->right_pad;		/* x2 = 8n+7 */
++    mi->p_width   = ((mi->x2 + 1) - mi->x1) / (mi->m_256 ? 2 : 4);
++    mi->p_height  =  (mi->y2 + 1) - mi->y1;
++
++    if(DEBUG) mag_show_struct(mi);
++}
++
++static void mag_read_palette(mi, r, g, b)
++    struct mag *mi;
++    byte *r, *g, *b;
++{
++    int num_palettes;
++    byte *buf;
++
++    if(mi->m_256)
++	num_palettes = 256;
++    else
++	num_palettes = 16;
++
++    buf = mag_malloc((size_t)num_palettes * 3, "mag_read_palette");
++
++    if(fread(buf, (size_t) 3, (size_t) num_palettes, mi->fp) != num_palettes){
++	free(buf);
++	mag_file_error(mi, MAG_CORRUPT);
++    }
++
++    for(num_palettes--; num_palettes >= 0; num_palettes--){
++	g[num_palettes] = buf[num_palettes * 3    ];
++	r[num_palettes] = buf[num_palettes * 3 + 1];
++	b[num_palettes] = buf[num_palettes * 3 + 2];
++    }
++
++    free(buf);
++}
++
++static void mag_read_flags(mi)
++     struct mag *mi;
++{
++    mi->a = mag_malloc((size_t) mi->a_size, "mag_read_flags#1");
++    mi->b = mag_malloc((size_t) mi->b_size, "mag_read_flags#2");
++
++    fseek(mi->fp, mi->a_off, SEEK_SET);
++    if(fread(mi->a, (size_t) mi->a_size, (size_t) 1, mi->fp) != 1)
++	mag_file_warning(mi, MAG_CORRUPT);
++    if(fread(mi->b, (size_t) mi->b_size, (size_t) 1, mi->fp) != 1)
++	mag_file_warning(mi, MAG_CORRUPT);
++}
++
++static void mag_read_pixel_data(mi)
++    struct mag *mi;
++{
++    mi->p = mag_malloc((size_t) mi->p_size, "mag_read_pixel_data");
++
++    fseek(mi->fp, mi->p_off, SEEK_SET);
++    if(fread(mi->p, (size_t) mi->p_size, (size_t) 1, mi->fp) != 1)
++	mag_file_warning(mi, MAG_CORRUPT);
++}
++
++/* MAG expanding routine */
++static void mag_expand_body(mi, pic0)
++    struct mag *mi;
++    byte **pic0;
++{
++    int ai, bi, fi, pi;
++    int px, py, x, y;
++    byte *flag;
++    byte mask;
++    data16 *pixel0;
++
++    flag   = mag_malloc((size_t) mi->p_width / 2, "mag_expand_body#1");
++    *pic0  = mag_malloc((size_t) mi->width * mi->height, "mag_expand_body#2");  // GRR POSSIBLE OVERFLOW / FIXME
++    pixel0 = mag_malloc((size_t) 2 * mi->p_width * 17, "mag_expand_body#3");  // GRR POSSIBLE OVERFLOW / FIXME
++
++#define pixel(x, y) pixel0[(y) % 17 * mi->p_width + (x)]
++
++    ai = bi = pi = 0;
++    mask = 0x80;
++    for(y = py = 0; py < mi->p_height; py++){
++	for(fi = 0; fi < mi->p_width / 2; fi++){
++	    if(py == 0){
++		if(mi->a[ai] & mask)
++		    flag[fi] = mi->b[bi++];
++		else
++		    flag[fi] = 0;
++	    }else{
++		if(mi->a[ai] & mask)
++		    flag[fi] ^= mi->b[bi++];
++	    }
++	    if((mask >>= 1) == 0){
++		mask = 0x80;
++		ai++;
++	    }
++	}
++
++	for(px = fi = 0; fi < mi->p_width / 2; fi++){
++	    int f = H4(flag[fi]);
++	    if(f == 0){
++		pixel(px, py) = mi->p[pi] + mi->p[pi + 1] * 256;
++		px++;
++		pi+=2;
++	    }else{
++		int dx = points[f].dx, dy = points[f].dy;
++		pixel(px, py) = pixel(px - dx, py - dy);
++		px++;
++	    }
++
++	    f = L4(flag[fi]);
++	    if(f == 0){
++		pixel(px, py) = mi->p[pi] + mi->p[pi + 1] * 256;
++		px++;
++		pi+=2;
++	    }else{
++		int dx = points[f].dx, dy = points[f].dy;
++		pixel(px, py) = pixel(px - dx, py - dy);
++		px++;
++	    }
++	}
++
++#define inside(x) ((unsigned int)(x) < mi->width)
++#define  pic(x, y) (*pic0)[(y) * mi->width + (x)]
++	for(x = -mi->left_pad, px = 0; px < mi->p_width; px++){
++	    data16 p = pixel(px, py);
++	    if(mi->m_256){
++		if(inside(x))
++		    pic(x, y) = L8(p);
++		x++;
++		if(inside(x))
++		    pic(x, y) = H8(p);
++		x++;
++	    }else{
++		if(inside(x))
++		    pic(x, y) = H4(L8(p));
++		x++;
++		if(inside(x))
++		    pic(x, y) = L4(L8(p));
++		x++;
++		if(inside(x))
++		    pic(x, y) = H4(H8(p));
++		x++;
++		if(inside(x))
++		    pic(x, y) = L4(H8(p));
++		x++;
++	    }
++	}
++	y++;
++    }
++#undef pic
++#undef inside
++#undef pixel
++
++    free(flag);
++    free(pixel0);
++}
++
++
++/* The main routine to write a MAG file. */
++int WriteMAG(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
++	      comment)
++    FILE *fp;
++    byte *pic;
++    int ptype, w, h;
++    byte *rmap, *gmap, *bmap;
++    int numcols, colorstyle;
++    char *comment;
++{
++    byte rtemp[256], gtemp[256], btemp[256];
++    struct mag mag;
++    int e;
++
++    if(DEBUG) fputs("WriteMag\n", stderr);
++
++    mag_init_info(&mag);
++    mag.fp = fp;
++
++    if(ptype == PIC24){
++	if(!(pic = Conv24to8(pic, w, h, 256, rtemp, gtemp, btemp)))
++	    mag_memory_error("Conv24to8", "WriteMAG");
++	rmap = rtemp;
++	gmap = gtemp;
++	bmap = btemp;
++	numcols = 256;
++	mag.m_256 = 1;
++    }else{
++	if(numcols > 16)
++	    mag.m_256 = 1;
++    }
++
++    if((e = setjmp(mag.jmp)) != 0){
++	/* When an error occurs, comes here. */
++	mag_cleanup_mag_info(&mag, 1);
++	return -1;
++    }
++
++    mag.x2 = w - 1;
++    mag.y2 = h - 1;
++    mag.right_pad = 07 - (mag.x2 & 07);
++    mag.p_width = (w + mag.right_pad) / (mag.m_256 ? 2 : 4);
++    mag.p_height = h;
++    mag.width = w;
++    mag.height = h;
++    mag.a_size = (mag.p_width * mag.p_height + 15) / 16;	/* x/2/8 */   // GRR POSSIBLE OVERFLOW / FIXME
++    if(mag.a_size % 2)
++	mag.a_size++;
++
++    mag_compress_data(&mag, pic);
++    mag_write_check_data(&mag);
++    mag_write_comment(&mag, comment);
++
++    mag.h_off = ftell(mag.fp);
++
++    mag_write_palette(&mag, numcols, rmap, gmap, bmap,
++		      colorstyle == F_GREYSCALE);
++    mag_write_flags(&mag);
++    mag_write_pixel_data(&mag);
++    mag_write_header(&mag);
++
++    mag_cleanup_mag_info(&mag, 1);
++    return 0;
++}
++
++/* MAG compressing routine */
++static void mag_compress_data(mi, pic0)
++    struct mag *mi;
++    byte *pic0;
++{
++    int ai, bi, pi, i;
++    int bmax, pmax;
++    byte mask;
++    byte *flag0;
++    data16 *pixel0;
++    int px, py, x, y;
++
++    pixel0 = mag_malloc((size_t) 2 * mi->p_width * mi->p_height,  // GRR POSSIBLE OVERFLOW / FIXME
++			"mag_compress_data#1");
++    flag0 = mag_malloc((size_t) mi->p_width * mi->p_height,  // GRR POSSIBLE OVERFLOW / FIXME
++		       "mag_compress_data#2");
++
++#define pic(x, y) pic0[(y) * mi->width + (x)]
++    /* convert dots to pixels */
++    i = 0;
++    for(y = py = 0; py < mi->p_height; py++){
++	for(x = px = 0; px < mi->p_width; px++){
++	    data16 p = 0;
++	    if(mi->m_256){
++		if(x < mi->width)
++		    p += pic(x, y);
++		x++;
++		if(x < mi->width)
++		    p += pic(x, y) * 256;
++		x++;
++	    }else{
++		if(x < mi->width)
++		    p += pic(x, y) * 16;
++		x++;
++		if(x < mi->width)
++		    p += pic(x, y);
++		x++;
++		if(x < mi->width)
++		    p += pic(x, y) * 4096;
++		x++;
++		if(x < mi->width)
++		    p += pic(x, y) * 256;
++		x++;
++	    }
++	    pixel0[i++] = p;
++	}
++	y++;
++    }
++#undef pic
++
++#define pixel(x, y) pixel0[(y) * mi->p_width + (x)]
++#define  flag(x, y)  flag0[(y) * mi->p_width + (x)]
++    /* get flags */
++    pmax = pi = 0;
++    for(py = 0; py < mi->p_height; py++){
++	for(px = 0; px < mi->p_width; px++){
++	    int t;
++	    for(t = 0; t < 15; t++){
++		int dx = points[try[t]].dx, dy = points[try[t]].dy;
++		if(dx <= px && dy <= py){
++		    if(pixel(px - dx, py - dy) == pixel(px, py))
++			break;
++		}
++	    }
++	    if(t < 15){
++		flag(px, py) = try[t];
++	    }else{
++		flag(px, py) = 0;
++		if(pmax <= pi + 1){
++		    pmax += 128;
++		    mi->p = mag_realloc(mi->p, (size_t) pmax,
++					"mag_compress_data#3");
++		}
++		mi->p[pi++] = L8(pixel(px, py));
++		mi->p[pi++] = H8(pixel(px, py));
++	    }
++	}
++    }
++#undef flag
++#undef pixel
++
++    /* pack 2 flags into 1 byte */
++    for(i = 0; i < mi->p_width / 2 * mi->p_height; i++)
++	flag0[i] = flag0[i * 2] * 16 + flag0[i * 2 + 1];
++
++#define flag(x, y)  flag0[(y) * mi->p_width / 2 + (x)]
++    for(py = mi->p_height - 1; py >= 1; py--){
++	for(px = 0; px < mi->p_width / 2; px++)
++	    flag(px, py) ^= flag(px, py - 1);
++    }
++#undef flag
++
++    mask = 0x80;
++    ai = bi = bmax = 0;
++    mi->a = mag_malloc((size_t) mi->a_size, "mag_compress_data#4");   // GRR POSSIBLE OVERFLOW / FIXME
++    for(i = 0; i < mi->p_width / 2 * mi->p_height; i++){
++	if(flag0[i] == 0){
++	    mi->a[ai] &= ~mask;
++	}else{
++	    if(bmax == bi){
++		bmax += 128;
++		mi->b = mag_realloc(mi->b, (size_t) bmax,
++				    "mag_compress_data#4");
++	    }
++	    mi->b[bi++] = flag0[i];
++	    mi->a[ai] |= mask;
++	}
++
++	if((mask >>= 1) == 0){
++	    mask = 0x80;
++	    ai++;
++	}
++    }
++
++    if(bi % 2)
++	bi++;
++    mi->b_size = bi;
++
++    mi->p_size = pi;
++
++    free(pixel0);
++    free(flag0);
++}
++
++static void mag_write_check_data(mi)
++    struct mag *mi;
++{
++    if(fwrite(mag_id, (size_t) 8, (size_t) 1, mi->fp) != 1)
++	mag_file_error(mi, MAG_WRITE);
++}
++
++static void mag_write_comment(mi, comment)
++    struct mag *mi;
++    char *comment;
++{
++    char *p;
++    int i;
++
++    if(fputs("XV   ", mi->fp) == EOF)
++	mag_file_error(mi, MAG_WRITE);
++
++    if((p = (char *) getenv("USER")) == NULL)
++	p = "????????";
++    for(i = 5; i < 24; i++){
++	if(*p == '\0')
++	    break;
++	if(fputc(*p++, mi->fp) == EOF)
++	    mag_file_error(mi, MAG_WRITE);
++    }
++    for( ; i < 24; i++){
++	if(fputc(' ', mi->fp) == EOF)
++	    mag_file_error(mi, MAG_WRITE);
++    }
++
++    if(comment){
++	int l = strlen(comment);
++	if(l > 0){
++	    int i;
++	    for(i = 0; i < l; i++){
++		if(comment[i] == 0x1a)
++		    comment[i] = ' ';
++	    }
++	    if(fwrite(comment, (size_t) l, (size_t) 1, mi->fp) != 1)
++		mag_file_error(mi, MAG_WRITE);
++	}
++    }
++
++    if(fputc(0x1a, mi->fp) == EOF)
++	mag_file_error(mi, MAG_WRITE);
++}
++
++static void mag_write_palette(mi, num, r, g, b, grey)
++    struct mag *mi;
++    int num;
++    byte *r, *g, *b;
++    int grey;
++{
++    int i, left;
++    char buf[3];
++
++    fseek(mi->fp, 32L, SEEK_CUR);	/* skip header area */
++    for(i = 0; i < num; i++){
++	buf[0] = *g++;
++	buf[1] = *r++;
++	buf[2] = *b++;
++	if(grey)
++	    buf[0] = buf[1] = buf[2] = MONO(buf[1], buf[0], buf[2]);
++	if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1)
++	    mag_file_error(mi, MAG_WRITE);
++    }
++    if(num < 16){
++	left = 16 - num;
++    }else if(num == 16){
++	left = 0;
++    }else if(num < 256){
++	left = 256 - num;
++    }else if(num == 256){
++	left = 0;
++    }else
++	left = 0;	/* shouldn't happen */
++
++    if(left > 0){
++	for(i = 0; i < left; i++){
++	    if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1)
++		mag_file_error(mi, MAG_WRITE);
++	}
++    }
++}
++
++static void mag_write_flags(mi)
++    struct mag *mi;
++{
++    int i;
++
++    mi->a_off = ftell(mi->fp);
++    for(i = 0; i < mi->a_size; i++){
++	if(fputc(mi->a[i], mi->fp) == EOF)
++	    mag_file_error(mi, MAG_WRITE);
++    }
++
++    mi->b_off = ftell(mi->fp);
++    for(i = 0; i < mi->b_size; i++){
++	if(fputc(mi->b[i], mi->fp) == EOF)
++	    mag_file_error(mi, MAG_WRITE);
++    }
++}
++
++static void mag_write_pixel_data(mi)
++    struct mag *mi;
++{
++    int i;
++
++    mi->p_off = ftell(mi->fp);
++    for(i = 0; i < mi->p_size; i++){
++	if(fputc(mi->p[i], mi->fp) == EOF)
++	    mag_file_error(mi, MAG_WRITE);
++    }
++}
++
++static void mag_write_header(mi)
++    struct mag *mi;
++{
++    byte buf[32];
++
++    if(DEBUG) mag_show_struct(mi);
++
++    mi->a_off -= mi->h_off;
++    mi->b_off -= mi->h_off;
++    mi->p_off -= mi->h_off;
++
++    buf[ 0] = buf[1] = buf[2] = 0;
++    buf[ 3] = (mi->m_256 ? 0x80 : 0);
++    buf[ 4] = buf[5] = 0;
++    buf[ 6] = buf[7] = 0;
++    buf[ 8] = L8(mi->x2);
++    buf[ 9] = H8(mi->x2);
++    buf[10] = L8(mi->y2);
++    buf[11] = H8(mi->y2);
++    mag_set_double_word(mi->a_off,  &buf[12]);
++    mag_set_double_word(mi->b_off,  &buf[16]);
++    mag_set_double_word(mi->b_size, &buf[20]);
++    mag_set_double_word(mi->p_off,  &buf[24]);
++    mag_set_double_word(mi->p_size, &buf[28]);
++
++    fseek(mi->fp, mi->h_off, SEEK_SET);
++    if(fwrite(buf, (size_t) 32, (size_t) 1, mi->fp) != 1)
++	mag_file_error(mi, MAG_WRITE);
++}
++
++static void mag_set_double_word(n, p)
++    long n;
++    byte *p;
++{
++    p[0] = n % 256;	/* ugly...anything wrong with shift/mask operations? */
++    p[1] = n / 256 % 256;		/* (n >> 8) & 0xff */
++    p[2] = n / 256 / 256 % 256;	/* (n >> 16) & 0xff */
++    p[3] = n / 256 / 256 / 256 % 256;	/* (n >> 24) & 0xff */
++}
++
++/*
++ * The routines to initialize or clean up.
++ * mag_init_info:
++ *	initializes a mag structure.
++ * mag_cleanup_mag_info:
++ *	cleans up a mag structure.
++ * mag_cleanup_pinfo:
++ *	cleans up a PICINFO structure.
++ */
++static void mag_init_info(mi)
++    struct mag *mi;
++{
++    mi->fp = NULL;
++    mi->fsize = 0;
++    mi->m_256 = mi->m_dig = mi->m_8 = mi->m_200 = 0;
++    mi->x1 = mi->y1 = mi->x2 = mi->y2 = 0;
++    mi->left_pad = mi->right_pad = 0;
++    mi->p_width = mi->p_height = mi->width = mi->height = 0;
++    mi->h_off = mi->p_off = mi->p_size = 0;
++    mi->a_off = mi->a_size = mi->b_off = mi->b_size = 0;
++    mi->a = NULL;
++    mi->b = NULL;
++    mi->p = NULL;
++}
++
++static void mag_cleanup_mag_info(mi, writing)
++    struct mag *mi;
++    int writing;
++{
++    if(mi->fp && !writing)
++	fclose(mi->fp);
++    if(mi->a)
++	free(mi->a);
++    if(mi->b)
++	free(mi->b);
++    if(mi->p)
++	free(mi->p);
++}
++
++static void mag_cleanup_pinfo(pinfo)
++    PICINFO *pinfo;
++{
++    if(pinfo->comment){
++	free(pinfo->comment);
++	pinfo->comment = NULL;
++    }
++    if(pinfo->pic){
++	free(pinfo->pic);
++	pinfo->pic = NULL;
++    }
++}
++
++/*
++ * Error handler.
++ * mag_memory_error:
++ *	shows an error message, and terminates.
++ * mag_error:
++ *	shows an non-file error message, and jumps to the entry for errors.
++ * mag_file_error:
++ *	shows an file error message, and jumps to the entry for errors.
++ * mag_file_warning:
++ *	shows an file warning message.
++ */
++static void mag_memory_error(scm, fn)
++    char *scm, *fn;
++{
++    char buf[128];
++    sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn);
++    FatalError(buf);
++}
++
++static void mag_error(mi, mn)
++    struct mag *mi;
++    int mn;
++{
++    SetISTR(ISTR_WARNING, "%s", mag_msgs[mn]);
++    longjmp(mi->jmp, 1);
++}
++
++static void mag_file_error(mi, mn)
++    struct mag *mi;
++    int mn;
++{
++    if(feof(mi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", mag_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", mag_msgs[mn], ERRSTR(errno));
++    longjmp(mi->jmp, 1);
++}
++
++static void mag_file_warning(mi, mn)
++    struct mag *mi;
++    int mn;
++{
++    if(feof(mi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", mag_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", mag_msgs[mn], ERRSTR(errno));
++}
++
++static void mag_show_struct (mi)
++    struct mag *mi;
++{
++    fprintf(stderr, "  256 colors: %s\n", mi->m_256 ? "true" : "false");
++    fprintf(stderr, "  8 colors: %s\n", mi->m_8 ? "true" : "false");
++    fprintf(stderr, "  digital colors: %s\n", mi->m_dig ? "true" : "false");
++    fprintf(stderr, "  aspect ratio: %f\n", mi->m_200 ? 0.5 : 1.0);
++    fprintf(stderr, "  image size: %dx%d\n", mi->width, mi->height);
++    fprintf(stderr, "  left pad: %d\n", mi->left_pad);
++    fprintf(stderr, "  right pad: %d\n", mi->right_pad);
++    fprintf(stderr, "  h_off: %ld\n", mi->h_off);
++    fprintf(stderr, "  A: off:%ld, size:%ld\n", mi->a_off, mi->a_size);
++    fprintf(stderr, "  B: off:%ld, size:%ld\n", mi->b_off, mi->b_size);
++    fprintf(stderr, "  P: off:%ld, size:%ld\n", mi->p_off, mi->p_size);
++}
++
++/* Memory related routines. */
++static void *mag_malloc(n, fn)
++    size_t n;
++    char *fn;
++{
++    void *r = (void *) malloc(n);
++    if(r == NULL)
++	mag_memory_error("malloc", fn);
++    return r;
++}
++
++static void *mag_realloc(p, n, fn)
++    void *p;
++    size_t n;
++    char *fn;
++{
++    void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n);
++    if(r == NULL)
++	mag_memory_error("realloc", fn);
++    return r;
++}
++#endif /* HAVE_MAG */
+diff -Naru xv-3.10a/xvmaki.c xv-3.10a.jumbo/xvmaki.c
+--- xv-3.10a/xvmaki.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvmaki.c	2005-04-18 07:57:01.000000000 +0200
+@@ -0,0 +1,794 @@
++/*
++ * xvmaki.c - load routine for `MAKI' format pictures.
++ *
++ * The `MAKI' format was used by some Japanese personal computer users.
++ */
++
++#include "xv.h"
++#include <setjmp.h>
++
++#ifdef HAVE_MAKI
++
++typedef unsigned short data16;
++typedef unsigned int data32;
++
++struct maki_info {
++    jmp_buf jmp;
++    FILE *fp;
++    long fsize;
++    int x0, y0, x1, y1;
++    int width, height;
++    float aspect;
++    long fb_size;
++    long pa_size, pb_size;
++    int m_maki01b, m_200, m_dig8;
++    data16 ext_flag;
++    byte *fa, *fb, *pa, *pb;
++    byte *vs;
++    int numcols;
++    byte *forma, *formb;
++};
++
++
++static void maki_open_file             PARM((struct maki_info*, char*));
++static void maki_check_id              PARM((struct maki_info*));
++static void maki_skip_comment          PARM((struct maki_info*));
++static void maki_read_header           PARM((struct maki_info*));
++static void maki_read_palette          PARM((struct maki_info*,
++					     byte*, byte*, byte*));
++static void maki_read_flags            PARM((struct maki_info*));
++static void maki_read_pixel_data       PARM((struct maki_info*));
++static void maki_expand_virtual_screen PARM((struct maki_info*));
++static void maki_expand_pixel_data     PARM((struct maki_info*, byte**));
++static void maki_init_info             PARM((struct maki_info*));
++
++static void maki_make_pixel_data       PARM((struct maki_info*, byte*));
++static void maki_make_virtual_screen   PARM((struct maki_info*));
++static void maki_make_flags            PARM((struct maki_info*));
++static void maki_write_check_id        PARM((struct maki_info*));
++static void maki_write_comment         PARM((struct maki_info*));
++static void maki_write_header          PARM((struct maki_info*));
++static void maki_write_palette         PARM((struct maki_info*,
++					     byte*, byte*, byte*, int));
++static void maki_write_flags           PARM((struct maki_info*));
++static void maki_write_pixel_data      PARM((struct maki_info*));
++
++static void maki_cleanup_maki_info     PARM((struct maki_info*, int));
++static void maki_cleanup_pinfo         PARM((PICINFO*));
++static void maki_memory_error          PARM((char*, char*));
++static void maki_error                 PARM((struct maki_info*, int));
++static void maki_file_error            PARM((struct maki_info*, int));
++static void maki_file_warning          PARM((struct maki_info*, int));
++static void maki_show_maki_info        PARM((struct maki_info*));
++static void *maki_malloc               PARM((size_t, char*));
++static void *maki_realloc              PARM((void *, size_t, char*));
++
++static char maki_id_a[] = "MAKI01A ";
++static char maki_id_b[] = "MAKI01B ";
++
++static char *maki_msgs[] = {
++    NULL,
++#define MAKI_OPEN 1
++    "can't open file.",
++#define MAKI_CORRUPT 2
++    "file corrupted.",
++#define MAKI_FORMAT 3
++    "not MAKI format.",
++#define MAKI_BAD_DATA 4
++    "bad data.",
++#define MAKI_COMMENT 5
++    "no '^Z' after comment.",
++#define MAKI_SIZE 6
++    "bad size.",
++#define MAKI_WRITE 7
++    "write failed.",
++};
++
++#define H4(b) ((b) >> 4 & 0xf)
++#define L4(b) ((b)      & 0xf)
++#define error(msg_num) longjmp(mi->jmp, msg_num)
++
++int LoadMAKI(fname, pinfo)
++    char *fname;
++    PICINFO *pinfo;
++{
++    struct maki_info maki;
++    int e;
++
++    if(DEBUG) fputs("LoadMAKI:\n", stderr);
++
++    pinfo->comment = NULL;
++    maki_init_info(&maki);
++    if((e = setjmp(maki.jmp)) != 0){
++	/* When an error occurs, comes here. */
++	maki_cleanup_maki_info(&maki, 0);
++	maki_cleanup_pinfo(pinfo);
++	return 0;
++    }
++
++    maki_open_file(&maki, fname);
++    maki_check_id(&maki);
++    maki_skip_comment(&maki);
++    maki_read_header(&maki);
++    maki_read_palette(&maki, pinfo->r, pinfo->g, pinfo->b);
++    maki_read_flags(&maki);
++    maki_read_pixel_data(&maki);
++    maki_expand_virtual_screen(&maki);
++    maki_expand_pixel_data(&maki, &pinfo->pic);
++
++    pinfo->w = pinfo->normw = maki.width;
++    pinfo->h = pinfo->normh = maki.height;
++    pinfo->type = PIC8;
++    pinfo->frmType = F_MAKI;
++    pinfo->colType = F_FULLCOLOR;
++    sprintf(pinfo->fullInfo, "MAKI, 16 colors (%ld bytes)", maki.fsize);
++    sprintf(pinfo->shrtInfo, "%dx%d MAKI", maki.width, maki.height);
++    normaspect = maki.aspect;
++
++    maki_cleanup_maki_info(&maki, 0);
++    return 1;
++}
++
++static void maki_open_file(mi, fname)
++    struct maki_info *mi;
++    char *fname;
++{
++    if((mi->fp = fopen(fname, "rb")) == NULL)
++	maki_file_error(mi, MAKI_OPEN);
++    fseek(mi->fp, (size_t) 0, SEEK_END);
++    mi->fsize = ftell(mi->fp);
++    fseek(mi->fp, (size_t) 0, SEEK_SET);
++}
++
++static void maki_check_id(mi)
++    struct maki_info *mi;
++{
++    char buf[8];
++    if(fread(buf, (size_t) 8, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_CORRUPT);
++    if(strncmp(buf, maki_id_a, (size_t) 8) != 0 &&
++       strncmp(buf, maki_id_b, (size_t) 8) != 0)
++	maki_error(mi, MAKI_FORMAT);
++    mi->m_maki01b = (buf[6] == 'B');
++}
++
++static void maki_skip_comment(mi)
++    struct maki_info *mi;
++{
++    int i;
++    int c;
++
++    for(i = 0; i < 24; i++){
++	if((c = fgetc(mi->fp)) == EOF)
++	    maki_file_error(mi, MAKI_CORRUPT);
++	if(c == '\032')	/* ^Z, 0x1a */
++	    break;
++    }
++    if(c != '\032')
++	maki_file_error(mi, MAKI_COMMENT);
++
++    fseek(mi->fp, 32L, SEEK_SET);
++}
++
++static void maki_read_header(mi)
++    struct maki_info *mi;
++{
++    byte buf[16];
++
++    if(fread(buf, (size_t) 16, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_CORRUPT);
++
++    mi->fb_size  = (long)buf[ 0] << 8 | (long)buf[ 1];
++    mi->pa_size  = (long)buf[ 2] << 8 | (long)buf[ 3];
++    mi->pb_size  = (long)buf[ 4] << 8 | (long)buf[ 5];
++    mi->ext_flag = (long)buf[ 6] << 8 | (long)buf[ 7];
++    mi->x0       = (long)buf[ 8] << 8 | (long)buf[ 9];
++    mi->y0       = (long)buf[10] << 8 | (long)buf[11];
++    mi->x1       = (long)buf[12] << 8 | (long)buf[13];
++    mi->y1       = (long)buf[14] << 8 | (long)buf[15];
++
++    mi->width  = mi->x1-- - mi->x0;
++    mi->height = mi->y1-- - mi->y0;
++    mi->m_200  = mi->ext_flag & 1;
++    mi->m_dig8 = mi->ext_flag & 2;
++    mi->aspect = mi->m_200 ? 0.5 : 1.0;
++
++    if(DEBUG) maki_show_maki_info(mi);
++}
++
++static void maki_read_palette(mi, r, g, b)
++    struct maki_info *mi;
++    byte *r, *g, *b;
++{
++    byte buf[48], *p;
++
++    if(fread(buf, (size_t) 48, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_CORRUPT);
++
++    for(p = buf; p < &buf[48]; ){
++	*g++ = *p++;
++	*r++ = *p++;
++	*b++ = *p++;
++    }
++}
++
++static void maki_read_flags(mi)
++    struct maki_info *mi;
++{
++    mi->fa = maki_malloc((size_t) 1000       , "maki_read_flags#1");
++    mi->fb = maki_malloc((size_t) mi->fb_size, "maki_read_flags#2");
++
++    if(fread(mi->fa, (size_t) 1000, (size_t) 1, mi->fp) != 1)
++	maki_file_warning(mi, MAKI_CORRUPT);
++    if(fread(mi->fb, (size_t) mi->fb_size, (size_t) 1, mi->fp) != 1)
++	maki_file_warning(mi, MAKI_CORRUPT);
++}
++
++static void maki_read_pixel_data(mi)
++    struct maki_info *mi;
++{
++    mi->pa = maki_malloc((size_t) mi->pa_size, "maki_read_pixel_data#1");
++    mi->pb = maki_malloc((size_t) mi->pb_size, "maki_read_pixel_data#2");
++
++    if(fread(mi->pa, (size_t) mi->pa_size, (size_t) 1, mi->fp) != 1)
++	maki_file_warning(mi, MAKI_CORRUPT);
++    if(fread(mi->pb, (size_t) mi->pb_size, (size_t) 1, mi->fp) != 1)
++	maki_file_warning(mi, MAKI_CORRUPT);
++}
++
++static void maki_expand_virtual_screen(mi)
++    struct maki_info *mi;
++{
++    int x, y, fai, fbi;
++    int bpl = mi->width / 2 / 8;		/* bytes per line */
++    byte mask;
++    mi->vs = maki_malloc((size_t) bpl * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
++			 "maki_expand_virtual_screen");
++
++    fai = fbi = 0;
++    mask = 0x80;
++    for(y = 0; y < mi->height; y += 4){
++	for(x = 0; x < mi->width / 2; x += 4){
++	    if(mi->fa[fai] & mask){
++		byte bh, bl;
++		bh = mi->fb[fbi++];
++		bl = mi->fb[fbi++];
++		if(x % 8 == 0){
++		    mi->vs[ y      * bpl + x / 8] = H4(bh) << 4;
++		    mi->vs[(y + 1) * bpl + x / 8] = L4(bh) << 4;
++		    mi->vs[(y + 2) * bpl + x / 8] = H4(bl) << 4;
++		    mi->vs[(y + 3) * bpl + x / 8] = L4(bl) << 4;
++		}else{
++		    mi->vs[ y      * bpl + x / 8] |= H4(bh);
++		    mi->vs[(y + 1) * bpl + x / 8] |= L4(bh);
++		    mi->vs[(y + 2) * bpl + x / 8] |= H4(bl);
++		    mi->vs[(y + 3) * bpl + x / 8] |= L4(bl);
++		}
++	    }else{
++		if(x % 8 == 0){
++		    mi->vs[ y      * bpl + x / 8] = 0;
++		    mi->vs[(y + 1) * bpl + x / 8] = 0;
++		    mi->vs[(y + 2) * bpl + x / 8] = 0;
++		    mi->vs[(y + 3) * bpl + x / 8] = 0;
++		}else{
++/*		    mi->vs[ y      * bpl + x / 8] |= 0;
++		    mi->vs[(y + 1) * bpl + x / 8] |= 0;
++		    mi->vs[(y + 2) * bpl + x / 8] |= 0;
++		    mi->vs[(y + 3) * bpl + x / 8] |= 0; */
++		}
++	    }
++
++	    if((mask >>= 1) == 0){
++		mask = 0x80;
++		fai++;
++	    }
++	}
++    }
++}
++
++static void maki_expand_pixel_data(mi, pic)
++    struct maki_info *mi;
++    byte **pic;
++{
++    int x, y;
++    int vsi, pi, max_pi;
++    byte *p;
++    byte mask;
++    int gap;
++    *pic = maki_malloc((size_t) mi->width * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
++		       "maki_expand_pixel_data");
++
++    vsi = pi = 0;
++    p = mi->pa;
++    max_pi = mi->pa_size - 1;
++    mask = 0x80;
++    for(y = 0; y < mi->height; y++){
++	for(x = 0; x < mi->width; x += 2){
++	    if(mi->vs[vsi] & mask){
++		if(pi > max_pi){
++		    if(p == mi->pb)
++			maki_error(mi, MAKI_BAD_DATA);
++		    pi = 0;
++		    p = mi->pb;
++		    max_pi = mi->pb_size - 1;
++		}
++		(*pic)[y * mi->width + x    ] = H4(p[pi]);
++		(*pic)[y * mi->width + x + 1] = L4(p[pi]);
++		pi++;
++	    }else{
++		(*pic)[y * mi->width + x    ] = 0;
++		(*pic)[y * mi->width + x + 1] = 0;
++	    }
++
++	    if((mask >>= 1) == 0){
++		mask = 0x80;
++		vsi++;
++	    }
++	}
++    }
++
++    gap = mi->m_maki01b ? 4 : 2;
++
++    for(y = gap; y < mi->height; y++){
++	for(x = 0; x < mi->width; x++)
++	    (*pic)[y * mi->width + x] ^= (*pic)[(y - gap) * mi->width + x];
++    }
++}
++
++
++int WriteMAKI(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle)
++    FILE *fp;
++    byte *pic;
++    int ptype, w, h;
++    byte *rmap, *gmap, *bmap;
++    int numcols, colorstyle;
++{
++    byte rtemp[256], gtemp[256], btemp[256];
++    struct maki_info maki, *mi = &maki;
++    int e;
++
++    if(DEBUG) fputs("WriteMAKI:\n", stderr);
++
++    maki_init_info(&maki);
++    if((e = setjmp(maki.jmp)) != 0){
++	/* An error occurs */
++	maki_cleanup_maki_info(&maki, 1);
++	return -1;
++    }
++
++    if(w != 640 || h != 400) {
++        char  str[512];
++        sprintf(str,"MAKI: %s Should be 640x400", maki_msgs[MAKI_SIZE]);
++	ErrPopUp(str, "\nBummer!");
++	maki_error(mi, MAKI_SIZE);
++    }
++
++    maki.fp = fp;
++    maki.width = w;
++    maki.height = h;
++    maki.x1 = w - 1;
++    maki.y1 = h - 1;
++
++    if(ptype == PIC24){
++	if(!(pic = Conv24to8(pic, w, h, 16, rtemp, gtemp, btemp)))
++	    maki_memory_error("Conv24to8#1", "WriteMAKI");
++	rmap = rtemp;
++	gmap = gtemp;
++	bmap = btemp;
++    }else if(numcols > 16){
++	if(!(pic = Conv8to24(pic, w, h, rmap, gmap, bmap)))
++	    maki_memory_error("Conv8to24", "WriteMAKI");
++	if(!(pic = Conv24to8(pic, w, h, 16, rtemp, gtemp, btemp)))
++	    maki_memory_error("Conv24to8#2", "WriteMAKI");
++	rmap = rtemp;
++	gmap = gtemp;
++	bmap = btemp;
++    }else
++	maki.numcols = numcols;
++
++    maki_make_pixel_data(&maki, pic);
++    maki_make_virtual_screen(&maki);
++    maki_make_flags(&maki);
++    maki_write_check_id(&maki);
++    maki_write_comment(&maki);
++    maki_write_header(&maki);
++    maki_write_palette(&maki, rmap, gmap, bmap, colorstyle == F_GREYSCALE);
++    maki_write_flags(&maki);
++    maki_write_pixel_data(&maki);
++
++    maki_cleanup_maki_info(&maki, 1);
++    return 0;
++}
++
++static void maki_make_pixel_data(mi, pic)
++    struct maki_info *mi;
++    byte *pic;
++{
++    int x, y, i;
++    int nza, nzb;
++
++    mi->forma = maki_malloc((size_t) mi->width / 2 * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
++			    "maki_make_pixel_data#1");
++    mi->formb = maki_malloc((size_t) mi->width / 2 * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
++			    "maki_make_pixel_data#2");
++
++    for(y = 0; y < mi->height; y++){
++	for(x = 0; x < mi->width; x += 2){
++	    byte b;
++	    b = pic[y * mi->width + x] << 4 | pic[y * mi->width + x + 1];
++	    mi->forma[y * mi->width / 2 + x / 2] = b;
++	    mi->formb[y * mi->width / 2 + x / 2] = b;
++	}
++    }
++
++    for(y = mi->height - 1; y >= 2; y--){
++	for(x = 0; x < mi->width / 2; x++){
++	    mi->forma[y * mi->width / 2 + x] ^=
++		mi->forma[(y - 2) * mi->width / 2 + x];
++	}
++    }
++
++    for(y = mi->height - 1; y >= 4; y--){
++	for(x = 0; x < mi->width / 2; x++){
++	    mi->formb[y * mi->width / 2 + x] ^=
++		mi->formb[(y - 4) * mi->width / 2 + x];
++	}
++    }
++
++    nza = nzb = 0;
++    for(i = 0; i < mi->width / 2 * mi->height; i++){
++	if(mi->forma[i] != 0)
++	    nza++;
++	if(mi->formb[i] != 0)
++	    nzb++;
++    }
++    if(nza > nzb){
++	mi->m_maki01b = 1;
++	free(mi->forma);
++	mi->forma = NULL;
++    }else{
++	mi->m_maki01b = 0;
++	free(mi->formb);
++	mi->formb = NULL;
++    }
++}
++
++static void maki_make_virtual_screen(mi)
++    struct maki_info *mi;
++{
++    int bpl = mi->width / 2 / 8;
++    int vsi, pai, pbi, max_pai, max_pbi;
++    byte mask;
++    byte *pixels;
++    int x, y;
++
++    mi->vs = maki_malloc((size_t) bpl * mi->height,  // GRR POSSIBLE OVERFLOW / FIXME
++			 "maki_make_virtual_screen#1");
++
++    if(mi->m_maki01b)
++	pixels = mi->formb;
++    else
++	pixels = mi->forma;
++
++    vsi = pai = pbi = 0;
++    max_pai = max_pbi = -1;
++    mask = 0x80;
++    for(y = 0; y < mi->height; y++){
++	for(x = 0; x < mi->width / 2; x++){
++	    if(pixels[y * mi->width / 2 + x] == 0){
++		mi->vs[vsi] &= ~mask;
++	    }else{
++		mi->vs[vsi] |= mask;
++		if(y < 200){
++		    if(pai > max_pai){
++			max_pai += 1024;
++			mi->pa = maki_realloc(mi->pa, (size_t) max_pai + 1,
++					      "maki_make_virtual_screen#2");
++		    }
++		    mi->pa[pai++] = pixels[y * mi->width / 2 + x];
++		}else{
++		    if(pbi > max_pbi){
++			max_pbi += 1024;
++			mi->pb = maki_realloc(mi->pb, (size_t) max_pbi + 2,
++					      "maki_make_virtual_screen#3");
++		    }
++		    mi->pb[pbi++] = pixels[y * mi->width / 2 + x];
++		}
++	    }
++
++	    if((mask >>= 1) == 0){
++		mask = 0x80;
++		vsi++;
++	    }
++	}
++    }
++
++    mi->pa_size = pai;
++    mi->pb_size = pbi;
++}
++
++static void maki_make_flags(mi)
++    struct maki_info *mi;
++{
++    int bpl = mi->width / 2 / 8;
++    int fbi, max_fbi;
++    int fai;
++    int x, y;
++    byte mask;
++
++    mi->fa = maki_malloc((size_t) bpl * mi->height, "maki_make_flags#1");  // GRR POSSIBLE OVERFLOW / FIXME
++
++    fbi = fai = 0;
++    max_fbi = -1;
++    mask = 0x80;
++    for(y = 0; y < mi->height; y += 4){
++	for(x = 0; x < mi->width / 2; x += 4){
++	    if(x % 8 == 0){
++		if(H4(mi->vs[ y      * bpl + x / 8]) == 0 &&
++		   H4(mi->vs[(y + 1) * bpl + x / 8]) == 0 &&
++		   H4(mi->vs[(y + 2) * bpl + x / 8]) == 0 &&
++		   H4(mi->vs[(y + 3) * bpl + x / 8]) == 0){
++		    mi->fa[fai] &= ~mask;
++		}else{
++		    mi->fa[fai] |= mask;
++		    if(fbi + 1 > max_fbi){
++			max_fbi += 1024;
++			mi->fb = maki_realloc(mi->fb, (size_t) max_fbi + 1,
++					      "maki_make_flags#2");
++		    }
++		    mi->fb[fbi++] = H4(mi->vs[ y      * bpl + x / 8]) << 4
++				  | H4(mi->vs[(y + 1) * bpl + x / 8]);
++		    mi->fb[fbi++] = H4(mi->vs[(y + 2) * bpl + x / 8]) << 4
++				  | H4(mi->vs[(y + 3) * bpl + x / 8]);
++		}
++	    }else{
++		if(L4(mi->vs[ y      * bpl + x / 8]) == 0 &&
++		   L4(mi->vs[(y + 1) * bpl + x / 8]) == 0 &&
++		   L4(mi->vs[(y + 2) * bpl + x / 8]) == 0 &&
++		   L4(mi->vs[(y + 3) * bpl + x / 8]) == 0){
++		    mi->fa[fai] &= ~mask;
++		}else{
++		    mi->fa[fai] |= mask;
++		    if(fbi + 1 > max_fbi){
++			max_fbi += 1024;
++			mi->fb = maki_realloc(mi->fb, (size_t) max_fbi + 1,
++					      "maki_make_flags#3");
++		    }
++		    mi->fb[fbi++] = L4(mi->vs[ y      * bpl + x / 8]) << 4
++				  | L4(mi->vs[(y + 1) * bpl + x / 8]);
++		    mi->fb[fbi++] = L4(mi->vs[(y + 2) * bpl + x / 8]) << 4
++				  | L4(mi->vs[(y + 3) * bpl + x / 8]);
++		}
++	    }
++
++	    if((mask >>= 1) == 0){
++		mask = 0x80;
++		fai++;
++	    }
++	}
++    }
++
++    mi->fb_size = fbi;
++}
++
++static void maki_write_check_id(mi)
++    struct maki_info *mi;
++{
++    char *id = mi->m_maki01b ? maki_id_b : maki_id_a;
++    if(fwrite(id, (size_t) 8, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_WRITE);
++}
++
++static void maki_write_comment(mi)
++    struct maki_info *mi;
++{
++    char buf[24];
++    char *p;
++    int i = 0;
++
++    strcpy(buf, "XV   ");
++
++    if((p = (char *) getenv("USER")) == NULL)
++	p = "????????";
++    for(i = 5; i < 23; i++){
++	if(*p == '\0')
++	    break;
++	buf[i] = *p++;
++    }
++    for( ; i < 23; i++)
++	buf[i] = ' ';
++
++    buf[i] = '\032';	/* ^Z, 0x1a */
++
++    if(fwrite(buf, (size_t) 24, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_WRITE);
++}
++
++static void maki_write_header(mi)
++    struct maki_info *mi;
++{
++    byte buf[16];
++
++    if(DEBUG) maki_show_maki_info(mi);
++
++#define set_word(i, v) {buf[i]=(v)>>8&0xff;buf[i+1]=(v)&0xff;}
++    set_word(0, mi->fb_size);
++    set_word(2, mi->pa_size);
++    set_word(4, mi->pb_size);
++    set_word(6, mi->ext_flag);
++    set_word(8, mi->x0);
++    set_word(10, mi->y0);
++    set_word(12, mi->x1 + 1);
++    set_word(14, mi->y1 + 1);
++#undef set_word
++
++    if(fwrite(buf, (size_t) 16, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_WRITE);
++}
++
++static void maki_write_palette(mi, r, g, b, grey)
++    struct maki_info *mi;
++    byte *r, *g, *b;
++    int grey;
++{
++    int i;
++    char buf[3];
++    for(i = 0; i < mi->numcols; i++){
++	buf[0] = *g++;
++	buf[1] = *r++;
++	buf[2] = *b++;
++	if(grey)
++	    buf[0] = buf[1] = buf[2] = MONO(buf[1], buf[0], buf[2]);
++	if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1)
++	    maki_file_error(mi, MAKI_WRITE);
++    }
++    for( ; i < 16; i++){
++	if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1)
++	    maki_file_error(mi, MAKI_WRITE);
++    }
++}
++
++static void maki_write_flags(mi)
++    struct maki_info *mi;
++{
++    int bpl = mi->width / 2 / 8;
++    if(fwrite(mi->fa, (size_t) bpl * mi->height / 16, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_WRITE);
++
++    if(fwrite(mi->fb, (size_t) mi->fb_size, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_WRITE);
++}
++
++static void maki_write_pixel_data(mi)
++    struct maki_info *mi;
++{
++    if(fwrite(mi->pa, (size_t) mi->pa_size, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_WRITE);
++
++    if(fwrite(mi->pb, (size_t) mi->pb_size, (size_t) 1, mi->fp) != 1)
++	maki_file_error(mi, MAKI_WRITE);
++}
++
++
++
++static void maki_init_info(mi)
++    struct maki_info *mi;
++{
++    xvbzero((char *)mi, sizeof(struct maki_info));
++    mi->fp = NULL;
++    mi->fsize = 0;
++    mi->x0 = mi->y0 = mi->x1 = mi->y1 = 0;
++    mi->width = mi->height = 0;
++    mi->aspect = 1.0;
++    mi->fb_size = mi->pa_size = mi->pb_size = 0;
++    mi->m_maki01b = mi->m_200 = mi->m_dig8 = 0;
++    mi->ext_flag = 0;
++    mi->fa = mi->fb = mi->pa = mi->pb = NULL;
++    mi->vs = NULL;
++    mi->numcols = 16;
++    mi->forma = mi->formb = NULL;
++}
++
++static void maki_cleanup_maki_info(mi, writing)
++    struct maki_info *mi;
++    int writing;
++{
++    if(mi->fp && !writing)
++	fclose(mi->fp);
++    if(mi->fa)
++	free(mi->fa);
++    if(mi->fb)
++	free(mi->fb);
++    if(mi->pa)
++	free(mi->pa);
++    if(mi->pb)
++	free(mi->pb);
++    if(mi->vs)
++	free(mi->vs);
++    if(mi->forma)
++	free(mi->forma);
++    if(mi->formb)
++	free(mi->formb);
++}
++
++static void maki_cleanup_pinfo(pi)
++    PICINFO *pi;
++{
++    if(pi->pic){
++	free(pi->pic);
++	pi->pic = NULL;
++    }
++}
++
++static void maki_memory_error(scm, fn)
++    char *scm, *fn;
++{
++    char buf[128];
++    sprintf(buf, "%s: coulndn't allocate memory. (%s)", scm, fn);
++    FatalError(buf);
++}
++
++static void maki_error(mi, mn)
++    struct maki_info *mi;
++    int mn;
++{
++    SetISTR(ISTR_WARNING, "%s", maki_msgs[mn]);
++    longjmp(mi->jmp, 1);
++}
++
++static void maki_file_error(mi, mn)
++    struct maki_info *mi;
++    int mn;
++{
++    if(feof(mi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", maki_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", maki_msgs[mn], ERRSTR(errno));
++    longjmp(mi->jmp, 1);
++}
++
++static void maki_file_warning(mi, mn)
++    struct maki_info *mi;
++    int mn;
++{
++    if(feof(mi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", maki_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", maki_msgs[mn], ERRSTR(errno));
++}
++
++static void maki_show_maki_info(mi)
++    struct maki_info *mi;
++{
++    fprintf(stderr, "  file size: %ld.\n", mi->fsize);
++    fprintf(stderr, "  image size: %dx%d.\n", mi->width, mi->height);
++    fprintf(stderr, "  aspect: %f.\n", mi->aspect);
++    fprintf(stderr, "  flag B size: %ld.\n", mi->fb_size);
++    fprintf(stderr, "  pixel data size: A:%ld, B:%ld.\n",
++	    mi->pa_size, mi->pb_size);
++    fprintf(stderr, "  MAKI01B: %s.\n", mi->m_maki01b ? "true" : "false");
++    fprintf(stderr, "  200 line mode: %s.\n", mi->m_200 ? "true" : "false");
++    fprintf(stderr, "  digital 8 colors: %s.\n", mi->m_dig8 ? "true" : "false");
++}
++
++static void *maki_malloc(n, fn)
++    size_t n;
++    char *fn;
++{
++    void *r = (void *) malloc(n);
++    if(r == NULL)
++	maki_memory_error("malloc", fn);
++    return r;
++}
++
++static void *maki_realloc(p, n, fn)
++    void *p;
++    size_t n;
++    char *fn;
++{
++    void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n);
++    if(r == NULL)
++	maki_memory_error("realloc", fn);
++    return r;
++}
++#endif /* HAVE_MAKI */
+diff -Naru xv-3.10a/xvmgcsfx.c xv-3.10a.jumbo/xvmgcsfx.c
+--- xv-3.10a/xvmgcsfx.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvmgcsfx.c	2007-04-16 00:02:32.000000000 +0200
+@@ -0,0 +1,2276 @@
++/*
++ * $Id: xvmgcsfx.c,v 1.23 95/11/27 19:03:36 tin329 Exp Locker: tin329 $
++ * xvmgcsfx.c - Use the filters as input and output method.
++ *
++ * Features
++ * ========
++ * Use the filters as input and output method for load and save unsupported
++ * image format file. The filter command is recognized by definition of
++ * magic number or suffix in "~/.xv_mgcsfx" .
++ *
++ * Bugs
++ * ====
++ * There are many bugs.
++ * Let's go hunting for insects with an insect net. (it's all joke.)
++ *
++ * Author
++ * ======
++ * Tetsuya INOUE  <tin329 at chino.it.okayama-u.ac.jp>
++ */
++
++/*
++ * Known Bugs and Todo  /  $B$"$l$3$l5$$K$J$k$3$H(B
++ *
++ *  ~/.xv_mgcsfx $BFb(B
++ *    $B!&Dj5A$,IT40A4$@$H%(%i!<(B (':'$B$N?t(B)$B!#(B
++ *    $B!&%G%j%_%?$H$7$F(B ':' $B$r;H$&$N$G!"%9%?!<%H%"%C%W%U%!%$%kFb$G(B
++ *      ':' $B$rMQ$$$FDj5A$O$G$-$J$$!#(B'\:'$B$G$b%@%a!#(B
++ *    $B!&(B magic $B%?%$%W$G!"#8?J?t$O#37eJ,#0!A#7$rD4$Y!"#1#6?J?t$O(B
++ *       isxdigit $B$,??$rJV$94VCf=hM}$5$l$k!#$7$+$7!"#1#b#y#t#e$H(B
++ *       $B$7$F$7$+I>2A$5$l$J$$!#(B
++ *    $B!&%W%j%W%m%;%C%5$r;H$&$H$-$O!"%3%a%s%H$N=q$-J}$KCm0U$7$J$1$l$P$J(B
++ *        $B$i$J$$!#%W%j%W%m%;%C%5$K$h$C$F$O%3%a%s%H$,%(%i!<$K$J$k!#(B
++ *    $B!&%Q%$%W$X$NF~=PNO$N%U%)!<%^%C%H$N<oN`$,(B PNM $B$N$_(B
++ *        $BF~NO(B
++ *            $B%U%!%$%k%]%$%s%?$r(B seek $B$7$F$O$$$1$J$$(B
++ *            $B%U%!%$%k%5%$%:$rMQ$$$F$O$$$1$J$$(B
++ *        $B=PNO(B
++ *            $B%U%!%$%k%]%$%s%?$r(B seek $B$7$F$O$$$1$J$$(B
++ *            exec $B$G$-$J$/$F=*N;$7$?%W%m%;%9$K=q$-9~$_IT2D(B
++ *    $B!&%5%U%#%C%/%9$H%^%8%C%/%J%s%P!<$N;H$$J,$1$r$I$&$9$k$+!#(B
++ *        $B%^%8%C%/%J%s%P!<$,F1$8$G!"%5%U%#%C%/%9$,0[$J$k>l9g$rG'$a$k$+!)(B
++ *    $B!&(Bcompress(gzip)$B$N%U%!%$%k$O%F%s%]%i%j$G$O(B xvtmp??? $B$H$$$&L>A0$J(B
++ *      $B$N$G(B suffix $B$G$O<1JL$G$-$J$$!#(B
++ *
++ *  $BG'<1$9$k;~$K(B MACBINARY $B$K$OIi$1$k(B(in xv.c)$B!#(B
++ *
++ *  $BB?=E$K(B pipe $B$rDL$9$3$H$,$G$-$J$$!#(B(pipe $B$,(B seek $B$G$-$J$$$+$i(B)
++ *    $B!&(Bsocketpair $B$G!"(Brecv $B$K(B MSG_PEEK $B%U%i%0$r$D$+$C$F6uFI$_$9$k!#(B
++ *    $B!&$3$l$r$d$k$H%U%!%$%k$NG'<1$,$a$A$c$a$A$cCY$/$J$k!#(B
++ *
++ *  $B%j%=!<%9$G at _Dj(B
++ *    $B!&%j%=!<%9$G at _Dj$9$kJ}$,LLE]$/$5$$(B
++ *
++ *  $B%^%8%C%/%J%s%P!<$N at _Dj$K at 55,I=8=(B
++ *
++ *  $B%;!<%VMQ%W%m%;%9$,<:GT$9$k>l9g$NBP:v$,:#0l$D(B
++ *
++ *  DEC OSF/1 V3.0 $B$G$O!"%Q%$%W$K%G!<%?$,$^$@$J$$;~$KFI$_9~$b$&$H$9$k$H!"(B
++ *  read $B$,IT40A4$K$J$k!#(B(in xvpbm.c)
++ *  $BF1MM$K=q$-9~$_;~$K$bLdBj$, at 8$8$k$+$b$7$l$J$$!#(B
++ */
++
++#define  NEEDSDIR               /* for stat() */
++#include "xv.h"
++
++
++#ifdef HAVE_MGCSFX
++
++
++#ifdef __osf__
++#  ifdef __alpha
++#    define ARCHITECTURE64 1
++#  endif /* __alpha */
++#endif /* __osf__ */
++
++#ifdef ARCHITECTURE64
++typedef short int16;
++typedef int   int32;
++typedef long  int64;
++#else
++typedef short int16;
++typedef long  int32;
++#endif /* ARCHITECTURE64 */
++
++#ifdef sgi
++#  define vfork fork
++#endif
++
++#define USE_SIGCHLD
++#if 0
++#  undef  USE_SIGCHLD
++#endif
++
++#ifdef USE_SIGCHLD
++#  include <sys/wait.h>
++#endif
++
++typedef struct _mgcsfxtab
++{
++  struct _mgcsfxtab *next;
++  char              *description;
++  int                mgcsfx_type;
++  int                offset;
++  union{
++    int16            int16_data;
++    int32            int32_data;
++    char            *string_data;
++  }                  dt;
++  int                string_len;
++  char              *suffix;
++  int                input_image_type;
++  char              *input_command;
++  int                output_image_type;
++  char              *output_command;
++} mgcsfxtab;
++
++
++#ifndef MGCSFXDIR
++#  define MGCSFXDIR       "/usr/local/lib"
++#endif
++#ifndef SYSCONFDIR
++#  define SYSCONFDIR      MGCSFXDIR
++#endif
++#ifndef MGCSFX_SITE_RC
++#  define MGCSFX_SITE_RC  "xv_mgcsfx"
++#endif
++#ifndef MGCSFX_RC
++#  define MGCSFX_RC       ".xv_mgcsfx"
++#endif
++
++#ifdef USE_MGCSFX_PREPROCESSOR
++#  ifndef MGCSFX_PREPROCESSOR
++#    define MGCSFX_PREPROCESSOR "/usr/lib/cpp"
++#  endif
++#endif
++
++
++/* Check type for Magic number and Suffix */
++enum {T_UNKNOWN,
++      T_MAGIC, T_SUFFIX,
++      T_BEINT16, T_BEINT32, T_BEINT64,
++      T_LEINT16, T_LEINT32, T_LEINT64};
++
++/* Image Type for input and output format */
++enum {IT_UNKNOWN,
++#ifdef HAVE_MGCSFX_AUTO
++      IT_AUTO,
++#endif /* HAVE_MGCSFX_AUTO */
++      IT_PNM, IT_PPM, IT_PGM, IT_PBM,
++      IT_PNM_RAW, IT_PPM_RAW, IT_PGM_RAW, IT_PBM_RAW,
++      IT_PNM_ASCII, IT_PPM_ASCII, IT_PGM_ASCII, IT_PBM_ASCII,
++      IT_GIF, IT_JPEG, IT_TIFF, IT_JFIF, /* IT_PS, IT_COMPRESS,*/
++      IT_XBM, IT_XPM, IT_BMP, IT_SUNRAS, IT_IRIS, IT_XWD,
++      /* IT_TARGA, IT_FITS, IT_PM, IT_UTAHRLE, IT_PCX, IT_PDSVICAR, IT_IFF, */
++      IT_MAG, IT_MAKI, IT_PI, IT_PIC, IT_PIC2 /* , IT_PCD */};
++
++
++/*--------------------------------------------------------------------------*/
++void  mgcsfx_handler        PARM((int));
++void  mgcsfx_handler_setup  PARM((void));
++
++#ifdef USE_MGCSFX_PREPROCESSOR
++static char      *get_tmp_fname          PARM((void));
++static char      *make_preprocessed_file PARM((char *));
++#endif /* USE_MGCSFX_PREPROCESSOR */
++
++int   is_mgcsfx             PARM((char *, unsigned char *, int));
++
++char *mgcsfx_auto_input_com PARM((char *));
++
++
++static mgcsfxtab *free_mgcsfx PARM((mgcsfxtab *));
++static char      *fgettoken   PARM((FILE*, int));
++static int        string_fin  PARM((char *));
++static int        type_mgcsfx PARM((char *));
++static int        type_image  PARM((char *));
++
++static void       read_mgcsfx PARM((mgcsfxtab **, char *));
++static void       init_mgcsfx PARM((void));
++static mgcsfxtab *find_mgcsfx PARM((char *, unsigned char *, int));
++
++int   LoadMGCSFX            PARM((char *, PICINFO *));
++
++#ifdef SVR4
++typedef void Sigfunc(int);
++static Sigfunc   *xv_signal   PARM((int , Sigfunc *));
++#endif
++
++/*--------------------------------------------------------------------------*/
++mgcsfxtab *mgcsfx_table = NULL;
++int       mgcsfx_setup_flag = 0;
++
++int       nitem_mgcsfx = 0;
++int       desc_width = 0;
++
++int       max_offset_mgcsfx = 0;
++int       max_length_mgcsfx = 0;
++int       need_buf_size = 0;
++
++static char input_command_ex[1024];
++static int  input_command_ex_flag = 0;
++
++#ifdef USE_SIGCHLD
++static int  w_p_fail=0;
++#endif
++
++/*--------------------------------------------------------------------------*/
++
++/***************************************************/
++void mgcsfx_handler(sig)
++     int sig;
++{
++#ifdef USE_SIGCHLD
++  int pid, pst;
++#endif
++
++#if defined(SYSV) || defined(SVR4)
++  sighold(sig);
++#else
++  sigblock(sigmask(sig));
++#endif
++
++#ifdef USE_SIGCHLD
++  if(w_p_fail == 1){
++    /*
++     * At this point, process write to broken pipe.
++     * Probably external command was can't exec.
++     */
++    w_p_fail = 2;
++    pid = wait(&pst);
++  }
++#endif
++
++  return;
++
++  /* Quit(1); */ /*exit(1);*/
++}
++
++void mgcsfx_handler_setup()
++{
++#ifdef SVR4
++  xv_signal(SIGPIPE, (void (*)PARM((int))) mgcsfx_handler);
++  xv_signal(SIGCHLD, (void (*)PARM((int))) mgcsfx_handler);
++#else
++# ifdef SYSV
++  sigset(SIGPIPE, (void (*)PARM((int))) mgcsfx_handler);
++  sigset(SIGCHLD, (void (*)PARM((int))) mgcsfx_handler);
++# else
++  signal(SIGPIPE, (void (*)PARM((int))) mgcsfx_handler);
++  signal(SIGCHLD, (void (*)PARM((int))) mgcsfx_handler);
++# endif
++#endif
++}
++
++/***************************************************/
++#ifdef USE_MGCSFX_PREPROCESSOR
++static char *get_tmp_fname()
++{
++  static char tmp[MAXPATHLEN+1];
++
++#ifndef VMS
++  sprintf(tmp, "%s/xvmgcsfxXXXXXX",tmpdir);
++#else
++  /* sprintf(tmp, "Sys$Scratch:xvmgcsfxXXXXXX"); */
++  strcpy(tmp, "[]xvmgcsfxXXXXXX");
++#endif /* VMS */
++
++#ifdef USE_MKSTEMP
++  close(mkstemp(tmp));
++#else
++  mktemp(tmp);
++#endif
++
++  return tmp;
++}
++
++static char *make_preprocessed_file(fname)
++     char *fname;
++{
++  char buf[512];
++  char *tmp_name;
++
++  tmp_name = get_tmp_fname();
++
++#ifndef VMS
++  sprintf(buf,"%s %s > %s", MGCSFX_PREPROCESSOR, fname, tmp_name);
++#else
++  sprintf(buf,"%s %s > %s", MGCSFX_PREPROCESSOR, fname, tmp_name); /* really OK? */
++#endif
++
++  SetISTR(ISTR_INFO, "Preprocessing '%s'...", BaseName(fname));
++#ifndef VMS
++  if (system(buf))
++#else
++  if (!system(buf))
++#endif
++  {
++    SetISTR(ISTR_INFO, "Unable to preprocess '%s'.", BaseName(fname));
++    Warning();
++    return NULL;
++  }
++
++  return tmp_name;
++}
++#endif /* USE_MGCSFX_PREPROCESSOR */
++
++/***************************************************/
++/* $BG'<1$G$-$k%U%!%$%k$+$I$&$+D4$Y$k(B */
++int is_mgcsfx(fname,buffer,size)
++     char          *fname;
++     unsigned char *buffer;
++     int            size;
++{
++  mgcsfxtab          *magic;
++  FILE               *fp;
++  unsigned char      *buf;
++  int                 s;
++
++  if(nomgcsfx){
++    return 0;
++  }else{
++    if(size < need_buf_size){
++      if((buf = (unsigned char *)calloc(need_buf_size, sizeof(char)))==NULL){
++	fprintf(stderr,"Can't allocate memory\n");
++	return 0;
++      }
++      if((fp = xv_fopen(fname, "r"))==NULL){
++	fprintf(stderr,"Can't open file %s\n", fname);
++	free(buf);
++	return 0;
++      }
++      s = fread(buf, 1, need_buf_size, fp);
++      if((magic = find_mgcsfx(fname, buf, s))!=NULL &&
++	magic->input_command != NULL){
++	free(buf);
++	fclose(fp);
++	return 1;
++      }else{
++	free(buf);
++	fclose(fp);
++	return 0;
++      }
++    }else{
++      if((magic = find_mgcsfx(fname, buffer, size))!=NULL &&
++	magic->input_command != NULL){
++	return 1;
++      }else{
++	return 0;
++      }
++    }
++  }
++}
++
++#ifdef HAVE_MGCSFX_AUTO
++char *mgcsfx_auto_input_com(fname)
++char *fname;
++{
++  static char command[1024];
++  mgcsfxtab       *magic;
++  char *ptr;
++
++  FILE *fp;
++  unsigned char *buf;
++  int                 s;
++
++  if((buf = (unsigned char *)calloc(need_buf_size, sizeof(char)))==NULL){
++    fprintf(stderr,"Can't allocate memory\n");
++    return NULL;
++  }
++  if((fp = xv_fopen(fname, "r"))==NULL){
++    fprintf(stderr,"Can't open file %s\n", fname);
++    free(buf);
++    return NULL;
++  }
++  s = fread(buf, 1, need_buf_size, fp);
++  if((magic = find_mgcsfx(fname, buf, s))!=NULL &&
++     magic->input_command != NULL && magic->input_image_type == IT_AUTO){
++    if ((ptr = strstr(magic->input_command, "%s"))){
++      sprintf(command, magic->input_command, fname);
++    }else{
++      sprintf(command, "%s < %s", magic->input_command, fname);
++    }
++    free(buf);
++    fclose(fp);
++    return command;
++  }else{
++    free(buf);
++    fclose(fp);
++    return NULL;
++  }
++}
++#endif /* HAVE_MGCSFX_AUTO */
++
++/***************************************************/
++static mgcsfxtab *free_mgcsfx(m)
++     mgcsfxtab *m;
++{
++  mgcsfxtab *next;
++  if(m == NULL) return NULL;
++  next = m->next;
++  if(m->description != NULL) free(m->description);
++  if(m->mgcsfx_type == T_MAGIC && m->dt.string_data != NULL)
++    free(m->dt.string_data);
++  if(m->suffix != NULL) free(m->suffix);
++  if(m->input_command != NULL) free(m->input_command);
++  if(m->output_command != NULL) free(m->output_command);
++  free(m);
++  return next;
++}
++
++
++
++/***************************************************/
++/* char c $B$^$?$O(B '\n' $B$G6h at Z$i$l$?J8;zNs$r<h$j=P$9(B
++ *  $B%U%!%$%k$N:G8e$^$GFI$s$@$i(B NULL $B$rJV$9(B
++ *  $B2~9T$J$i2~9T$rJV$9(B($B2~9T$G6h at Z$i$l$?>l9g$O(B '\n' $B$r%9%H%j!<%`$KLa$9(B)
++ */
++#define CBUF_SIZE 1024
++static char *fgettoken(fp, c)
++     FILE *fp;
++     int   c; /* Real mean is char */
++{
++  char *buf;
++  char *buf2;
++  int   i;
++  int   n=0;
++  int   max=0;
++  int   count = 1;
++
++  char *ss;
++  char *se;
++
++  if((buf = (char *)calloc(CBUF_SIZE, sizeof(char))) == NULL){
++    fprintf(stderr,"Can't allocate memory\n");
++    exit(1);
++  }
++  max = CBUF_SIZE;
++  count = 2;
++
++  do{
++    if((i = getc(fp))==EOF || i == '\n' || i == c) break;
++
++    buf[n] = (char)i;
++
++    if(i != c && n == max-1){
++      buf[max] = '\0';
++      if((buf2 = (char *)calloc(CBUF_SIZE * count, sizeof(char))) == NULL){
++	fprintf(stderr,"Can't allocate memory\n");
++	exit(1);
++      }
++      strcpy(buf2, buf);
++      free(buf);
++      buf = buf2;
++      buf2 = NULL;
++      max = CBUF_SIZE * count;
++      count++;
++    }
++
++    n++;
++  }while(i != c);
++
++  buf[n] = '\0';
++
++  /* $B:G=i$H:G8e$N6uGrJ8;z$r at Z$j5M$a$k(B */
++  ss = buf + strspn(buf, " \t\b\r\n"); /* find the first non-white space */
++  se = buf + strlen(buf);              /* find the end of the string */
++
++  /* strip from the end first */
++  while ((--se >= ss) && strchr(" \t\b\r\n", *se));
++  *(++se) = '\0';
++
++  if(i == EOF && strlen(ss)==0){        /* EOF $B$J$i(B NULL $B$rJV$9(B */
++    free(buf);
++    return NULL;
++  }else if(i == '\n' && strlen(ss)==0){ /* $B2~9T$N$_$N>l9g(B */
++    static char cr[2] = {'\n','\0'};
++    buf2 = strdup(cr);
++    free(buf);
++    return buf2;
++  }else{                                /* $BDL>o(B */
++    if(i == '\n' && strlen(ss)>0) ungetc(i,fp);
++    buf2 = strdup(ss);
++    free(buf);
++    return buf2;
++  }
++}
++
++
++
++/***************************************************/
++/* $BJ8;zNsCf$NFC<l5-9f(B(\)$B$r at 5$7$$$b$N$K$9$k(B
++ */
++static int string_fin(string_data)
++     char *string_data;
++{
++  char *cptr;
++  char *ptr;
++  int   length;
++
++  /* Change all the \xx sequences into a single character */
++  cptr = string_data;
++
++  for (ptr = cptr; *ptr; ++ptr){
++    if (*ptr != '\\'){
++      *cptr = *ptr;
++    }else{
++      switch (*(++ptr)){
++#if defined(__STDC__)
++      case 'a': /* Audible alert (terminal bell) */
++	*cptr = '\007';
++	break;
++      case '?': /* Question mark */
++	*cptr = '\?';
++	break;
++#endif
++      case 'b': /* Backspace */
++	*cptr = '\b';
++	break;
++      case 'f': /* Form feed */
++	*cptr = '\f';
++	break;
++      case 'n': /* Line feed */
++	*cptr = '\n';
++	break;
++      case 'r': /* Carriage return */
++	*cptr = '\r';
++	break;
++      case 't': /* Horizontal tab */
++	*cptr = '\t';
++	break;
++      case 'v': /* Vertical tab */
++	*cptr = '\v';
++	break;
++      case '\\': /* Backslash */
++	*cptr = '\\';
++	break;
++      case '\'': /* Single quote */
++	*cptr = '\'';
++	break;
++      case '"': /* Double quote */
++	*cptr = '\"';
++	break;
++      case '0': /* Octal constant  \0 ... \377 */
++      case '1':
++      case '2':
++      case '3':
++      case '4':
++      case '5':
++      case '6':
++      case '7':
++	if ((ptr[1] >= '0') && (ptr[1] <= '7')){
++	  if ((ptr[2] >= '0') && (ptr[2] <= '7')){ /* \000 ...\377 */
++	    *cptr = ((*ptr - '0') * 64) +((ptr[1] - '0') * 8) +(ptr[1] - '0');
++	    ptr += 2;
++	  }else{ /* \00 ...\77 */
++	    *cptr = ((*ptr - '0') * 8) + (ptr[1] - '0');
++	    ++ptr;
++	  }
++	}else{ /* \0 ...\7 */
++	  *cptr = *ptr - '0';
++	}
++	break;
++      case 'x': /* Hexadecimal constant  \x0 .. \xff */
++	if (isxdigit (ptr[1])){
++	  *cptr = 0;
++	  while (isxdigit (*(++ptr)))
++	    *cptr = (*cptr * 16) +
++	      (*ptr > '9' ? tolower (*ptr) - ('a' - 10) : *ptr - '0');
++	  --ptr;
++	  break;
++	}
++      default:
++	/*  *(cptr++) = '\\';  No use for treat '\z' as 'z' */
++	*cptr = *ptr;
++	break;
++      }
++    }
++    ++cptr;
++  }
++  *cptr = '\0';
++  length = cptr - string_data;
++  return length;
++}
++
++/***************************************************/
++static int type_mgcsfx(str)
++     char *str;
++{
++  if(str == NULL){
++    return T_UNKNOWN;
++  }else if(!strcmp(str, "magic")   || !strcmp(str, "MAGIC")){
++    return T_MAGIC;
++  }else if(!strcmp(str, "string")  || !strcmp(str, "STRING")){
++    return T_MAGIC;
++  }else if(!strcmp(str, "suffix")  || !strcmp(str, "SUFFIX")){
++    return T_SUFFIX;
++  }else if(!strcmp(str, "beint16") || !strcmp(str, "BEINT16")){
++    return T_BEINT16;
++  }else if(!strcmp(str, "leint16") || !strcmp(str, "LEINT16")){
++    return T_LEINT16;
++  }else if(!strcmp(str, "beint32") || !strcmp(str, "BEINT32")){
++    return T_BEINT32;
++  }else if(!strcmp(str, "leint32") || !strcmp(str, "LEINT32")){
++    return T_LEINT32;
++  }else{
++    return T_UNKNOWN;
++  }
++}
++
++/***************************************************/
++static int type_image(str)
++     char *str;
++{
++  if(str == NULL){
++    return IT_UNKNOWN;
++#ifdef HAVE_MGCSFX_AUTO
++  }else if(!strcmp(str, "auto") || !strcmp(str, "AUTO")){
++    return IT_AUTO;
++#endif /* HAVE_MGCSFX_AUTO */
++  }else if(!strcmp(str, "pnm") || !strcmp(str, "PNM")){
++    return IT_PNM;
++  }else if(!strcmp(str, "ppm") || !strcmp(str, "PPM")){
++    return IT_PPM;
++  }else if(!strcmp(str, "pgm") || !strcmp(str, "PGM")){
++    return IT_PGM;
++  }else if(!strcmp(str, "pbm") || !strcmp(str, "PBM")){
++    return IT_PBM;
++  }else if(!strcmp(str, "pnm_raw") || !strcmp(str, "PNM_RAW")){
++    return IT_PNM_RAW;
++  }else if(!strcmp(str, "ppm_raw") || !strcmp(str, "PPM_RAW")){
++    return IT_PPM_RAW;
++  }else if(!strcmp(str, "pgm_raw") || !strcmp(str, "PGM_RAW")){
++    return IT_PGM_RAW;
++  }else if(!strcmp(str, "pbm_raw") || !strcmp(str, "PBM_RAW")){
++    return IT_PBM_RAW;
++  }else if(!strcmp(str, "pnm_ascii") || !strcmp(str, "PNM_ASCII")){
++    return IT_PNM_ASCII;
++  }else if(!strcmp(str, "ppm_ascii") || !strcmp(str, "PPM_ASCII")){
++    return IT_PPM_ASCII;
++  }else if(!strcmp(str, "pgm_ascii") || !strcmp(str, "PGM_ASCII")){
++    return IT_PGM_ASCII;
++  }else if(!strcmp(str, "pbm_ascii") || !strcmp(str, "PBM_ASCII")){
++    return IT_PBM_ASCII;
++
++  }else if(!strcmp(str, "gif")  || !strcmp(str, "GIF")){
++    return IT_GIF;
++  }else if(!strcmp(str, "jpeg") || !strcmp(str, "JPEG")){
++    return IT_JPEG;
++  }else if(!strcmp(str, "tiff") || !strcmp(str, "TIFF")){
++    return IT_TIFF;
++  }else if(!strcmp(str, "jfif") || !strcmp(str, "JFIF")){
++    return IT_JFIF;
++
++  }else if(!strcmp(str, "xbm") || !strcmp(str, "XBM")){
++    return IT_XBM;
++  }else if(!strcmp(str, "xpm") || !strcmp(str, "XPM")){
++    return IT_XPM;
++  }else if(!strcmp(str, "bmp") || !strcmp(str, "BMP")){
++    return IT_BMP;
++  }else if(!strcmp(str, "sunras") || !strcmp(str, "SUNRAS")){
++    return IT_SUNRAS;
++  }else if(!strcmp(str, "iris") || !strcmp(str, "IRIS")){
++    return IT_IRIS;
++  }else if(!strcmp(str, "xwd") || !strcmp(str, "XWD")){
++    return IT_XWD;
++
++  }else if(!strcmp(str, "mag") || !strcmp(str, "MAG")){
++    return IT_MAG;
++  }else if(!strcmp(str, "maki") || !strcmp(str, "MAKI")){
++    return IT_MAKI;
++  }else if(!strcmp(str, "pi") || !strcmp(str, "PI")){
++    return IT_PI;
++  }else if(!strcmp(str, "pic") || !strcmp(str, "PIC")){
++    return IT_PIC;
++  }else if(!strcmp(str, "pic2") || !strcmp(str, "PIC2")){
++    return IT_PIC2;
++
++  }else{
++    return IT_UNKNOWN;
++  }
++}
++
++/*--------------------------------------------------------------------------*/
++#define mgcsfx_read_error(FILENAME, LINENUM, AFTERFIELD) \
++fprintf (stderr,\
++"%s: line %d: missing fields of %s field\n",\
++FILENAME, LINENUM, AFTERFIELD);
++
++#define magic_type_error(FILENAME, LINENUM, MAGICNUMBER) \
++fprintf (stderr,\
++"%s: line %d: invalid <magic type> field '%s'\n",\
++FILENAME, LINENUM, MAGICNUMBER);
++/*--------------------------------------------------------------------------*/
++
++/***************************************************/
++static void read_mgcsfx(mgcsfx_table, fname)
++     mgcsfxtab **mgcsfx_table;
++     char       *fname;
++{
++  FILE *fp;
++  char *s;
++  int   line_number = 0;
++  int   str_len;
++  int   reach_end;
++  int   def_err;
++
++  char *description;
++  char *mgcsfx_type;
++  char *offset;
++  char *magic;
++  char *suffix;
++  char *i_img;
++  char *i_com;
++  char *o_img;
++  char *o_com;
++
++  mgcsfxtab  *ent;
++  mgcsfxtab **entry;
++
++
++  if((fp=fopen(fname, "r"))==NULL){
++    /* fprintf(stderr, "Can't open %s\n",fname); */
++    return;
++  }
++
++  while(1){
++retry:
++    line_number++;
++    def_err = 0;
++
++    s= NULL;
++    description = mgcsfx_type = offset = magic = suffix
++      = i_img = i_com = o_img = o_com = NULL;
++    reach_end = 0;
++
++    if((s = fgettoken(fp, ':'))==NULL) break; /* EOF $B$J$i=*$j(B */
++    if(*s == '#'){/* $B at hF,$,(B '#' $B$J$iFI$_$H$P$9(B */
++      while((s = fgettoken(fp, '\n'))!=NULL){
++	if(*s == '\n'){
++	  free(s);
++	  goto retry;
++	}
++	free(s);
++      }
++      if(s == NULL) break;
++    }else if(*s == '\n'){/* $B6u9T$OL5;k(B */
++      free(s);
++      goto retry;
++    }
++    if(strlen(s) > 0) description = s;
++    else free(s);
++
++    if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++      if(s != NULL) free(s);
++      mgcsfx_read_error(fname, line_number, "data type");
++      goto next;
++    }
++    if(strlen(s) > 0) mgcsfx_type = s;
++    else free(s);
++
++    if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++      if(s != NULL) free(s);
++      mgcsfx_read_error(fname, line_number, "byte offset");
++      goto next;
++    }
++    if(strlen(s) > 0) offset = s;
++    else free(s);
++
++    if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++      if(s != NULL) free(s);
++      mgcsfx_read_error(fname, line_number, "magic number");
++      goto next;
++    }
++    if(strlen(s) > 0) magic = s;
++    else free(s);
++
++    if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++      if(s != NULL) free(s);
++      mgcsfx_read_error(fname, line_number, "suffix");
++      goto next;
++    }
++    if(strlen(s) > 0) suffix = s;
++    else free(s);
++
++    if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++      if(s != NULL) free(s);
++      mgcsfx_read_error(fname, line_number, "input image type");
++      goto next;
++    }
++    if(strlen(s) > 0) i_img = s;
++    else free(s);
++
++    if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++      if(s != NULL) free(s);
++      mgcsfx_read_error(fname, line_number, "input command");
++      goto next;
++    }
++    if(strlen(s) > 0) i_com = s;
++    else free(s);
++
++    if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++      if(s != NULL) free(s);
++      mgcsfx_read_error(fname, line_number, "output image type");
++      goto next;
++    }
++    if(strlen(s) > 0) o_img = s;
++    else free(s);
++
++    if((s = fgettoken(fp, '#'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i at _Dj%_%9(B */
++    /*
++      free(s);
++      mgcsfx_read_error(fname, line_number, "output command");
++      goto next;
++     */
++      if(s != NULL){
++	*s = '\0';
++	reach_end = 1;
++      }
++    }
++    if(s != NULL){
++      if(strlen(s) > 0) o_com = s;
++      else free(s);
++    }
++
++    if(reach_end == 0){
++      while((s = fgettoken(fp, '\n'))!=NULL){/* $B9TKv$N%4%_$r<N$F$k(B */
++	if(*s == '\n'){
++	  free(s);
++	  break; /* goto next; */
++	}
++	free(s);
++      }
++    }else{
++      reach_end = 0;
++    }
++
++
++
++    /* --------------------------------------------------------------------- */
++next:;
++
++    if(DEBUG){
++      fprintf(stderr,"Read:  file %s:  line %d.\n", fname, line_number);
++      fprintf(stderr,"Description : %s\n",
++	      description ? description : "-- error --");
++      fprintf(stderr,"Type        : %s\n",
++	      mgcsfx_type ? mgcsfx_type : "-- error --");
++      fprintf(stderr,"Offset      : %s\n", offset ? offset : "--+--");
++      fprintf(stderr,"Magic       : %s\n", magic ? magic : "--+--");
++      fprintf(stderr,"Suffix      : %s\n", suffix ? suffix : "--+--");
++      fprintf(stderr,"i Image     : %s\n", i_img ? i_img : "--+--");
++      fprintf(stderr,"i Command   : %s\n", i_com ? i_com : "--+--");
++      fprintf(stderr,"o Image     : %s\n", o_img ? o_img : "--+--");
++      fprintf(stderr,"o Command   : %s\n", o_com ? o_com : "--+--");
++      fprintf(stderr,"\n");
++    }
++
++    /* create mgcsfxtab */
++    if((ent = (mgcsfxtab *) malloc (sizeof (mgcsfxtab)))==NULL){
++      fprintf(stderr,"Can't allocate memory\n");
++      exit(1);
++    }
++    ent->next              = NULL;
++    ent->description       = NULL;
++    ent->mgcsfx_type       = T_UNKNOWN;
++    ent->offset            = 0;
++    ent->string_len        = 0;
++    ent->suffix            = NULL;
++    ent->input_image_type  = IT_UNKNOWN;
++    ent->input_command     = NULL;
++    ent->output_image_type = IT_UNKNOWN;
++    ent->output_command    = NULL;
++
++    if(description != NULL){
++      ent->description = description;
++      description = NULL;
++    }else{
++      fprintf (stderr,"%s: line %d: undefined <description> field.\n",
++	       fname, line_number);
++      def_err ++;
++      goto next2;
++    }
++
++    if(mgcsfx_type == NULL){
++      fprintf (stderr,"%s: line %d: undefined <mgcsfx type> field.\n",
++	       fname, line_number);
++      def_err ++;
++      goto next2;
++    }
++    ent->mgcsfx_type = type_mgcsfx(mgcsfx_type);
++    switch(ent->mgcsfx_type){
++    case T_SUFFIX:
++      if(suffix == NULL){
++	fprintf (stderr,
++              "%s: line %d: conflict definition : undefined <suffix> field.\n",
++		 fname, line_number);
++	def_err ++;
++	goto next2;
++      }
++      break;
++    case T_BEINT16:
++      if (sscanf(magic, "%hi", &(ent->dt.int16_data)) != 1){
++	magic_type_error(fname, line_number, magic);
++	def_err ++;
++	goto next2;
++      }
++      break;
++    case T_LEINT16:
++      if (sscanf(magic, "%hi", &(ent->dt.int16_data)) != 1){
++	magic_type_error(fname, line_number, magic);
++	def_err ++;
++	goto next2;
++      }
++      break;
++#ifdef ARCHITECTURE64
++    case T_BEINT32:
++      if (sscanf(magic, "%i", &(ent->dt.int32_data)) != 1){
++	magic_type_error(fname, line_number, magic);
++	def_err ++;
++	goto next2;
++      }
++      break;
++    case T_LEINT32:
++      if (sscanf(magic, "%i", &(ent->dt.int32_data)) != 1){
++	magic_type_error(fname, line_number, magic);
++	def_err ++;
++	goto next2;
++      }
++      break;
++#else
++    case T_BEINT32:
++      if (sscanf(magic, "%li", &(ent->dt.int32_data)) != 1){
++	magic_type_error(fname, line_number, magic);
++	def_err ++;
++	goto next2;
++      }
++      break;
++    case T_LEINT32:
++      if (sscanf(magic, "%li", &(ent->dt.int32_data)) != 1){
++	magic_type_error(fname, line_number, magic);
++	def_err ++;
++	goto next2;
++      }
++      break;
++#endif /* ARCHITECTURE64 */
++    case T_MAGIC:
++      if(magic == NULL){
++	fprintf (stderr,"%s: line %d: undefined <magic> field.\n",
++		 fname, line_number);
++	def_err ++;
++	goto next2;
++      }
++      if((str_len = string_fin(magic))<=0){
++	fprintf (stderr,"%s: line %d: invalid <magic> field.\n",
++		 fname, line_number);
++	def_err ++;
++	goto next2;
++      }
++
++      ent->string_len = str_len;
++      if((ent->dt.string_data = (char *)malloc(str_len + 1))==NULL){
++	fprintf(stderr,"Can't allocate memory\n");
++	exit(1);
++      }
++      memcpy(ent->dt.string_data, magic, str_len + 1);
++      break;
++    case T_UNKNOWN:
++    default:
++      fprintf (stderr,"%s: line %d: invalid <mgcsfx type> field.\n",
++	       fname, line_number);
++      def_err ++;
++      goto next2;
++      break;
++    };
++
++
++    if(offset == NULL){
++      if(ent->mgcsfx_type == T_MAGIC ||
++	 ent->mgcsfx_type == T_BEINT16 ||
++	 ent->mgcsfx_type == T_LEINT16 ||
++	 ent->mgcsfx_type == T_BEINT32 ||
++	 ent->mgcsfx_type == T_LEINT32){
++	fprintf (stderr,
++	      "%s: line %d: conflict definition : undefined <offset> field.\n",
++		 fname, line_number);
++	def_err ++;
++	goto next2;
++      }
++    }else{
++      if(ent->mgcsfx_type != T_SUFFIX) sscanf(offset, "%i", &(ent->offset));
++    }
++
++    if(suffix != NULL){
++      ent->suffix = suffix;
++      suffix = NULL;
++    }
++
++    if((i_img == NULL && i_com == NULL) && (o_img == NULL || o_com == NULL)){
++      fprintf (stderr,"%s: line %d: invalid definition.\n",
++	       fname, line_number);
++      def_err ++;
++      goto next2;
++    }
++    if((o_img == NULL && o_com == NULL) && (i_img == NULL || i_com == NULL)){
++      fprintf (stderr,"%s: line %d: invalid definition.\n",
++	       fname, line_number);
++      def_err ++;
++      goto next2;
++    }
++
++    if(i_img != NULL && i_com != NULL){
++      ent->input_image_type  = type_image(i_img);
++      ent->input_command = i_com;
++      i_com = NULL;
++    }else{
++      ent->input_image_type  = IT_UNKNOWN;
++      ent->input_command = NULL;
++    }
++
++    if(o_img != NULL && o_com != NULL){
++      ent->output_image_type = type_image(o_img);
++      ent->output_command = o_com;
++      o_com = NULL;
++    }else{
++      ent->output_image_type = IT_UNKNOWN;
++      ent->output_command = NULL;
++    }
++    /* end of create mgcsfxtab */
++
++
++next2:;
++
++    if(def_err != 0 || DEBUG){
++      fprintf(stderr,"Description : %s \t -> %s\n",
++	      description ? description : "--+--",
++	      ent->description ? ent->description : "-- error --");
++      fprintf(stderr,"Type        : %s \t -> %d\n",
++	      mgcsfx_type ? mgcsfx_type : "--+--",
++	      ent->mgcsfx_type);
++      fprintf(stderr,"Offset      : %s \t -> %d\n",
++	      offset ? offset : "--+--",
++	      ent->offset);
++
++      fprintf(stderr,"Magic       : %s", magic ? magic : "--+--");
++      switch(ent->mgcsfx_type){
++      case T_BEINT16:
++      case T_LEINT16:
++	fprintf(stderr," \t -> %d\n",ent->dt.int16_data);
++	break;
++      case T_BEINT32:
++      case T_LEINT32:
++	fprintf(stderr," \t -> %ld\n",ent->dt.int32_data);
++	break;
++      case T_MAGIC:
++	fprintf(stderr," \t -> %s\n",ent->dt.string_data);
++	break;
++      default:
++	fprintf(stderr,"\n");
++	break;
++      };
++
++      fprintf(stderr,"Suffix      : %s \t -> %s\n",
++	      suffix ? suffix : "--+--",
++	      ent->suffix ? ent->suffix : "--+--");
++      fprintf(stderr,"i Image     : %s \t -> %d\n",
++	      i_img ? i_img : "--+--",
++	      ent->input_image_type);
++      fprintf(stderr,"i Command   : %s \t -> %s\n",
++	      i_com ? i_com : "--+--",
++	      ent->input_command ? ent->input_command : "--+--");
++      fprintf(stderr,"o Image     : %s \t -> %d\n",
++	      o_img ? o_img : "--+--",
++	      ent->output_image_type);
++      fprintf(stderr,"o Command   : %s \t -> %s\n",
++	      o_com ? o_com : "--+--",
++	      ent->output_command ? ent->output_command : "--+--");
++      fprintf(stderr,"\n");
++    }
++
++    if(description != NULL) free(description);
++    if(mgcsfx_type != NULL) free(mgcsfx_type);
++    if(offset      != NULL) free(offset);
++    if(magic       != NULL) free(magic);
++    if(suffix      != NULL) free(suffix);
++    if(i_img       != NULL) free(i_img);
++    if(i_com       != NULL) free(i_com);
++    if(o_img       != NULL) free(o_img);
++    if(o_com       != NULL) free(o_com);
++
++
++    if(def_err != 0) goto next3;
++
++    /* Override any existing entry for this magic number/file type */
++    for(entry = mgcsfx_table; *entry; entry = &((*entry)->next)){
++      if((ent->mgcsfx_type == (*entry)->mgcsfx_type) &&
++	 (
++	   ((ent->offset == (*entry)->offset) &&
++	    (((ent->mgcsfx_type == T_BEINT16) &&
++	      (ent->dt.int16_data == (*entry)->dt.int16_data)) ||
++	     ((ent->mgcsfx_type == T_BEINT32) &&
++	      (ent->dt.int32_data == (*entry)->dt.int32_data)) ||
++	     ((ent->mgcsfx_type == T_LEINT16) &&
++	      (ent->dt.int16_data == (*entry)->dt.int16_data)) ||
++	     ((ent->mgcsfx_type == T_LEINT32) &&
++	      (ent->dt.int32_data == (*entry)->dt.int32_data)) ||
++
++	     ((ent->mgcsfx_type == T_MAGIC) &&
++	      !memcmp(ent->dt.string_data, (*entry)->dt.string_data,
++		      ent->string_len))
++	      )) ||
++	  ((ent->mgcsfx_type == T_SUFFIX) &&
++	   !strcmp(ent->suffix, (*entry)->suffix))
++	 )
++	){
++
++	free ((*entry)->description);
++	(*entry)->description = ent->description;
++	ent->description = NULL;
++
++	(*entry)->input_image_type = ent->input_image_type;
++	if ((*entry)->input_command) free ((*entry)->input_command);
++	(*entry)->input_command = ent->input_command;
++	ent->input_command = NULL;
++
++	(*entry)->output_image_type = ent->output_image_type;
++	if ((*entry)->output_command) free ((*entry)->output_command);
++	(*entry)->output_command = ent->output_command;
++	ent->output_command = NULL;
++
++	free_mgcsfx(ent);
++	break;
++      }
++    }
++    if (!*entry){
++      ent->next = NULL;
++      *entry = ent;
++    }
++
++    /* if(s == NULL) break; */
++next3:;
++    if(def_err != 0) free_mgcsfx(ent);
++  } /* end of while(1) */
++}
++
++
++/***************************************************/
++/* $B%^%8%C%/%J%s%P!<Dj5A%U%!%$%kL>$rF@$F!"FI$_9~$^$;$k(B */
++static void init_mgcsfx ()
++{
++  extern char *getenv ();
++
++  char      *home_dir;
++  char       fname[1024];
++  mgcsfxtab *entry;
++  int        len;
++  struct stat st;
++
++#ifdef USE_MGCSFX_PREPROCESSOR
++  char      *pp_fname;
++#endif /* USE_MGCSFX_PREPROCESSOR */
++
++  mgcsfx_table = NULL;
++
++  mgcsfx_handler_setup();
++
++  if(nomgcsfx){
++    mgcsfx_setup_flag = 1;
++    nitem_mgcsfx = 0;
++    desc_width = 0;
++  }else{
++    sprintf (fname, "%s/%s", SYSCONFDIR, MGCSFX_SITE_RC);
++    if(stat(fname, &st) == 0 && S_ISREG(st.st_mode)){
++      /* Read the site MagicSuffix table into a linked list */
++#ifdef USE_MGCSFX_PREPROCESSOR
++      if((pp_fname = make_preprocessed_file(fname)) != NULL){
++	read_mgcsfx (&mgcsfx_table, pp_fname);
++      }
++      unlink(pp_fname);
++#else
++      read_mgcsfx (&mgcsfx_table, fname);
++#endif /* USE_MGCSFX_PREPROCESSOR */
++    }
++
++    /* Read the personal MgcSfx table into the list overriding site entries */
++    if ((home_dir = getenv ("HOME"))){
++      sprintf (fname, "%s/%s", home_dir, MGCSFX_RC);
++      if(stat(fname, &st) == 0 && S_ISREG(st.st_mode)){
++#ifdef USE_MGCSFX_PREPROCESSOR
++	if((pp_fname = make_preprocessed_file(fname)) != NULL){
++	  read_mgcsfx (&mgcsfx_table, pp_fname);
++	}
++	unlink(pp_fname);
++#else
++	read_mgcsfx (&mgcsfx_table, fname);
++#endif /* USE_MGCSFX_PREPROCESSOR */
++      }
++    }
++
++    mgcsfx_setup_flag = 1;
++
++    nitem_mgcsfx = 0;
++    desc_width = 0;
++    for (entry = mgcsfx_table; entry; entry = entry->next){
++      nitem_mgcsfx ++;
++      len = strlen(entry->description);
++      if(len > desc_width) desc_width = len;
++      if(max_offset_mgcsfx < entry->offset) max_offset_mgcsfx = entry->offset;
++      if(entry->mgcsfx_type == T_MAGIC &&
++	 max_length_mgcsfx < entry->string_len)
++	max_length_mgcsfx = entry->string_len;
++    }
++    if(max_length_mgcsfx == 0) max_length_mgcsfx = sizeof(int32);
++    need_buf_size = max_offset_mgcsfx + max_length_mgcsfx + 1;/* 1 is safety */
++  }
++}
++
++/***************************************************/
++/* $B%^%8%C%/%J%s%P!<$rD4$Y$F!"Dj5A$7$F$$$k%F!<%V%k$r8!:w$9$k(B
++   $B%^%8%C%/%J%s%P!<$N%F!<%V%k$rFI$_9~$s$G$$$J$$$J$iFI$_9~$`(B */
++static mgcsfxtab *find_mgcsfx (fname, buffer, buffer_size)
++     char           *fname;
++     unsigned char  *buffer;
++     int             buffer_size;
++{
++  mgcsfxtab *entry;
++  int16      buf16;
++  int32      buf32;
++  char      *suf;
++
++  if (mgcsfx_setup_flag == 0) init_mgcsfx ();
++
++  for (entry = mgcsfx_table; entry; entry = entry->next){
++    switch (entry->mgcsfx_type){
++    case T_BEINT16:
++      if ((buffer_size > 0) &&
++	  ((entry->offset + sizeof (int16)) <= buffer_size)){
++	buf16 = ((char)*(buffer + entry->offset) << 8) |
++	  ((char)*(buffer + entry->offset +1));
++	if(entry->dt.int16_data == buf16) return entry;
++      }
++      break;
++    case T_LEINT16:
++      if ((buffer_size > 0) &&
++	  ((entry->offset + sizeof (int16)) <= buffer_size)){
++	buf16 = ((char)*(buffer + entry->offset +1) << 8) |
++	  ((char)*(buffer + entry->offset));
++	if(entry->dt.int16_data == buf16) return entry;
++      }
++      break;
++    case T_BEINT32:
++      if ((buffer_size > 0) &&
++	  ((entry->offset + sizeof (int32)) <= buffer_size)){
++	buf32 = ((char)*(buffer + entry->offset) << 24) |
++	  ((char)*(buffer + entry->offset +1) << 16) |
++	  ((char)*(buffer + entry->offset +2) << 8) |
++	  ((char)*(buffer + entry->offset +3));
++	if(entry->dt.int32_data == buf32) return entry;
++      }
++      break;
++    case T_LEINT32:
++      if ((buffer_size > 0) &&
++	  ((entry->offset + sizeof (int32)) <= buffer_size)){
++	buf32 = ((char)*(buffer + entry->offset +3) << 24) |
++	  ((char)*(buffer + entry->offset +2) << 16) |
++	  ((char)*(buffer + entry->offset +1) << 8) |
++	  ((char)*(buffer + entry->offset));
++	if(entry->dt.int32_data == buf32) return entry;
++      }
++      break;
++    case T_MAGIC:
++      if ((buffer_size > 0) &&
++	  ((entry->offset + entry->string_len)
++	   <= buffer_size) &&
++	  !memcmp (entry->dt.string_data, buffer + entry->offset,
++		   entry->string_len ))
++	return entry;
++      break;
++    case T_SUFFIX:
++      if(fname != NULL && entry->suffix != NULL){
++	if(strlen(fname) - strlen(entry->suffix) > 0){
++	  suf = fname + (strlen(fname) - strlen(entry->suffix));
++	  if(!strcmp(suf, entry->suffix)) return entry;
++	}
++      }
++      break;
++    case T_UNKNOWN:
++    default:
++      return NULL;
++      break;
++    }
++  }
++  return NULL;
++}
++
++
++
++
++
++/***************************************************/
++/* $B%^%8%C%/%J%s%P!<$NDj5A$rD4$Y$F!"$=$l$K$"$o$;$?%3%^%s%I$r<B9T$9$k(B */
++/* if OK return 1, else if ERROR return 0 */
++int
++LoadMGCSFX(file_name, pinfo)
++     char    *file_name;
++     PICINFO *pinfo;
++{
++  unsigned char *buffer;
++  int            size;
++  mgcsfxtab     *magic;
++  mgcsfxtab     *magic_cur;
++  char          *ptr;
++  char           command[1024];
++  int            fd[2];
++  int            pid = -2;
++  int            file;
++  char          *fname;
++  int            rv;
++  int            pst;
++
++  int            i_it;
++  char          *i_com;
++
++  WaitCursor();
++
++  fname = file_name;
++  if((file = open (fname, O_RDONLY))<0){
++    SetISTR(ISTR_WARNING, "Can't open %s",fname);
++    return 0;
++  }
++
++  if((buffer = (unsigned char *)calloc(need_buf_size, sizeof(char))) == NULL){
++    SetISTR(ISTR_WARNING, "Can't allocate memory");
++    return 0;
++  }
++
++  magic_cur = NULL;
++
++/*  do{ */
++    size = read (file, buffer, need_buf_size);
++
++    if (lseek (file, 0L, 0) < 0){ /* can't seek pipe !! */
++      fprintf (stderr, "Can't lseek %s\n", file_name);
++      close(file);
++      return 0;
++    }
++
++    magic = find_mgcsfx (fname, buffer, size);
++
++    if ((magic != NULL && magic->input_command) ||
++        (magic == NULL && mgcsfx && input_command_ex_flag)){
++
++      if(magic == NULL){
++	if (fname != NULL && (ptr = strstr(input_command_ex, "%s"))){
++	  sprintf (command, input_command_ex, fname);
++	}else{
++	  strcpy (command, input_command_ex);
++	  fname=NULL;
++	}
++      }else{
++	/* Use stdin or give file name */
++	if (fname != NULL && (ptr = strstr(magic->input_command, "%s"))){
++	  sprintf (command, magic->input_command, fname);
++	}else{
++	  strcpy (command, magic->input_command);
++	  fname=NULL;
++	}
++      }
++
++      /* Do the pipe/fork/exec here */
++      if (pipe (fd) < 0){
++	fprintf (stderr, "Can't pipe : %s\n", file_name);
++	close(file);
++	return 0;
++      }
++
++      if ((pid = vfork ()) < 0){
++	fprintf (stderr, "Can't vfork : %s\n", file_name);
++	close (fd[0]);
++	close (fd[1]);
++	close(file);
++	return 0;
++      }
++
++      if (!pid){
++	 close(0);
++	if (fname == NULL || (open ("/dev/null", O_RDONLY) < 0)){
++	   dup(file);
++	}
++	 close(file);
++	 close(1);
++	 dup(fd[1]);
++	 close(2);
++	 open("/dev/null", O_WRONLY);
++	 close(fd[0]);
++	 execl("/bin/sh", "/bin/sh", "-c", command, 0);
++	_exit(127);
++      }
++
++      close (fd[1]);
++      dup2(fd[0], file);
++      close (fd[0]);
++      fname = NULL;
++      magic_cur = magic;
++    }
++/*  } while(magic != NULL); */
++
++  free(buffer);
++
++  if(magic_cur == NULL && mgcsfx && input_command_ex_flag){
++    i_it  = IT_PNM;
++    i_com = input_command_ex;
++  }else{
++    i_it  = magic_cur->input_image_type;
++    i_com = magic_cur->input_command;
++  }
++
++  if((magic_cur != NULL && i_com) ||
++    (magic_cur == NULL && mgcsfx && input_command_ex_flag)){
++    switch(i_it){
++    case IT_PNM:
++    case IT_PPM:
++    case IT_PGM:
++    case IT_PBM:
++    case IT_PNM_RAW:
++    case IT_PPM_RAW:
++    case IT_PGM_RAW:
++    case IT_PBM_RAW:
++    case IT_PNM_ASCII:
++    case IT_PPM_ASCII:
++    case IT_PGM_ASCII:
++    case IT_PBM_ASCII:
++      rv = LoadPBM(file_name, pinfo, file);
++      break;
++    case IT_GIF:
++    case IT_JPEG:
++    case IT_TIFF:
++    case IT_JFIF:
++    case IT_XBM:
++    case IT_XPM:
++    case IT_BMP:
++    case IT_SUNRAS:
++    case IT_IRIS:
++    case IT_XWD:
++    case IT_MAG:
++    case IT_MAKI:
++    case IT_PI:
++    case IT_PIC:
++    case IT_PIC2:
++      SetISTR(ISTR_WARNING, "Yet supported input image type (from filter output)");
++      rv = 0;
++      break;
++    case IT_UNKNOWN:
++      SetISTR(ISTR_WARNING, "Unknown input image type (from filter output)");
++      rv = 0;
++      break;
++#ifdef HAVE_MGCSFX_AUTO
++    case IT_AUTO:
++#endif
++    default:
++      SetISTR(ISTR_WARNING, "Error in input image type (from filter output)");
++      rv = 0;
++      break;
++    }
++  }else{
++    rv = 0;
++  }
++
++  /* fail if pid still == -2? */
++  while(wait(&pst) != pid);  /* FIXME?  pid isn't necessarily initialized... */
++  if( *((char *)&pst) != 0 ) rv = 0;
++
++  input_command_ex_flag = 0;
++
++  return rv;
++
++  /* fclose(fp);  close in Load??? */
++  /* return 0; error */
++  /* return 1; ok */
++}
++
++
++
++
++
++/*--------------------------------------------------------------------------*/
++#ifndef MGCSFX_DEFAULT_INPUT_COMMAND
++#  define MGCSFX_DEFAULT_INPUT_COMMAND  "tifftopnm"
++#endif
++#ifndef MGCSFX_DEFAULT_OUTPUT_COMMAND
++#  define MGCSFX_DEFAULT_OUTPUT_COMMAND "pnmtotiff"
++#endif
++
++int MSWIDE  =  0;
++int MSHIGH  =  0;
++
++#define MS_NBUTTS 2
++#define MS_BOK    0
++#define MS_BCANC  1
++#define BUTTW    60  /* width of buttons (OK or Cancel) */
++#define BUTTH    24  /* height of buttons (OK or Cancel) */
++#define RBSIZE   15  /* width and height of RB button (select, ON or OFF)*/
++#define CWIDE    8   /* width of character */
++/* #define CHIGH        height of character      defined in xv.h */
++#define MARGIN    3  /* margin of button and label     SPACING */
++
++#define MSD_TITLE       "Save file with external command..."
++#define MSD_RBTITLE     "Type of Magic and Suffix"
++#define MSD_IC_TITLE    "input command"
++
++static BUTT  msbut[MS_NBUTTS];
++static RBUTT *typeRB;
++
++static char output_command_ex[1024];
++static int  output_command_ex_flag = 0;
++
++static int   colorType;
++
++static int   w_pid;
++static int   w_pstatus;
++
++#define MSNAMWIDE 252               /* width of 'file name' entry window */
++#define MAXFNLEN 256               /* max len of filename being entered */
++static char   DialogFileName[MAXFNLEN+100];   /* filename being entered */
++static int    curPos, stPos, enPos;     /* filename textedit stuff */
++
++
++static mgcsfxtab *get_mgcsfx PARM((int));
++static void changeSuffix PARM((int));
++
++static int WriteMGCSFX  PARM((FILE**,byte*,int,int,int,
++			    byte*,byte*,byte*,int,int,char*,
++			    int, int, char*));
++void  CreateMGCSFXW         PARM((void));
++void  MGCSFXDialog          PARM((int));
++int   MGCSFXCheckEvent      PARM((XEvent *));
++int   MGCSFXSaveParams      PARM((char *, int));
++
++static void drawMSD     PARM((int,int,int,int));
++static void clickMSD    PARM((int,int));
++static void doCmd       PARM((int));
++static int writeMGCSFX  PARM((void));
++
++static void changeSuffix   PARM((int));
++static void redrawNamMSD   PARM((void));
++static void showFNamMSD    PARM((void));
++static int keyinMSD        PARM((int));
++
++int getInputCom  PARM((void));
++int getOutputCom PARM((void));
++/*--------------------------------------------------------------------------*/
++
++/***************************************************/
++/* $B$I$l$rA*$s$@$+D4$Y$k!##0$O%3%^%s%I$rF~NO$9$k$b$N$H$9$k(B */
++static mgcsfxtab *get_mgcsfx(ms_type)
++     int ms_type;
++{
++  mgcsfxtab *magic;
++  int        i;
++
++  magic = NULL;
++  if(ms_type != 0){
++    i = 1;
++    for(magic = mgcsfx_table; (magic && i<ms_type); magic = magic->next){i++;}
++  }
++  return magic;
++}
++
++/***************************************************/
++/* $B30It%3%^%s%I$r<B9T$7$F!"$=$l$K=PNO$9$k(B */
++/* if OK return 0, else if ERROR return -1 */
++static
++int WriteMGCSFX(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,file_name,
++		ms_type, file, comment)
++     FILE **fp;
++     byte  *pic;
++     int    ptype, w,h;
++     byte  *rmap, *gmap, *bmap;
++     int    numcols, colorstyle;
++     char  *file_name;
++     int    ms_type;
++     int    file; /* file descriptor */
++     char  *comment;
++{
++  mgcsfxtab *magic;
++
++  int        fd[2];
++  int        pid;
++  int        rv;
++
++  WaitCursor();
++
++#ifdef USE_SIGCHLD
++  w_p_fail = 1;
++#endif
++
++  magic = get_mgcsfx(ms_type);
++  if(ms_type != 0 && magic == NULL) return -1;
++
++  if ((ms_type == 0 && output_command_ex_flag) ||
++      (ms_type !=0 && magic != NULL && magic->output_command)){
++
++    /* Do the pipe/fork/exec here */
++    if (pipe (fd) < 0){
++      fprintf (stderr, "Can't pipe : %s\n", file_name);
++      return -1;
++    }
++
++    if ((pid = vfork ()) < 0){
++      fprintf (stderr, "Can't vfork : %s\n", file_name);
++      close (fd[0]);
++      close (fd[1]);
++      return -1;
++    }
++
++    if (!pid){
++      close(1);
++      dup(file);
++      close(file);
++      close(0);
++      dup(fd[0]);
++      close(2);
++      open("/dev/null", O_WRONLY);
++      close(fd[1]);
++      if(ms_type == 0){
++	execl("/bin/sh", "/bin/sh", "-c", output_command_ex, 0);
++      }else{
++	execl("/bin/sh", "/bin/sh", "-c", magic->output_command, 0);
++      }
++      _exit(127);
++    }
++
++    close (fd[0]);
++    dup2(fd[1], file);
++    close (fd[1]);
++
++  }else{
++    return -1;
++  }
++
++
++  *fp = fdopen(file, "w");
++
++  /* sleep(1); Best way is wait for checking SIGCHLD, but it's feel waist.*/
++
++#ifdef USE_SIGCHLD
++  if(w_p_fail != 2){
++#endif
++    if(ms_type == 0){
++      rv = WritePBM(*fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,
++		    1, comment);
++    }else{
++      switch(magic -> output_image_type){
++      case IT_PNM:
++      case IT_PPM:
++      case IT_PGM:
++      case IT_PBM:
++      case IT_PNM_RAW:
++      case IT_PPM_RAW:
++      case IT_PGM_RAW:
++      case IT_PBM_RAW:
++	rv = WritePBM(*fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,
++		      1, comment);
++	break;
++      case IT_PNM_ASCII:
++      case IT_PPM_ASCII:
++      case IT_PGM_ASCII:
++      case IT_PBM_ASCII:
++	rv = WritePBM(*fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,
++		      0, comment);
++	break;
++      case IT_GIF:
++      case IT_JPEG:
++      case IT_TIFF:
++      case IT_JFIF:
++      case IT_XBM:
++      case IT_XPM:
++      case IT_BMP:
++      case IT_SUNRAS:
++      case IT_IRIS:
++      case IT_XWD:
++      case IT_MAG:
++      case IT_MAKI:
++      case IT_PI:
++      case IT_PIC:
++      case IT_PIC2:
++	SetISTR(ISTR_WARNING, "Yet supported output image type (to filter input)");
++	rv = -1;
++	break;
++      case IT_UNKNOWN:
++	SetISTR(ISTR_WARNING, "Unknown output image type (to filter input)");
++	rv = -1;
++	break;
++#ifdef HAVE_MGCSFX_AUTO
++      case IT_AUTO:
++#endif
++      default:
++	SetISTR(ISTR_WARNING, "Error in output image type (to filter input)");
++	rv = -1;
++	break;
++      }
++    }
++#ifdef USE_SIGCHLD
++  }else{
++    rv = -1;
++  }
++#endif
++
++#ifdef USE_SIGCHLD
++  if(w_p_fail != 2){
++#endif
++    w_pid = pid;
++#ifdef USE_SIGCHLD
++    w_p_fail = 0;
++  }else{
++    rv = -1;
++  }
++#endif
++
++  output_command_ex_flag = 0;
++
++  return rv;
++
++  /* fclose(*fp);   close in CloseOutFile in writeMGCSFX */
++  /* return  0; ok */
++  /* return -1; error */
++}
++
++/***************************************************/
++void CreateMGCSFXW()
++{
++  int	     y;
++  int        type_num;
++  mgcsfxtab *entry;
++
++  if (mgcsfx_setup_flag == 0) init_mgcsfx ();
++
++  if(desc_width < strlen(MSD_IC_TITLE))  desc_width = strlen(MSD_IC_TITLE);
++  nitem_mgcsfx ++;
++
++  MSWIDE = desc_width * CWIDE + RBSIZE + 36; /* 36 is start of RB button */
++  MSHIGH = nitem_mgcsfx * (RBSIZE + MARGIN);
++
++  if(MSWIDE < strlen(MSD_TITLE) + 20) MSWIDE = strlen(MSD_TITLE) + 20;
++  if(MSWIDE < strlen(MSD_RBTITLE) + 16) MSWIDE = strlen(MSD_RBTITLE) + 16;
++  if(MSWIDE < MSNAMWIDE + 10) MSWIDE = MSNAMWIDE + 10;
++  if(MSWIDE <  BUTTW * 2 + 10) MSWIDE = BUTTW * 2 + 10;
++
++  MSHIGH += 55 + LINEHIGH + 10 + BUTTH + 10;
++
++  MSWIDE += 20; /* right side margin */
++  MSHIGH += 10; /* RB buttun down side margin */
++
++
++  mgcsfxW = CreateWindow("xv mgcsfx", "XVmgcsfx", NULL,
++			 MSWIDE, MSHIGH, infofg, infobg, 0);
++  if (!mgcsfxW) FatalError("can't create mgcsfx window!");
++
++  XSelectInput(theDisp, mgcsfxW,
++	       ExposureMask | ButtonPressMask | KeyPressMask);
++
++  mgcsfxNameW = XCreateSimpleWindow(theDisp, mgcsfxW,
++				    10,  MSHIGH-LINEHIGH-10-BUTTH-10-1,
++				    (u_int) MSNAMWIDE+6, (u_int) LINEHIGH+5,
++				    1, infofg, infobg);
++  if (!mgcsfxNameW) FatalError("can't create mgcsfx name window");
++  XSelectInput(theDisp, mgcsfxNameW, ExposureMask);
++
++  /* Ok $B%\%?%s(B */
++  BTCreate(&msbut[MS_BOK], mgcsfxW,
++	   MSWIDE-BUTTW-10-BUTTW-10-1, MSHIGH-BUTTH-10-1,
++	   BUTTW, BUTTH,
++	   "Ok", infofg, infobg, hicol, locol);
++  /* Cancel $B%\%?%s(B*/
++  BTCreate(&msbut[MS_BCANC], mgcsfxW,
++	   MSWIDE-BUTTW-10-1, MSHIGH-BUTTH-10-1,
++	   BUTTW, BUTTH,
++	   "Cancel", infofg, infobg, hicol, locol);
++
++  y = 55;
++  /* User should input command to exec external command */
++  typeRB = RBCreate(NULL, mgcsfxW, 36, y,          MSD_IC_TITLE,
++		    infofg, infobg,hicol,locol);
++  y += (RBSIZE + MARGIN); /* 18 */
++
++  type_num = 1;
++  for (entry = mgcsfx_table; entry; entry = entry->next){
++    RBCreate(typeRB, mgcsfxW, 36, y,            entry->description,
++	     infofg, infobg,hicol,locol);
++    y += (RBSIZE + MARGIN); /* 18 */
++    if(entry->output_command == NULL){
++      RBSetActive(typeRB, type_num, 0); /* if no command, off */
++    }
++    type_num++;
++  }
++
++  XMapSubwindows(theDisp, mgcsfxW);
++}
++
++
++/***************************************************/
++void MGCSFXDialog(vis)
++     int vis;
++{
++  if (vis) {
++    CenterMapWindow(mgcsfxW, msbut[MS_BOK].x + msbut[MS_BOK].w/2,
++		    msbut[MS_BOK].y + msbut[MS_BOK].h/2, MSWIDE, MSHIGH);
++  }
++  else     XUnmapWindow(theDisp, mgcsfxW);
++  mgcsfxUp = vis;
++}
++
++
++/***************************************************/
++int MGCSFXCheckEvent(xev)
++     XEvent *xev;
++{
++  /* check event to see if it's for one of our subwindows.  If it is,
++     deal accordingly, and return '1'.  Otherwise, return '0' */
++
++  int rv;
++  rv = 1;
++
++  if (!mgcsfxUp) return (0);
++
++  if (xev->type == Expose) {
++    int x,y,w,h;
++    XExposeEvent *e = (XExposeEvent *) xev;
++    x = e->x;  y = e->y;  w = e->width;  h = e->height;
++
++    if (e->window == mgcsfxW)       drawMSD(x, y, w, h);
++    else rv = 0;
++  }
++
++  else if (xev->type == ButtonPress) {
++    XButtonEvent *e = (XButtonEvent *) xev;
++    int x,y;
++    x = e->x;  y = e->y;
++
++    if (e->button == Button1) {
++      if      (e->window == mgcsfxW)     clickMSD(x,y);
++      else rv = 0;
++    }  /* button1 */
++    else rv = 0;
++  }  /* button press */
++
++  else if (xev->type == KeyPress) {
++    XKeyEvent *e = (XKeyEvent *) xev;
++    char buf[128];  KeySym ks;  XComposeStatus status;
++    int stlen;
++
++    stlen = XLookupString(e,buf,128,&ks,&status);
++    buf[stlen] = '\0';
++
++    if (e->window == mgcsfxW) {
++      if (stlen) {
++	keyinMSD(buf[0]);
++      }
++    }
++    else rv = 0;
++  }
++  else rv = 0;
++
++  if (rv == 0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
++    XBell(theDisp, 50);
++    rv = 1;   /* eat it */
++  }
++
++  return (rv);
++}
++
++
++/***************************************************/
++int MGCSFXSaveParams(fname, col)
++     char *fname;
++     int col;
++{
++  colorType = col;
++  strcpy(DialogFileName, GetDirFName());
++  return (0);
++}
++
++/***************************************************/
++/* $B%@%$%"%m%0$rI=<($9$k$H$-$N=hM}(B */
++static void drawMSD(x,y,w,h)
++     int x,y,w,h;
++{
++  int        i;
++  XRectangle xr;
++
++  xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
++  XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
++
++  XSetForeground(theDisp, theGC, infofg);
++  XSetBackground(theDisp, theGC, infobg);
++
++  for (i = 0; i < MS_NBUTTS; i++) BTRedraw(&msbut[i]);
++
++  ULineString(mgcsfxW, typeRB->x-16, typeRB->y-3-DESCENT,
++	      MSD_RBTITLE);
++  RBRedraw(typeRB, -1);
++
++  DrawString(mgcsfxW, 20, 29, MSD_TITLE);
++
++  XSetClipMask(theDisp, theGC, None);
++
++  showFNamMSD();
++}
++
++/***************************************************/
++/* $B%@%$%"%m%0$r%/%j%C%/$7$?$H$-$N=hM}(B */
++static void clickMSD(x,y)
++     int x,y;
++{
++  int   i;
++  BUTT *bp;
++
++  /* check BUTTs */
++
++  /* check the RBUTTS first, since they don't DO anything */
++  if ((i = RBClick(typeRB, x,y)) >= 0) { /* $BA*Br(B(type)$B%\%?%s$N=hM}(B */
++    (void) RBTrack(typeRB, i);  /* $BA*Br(B(type)$B%\%?%s$r2!$7$?$H$-(B */
++    changeSuffix(i);
++    return;
++  }
++
++  for (i = 0; i < MS_NBUTTS; i++) { /* Ok,Cancel $B%\%?%s$N=hM}(B */
++    bp = &msbut[i];
++    if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h))
++      break;
++  }
++  if (i < MS_NBUTTS)  /* found one */ /* Ok,Cancel $B%\%?%s$r2!$7$?$H$-(B */
++    if (BTTrack(bp)) doCmd(i);
++}
++
++/***************************************************/
++/* $B%\%?%s(B(Ok, Cancel) $B$N=hM}(B */
++static void doCmd(cmd)
++     int cmd;
++{
++  int rv;
++
++  switch (cmd) {
++  case MS_BOK: /* Ok button */ {
++    char *fullname;
++
++    rv = writeMGCSFX(); /* Save with filter(MGCSFX) */
++    MGCSFXDialog(0);
++
++    fullname = GetDirFullName();
++    if (!ISPIPE(fullname[0])) {
++      XVCreatedFile(fullname);
++      if(!rv) StickInCtrlList(0);
++    }
++  }
++    break;
++  case MS_BCANC: /* Cancel button */
++    DialogFileName[0] = '\0';
++    curPos = stPos = enPos = 0;
++    MGCSFXDialog(0);
++    break;
++  default:
++    break;
++  }
++}
++
++/*******************************************/
++static int writeMGCSFX()
++{
++  int   rv, type;
++  int   ptype, w, h, pfree, nc;
++  byte *inpix, *rmap, *gmap, *bmap;
++
++  FILE *fp = NULL;
++  int   file;
++  char *fullname;
++
++  rv = -1;
++  type = RBWhich(typeRB);
++
++  SetDirFName(DialogFileName); /* change filename in dir dialog */
++  fullname = GetDirFullName();
++
++  if(type == 0){
++    if(getOutputCom() == 0) return rv;
++  }
++
++  file = OpenOutFileDesc(fullname);
++  if(file < 0) return rv;
++
++  WaitCursor();
++  inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap);
++
++  rv = WriteMGCSFX(&fp, inpix, ptype, w, h,
++		   rmap, gmap, bmap, nc, colorType, fullname,
++		   type, file, picComments);
++
++  SetCursors(-1);
++
++  if (CloseOutFile(fp, fullname, rv) == 0) DirBox(0);
++
++  WaitCursor();
++#ifdef USE_SIGCHLD
++  if(w_p_fail == 0){
++#endif
++    while(wait(&w_pstatus) != w_pid);  /* if( *((char *)&w_pstatus) != 0 ) ; */
++#ifdef USE_SIGCHLD
++  }else{
++    w_p_fail = 0;
++  }
++#endif
++  w_pid = 0;
++  w_pstatus = 0;
++
++  if (pfree) free(inpix);
++  return rv;
++}
++
++
++/***************************************/
++static void changeSuffix(ms_type)
++     int ms_type;
++{
++  /* see if there's a common suffix at the end of the DialogFileName.
++     if there is, remember what case it was (all caps or all lower), lop
++     it off, and replace it with a new appropriate suffix, in the
++     same case */
++
++  int allcaps;
++  char *suffix, *sp, *dp, lowsuf[512];
++  mgcsfxtab *magic;
++
++  /* find the last '.' in the DialogFileName */
++  suffix = (char *) rindex(DialogFileName, '.');
++  if (!suffix) return;
++  suffix++;  /* point to first letter of the suffix */
++
++  /* check for all-caposity */
++  for (sp = suffix, allcaps=1; *sp; sp++)
++    if (islower(*sp)) allcaps = 0;
++
++  /* copy the suffix into an all-lower-case buffer */
++  for (sp=suffix, dp=lowsuf; *sp; sp++, dp++) {
++    *dp = (isupper(*sp)) ? tolower(*sp) : *sp;
++  }
++  *dp = '\0';
++
++
++  magic = get_mgcsfx(ms_type);
++  if(magic != NULL && magic->suffix != NULL){
++    strcpy(lowsuf,(magic->suffix)+1);
++
++    if (allcaps) {  /* upper-caseify lowsuf */
++      for (sp=lowsuf; *sp; sp++)
++	*sp = (islower(*sp)) ? toupper(*sp) : *sp;
++    }
++
++    /* one other case:  if the original suffix started with a single
++       capital letter, make the new suffix start with a single cap */
++    if (isupper(suffix[0])) lowsuf[0] = toupper(lowsuf[0]);
++
++    strcpy(suffix, lowsuf);   /* tack onto DialogFileName */
++    showFNamMSD();
++  }
++}
++
++/***************************************************/
++/* $B%@%$%"%m%0Fb$K%U%!%$%k%M!<%`$rI=<($9$k$H$-$N=hM}(B ($B2<@A$1(B)*/
++static void redrawNamMSD()
++{
++  int cpos;
++
++  /* draw substring DialogFileName[stPos:enPos] and cursor */
++
++  Draw3dRect(mgcsfxNameW, 0, 0, (u_int) MSNAMWIDE+5, (u_int) LINEHIGH+4, R3D_IN, 2,
++	     hicol, locol, infobg);
++
++  XSetForeground(theDisp, theGC, infofg);
++
++  if (stPos>0) {  /* draw a "there's more over here" doowah */
++    XDrawLine(theDisp, mgcsfxNameW, theGC, 0,0,0,LINEHIGH+5);
++    XDrawLine(theDisp, mgcsfxNameW, theGC, 1,0,1,LINEHIGH+5);
++    XDrawLine(theDisp, mgcsfxNameW, theGC, 2,0,2,LINEHIGH+5);
++  }
++
++  if ((size_t) enPos < strlen(DialogFileName)) {
++    /* draw a "there's more over here" doowah */
++    XDrawLine(theDisp, mgcsfxNameW, theGC, MSNAMWIDE+5,0,MSNAMWIDE+5,LINEHIGH+5);
++    XDrawLine(theDisp, mgcsfxNameW, theGC, MSNAMWIDE+4,0,MSNAMWIDE+4,LINEHIGH+5);
++    XDrawLine(theDisp, mgcsfxNameW, theGC, MSNAMWIDE+3,0,MSNAMWIDE+3,LINEHIGH+5);
++  }
++
++  XDrawString(theDisp, mgcsfxNameW, theGC,3,ASCENT+3,DialogFileName+stPos, enPos-stPos);
++
++  cpos = XTextWidth(mfinfo, &DialogFileName[stPos], curPos-stPos);
++  XDrawLine(theDisp, mgcsfxNameW, theGC, 3+cpos, 2, 3+cpos, 2+CHIGH+1);
++  XDrawLine(theDisp, mgcsfxNameW, theGC, 3+cpos, 2+CHIGH+1, 5+cpos, 2+CHIGH+3);
++  XDrawLine(theDisp, mgcsfxNameW, theGC, 3+cpos, 2+CHIGH+1, 1+cpos, 2+CHIGH+3);
++}
++
++/***************************************************/
++/* $B%@%$%"%m%0Fb$K%U%!%$%k%M!<%`$rI=<($9$k(B */
++static void showFNamMSD()
++{
++  int len;
++
++  len = strlen(DialogFileName);
++
++  if (curPos<stPos) stPos = curPos;
++  if (curPos>enPos) enPos = curPos;
++
++  if (stPos>len) stPos = (len>0) ? len-1 : 0;
++  if (enPos>len) enPos = (len>0) ? len-1 : 0;
++
++  /* while substring is shorter than window, inc enPos */
++
++  while (XTextWidth(mfinfo, &DialogFileName[stPos], enPos-stPos) < MSNAMWIDE
++	 && enPos<len) { enPos++; }
++
++  /* while substring is longer than window, dec enpos, unless enpos==curpos,
++     in which case, inc stpos */
++
++  while (XTextWidth(mfinfo, &DialogFileName[stPos], enPos-stPos) > MSNAMWIDE) {
++    if (enPos != curPos) enPos--;
++    else stPos++;
++  }
++
++
++  if (ctrlColor) XClearArea(theDisp, mgcsfxNameW, 2,2, (u_int) MSNAMWIDE+5-3,
++			    (u_int) LINEHIGH+4-3, False);
++  else XClearWindow(theDisp, mgcsfxNameW);
++
++  redrawNamMSD();
++  BTSetActive(&msbut[MS_BOK], strlen(DialogFileName)!=0);
++}
++
++/***************************************************/
++/* $B%-!<F~NO$7$?$H$-$N=hM}(B */
++static int keyinMSD(c)
++     int c;
++{
++  /* got keypress in dirW.  stick on end of DialogFileName */
++  int len;
++
++  len = strlen(DialogFileName);
++
++  if (c>=' ' && c<'\177') {             /* printable characters */
++    /* note: only allow 'piped commands' in savemode... */
++
++    /* only allow spaces in 'piped commands', not filenames */
++    if (c==' ' && (!ISPIPE(DialogFileName[0]) || curPos==0)) return (-1);
++
++    /* only allow vertbars in 'piped commands', not filenames */
++    if (c=='|' && curPos!=0 && !ISPIPE(DialogFileName[0])) return(-1);
++
++    if (len >= MAXFNLEN-1) return(-1);  /* max length of string */
++    xvbcopy(&DialogFileName[curPos], &DialogFileName[curPos+1], (size_t) (len-curPos+1));
++    DialogFileName[curPos]=c;  curPos++;
++  }
++
++  else if (c=='\010' || c=='\177') {    /* BS or DEL */
++    if (curPos==0) return(-1);          /* at beginning of str */
++    xvbcopy(&DialogFileName[curPos], &DialogFileName[curPos-1], (size_t) (len-curPos+1));
++    curPos--;
++  }
++
++  else if (c=='\025') {                 /* ^U: clear entire line */
++    DialogFileName[0] = '\0';
++    curPos = 0;
++  }
++
++  else if (c=='\013') {                 /* ^K: clear to end of line */
++    DialogFileName[curPos] = '\0';
++  }
++
++  else if (c=='\001') {                 /* ^A: move to beginning */
++    curPos = 0;
++  }
++
++  else if (c=='\005') {                 /* ^E: move to end */
++    curPos = len;
++  }
++
++  else if (c=='\004') {                 /* ^D: delete character at curPos */
++    if (curPos==len) return(-1);
++    xvbcopy(&DialogFileName[curPos+1], &DialogFileName[curPos], (size_t) (len-curPos));
++  }
++
++  else if (c=='\002') {                 /* ^B: move backwards char */
++    if (curPos==0) return(-1);
++    curPos--;
++  }
++
++  else if (c=='\006') {                 /* ^F: move forwards char */
++    if (curPos==len) return(-1);
++    curPos++;
++  }
++
++  else if (c=='\012' || c=='\015') {    /* CR(\r) or LF(\n) */
++    FakeButtonPress(&msbut[MS_BOK]);
++  }
++
++  else if (c=='\033') {                  /* ESC = Cancel */
++    FakeButtonPress(&msbut[MS_BCANC]);
++  }
++
++  else if (c=='\011') {                  /* tab = filename expansion */
++    if (1 /* !autoComplete() */) XBell(theDisp, 0);
++    else {
++      curPos = strlen(DialogFileName);
++    }
++  }
++
++  else return(-1);                      /* unhandled character */
++
++  showFNamMSD();
++
++  return(0);
++}
++
++
++/*******************************************/
++int getInputCom()
++{
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  int                i;
++
++  strcpy(input_command_ex, MGCSFX_DEFAULT_INPUT_COMMAND);
++  i = GetStrPopUp("Input External Command (Input is PNM):", labels, 2,
++		  input_command_ex, 1024, "",0);
++  if (i == 0 && strlen(input_command_ex) != 0){
++    input_command_ex_flag = 1;
++    return 1;
++  }else{
++    input_command_ex_flag = 0;
++    return 0;
++  }
++}
++
++int getOutputCom()
++{
++  static const char *labels[] = { "\nOk", "\033Cancel" };
++  int                i;
++
++  strcpy(output_command_ex, MGCSFX_DEFAULT_OUTPUT_COMMAND);
++  i = GetStrPopUp("Input External Command (Output is PNM_RAW):", labels, 2,
++		  output_command_ex, 1024, "",0);
++  if (i == 0 && strlen(output_command_ex) != 0){
++    output_command_ex_flag = 1;
++    return 1;
++  }else{
++    output_command_ex_flag = 0;
++    return 0;
++  }
++}
++
++#ifdef SVR4
++Sigfunc *
++xv_signal(signo, func)
++     int signo;
++     Sigfunc *func;
++{
++  struct sigaction act, oact;
++
++  act.sa_handler = func;
++  sigemptyset(&act.sa_mask);
++  act.sa_flags = 0;
++  act.sa_flags |= SA_RESTART;
++
++  if (sigaction(signo, &act, &oact) < 0)
++    return SIG_ERR;
++
++  return oact.sa_handler;
++}
++#endif
++
++#endif /* HAVE_MGCSFX */
+diff -Naru xv-3.10a/xv_mgcsfx.sample xv-3.10a.jumbo/xv_mgcsfx.sample
+--- xv-3.10a/xv_mgcsfx.sample	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xv_mgcsfx.sample	2005-04-17 23:04:22.000000000 +0200
+@@ -0,0 +1,125 @@
++#/*
++# Configuration file for XV with recognition of 'Magic and Suffix'
++#
++#
++# $Id: xv_mgcsfx.sample,v 1.11 95/10/03 17:00:05 tin329 Exp Locker: tin329 $
++#
++# Author: Tetsuya INOUE  <tin329 at chino.it.okayama-u.ac.jp>
++#
++#
++# MgcSfx definition should write in one line.
++#  Format:
++#      <desc>:<ms type>:<ofs>:<magic>:<suffix>:<in it>:<in c>:<out it>:<out c>
++#  If you decide to not use preprocessor, comment style is allowed.
++#      # <comment>
++#
++#   <desc>            Description of your recognized image format.
++#   <ms type>         Type ID for recognition. (You should use 'magic'.)
++#                        * magic        Data of string style.
++#                                        `\' escape for special characters:
++#                                           \b \f \n \r \t \v \\ \' \" \a \?
++#                                           \0  ...\377   octal value
++#                                           \x0 ...\xff   hexadecimal value
++#                        * suffix       Suffix of file name.
++#                                         This type check <suffix> instead
++#                                         of <magic>.
++#                        * [b|l]eint16  2 byte integer of [big|little] endian.
++#                        * [b|l]eint32  4 byte integer of [big|little] endian.
++#   <ofs>             Offset of magic number in the target image file.
++#   <magic>           Data(magic number) of <ms type> to match at <ofs>.
++#   <suffix>          Suffix of filename with '.'start.
++#
++#   <in it>           Input image format type (output from <in c>).
++#                        * PNM       (PPM, PGM, PBM)
++#                        * AUTO      Recognized by xv management, and load.
++#                                    This is different from others, because
++#                                    this write file to temporary.
++#   <out it>          Output image format type (input to <out c>).
++#                        * PNM_RAW   (PPM_RAW, PGM_RAW, PBM_RAW)
++#                        * PNM_ASCII (PPM_ASCII, PGM_ASCII, PBM_ASCII)
++#
++#   <in c>            Command to get the input image.
++#                        * Command mast read stdin or file(specified by
++#                          argument), and write to stdout.
++#                        * Use %s to represent the file name. Without %s,
++#                          get file on stdin.
++#   <out c>           Command to put the output image.
++#                        * Command mast read stdin and write to stdout.
++#
++#   <comment>         Any message.
++#*/
++
++#/*############################################################################
++#
++# definition of the rule with Magic and Suffix
++#
++#*/
++
++# /* Canon View Station Image Format */
++ViewStation(std):magic:0:VsStdImf V0.2:.vs:PNM:VStopnm %s:PNM_RAW:pnmtoVS
++ViewStation(obj):magic:0:VsObjFormat V1.0:.vs:PNM:VSobjtopnm -:PNM_RAW:pnmtoVSobj
++
++# /* CERN httpd cache */
++# /* unchc skip header of CERN httpd cache file, and write data to stdout. */
++CERN httpd cache:magic:0:HTTP/1.0::AUTO:unchc %s::
++
++# /* XLD4(Q4) image format */
++XLD(Q4):magic:11:MAJYO:.q4:PNM:q4toppm::
++
++# /* ML1 image format */
++ML1:magic:0:\1\0\0\x1a:.ml1:PNM:ml1toppm %s::
++
++# /* Pict image format, 256 color only */
++PICT:suffix:::.pict:PNM:picttoppm:PNM_RAW:ppmquant 256 | ppmtopict 
++PICT(gzip):suffix:::.pict.gz:PNM:gzip -dc | picttoppm:PNM_RAW:ppmquant 256 | ppmtopict | gzip
++PICT(compress):suffix:::.pict.Z:PNM:compress -dc | picttoppm:PNM_RAW:ppmquant 256 | ppmtopict | compress
++
++# /* Tim image format(used by SONY PlayStation) */
++TIM:magic:0:\x10\x00\x00\x00:.tim:PNM:timtoppm::
++
++# /* Cam image format(used by CASIO QV-10) */
++# /* CAM:magic:0:\x07\x20\x4d\x4d:.cam:AUTO:camtoppm -j:PNM_RAW */
++CAM:magic:0:\x07\x20\x4d\x4d:.cam:PNM:camtoppm::
++
++# /* Portable Network Graphics (PNG) format : magic is "0x89 PNG" */
++PNG:magic:0:\x89\x50\x4e\x47:.png:PNM:pngtopnm %s:PNM_RAW:pnmtopng
++# /* PNG(interlace):magic:0:\x89\x50\x4e\x47:.png:PNM:pngtopnm %s:PNM_RAW:pnmtopng -interlace */
++
++# /* DB-Z, SAURUS Freehand Memo, PV-F1 Action Board, Wiz Quick Memo format */
++# /* Use xbm2free-1.10 or later. Old version is NOT a filter. */
++# /* To show version of xbm2free, type "xbm2free" (with no argument). */
++ZAURUS:magic:19:IMG1:.zau:PBM_ASCII:free2pbm:PBM:pbmtoxbm|xbm2free -s -
++DBZ:magic:19:IMG1:.dbz:::PBM:pbmtoxbm|xbm2free -d -
++PVF1:magic:12:IMG1:.pvf1:PBM_ASCII:free2pbm:PBM:pbmtoxbm|xbm2free -v -
++# /* WIZ:magic:19:IMG1:.wiz:::PBM:pbmtoxbm|xbm2free -w - */
++
++
++
++# /* Compress:magic:0:\037\235:.Z:AUTO:uncompress %s:: */
++# /* Gzip:magic:0:\037\213:.gz:AUTO:gunzip %s:: */
++# /* Gzip(old):magic:0:\037\236:.z:AUTO:gunzip %s:: */
++
++# /* MAKI:magic:0:MAKI01A\040:.mki:::: */
++# /* MAKI:magic:0:MAKI01B\040:.mki:::: */
++# /* MAG:magic:0:MAKI02\040\040:.mag:::: */
++# /* Pi:magic:0:Pi:.pi:::: */
++# /* PIC:magic:0:PIC:.pic:::: */
++# /* PIC2:magic:0:P2DT:.p2:::: */
++# /* PhotoCD:magic:0:\xff\xff\xff\xff:.pcd:::: */
++
++# /* PBM(ascii):magic:0:P1:.pbm:::: */
++# /* PGM(ascii):magic:0:P2:.pgm:::: */
++# /* PPM(ascii):magic:0:P3:.ppm:::: */
++# /* PBM(raw):magic:0:P4:.pbm:::: */
++# /* PGM(raw):magic:0:P5:.pgm:::: */
++# /* PPM(raw):magic:0:P6:.ppm:::: */
++
++# /* Sun raster:magic:0:\131\246\152\225:.sun:::: */
++# /* JFIF(JPEG):magic:0:\xff\xd8\xff:.jpg:::: */
++# /* TIFF big-endian:magic:0:\115\115:.tif:::: */
++# /* TIFF little-endian:magic:0:\111\111:.tif:::: */
++# /* GIF(87):magic:0:GIF87a:.gif:::: */
++# /* GIF(89):magic:0:GIF89a:.gif:::: */
++# /* SGI(1):magic:0:\x01\xda:.rgb:::: */
++# /* SGI(2):magic:0:\xda\x01:.rgb:::: */
++# /* XWD:magic:0:\0\0\0\7: :::: */
+diff -Naru xv-3.10a/xvml.c xv-3.10a.jumbo/xvml.c
+--- xv-3.10a/xvml.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvml.c	2005-04-18 07:57:34.000000000 +0200
+@@ -0,0 +1,989 @@
++/*
++ * xvml.c  -  makes text item structure for multi-lingual textviewer.
++ *
++ * Entry Points:
++ *  struct ml_text *ml_draw_text()
++ *  struct context *ml_create_context()
++ *  int ml_set_charsets()
++ *  void get_monofont_size()
++ */
++
++#include "xv.h"
++#include <X11/Xresource.h>
++
++#ifdef TV_MULTILINGUAL	/* whole this file. */
++
++#include "xvml.h"
++#define HAVE_STRDUP 1
++#define USE_MULE_EXTENSION
++
++#ifndef __STDC__
++#define CHAR char
++#else
++#define CHAR int
++#endif
++
++#define CODE_SI  0x0e	/* LS0 */
++#define CODE_SO  0x0f	/* LS1 */
++#define CODE_SS2 ((unsigned char) 0x8e)
++#define CODE_SS3 ((unsigned char) 0x8f)
++
++int ml_tab_width = 64;	/* dots */
++
++struct charset {
++    int bpc;		/* bytes per char */
++    int noc;		/* number of chars */
++    char designator;
++    char *registry;
++    int bit7;
++
++    int loaded;
++    char *fontname;
++
++    XFontStruct *fs;
++} charset[] = {
++    { 1, 94, 'B', "iso8859-1",       0, 0, NULL, NULL},
++    { 1, 96, 'A', "iso8859-1",       1, 0, NULL, NULL},
++    { 1, 94, '0', "omron_udc_zh-0",  0, 0, NULL, NULL},
++    { 1, 94, '2', "mulearabic-0",    0, 0, NULL, NULL},
++    { 1, 94, '3', "mulearabic-1",    0, 0, NULL, NULL},
++    { 1, 94, '4', "mulearabic-2",    0, 0, NULL, NULL},
++    { 1, 94, 'J', "jisx0201.1976-0", 0, 0, NULL, NULL},
++    { 1, 96, '0', "muleipa-1",       1, 0, NULL, NULL},
++    { 1, 96, '1', "viscii1.1-1",     1, 0, NULL, NULL},
++    { 1, 96, '2', "viscii1.1-1",     1, 0, NULL, NULL},
++    { 1, 96, 'B', "iso8859-2",       1, 0, NULL, NULL},
++    { 1, 96, 'C', "iso8859-3",       1, 0, NULL, NULL},
++    { 1, 96, 'D', "iso8859-4",       1, 0, NULL, NULL},
++    { 1, 96, 'T', "tis620.1986-0",   1, 0, NULL, NULL},
++    { 1, 96, 'F', "iso8859-7",       1, 0, NULL, NULL},
++    { 1, 96, 'G', "iso8859-6",       1, 0, NULL, NULL},
++    { 1, 96, 'H', "iso8859-8",       1, 0, NULL, NULL},
++    { 1, 94, 'I', "jisx0201.1976-0", 1, 0, NULL, NULL},
++    { 1, 96, 'L', "iso8859-5",       1, 0, NULL, NULL},
++    { 1, 96, 'M', "iso8859-9",       1, 0, NULL, NULL},
++    { 2, 94, '2', "ethio-0",         0, 0, NULL, NULL},
++    { 2, 94, '@', "jisx0208.1978",   0, 0, NULL, NULL},
++    { 2, 94, 'A', "gb2312.1980-0",   0, 0, NULL, NULL},
++    { 2, 94, 'B', "jisx0208.1983-0", 0, 0, NULL, NULL},
++    { 2, 94, 'C', "ksc5601.1987-0",  0, 0, NULL, NULL},
++    { 2, 94, 'D', "jisx0212.1990-0", 0, 0, NULL, NULL},
++    { 2, 94, '0', "big5.eten-0",     0, 0, NULL, NULL},
++    { 2, 94, '1', "big5.hku-0",      0, 0, NULL, NULL},
++    /* End Mark */
++    { 0,  0,   0,        NULL,       0, 0, NULL, NULL},
++};
++#define NR_CHARSETS ((int) (sizeof charset / sizeof charset[0]))
++
++static struct charset *ascii = NULL;
++
++struct context {
++    struct charset *g[4];
++    struct charset **gl, **gr;
++    struct charset **ss;
++    int eol;		/* 0: \n,  1: \r\n,  2: \r,  3: any */
++    int valid[4];	/* g[i] is valid? */
++    int short_form;	/* allow shortened designator sequence? */
++    int lock_shift;	/* allow locking shift? */
++
++    unsigned char *cbuf, *cbp;
++    struct ml_text text;
++    int line;
++    int delta;
++    int toolong;
++
++    Display *dpy;
++    Screen *scr;
++    Window root_win;
++};
++#define DPY (context->dpy)
++#define SCR (context->scr)
++#define ROOT_WIN (context->root_win)
++
++static unsigned char *escape_sequence		PARM((unsigned char *));
++static unsigned char *designator_sequence	PARM((unsigned char *));
++static void locking_shift			PARM((unsigned CHAR));
++static void single_shift			PARM((unsigned CHAR));
++static void put_unknown_char			PARM((unsigned CHAR));
++static struct charset *search_charset		PARM((int, int, int));
++static void pack_string				PARM((struct charset *,
++						      unsigned char *, int));
++static void init_xrm				PARM((void));
++static void init_xrm_fonts			PARM((void));
++static void init_xrm_tab			PARM((void));
++#ifndef HAVE_STRDUP
++static char *strdup				PARM((char *));
++#endif
++
++static char *default_fonts[] = {		/* default for xrm_fonts */
++    "-sony-fixed-medium-r-normal--16-*-*-*-*-*-iso8859-1",
++    "-jis-fixed-medium-r-normal--16-*-*-*-*-*-jisx0208.1983-0",
++};
++static int xrm_nfonts;
++static char **xrm_fonts;
++
++static struct context *context;	/* current context */
++
++struct ml_text *ml_draw_text(ctx, string, len)
++    struct context *ctx;
++    char *string;
++    int len;
++{
++    unsigned char *str = (unsigned char *) string;
++    unsigned char *estr = str + len;
++
++    context = ctx;
++
++    if(ascii == NULL){
++	fputs("ml_draw_text: call ml_set_charsets, first.\n", stderr);
++	return NULL;
++    }
++
++    if(!str)
++	return &context->text;
++
++    WaitCursor();
++
++    if (context->text.maxlines != 0) {
++	struct ml_text *tp = &context->text;
++	struct ml_line *lp;
++	int i;
++	for (i = tp->nlines, lp = tp->lines; i > 0; i--, lp++) {
++	    if (lp->maxitems != 0)
++		free((char *) lp->items);
++	}
++	free((char *) tp->lines);
++	tp->maxlines = tp->nlines = 0;
++    }
++    if (context->cbuf != NULL)
++	free((char *) context->cbuf);
++    context->cbp = (unsigned char *) malloc((size_t) len * 8);/* all \xxx */
++    context->cbuf = context->cbp;
++    context->line = 0;
++    context->delta = 0;
++    context->ss = NULL;
++
++    while(str < estr){
++	if((*str & 0x80) == 0){				/* left half */
++	    struct charset *cs = context->ss ? *context->ss : *context->gl;
++	    unsigned char min_char, max_char;
++	    if (cs != NULL) {
++		if(cs->noc == 94){
++		    min_char = 0x21;
++		    max_char = 0x7e;
++		}else{
++		    min_char = 0x20;
++		    max_char = 0x7f;
++		}
++	    }
++
++	    if (cs == NULL)
++		put_unknown_char(*str++);
++	    else if(*str < min_char || *str > max_char){	/* C1 */
++		switch(*str){
++		case ' ':
++		    {
++			unsigned char *p = str + 1;
++			while (*p == ' ' && p < estr)
++			    p++;
++			pack_string(ascii, str, (int) (p - str));
++			str = p;
++		    }
++		    break;
++
++		case '\t':
++		    pack_string(ascii, str++, 0);
++		    break;
++
++		case '\n':
++		    switch (context->eol) {
++		    case 0:				/* unix type eol */
++			pack_string(ascii, str, 0);
++			WaitCursor();
++			str++;
++			break;
++		    case 1:				/* dos type eol */
++		    case 2:				/* mac type eol */
++			put_unknown_char('\n');
++			str++;
++			break;
++		    case 3:				/* any type eol */
++			pack_string(ascii, str++, 0);
++			while (*str == '\n' || *str == '\r')
++			    str++;
++			WaitCursor();
++			break;
++		    }
++		    break;
++
++		case '\r':
++		    switch (context->eol) {
++		    case 0:
++			put_unknown_char('\r');
++			str++;
++			break;
++		    case 1:
++			str++;
++			if (*str == '\n')
++			    pack_string(ascii, str++, 0);
++			else
++			    put_unknown_char('\r');
++			break;
++		    case 2:
++			pack_string(ascii, str, 0);
++			WaitCursor();
++			str++;
++			break;
++		    case 3:
++			pack_string(ascii, str++, 0);
++			while (*str == '\n' || *str == '\r')
++			    str++;
++			WaitCursor();
++			break;
++		    }
++		    break;
++
++		case '\033':
++		    {
++			unsigned char *p;
++			str++;
++			if((p = escape_sequence(str)) == str)
++			    put_unknown_char('\033');
++			else
++			    str = p;
++		    }
++		    break;
++
++		case CODE_SI:
++		case CODE_SO:
++		    if (!context->lock_shift)
++			put_unknown_char((unsigned int) *str++);
++		    else
++			locking_shift((unsigned int) *str++);
++		    break;
++
++		default:
++		    put_unknown_char((unsigned int) *str++);
++		}
++	    }else{					/* GL */
++		if (context->ss != NULL) {
++		    pack_string(cs, str, 1);
++		    str += cs->bpc;
++		    context->ss = NULL;
++		} else {
++		    int n;
++
++		    if (cs->bpc == 1) {
++			unsigned char *p = str;
++			for (n = 0; p < estr; n++) {
++			    if (*p < min_char || *p > max_char)
++				break;
++			    p++;
++			}
++			pack_string(cs, str, n);
++			str = p;
++		    } else {
++			unsigned char *p = str;
++			for (n = 0; p < estr - 1; n++) {
++			    if (*p < min_char || *p > max_char ||
++				    *(p + 1) < min_char || *(p + 1) > max_char)
++				break;
++			    p += 2;
++			}
++			if (n > 0)
++			    pack_string(cs, str, n);
++			else
++			    put_unknown_char(*p++);
++			str = p;
++		    }
++		}
++	    }
++	}else{						/* right half */
++	    struct charset *cs = context->ss ? *context->ss : *context->gr;
++	    unsigned char min_char, max_char;
++	    if (cs != NULL) {
++		if(cs->noc == 94){
++		    min_char = 0xa1;
++		    max_char = 0xfe;
++		}else{
++		    min_char = 0xa0;
++		    max_char = 0xff;
++		}
++	    }
++
++	    if (cs == NULL)
++		put_unknown_char(*str++);
++	    else if(*str < min_char || *str > max_char){	/* C2 */
++		unsigned char c = *str++;
++		switch(c){
++		case CODE_SS2:
++		case CODE_SS3:
++		    single_shift((unsigned CHAR) c);
++		    break;
++		default:
++		    put_unknown_char(c);
++		}
++	    }else{					/* GR */
++		if (context->ss != NULL) {
++		    pack_string(cs, str, 1);
++		    str += cs->bpc;
++		    context->ss = NULL;
++		} else {
++		    int n;
++
++		    if (cs->bpc == 1) {
++			unsigned char *p = str;
++			for (n = 0; p < estr; n++) {
++			    if (*p < min_char || *p > max_char)
++				break;
++			    p++;
++			}
++			pack_string(cs, str, n);
++			str = p;
++		    } else {
++			unsigned char *p = str;
++			for (n = 0; p < estr - 1; n++) {
++			    if (*p < min_char || *p > max_char ||
++				    *(p + 1) < min_char || *(p + 1) > max_char)
++				break;
++			    p += 2;
++			}
++			if (n > 0)
++			    pack_string(cs, str, n);
++			else
++			    put_unknown_char(*p++);
++			str = p;
++		    }
++		}
++	    }
++	}
++    }
++
++    {
++	struct ml_text *tp = &context->text;
++	struct ml_line *lp;
++	int i;
++
++	tp->width = 0;
++	tp->height = 0;
++	for (lp = tp->lines, i = tp->nlines; i > 0; lp++, i--) {
++	    if (lp->nitems == 0) {
++		lp->ascent  = ascii->fs->ascent;
++		lp->descent = ascii->fs->descent;
++	    }
++	    if (tp->width < lp->width)
++		tp->width = lp->width;
++	    tp->height += lp->ascent + lp->descent;
++	}
++    }
++
++    SetCursors(-1);
++    return &context->text;
++}
++
++static unsigned char *escape_sequence(str)
++    unsigned char *str;
++{
++    unsigned char *p;
++    switch(*str){
++    case '$':
++    case '(': case ')': case '*': case '+':
++    case '-': case '.': case '/': case ',':
++	if((p = designator_sequence(str)) == NULL)
++	    return str;
++	return p;
++    case 'n': case 'o': case '~': case '}': case '|':
++	if (!context->lock_shift)
++	    return str;
++	locking_shift(*str);
++	return str + 1;
++    case 'N': case 'O':
++	single_shift(*str);
++	return str + 1;
++    }
++    return str;
++
++}
++
++static unsigned char *designator_sequence(str)
++    unsigned char *str;
++{
++    unsigned char *p = str;
++    int noc, bpc, n_g, shortened;
++    unsigned char des;
++    struct charset *cs;
++
++    if(*p == '$'){
++	bpc = 2;
++	p++;
++    }else
++	bpc = 1;
++
++    switch(*p++){
++    case '(':	noc = 94; n_g = 0; des = *p++; shortened = 0; break;
++    case ')':	noc = 94; n_g = 1; des = *p++; shortened = 0; break;
++    case '*':	noc = 94; n_g = 2; des = *p++; shortened = 0; break;
++    case '+':	noc = 94; n_g = 3; des = *p++; shortened = 0; break;
++#ifdef USE_MULE_EXTENSION
++    case ',':	noc = 96; n_g = 0; des = *p++; shortened = 0; break;
++#endif
++    case '-':	noc = 96; n_g = 1; des = *p++; shortened = 0; break;
++    case '.':	noc = 96; n_g = 2; des = *p++; shortened = 0; break;
++    case '/':	noc = 96; n_g = 3; des = *p++; shortened = 0; break;
++    case '@':	noc = 94; n_g = 0; des = 'B';  shortened = 0; break;
++    case 'A':	noc = 94; n_g = 0; des = 'A';  shortened = 1; break;
++    case 'B':	noc = 94; n_g = 0; des = 'B';  shortened = 1; break;
++    default:	return NULL;
++    }
++    if (!context->short_form && shortened)
++	return NULL;
++
++    if((cs = search_charset(bpc, noc, des)) == NULL){
++	if(DEBUG){
++	    fprintf(stderr, "designator_sequence: (%d,%d,%c) not found.\n",
++		    bpc, noc, des);
++	}
++	return NULL;
++    }
++    if (!context->valid[n_g])
++	return NULL;
++    context->g[n_g] = cs;
++    if(DEBUG){
++	fprintf(stderr,
++		"designator_sequence: G%d is `%s'.\n", n_g, cs->registry);
++    }
++    return p;
++}
++
++static void locking_shift(c)
++    unsigned CHAR c;
++{
++    switch((unsigned char) c){
++    case CODE_SI:	context->gl = &context->g[0]; break;
++    case CODE_SO:	context->gl = &context->g[1]; break;
++    case 'n':		context->gl = &context->g[2]; break;
++    case 'o':		context->gl = &context->g[3]; break;
++    case '~':		context->gr = &context->g[1]; break;
++    case '}':		context->gr = &context->g[2]; break;
++    case '|':		context->gr = &context->g[3]; break;
++    }
++    if(DEBUG){
++	fprintf(stderr, "locking_shift: (%d,%d).\n",
++		(int)(context->gl - context->g),
++		(int)(context->gr - context->g));
++    }
++}
++
++static void single_shift(c)
++    unsigned CHAR c;
++{
++    switch((unsigned char) c){
++    case CODE_SS2:	context->ss = &context->g[2]; break;
++    case CODE_SS3:	context->ss = &context->g[3]; break;
++    }
++}
++
++
++static void put_unknown_char(chr)
++    unsigned CHAR chr;
++{
++    unsigned char c = chr;
++
++    if(c < 0x20){
++	unsigned char buf[2];
++	buf[0] = '^';
++	buf[1] = c + 0x40;
++	pack_string(ascii, buf, 2);
++    }else{
++	unsigned char buf[4];
++	buf[0] = '\\';
++	buf[1] =  ((c >> 6) & 07) + '0';
++	buf[2] =  ((c >> 3) & 07) + '0';
++	buf[3] =  ((c     ) & 07) + '0';
++	pack_string(ascii, buf, 4);
++    }
++}
++
++struct context *ml_create_context(s)
++    Screen *s;
++{
++    context = (struct context *) malloc(sizeof *context);
++
++    context->g[0] = NULL;
++    context->g[1] = NULL;
++    context->g[2] = NULL;
++    context->g[3] = NULL;
++    context->gl = NULL;
++    context->gr = NULL;
++    context->ss = NULL;
++
++    context->cbuf = NULL;
++    context->text.maxlines = context->text.nlines = 0;
++    context->line = 0;
++    context->delta = 0;
++    context->toolong = 0;
++
++    DPY = DisplayOfScreen(s);
++    SCR = s;
++    ROOT_WIN = RootWindowOfScreen(s);
++
++    return context;
++}
++
++
++int ml_set_charsets(ctx, sys)
++    struct context *ctx;
++    struct coding_system *sys;
++{
++    int retval = 0;
++    int i;
++
++    context = ctx;
++
++    if(ascii == NULL){
++	init_xrm();
++	if((ascii = search_charset(1, 94, 'B')) == NULL){
++	    fputs("ml_set_charsets: ascii charset not found.\n", stderr);
++	    Quit(1);
++	}
++	if (ascii->fs == NULL) {
++	    fputs("ml_set_charsets: iso8859-1 font not found.\n", stderr);
++	    Quit(1);
++	}
++    }
++    for(i = 0; i < 4; i++){
++	switch(sys->design[i].bpc){
++	case -1:	/* make G[i] invalid */
++	    context->valid[i] = 0;
++	    break;
++
++	case 0:		/* don't change */
++	    break;
++
++	case 1: case 2:	/* change it */
++	    if((context->g[i] = search_charset(sys->design[i].bpc,
++					       sys->design[i].noc,
++					       sys->design[i].des)) == NULL){
++		fputs("ml_set_charsets: ", stderr);
++		fprintf(stderr, "(%d,%d,%c) is specified as G%d, ",
++			sys->design[i].bpc, sys->design[i].noc,
++			sys->design[i].des, i);
++		fputs("but not found. using `iso8859-1'.\n", stderr);
++		context->g[i] = ascii;
++		retval++;
++	    }
++	    context->valid[i] = 1;
++	    break;
++
++	default:	/* error */
++	    fprintf(stderr,"ml_set_charsets: bad arguments of G%d. ", i);
++	    fputs("using `iso8859-1'.\n", stderr);
++	    context->g[i] = ascii;
++	    retval++;
++	}
++    }
++    if((unsigned int) sys->gl < 4)
++	context->gl = &context->g[sys->gl];
++    else{
++	fprintf(stderr, "ml_set_charsets: bad number as GL. using G0.\n");
++	context->gl = &context->g[0];
++    }
++    if((unsigned int) sys->gr < 4)
++	context->gr = &context->g[sys->gr];
++    else{
++	fprintf(stderr, "ml_set_charsets: bad number as GR. using G0.\n");
++	context->gr = &context->g[0];
++    }
++    context->eol = sys->eol;
++    context->short_form = sys->short_form;
++    context->lock_shift = sys->lock_shift;
++    return retval;
++}
++
++static struct charset *search_charset(bpc, noc, des)
++    int bpc, noc;
++    int des;
++{
++    struct charset *cset;
++    for(cset = charset; cset->bpc != 0; cset++){
++	if(cset->bpc == bpc &&
++	   cset->noc == noc &&
++	   cset->designator == (char) des){
++	    if(!cset->loaded){
++#if 0
++		int i, l;
++		l = strlen(cset->registry);
++		for (i = 0; i < xrm_nfonts; i++) {
++		    int li = strlen(xrm_fonts[i]);
++		    if (li > l) {
++			if (xrm_fonts[i][li - l - 1] == '-' &&
++				strcmp(xrm_fonts[i] + li - l,
++				       cset->registry) == 0) {
++			    if ((cset->fs = XLoadQueryFont(DPY, xrm_fonts[i]))
++				    != NULL) {
++				if (DEBUG) {
++				    fprintf(stderr, "%s for %s\n",
++					    xrm_fonts[i], cset->registry);
++				}
++				cset->fontname = xrm_fonts[i];
++				break;
++			    } else
++				SetISTR(ISTR_WARNING,
++					"%s: font not found.", xrm_fonts[i]);
++			}
++		    }
++		}
++#else
++		int i, l;
++		l = strlen(cset->registry);
++		for (i = 0; i < xrm_nfonts && cset->fs == NULL; i++) {
++		    int j, nfnts = 0;
++		    char **fnts = XListFonts(DPY, xrm_fonts[i],
++					     65535, &nfnts);
++		    for (j = 0 ; j < nfnts; j++) {
++			int ll = strlen(fnts[j]);
++			if (*(fnts[j] + ll - l - 1) == '-' &&
++			    strcmp(fnts[j] + ll - l, cset->registry)== 0) {
++			    if ((cset->fs = XLoadQueryFont(DPY, fnts[j]))
++				!= NULL) {
++				if (DEBUG) {
++				    fprintf(stderr, "%s for %s\n",
++					    fnts[j], cset->registry);
++				}
++				cset->fontname = strdup(fnts[j]);
++				break;
++			    } else
++				SetISTR(ISTR_WARNING,
++					"%s: font not found", fnts[j]);
++			}
++		    }
++		    if (fnts != NULL)
++			XFreeFontNames(fnts);
++		}
++#endif
++		if(cset->fs == NULL){
++		    SetISTR(ISTR_WARNING,
++			    "font for %s not found.\nusing ascii font.",
++			    cset->registry);
++		    if (ascii != NULL)
++			cset->fs = ascii->fs;
++		}
++
++		cset->loaded = 1;
++	    }
++	    return cset;
++	}
++    }
++    return NULL;
++}
++
++static void pack_string(cs, str, len)
++    struct charset *cs;
++    unsigned char *str;
++    int len;	/* number of chars(not bytes) */
++{
++    struct ml_text *mt = &context->text;
++    struct ml_line *lp;
++    XTextItem16 *ip;
++
++    if (context->line == mt->maxlines) {
++	int oldmax = mt->maxlines;
++	if (mt->maxlines < 1)
++	    mt->maxlines = 1;
++	else
++	    mt->maxlines = 2 * mt->maxlines;
++	if (oldmax == 0)
++	    mt->lines = (struct ml_line *)
++				malloc(sizeof(struct ml_line) * mt->maxlines);
++	else {
++	    mt->lines = (struct ml_line *)
++				realloc(mt->lines,
++					sizeof(struct ml_line) * mt->maxlines);
++	}
++    }
++    lp = &mt->lines[context->line];
++    if (mt->nlines == context->line) {
++	mt->nlines++;
++	lp->maxitems = 0;
++	lp->nitems = 0;
++	lp->width = 0;
++	lp->ascent = lp->descent = 0;
++    }
++
++    if (len == 0) {
++	switch (*str) {
++	case '\n':
++	    context->line++;
++	    context->delta = 0;
++	    context->toolong = 0;
++	    break;
++	case '\t':
++	    {
++		int nx, x = lp->width + context->delta;
++		nx = (x + ml_tab_width) / ml_tab_width * ml_tab_width;
++		context->delta += nx - x;
++	    }
++	    break;
++	}
++	return;
++    }
++
++    if (context->toolong)
++	return;
++    if (lp->width > 30000) {
++	context->toolong = 1;
++	cs = ascii;
++	str = (unsigned char *) "...";
++	len = 3;
++    }
++
++    if (lp->nitems == lp->maxitems) {
++	int oldmax = lp->maxitems;
++	if (lp->maxitems < 1)
++	    lp->maxitems = 1;
++	else
++	    lp->maxitems = 2 * lp->maxitems;
++	if (oldmax == 0)
++	    lp->items = (XTextItem16 *)
++				malloc(sizeof(XTextItem16) * lp->maxitems);
++	else
++	    lp->items = (XTextItem16 *)
++				realloc(lp->items,
++					sizeof(XTextItem16) * lp->maxitems);
++    }
++    ip = &lp->items[lp->nitems++];
++    ip->chars = (XChar2b *) context->cbp;
++    ip->nchars = len;
++    ip->delta = context->delta;
++    ip->font = cs->fs->fid;
++    context->cbp += 2 * len;
++    context->delta = 0;
++
++    if (cs->bpc == 1) {
++	XChar2b *p;
++	unsigned char b7 = cs->bit7 ? 0x80 : 0;
++	int i;
++	for (i = len, p = ip->chars; i > 0; i--, p++) {
++	    p->byte1 = '\0';
++	    p->byte2 = (*str++ & 0x7f) | b7;
++	}
++    } else {
++	XChar2b *p;
++	unsigned char b7 = cs->bit7 ? 0x80 : 0;
++	int i;
++	for (i = len, p = ip->chars; i > 0; i--, p++) {
++	    p->byte1 = (*str++ & 0x7f) | b7;
++	    p->byte2 = (*str++ & 0x7f) | b7;
++	}
++    }
++
++    lp->width += XTextWidth16(cs->fs, ip->chars, ip->nchars);
++    if (lp->ascent < cs->fs->ascent)
++	lp->ascent = cs->fs->ascent;
++    if (lp->descent < cs->fs->descent)
++	lp->descent = cs->fs->descent;
++}
++
++void get_monofont_size(wide, high)
++    int *wide, *high;
++{
++    if (ascii == NULL) {
++	fputs("ml_draw_text: call ml_set_charsets, first.\n", stderr);
++	return;
++    }
++    *wide = ascii->fs->max_bounds.width;
++    *high = ascii->fs->ascent + ascii->fs->descent;
++}
++
++static void init_xrm()
++{
++    init_xrm_fonts();
++    init_xrm_tab();
++}
++
++static void init_xrm_fonts()
++{
++    char *p, *fns = XGetDefault(theDisp, "xv", "fontSet");
++    int n;
++    if (fns == NULL) {
++	xrm_fonts = default_fonts;
++	xrm_nfonts = sizeof default_fonts / sizeof *default_fonts;
++	return;
++    }
++    while(*fns == ' ' || *fns == '\t')
++	fns++;
++    if (*fns == '\0') {
++	xrm_fonts = default_fonts;
++	xrm_nfonts = sizeof default_fonts / sizeof *default_fonts;
++	return;
++    }
++    fns = strdup(fns);
++
++    n = 1;
++    for (p = fns; *p != '\0'; p++) {
++	if (*p == ',')
++	    n++;
++    }
++    xrm_nfonts = n;
++    xrm_fonts = (char **) malloc(sizeof (char *) * xrm_nfonts);
++    for (n = 0, p = fns; n < xrm_nfonts && *p != '\0'; ) {
++	while (*p == ' ' || *p == '\t')
++	    p++;
++	xrm_fonts[n++] = p;
++	while (1) {
++	    char *q;
++	    while (*p != ' ' && *p != '\t' && *p != ',' && *p != '\0')
++		p++;
++	    q = p;
++	    while (*q == ' ' || *q == '\t')
++		q++;
++	    if (*q == ',' || *q == '\0') {
++		*p = '\0';
++		p = q + 1;
++		break;
++	    } else
++		p = q;
++	}
++    }
++    for ( ; n < xrm_nfonts; n++)
++	xrm_fonts[n] = "";
++}
++
++static void init_xrm_tab()
++{
++    char *ts = XGetDefault(theDisp, "xv", "tabWidth");
++    unsigned short tab;
++    if (ts == NULL)
++	tab = 64;
++    else {
++	char *ep;
++	long t;
++	int bad = 0;
++	t = strtol(ts, &ep, 0);
++	tab = (unsigned short) t;
++	if (ep != NULL) {
++	    while (*ep == ' ' && *ep == '\t')
++		ep++;
++	    if (*ep != '\0')
++		bad = 1;
++	}
++	if (tab != (long) (unsigned long) t)
++	    bad = 1;
++	if (bad) {
++	    SetISTR(ISTR_WARNING, "bad tab width.");
++	    tab = 64;
++	}
++    }
++    ml_tab_width = tab;
++}
++
++
++#ifndef HAVE_STRDUP
++static char *strdup(str)
++    char *str;
++{
++    return strcpy(malloc(strlen(str) + 1), str);
++}
++#endif
++
++char *lookup_registry(d, b7)
++    struct design d;
++    int *b7;
++{
++    int i;
++    for (i = 0; i < NR_CHARSETS; i++) {
++	if (charset[i].bpc == d.bpc && charset[i].noc == d.noc &&
++	    charset[i].designator == d.des) {
++	    *b7 = charset[i].bit7;
++	    return charset[i].registry;
++	}
++    }
++    return NULL;
++}
++
++struct design lookup_design(registry, b7)
++    char *registry;
++    int b7;
++{
++    struct design d;
++    int i;
++    d.bpc = 0;
++    d.noc = 0;
++    d.des = '\0';
++    for (i = 0; i < NR_CHARSETS; i++) {
++	if (strcmp(charset[i].registry, registry) == 0 &&
++		charset[i].bit7 == b7) {
++	    d.bpc = charset[i].bpc;
++	    d.noc = charset[i].noc;
++	    d.des = charset[i].designator;
++	    break;
++	}
++    }
++    return d;
++}
++
++char *sjis_to_jis(orig, len, newlen)
++    char *orig;
++    int len, *newlen;
++{
++    unsigned char *new;
++    unsigned char *p, *q, *endp;
++    if (len == 0) {
++	*newlen = 0;
++	return (char *) malloc((size_t) 1);
++    }
++    new = (unsigned char *) malloc((size_t) len * 4);	/* big enough */
++    for (p = (unsigned char *) orig, endp = p + len, q = new; p < endp; ) {
++	if ((*p & 0x80) == 0)			/* 1 byte char */
++	    *q++ = *p++;
++	else if (*p >= 0x81 && *p <= 0x9f) {	/* kanji 1st byte */
++	    unsigned char c1 = *p++;
++	    unsigned char c2 = *p++;
++	    if (c2 < 0x40 || c2 > 0xfc) {		/* bad 2nd byte */
++		*q++ = CODE_SS2;
++		*q++ = c1;
++		*q++ = CODE_SS2;
++		*q++ = c2;
++	    } else {					/* right 2nd byte */
++		if (c2 <= 0x9e) {
++		    if (c2 > 0x7f)
++			c2--;
++		    c1 = (c1 - 0x81) * 2 + 1 + 0xa0;
++		    c2 = (c2 - 0x40)     + 1 + 0xa0;
++		} else {
++		    c1 = (c1 - 0x81) * 2 + 2 + 0xa0;
++		    c2 = (c2 - 0x9f)     + 1 + 0xa0;
++		}
++		*q++ = c1;
++		*q++ = c2;
++	    }
++	} else if (*p >= 0xe0 && *p <= 0xef) {	/* kanji 1st byte */
++	    unsigned char c1 = *p++;
++	    unsigned char c2 = *p++;
++	    if (c2 < 0x40 || c2 > 0xfc) {		/* bad 2nd byte */
++		*q++ = CODE_SS2;
++		*q++ = c1;
++		*q++ = CODE_SS2;
++		*q++ = c2;
++	    } else {					/* right 2nd byte */
++		if (c2 <= 0x9e) {
++		    c1 = (c1 - 0xe0) * 2 + 63 + 0xa0;
++		    c2 = (c2 - 0x40)     +  1 + 0xa0;
++		} else {
++		    c1 = (c1 - 0xe0) * 2 + 64 + 0xa0;
++		    c2 = (c2 - 0x9f)     +  1 + 0xa0;
++		}
++		*q++ = c1;
++		*q++ = c2;
++	    }
++	} else {				/* katakana or something */
++	    *q++ = CODE_SS2;
++	    *q++ = *p++;
++	}
++    }
++    *newlen = q - new;
++
++    return (char *) realloc(new, (size_t) *newlen);
++}
++
++#endif /* TV_MULTILINGUAL */
+diff -Naru xv-3.10a/xvml.h xv-3.10a.jumbo/xvml.h
+--- xv-3.10a/xvml.h	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvml.h	2005-04-18 07:57:45.000000000 +0200
+@@ -0,0 +1,96 @@
++#ifndef MLVIEW_H
++#define MLVIEW_H
++
++/*
++ * What is this?
++ *
++ *  It is a package to show multi-lingual text.
++ *
++ * How to use?
++ *
++ *  1. Call ml_set_screen(Screen *scr);
++ *	Tell this package the screen you use.
++ *
++ *  2. Call ml_set_charsets(struct char_spec spec[4], int gl, int gr);
++ *	Tell this package the initial charsets.
++ *	Gn is set to the charset specified by spec[n], respectively.
++ *	GL and GR are set to G[gl] and G[gr], respectively.
++ *	If first call, iso8859-1 font is loaded.
++ *
++ *  3. Call ml_draw_text(char *string);
++ *	It Creates a bitmap, and returns it to you.
++ *	If something goes wrong, it returns None.
++ *	DON'T free the returned pixmaps!!
++ *
++ * BUGS:
++ *  - Amharic and Tigrigna characters are strange.
++ *  - Big5 is not supported.
++ *  - Reverse direction is not supported.
++ *  - Composing is not supported.
++ *  - Cantonese can't be shown.
++ *  - Texts which have many lines are buggy.
++ *
++ * NOTE:
++ *  - Shifted JIS and Shifted GB must be converted to iso2022 in advance.
++ *
++ * Example of parameters to ml_set_charsets:
++ *  - EUC-Japan
++ *	spec = { {1, 94, 'B'},		G0 is US-ASCII
++ *		 {2, 94, 'B'},		G1 is JIS X0208
++ *		 {1, 94, 'J'},		G2 is (right-half of)JIS X0201
++ *		 {2, 94, 'D'} };	G3 is JIS X0212
++ *	gl = 0;				GL is G0
++ *	gr = 1;				GR is G1
++ *
++ *  - Compound Text
++ *	spec = { {1, 94, 'B'},		G0 is US-ASCII
++ *		 {1, 96, 'A'},		G1 is Latin-1
++ *		 {1, 94, 'B'},		G2 is US-ASCII (maybe unused)
++ *		 {1, 94, 'B'} };	G3 is US-ASCII (maybe unused)
++ *	gl = 0;				GL is G0
++ *	gr = 1;				GR is G1
++ *
++ *  - Korean Mail
++ *	spec = { {1, 94, 'B'},		G0 is US-ASCII
++ *		 {2, 94, 'C'},		G1 is KSC5601
++ *		 {1, 94, 'B'},		G2 is US-ASCII (maybe unused)
++ *		 {1, 94, 'B'} };	G3 is US-ASCII (maybe unused)
++ *	gl = 0;				GL is G0
++ *	gl = 1;				GR is G1
++ */
++
++struct coding_system {
++    struct design {
++	int bpc;	/* byte per char if 1 or 2,
++			   don't touch if 0, or
++			   don't use if -1.*/
++	int noc;	/* number of chars (94 or 96) */
++	char des;	/* designator ('A', 'B', ...) */
++    } design[4];
++    int gl, gr;
++    int eol;
++    int short_form;
++    int lock_shift;
++};
++
++struct ml_text {
++    int maxlines, nlines;
++    struct ml_line {
++	int maxitems, nitems;
++	int width, ascent, descent;
++	XTextItem16 *items;
++    } *lines;
++    int width, height;
++};
++
++struct context;
++struct ml_text *ml_draw_text		PARM((struct context *, char *, int));
++struct context *ml_create_context	PARM((Screen *));
++int ml_set_charsets			PARM((struct context *,
++					      struct coding_system *));
++void get_monofont_size			PARM((int *, int *));
++char *sjis_to_jis			PARM((char *, int, int *));
++char *lookup_registry			PARM((struct design, int *));
++struct design lookup_design		PARM((char *, int));
++
++#endif
+diff -Naru xv-3.10a/xvpcd.c xv-3.10a.jumbo/xvpcd.c
+--- xv-3.10a/xvpcd.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvpcd.c	2007-05-14 03:02:13.000000000 +0200
+@@ -0,0 +1,1311 @@
++/*
++ * xvpcd.c - load routine for 'PhotoCD' format pictures
++ *
++ * LoadPCD(fname, pinfo, size)  -  loads a PhotoCD file
++ *
++ * This routine will popup a choice of which of the 5 available resolutions
++ * the user wants to choose, then load it as a 24 bit image.
++ *
++ * Copyright 1993 David Clunie, Melbourne, Australia.
++ *
++ * The outline of this is shamelessly derived from xvpbm.c to read the
++ * file, and xvtiffwr.c to handle the popup window and X stuff (X never
++ * has been my forte !), and the PhotoCD format information (though not
++ * the code) was found in Hadmut Danisch's (danisch at ira.uka.de) hpcdtoppm
++ * program in which he has reverse engineered the format by studying
++ * hex dumps of PhotoCDs ! After all who can afford the Kodak developer's
++ * kit, which none of us have seen yet ? Am I even allowed to mention these
++ * words (Kodak, PhotoCD) ? I presume they are registered trade marks.
++ *
++ * PS. I have no idea how Halmut worked out the YCC <-> RGB conversion
++ * factors, but I have calculated them from his tables and the results
++ * look good enough to me.
++ *
++ * Added size parameter to allow the schnautzer to create thumnails
++ * without requesting the size every time.
++ */
++
++#include "xv.h"
++
++#ifdef HAVE_PCD
++
++#include <memory.h>
++#ifndef alloca
++#  include <alloca.h> /* "not in POSIX or SUSv3" according to Linux man page */
++#endif                /* ...but required for Sun C compiler (alloca = macro) */
++
++#define  TRACE  0
++#if TRACE
++#  define trace(x) fprintf x
++#else
++#  define trace(x)
++#endif
++
++/* Comments on error-handling:
++   A truncated file is not considered a Major Error.  The file is loaded,
++   and the rest of the pic is filled with 0's.
++
++   Not being able to malloc is a Fatal Error.  The program is aborted. */
++
++
++#ifdef __STDC__
++static void magnify(int, int, int, int, int, byte *);
++static int pcdError(const char *, const char *);
++static int gethuffdata(byte *, byte *, byte *, int, int);
++#else
++static void magnify();
++static int pcdError();
++static int gethuffdata();
++#endif
++
++#define wcurfactor 16  /* Call WaitCursor() every n rows */
++
++static int  size;    /* Set by window routines */
++static int  leaveitup;/* Cleared by docmd() when OK or CANCEL pressed */
++static int  goforit;  /* Set to 1 if OK or 0 if CANCEL */
++static FILE  *fp;
++static CBUTT  lutCB;
++
++/*
++ * This "beyond 100%" table is taken from ImageMagick (gamma 2.2).
++ * Why there are 351 entries and not 346 as per Kodak documentation
++ * is a mystery.
++ */
++static  double  rscale = 1.00,
++    gscale = 1.00,
++    bscale = 1.00;
++
++static  byte  Y[351] = {
++    0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
++   10,  11,  12,  13,  14,  15,  16,  17,  18,  19,
++   20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
++   30,  32,  33,  34,  35,  36,  37,  38,  39,  40,
++   41,  42,  43,  45,  46,  47,  48,  49,  50,  51,
++   52,  53,  54,  56,  57,  58,  59,  60,  61,  62,
++   63,  64,  66,  67,  68,  69,  70,  71,  72,  73,
++   74,  76,  77,  78,  79,  80,  81,  82,  83,  84,
++   86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
++   97,  98,  99, 100, 101, 102, 103, 104, 105, 106,
++  107, 108, 110, 111, 112, 113, 114, 115, 116, 117,
++  118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
++  129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
++  139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
++  149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
++  159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
++  169, 170, 171, 172, 173, 174, 175, 176, 176, 177,
++  178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
++  188, 189, 190, 191, 192, 193, 193, 194, 195, 196,
++  197, 198, 199, 200, 201, 201, 202, 203, 204, 205,
++  206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
++  214, 215, 215, 216, 217, 218, 218, 219, 220, 221,
++  221, 222, 223, 224, 224, 225, 226, 226, 227, 228,
++  228, 229, 230, 230, 231, 232, 232, 233, 234, 234,
++  235, 236, 236, 237, 237, 238, 238, 239, 240, 240,
++  241, 241, 242, 242, 243, 243, 244, 244, 245, 245,
++  245, 246, 246, 247, 247, 247, 248, 248, 248, 249,
++  249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
++  251, 251, 252, 252, 252, 252, 252, 253, 253, 253,
++  253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
++  254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
++  254, 254, 254, 254, 254, 254, 254, 254, 254, 255,
++  255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
++  255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
++  255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
++  255
++};
++
++/*******************************************/
++/* The size should be -1 for the popup to ask otherwise fast is assumed */
++/* returns '1' on success */
++/*******************************************/
++int
++LoadPCD(char *fname, PICINFO *pinfo, int theSize)
++{
++  long   offset;
++  int    mag;
++  int   rotate;
++  byte   header[3*0x800];
++  byte  *pic24, *luma, *chroma1, *chroma2, *ptr, *lptr, *c1ptr, *c2ptr;
++  int   w, h, npixels, bufsize;
++  int   row, col;
++  int  huffplanes;
++  const char  *bname;
++
++  bname    = BaseName(fname);
++  pinfo->pic  = NULL;
++  pinfo->comment  = NULL;
++
++
++  /*
++   *  open the file
++   */
++  if((fp=fopen(fname,"r")) == NULL)
++    return pcdError(bname, "can't open file");
++
++  /*
++   * inspect the header
++   */
++  if(fread(&header[0], 1, sizeof(header), fp) != sizeof(header))
++    return pcdError(bname, "could not load PCD header");
++  if(strncmp((char *)&header[0x800], "PCD_", 4) != 0)
++    return pcdError(bname, "not a PCD file");
++  rotate = header[0x0E02] & 0x03;
++
++/* base/16
++  - plain data starts at sector 1+2+1=4
++    (numbered from 0, ie. the 5th sector)
++  - luma 192*128 = 24576 bytes (12 sectors)
++    + chroma1 96*64 = 6144 bytes (3 sectors)
++    + chroma2 96*64 = 6144 bytes (3 sectors)
++    = total 18 sectors
++
++  - NB. "Plain" data is interleaved - 2 luma rows 192 wide,
++    then 1 of each of the chroma rows 96 wide !
++
++   base/4
++  - plain data starts at sector 1+2+1+18+1=23
++  - luma 384*256 = 98304 bytes (48 sectors)
++    + chroma1 192*128 = 24576 bytes (12 sectors)
++    + chroma2 192*128 = 24576 bytes (12 sectors)
++    = total 72 sectors
++
++  - NB. "Plain" data is interleaved - 2 luma rows 384 wide,
++    then 1 of each of the chroma rows 192 wide !
++
++   base
++  - plain data starts at sector 1+2+1+18+1+72+1=96
++
++  - luma 768*512 = 393216 bytes (192 sectors)
++    + chroma1 384*256 = 98304 bytes (48 sectors)
++    + chroma2 384*256 = 98304 bytes (48 sectors)
++    = total 288 sectors
++
++  - NB. "Plain" data is interleaved - 2 luma rows 768 wide,
++    then 1 of each of the chroma rows 384 wide !
++
++   4base
++  - plain data for base is read
++  - luma data interpolated *2
++  - chroma data interpolated *4
++
++  - cd_offset is 1+2+1+18+1+72+1+288=384
++  - at cd_offset+4 (388) is huffman table
++  - at cd_offset+5 (389) is 4base luma plane
++
++  (the sector at cd_offset+3 seems to contain 256 words each of
++  which is an offset presumably to the sector containing certain
++  rows ? rows/4 given 1024 possible rows. The rest of this sector
++  is filled with zeroes)
++
++
++   16base
++  - plain data for base is read
++  - luma data interpolated *2
++  - chroma data interpolated *4
++
++  - cd_offset is 1+2+1+18+1+72+1+288=384
++  - at cd_offset+4 (388) is huffman table for 4 base
++  - at cd_offset+5 (389) is 4base luma plane
++  - luma plane interpolated *2
++
++  - cd_offset is set to current position (should be start of sector)
++  - at cd_offset+12 is huffman table for 16 base
++  - at cd_offset+14 is 16 base luma & 2 chroma planes which are read
++          (note that the luma plane comes first, with a sync pattern
++           announcing each row from 0 to 2047, then the two chroma planes
++           are interleaved by row, the row # being even from 0 to 2046, with
++           each row containing 1536 values, the chroma1 row coming first,
++           finally followed by a sync pattern with a row of 2048 announcing
++           the end (its plane seems to be set to 3, ie. chroma2)
++  - chroma planes interpolated *2
++
++  (the sector at cd_offset+10 & 11 seem to contain 1024 pairs of words
++        the first for luma and the second for chroma, each of
++  which is an offset presumably to the sector containing certain
++  rows ? rows/2 given 2048 possible rows)
++
++Not yet implemented:
++
++In order to do overskip for base and 4base, one has to reach the chroma
++data for 16 base:
++
++  - for 4base, after reading the 4base luma plane (and presumably
++    skipping the chroma planes) one sets cd_offset to the start of
++    the "current" sector
++
++  - for base, one has to skip the 4base data first:
++  - cd_offset is set to 384
++  - at (cd_offset+3 sectors)[510] is a 16 bit word high byte 1st
++    containing an offset to the beginning of the 16base stuff
++    though there is then a loop until >30 0xff's start a sector !
++
++  - being now positioned after the end of the 4base stuff,
++  - at (cd_offset+10 sectors)[2] is a 16 bit word high byte 1st
++    containing an offset to the chroma planes.
++  - at cd_offset+12 is the set of huffman tables
++
++  - for base, the 16base chroma planes are then halved
++*/
++
++  PCDSetParamOptions(bname);
++  if (theSize == -1)
++  {
++    PCDDialog(1);                   /* Open PCD Dialog box */
++    SetCursors(-1);                 /* Somebody has already set it to wait :( */
++    leaveitup=1;
++    goforit=0;
++  size = 1;
++    /* block until the popup window gets closed */
++    while (leaveitup) {
++      int i;
++      XEvent event;
++      XNextEvent(theDisp, &event);
++      HandleEvent(&event, &i);
++    }
++    /* At this point goforit and size will have been set */
++    if (!goforit) {
++      /* nothing allocated so nothing needs freeing */
++      return 0;
++    }
++    WaitCursor();
++  }
++  else
++  {
++    size = theSize;
++    goforit = 1;
++  }
++
++  if(lutCB.val)
++    rscale = gscale = bscale = 255.0/346.0;
++  else
++    rscale = gscale = bscale = 1.0;
++
++  switch (size) {
++  case 0:
++    pinfo->w = 192;
++    pinfo->h = 128;
++    offset=4*0x800;
++    mag=1;
++    huffplanes=0;
++    sprintf(pinfo->fullInfo, "PhotoCD, base/16 resolution");
++    break;
++
++  case 1:
++    pinfo->w = 384;
++    pinfo->h = 256;
++    offset=23*0x800;
++    mag=1;
++    huffplanes=0;
++    sprintf(pinfo->fullInfo, "PhotoCD, base/4 resolution");
++    break;
++
++  case 2:
++  default:
++    pinfo->w = 768;
++    pinfo->h = 512;
++    offset=96*0x800;
++    mag=1;
++    huffplanes=0;
++    sprintf(pinfo->fullInfo, "PhotoCD, base resolution");
++    break;
++
++  case 3:
++    pinfo->w = 1536;
++    pinfo->h = 1024;
++    offset=96*0x800;
++    mag=2;
++    huffplanes=1;
++    sprintf(pinfo->fullInfo, "PhotoCD, 4base resolution");
++    break;
++
++  case 4:
++    pinfo->w=3072;
++    pinfo->h=2048;
++    offset=96*0x800;
++    mag=4;
++    huffplanes=2;
++    sprintf(pinfo->fullInfo, "PhotoCD, 16base resolution");
++    break;
++  }
++
++  /*
++   * rotate?
++   */
++  w = pinfo->w;
++  h = pinfo->h;
++  switch(rotate) {
++  case  0:
++    break;
++
++  case  1:
++  case  3:
++    pinfo->w = h;
++    pinfo->h = w;
++    break;
++
++  default:
++    fprintf(stderr, "unknown image rotate %d; assuming none\n",
++      rotate);
++    rotate = 0;
++  }
++
++  /*
++   * allocate 24-bit image
++   */
++  npixels = pinfo->w * pinfo->h;
++  bufsize = 3 * npixels;
++  if (pinfo->w <= 0 || pinfo->h <= 0 || npixels/pinfo->w != pinfo->h ||
++      bufsize/3 != npixels)
++    FatalError("image dimensions out of range");
++
++  pinfo->pic = (byte *)malloc((size_t) bufsize);
++  if(!pinfo->pic)
++    FatalError("couldn't malloc '24-bit RGB plane'");
++
++  pinfo->type = PIC24;
++  sprintf(pinfo->shrtInfo, "%dx%d PhotoCD.", pinfo->w, pinfo->h);
++  pinfo->colType = F_FULLCOLOR;
++  pinfo->frmType = -1;
++
++  if(fseek(fp, offset, SEEK_SET) == -1) {
++    free(pinfo->pic);
++    return pcdError(bname,"Can't find start of data.");
++  }
++
++  pic24 = pinfo->pic;
++
++  luma=(byte *)calloc(npixels,1);
++  if(!luma) {
++    free(pinfo->pic);
++    FatalError("couldn't malloc 'luma plane'");
++  }
++
++  chroma1=(byte *)calloc(npixels/4,1);
++  if(!chroma1) {
++    free(pinfo->pic);
++    free(luma);
++    FatalError("couldn't malloc 'chroma1 plane'");
++  }
++
++  chroma2=(byte *)calloc(npixels/4,1);
++  if(!chroma2) {
++    free(pinfo->pic);
++    free(luma);
++    free(chroma1);
++    FatalError("couldn't malloc 'chroma2 plane'");
++  }
++
++  /* Read 2 luma rows length w, then one of each chroma rows w/2 */
++  /* If a mag factor is active, the small image is read into the */
++  /* top right hand corner of the larger allocated image */
++
++  trace((stderr, "base image: start @ 0x%08lx (sector %ld.%ld)\n",
++        ftell(fp), ftell(fp)/0x800, ftell(fp) % 0x800));
++  for(row=0,lptr=luma,c1ptr=chroma1,c2ptr=chroma2; row <h/mag;
++        row+=2,lptr+=w*2,c1ptr+=w/2,c2ptr+=w/2) {
++    if(fread(lptr, 1, w/mag, fp) != w/mag) {
++      pcdError(bname, "Luma plane too short.");
++      break;
++    }
++    if(fread(lptr+w, 1, w/mag, fp) != w/mag) {
++      pcdError(bname, "Luma plane too short.");
++      break;
++    }
++    if(fread(c1ptr, 1, w/2/mag, fp) != w/2/mag) {
++      pcdError(bname, "Chroma1 plane too short.");
++      break;
++    }
++    if(fread(c2ptr, 1, w/2/mag, fp) != w/2/mag) {
++      pcdError(bname, "Chroma2 plane too short.");
++      break;
++    }
++    if(row%wcurfactor == 0)
++      WaitCursor();
++  }
++  trace((stderr, "base image: done @ 0x%08lx (sector %ld.%ld)\n",
++        ftell(fp), ftell(fp)/0x800, ftell(fp) % 0x800));
++
++  if(huffplanes) {
++    if(fseek(fp, 388*0x800, SEEK_SET) == -1)
++      return pcdError(bname,
++          "Can't find start of huffman tables.");
++
++    magnify(2, h/mag, w/mag, h, w, luma);
++    magnify(2, h/2/mag, w/2/mag, h/2, w/2, chroma1);
++    magnify(2, h/2/mag, w/2/mag, h/2, w/2, chroma2);
++
++    /*
++     * doesn't really touch the chroma planes which aren't
++     * present in 4base
++     */
++    gethuffdata(luma, chroma1, chroma2, w, h/mag*2);
++
++    /*
++     * if only doing 4base should probably fetch 16bases
++     * chroma planes here
++     */
++    if(huffplanes == 2) {
++      /*
++       * This depends on gethuffdata() having grabbed
++       * things in 0x800 sectors AND still being
++       * positioned in the "last" sector of the data
++       * (cf. Hadmut's code which is positioned at start
++       * of the next sector)
++       */
++      long  offset = ftell(fp)/0x800+12;
++
++      if(fseek(fp, offset*0x800, SEEK_SET) == 0) {
++        magnify(2,h/2,w/2,h,w,luma);
++        magnify(2,h/4,w/4,h/2,w/2,chroma1);
++        magnify(2,h/4,w/4,h/2,w/2,chroma2);
++        gethuffdata(luma,chroma1,chroma2,w,h);
++      } else
++        fprintf(stderr, "can't seek to 2nd huffman tables\n");
++    }
++  }
++  fclose(fp);
++
++  /*
++   * YCC -> R'G'B' and image rotate
++   */
++  ptr=pic24;
++  lptr=luma; c1ptr=chroma1; c2ptr=chroma2;
++  for(row = 0; row < h; ++row) {
++    byte  *rowc1ptr = c1ptr,
++      *rowc2ptr = c2ptr;
++    int  k = 0;
++
++    switch(rotate) {
++    case  1:
++      ptr = &pic24[row*3 + (w - 1)*h*3];
++        k = -3*(h + 1);
++      break;
++
++    case  3:
++      ptr = &pic24[(h - 1 - row)*3];
++        k =  3*(h - 1);
++      break;
++
++    default:
++      ptr = &pic24[row*w*3];
++        k = 0;
++      break;
++    }
++    for(col = 0; col < w; ++col) {
++      double  L  = 1.3584*(double) *lptr++,
++        C1  = 2.2179*(double) (*c1ptr - 156),
++        C2  = 1.8215*(double) (*c2ptr - 137);
++      int  r  = rscale*(L + C2),
++        g  = gscale*(L - 0.194*C1 - 0.509*C2),
++        b  = bscale*(L + C1);
++
++      if(lutCB.val) {
++        if(r < 0) r = 0; else if(r >= 255) r = 255;
++        if(g < 0) g = 0; else if(g >= 255) g = 255;
++        if(b < 0) b = 0; else if(b >= 255) b = 255;
++      } else {
++        if(r < 0) r = 0; else if(r >= 351) r = 350;
++        if(g < 0) g = 0; else if(g >= 351) g = 350;
++        if(b < 0) b = 0; else if(b >= 351) b = 350;
++        r = Y[r]; g = Y[g]; b = Y[b];
++      }
++      *ptr++ = r;
++      *ptr++ = g;
++      *ptr++ = b;
++      ptr   += k;
++      if(col & 1) {
++        ++c1ptr;
++        ++c2ptr;
++      }
++    }
++    if((row & 1) == 0) {
++      c1ptr = rowc1ptr;
++      c2ptr = rowc2ptr;
++    }
++    if(row%wcurfactor == 0)
++      WaitCursor();
++  }
++  free(luma); free(chroma1); free(chroma2);
++  return 1;
++}
++
++/*
++ * derived from Hadmut Danisch's interpolate()
++ */
++static void
++magnify(int mag,  /* power of 2 by which to magnify in place */
++  int h, int w,  /* the "start" unmag'd dimensions of the array */
++  int mh, int mw,  /* the real (maximum) dimensions of the array */
++  byte *p)  /* pointer to the data */
++{
++  int x,y,yi;
++  byte *optr,*nptr,*uptr;  /* MUST be unsigned, else averaging fails */
++
++  while (mag > 1) {
++
++    /* create every 2nd new row from 0 */
++    /*  even pixels being equal to the old, odd ones averaged with successor */
++    /*  special case being the last column which is just set equal to the */
++    /*  second last) ... */
++
++    for(y=0;y<h;y++) {
++      yi=h-1-y;
++      optr=p+  yi*mw + (w-1);            /* last pixel of an old row */
++      nptr=p+2*yi*mw + (2*w - 2);         /* last pixel of a new row */
++
++      nptr[0]=nptr[1]=optr[0];            /* special cases */
++
++      for(x=1;x<w;x++) {
++        optr--; nptr-=2;                  /* next lower pixel(s) */
++        nptr[0]=optr[0];                  /* even pixels duped */
++        nptr[1]=(((int)optr[0])+
++                 ((int)optr[1])+1)>>1;    /* odd averaged */
++      }
++    }
++
++    /* Fill in odd rows, as average of prior & succeeding rows, with */
++    /* even pixels average of one column, odd pixels average of two */
++
++    for(y=0;y<h-1;y++) {                  /* all but the last old row */
++      optr=p + 2*y*mw;                    /* start of the new "even" rows */
++      nptr=optr+mw;                       /* start of the next empty row */
++      uptr=nptr+mw;                       /* start of the next again (even) */
++
++      for(x=0;x<w-1;x++) {                /* for all cols except the last */
++        nptr[0]=(((int)optr[0])+
++                 ((int)uptr[0])+1)>>1;    /* even pixels */
++        nptr[1]=(((int)optr[0])+
++                 ((int)optr[2])+
++                 ((int)uptr[0])+
++                 ((int)uptr[2])+2)>>2;    /* odd pixels */
++        nptr+=2; optr+=2; uptr+=2;
++      }
++      *(nptr++)=(((int)*(optr++))+
++                 ((int)*(uptr++))+1)>>1;  /* 2nd last pixel */
++      *(nptr++)=(((int)*(optr++))+
++                 ((int)*(uptr++))+1)>>1;  /* last pixel */
++    }
++
++    xvbcopy((char *)(p + (2*h-2)*mw),     /* 2nd last row */
++            (char *)(p + (2*h-1)*mw),     /* the last row */
++            2*w);                         /* length of a new row */
++
++    h*=2; w*=2;
++    mag>>=1;  /* Obviously mag must be a power of 2 ! */
++  }
++}
++
++/*******************************************/
++static int
++pcdError(const char *fname, const char *st)
++{
++  SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
++  return 0;
++}
++
++
++/**** Stuff for PCDDialog box ****/
++
++#define TWIDE 380
++#define THIGH 160
++#define T_NBUTTS 2
++#define T_BOK    0
++#define T_BCANC  1
++#define BUTTH    24
++
++static void drawTD    PARM((int, int, int, int));
++static void clickTD   PARM((int, int));
++static void doCmd     PARM((int));
++static void PCDSetParams PARM((void));
++
++/* local variables */
++static BUTT  tbut[T_NBUTTS];
++static RBUTT *resnRB;
++
++
++
++/***************************************************/
++void CreatePCDW()
++{
++  int       y;
++
++  pcdW = CreateWindow("xv pcd", "XVpcd", NULL,
++           TWIDE, THIGH, infofg, infobg, 0);
++  if (!pcdW) FatalError("can't create pcd window!");
++
++  XSelectInput(theDisp, pcdW, ExposureMask | ButtonPressMask | KeyPressMask);
++
++  BTCreate(&tbut[T_BOK], pcdW, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH,
++     "Ok", infofg, infobg, hicol, locol);
++
++  BTCreate(&tbut[T_BCANC], pcdW, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH,
++     "Cancel", infofg, infobg, hicol, locol);
++
++  y = 55;
++  resnRB = RBCreate(NULL, pcdW, 36, y,   "192*128   Base/16",
++           infofg, infobg,hicol,locol);
++  RBCreate(resnRB, pcdW, 36, y+18,       "384*256   Base/4",
++           infofg, infobg,hicol,locol);
++  RBCreate(resnRB, pcdW, 36, y+36,       "768*512   Base",
++           infofg, infobg, hicol, locol);
++  RBCreate(resnRB, pcdW, TWIDE/2, y,     "1536*1024 4Base",
++           infofg, infobg, hicol, locol);
++  RBCreate(resnRB, pcdW, TWIDE/2, y+18,  "3072*2048 16Base",
++           infofg, infobg, hicol, locol);
++
++  CBCreate(&lutCB, pcdW, TWIDE/2, y+36,  "Linear LUT",
++           infofg, infobg, hicol, locol);
++
++  RBSelect(resnRB, 2);
++
++  XMapSubwindows(theDisp, pcdW);
++}
++
++
++/***************************************************/
++void PCDDialog(vis)
++int vis;
++{
++  if (vis) {
++    CenterMapWindow(pcdW, tbut[T_BOK].x + tbut[T_BOK].w/2,
++        tbut[T_BOK].y + tbut[T_BOK].h/2, TWIDE, THIGH);
++  }
++  else     XUnmapWindow(theDisp, pcdW);
++  pcdUp = vis;
++}
++
++
++/***************************************************/
++int PCDCheckEvent(xev)
++XEvent *xev;
++{
++  /* check event to see if it's for one of our subwindows.  If it is,
++     deal accordingly, and return '1'.  Otherwise, return '0' */
++
++  int rv;
++  rv = 1;
++
++  if (!pcdUp) return 0;
++
++  if (xev->type == Expose) {
++    int x,y,w,h;
++    XExposeEvent *e = (XExposeEvent *) xev;
++    x = e->x;  y = e->y;  w = e->width;  h = e->height;
++
++    if (e->window == pcdW)       drawTD(x, y, w, h);
++    else rv = 0;
++  }
++
++  else if (xev->type == ButtonPress) {
++    XButtonEvent *e = (XButtonEvent *) xev;
++    int x,y;
++    x = e->x;  y = e->y;
++
++    if (e->button == Button1) {
++      if      (e->window == pcdW)     clickTD(x,y);
++      else rv = 0;
++    }  /* button1 */
++    else rv = 0;
++  }  /* button press */
++
++
++  else if (xev->type == KeyPress) {
++    XKeyEvent *e = (XKeyEvent *) xev;
++    char buf[128];  KeySym ks;  XComposeStatus status;
++    int stlen;
++
++    stlen = XLookupString(e,buf,128,&ks,&status);
++    buf[stlen] = '\0';
++
++    RemapKeyCheck(ks, buf, &stlen);
++
++    if (e->window == pcdW) {
++      if (stlen) {
++  if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
++    FakeButtonPress(&tbut[T_BOK]);
++  }
++  else if (buf[0] == '\033') {            /* ESC */
++    FakeButtonPress(&tbut[T_BCANC]);
++  }
++      }
++    }
++    else rv = 0;
++  }
++  else rv = 0;
++
++  if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
++    XBell(theDisp, 50);
++    rv = 1;   /* eat it */
++  }
++
++  return rv;
++}
++
++
++/***************************************************/
++void
++PCDSetParamOptions(const char *fname)
++{
++  int cur;
++  cur = RBWhich(resnRB);
++
++  RBSetActive(resnRB,0,1);
++  RBSetActive(resnRB,1,1);
++  RBSetActive(resnRB,2,1);
++  RBSetActive(resnRB,3,1);
++  RBSetActive(resnRB,4,1);
++  CBSetActive(&lutCB,1);
++}
++
++
++/***************************************************/
++static void
++drawTD(int x, int y, int w, int h)
++{
++  const char *title = "Load PhotoCD file...";
++  int         i;
++  XRectangle  xr;
++
++  xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
++  XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
++
++  XSetForeground(theDisp, theGC, infofg);
++  XSetBackground(theDisp, theGC, infobg);
++
++  for (i=0; i<T_NBUTTS; i++) BTRedraw(&tbut[i]);
++
++  ULineString(pcdW, resnRB->x-16, resnRB->y-10-DESCENT, "Resolution");
++  RBRedraw(resnRB, -1);
++  CBRedraw(&lutCB);
++
++  XDrawString(theDisp, pcdW, theGC, 20, 19, title, strlen(title));
++
++  XSetClipMask(theDisp, theGC, None);
++}
++
++
++/***************************************************/
++static void clickTD(x,y)
++int x,y;
++{
++  int i;
++  BUTT *bp;
++
++  /* check BUTTs */
++
++  /* check the RBUTTS first, since they don't DO anything */
++  if ( (i=RBClick(resnRB, x,y)) >= 0) {
++    (void) RBTrack(resnRB, i);
++    return;
++  }
++
++  if(CBClick(&lutCB, x, y)) {
++    (void) CBTrack(&lutCB);
++    return;
++  }
++
++  for (i=0; i<T_NBUTTS; i++) {
++    bp = &tbut[i];
++    if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
++  }
++
++  if (i<T_NBUTTS) {  /* found one */
++    if (BTTrack(bp)) doCmd(i);
++  }
++}
++
++
++
++/***************************************************/
++static void doCmd(cmd)
++int cmd;
++{
++  leaveitup=0;
++  goforit=0;
++  switch (cmd) {
++  case T_BOK:    PCDSetParams();
++                goforit=1;
++  case T_BCANC:  PCDDialog(0);
++                break;
++
++  default:  break;
++  }
++}
++
++
++/*******************************************/
++static void PCDSetParams()
++{
++  switch (RBWhich(resnRB)) {
++  case 0: size = 0;      break;
++  case 1: size = 1;      break;
++  case 2: size = 2;      break;
++  case 3: size = 3;      break;
++  case 4: size = 4;      break;
++  case 5: size = 0;      break;
++  default: size = 0;     break;
++  }
++}
++
++/*
++ * Read the Huffman tables which consist of an unsigned byte # of entries
++ * (less 1) followed by up to 256 entries, each of which is a series of 4
++ * unsigned bytes - length, highseq, lowseq, and key.
++ *
++ * Store the huffman table into tree type structure:
++ *
++ *   int int[n of entries*2]
++ *
++ * Each entry consists of two words (the 1st for zero and the 2nd for one).
++ *
++ * If the word is negative, then subtract it from the current pointer to
++ * get the next entry (ie. it is the negative offset from the current
++ * position*2 in order to skip entries not words) with which to
++ * make a decision.
++ *
++ * If the word is not negative, then the low 8 bits contain the value (which
++ * is supposed to be a signed char) and the rest of the word is zero.
++ */
++static void
++dumphufftab(int n, const byte *h, int m, const int *t)
++{
++  int  j;
++
++  for(j = 0; j < n || j < m; ++j) {
++    if(j < m)
++      fprintf(stderr, "%04x %04x ::", 0xffff & t[2*j + 0],
++               0xffff & t[2*j + 1]);
++    else
++      fprintf(stderr, "%s %s ::", "    ", "    ");
++    if(j < n) {
++      int   k;
++      unsigned l = (h[4*j + 1] << 8) | h[4*j + 2];
++
++      fprintf(stderr, " %02x %2d ", h[4*j + 3], h[4*j + 0]);
++      for(k = 0; k <= h[4*j + 0]; ++k, l *= 2)
++        fprintf(stderr, "%c", '0'+((l & 0x8000) != 0));
++    }
++    fprintf(stderr, "\n");
++  }
++}
++
++static int *
++gethufftable(void)
++{
++  int  *hufftab, *h, i, j, N, num, bufsize, huffptr, hufftop;
++  byte  *huf;
++
++  /*
++   * absorb the entirety of the table in one chunk (for better
++   * dumps in case of error)
++   */
++  trace((stderr, "hufftab 0x%08lx ", ftell(fp)));
++  num = 1 + fgetc(fp);   /* 256 max */
++  huf = (byte *)alloca(4*num*sizeof(byte));
++  if((i = fread(huf, 1, 4*num, fp)) != 4*num) {
++    fprintf(stderr, "unexpected EOF: got %d bytes, wanted %d\n",
++                i, 4*num);
++    return NULL;
++  }
++
++  /*
++   * guess an initial size and prepare the initial entry
++   */
++  trace((stderr, "length %u\n", num));
++  N = 2*num;   /* 512 max */
++  bufsize = N * sizeof(int);
++/*  this case can't happen, but added for symmetry with loop below
++  if (N/2 != num || bufsize/N != sizeof(int)) {
++    SetISTR(ISTR_WARNING, "Huffman table size out of range");
++    return NULL;
++  }
++ */
++  if((hufftab = (int *)malloc(bufsize)) == NULL)
++    FatalError("couldn't malloc initial Huffman table");
++  hufftab[0] = hufftab[1] = 0;
++
++  /*
++   * we check the table for reasonableness;  there is a lack of detailed
++   * documentation on this format.  in particular, for the base16,
++   * the position of the huffman tables is uncertain to within one
++   * "sector", and we have to detect his before trying to read
++   * bogusness.
++   */
++  hufftop = 0;
++  for(i = 0; i < num; ++i) {
++    unsigned length   =  huf[4*i + 0],
++       codeword = (huf[4*i + 1] << 8) | huf[4*i + 2];
++
++    /*
++     * some sanity checks
++     */
++    if(length >= 16) {
++      fprintf(stderr,
++        "gethufftable: improbable length @ %d/%d\n",
++          i, num);
++      dumphufftab(num, huf, hufftop/2, hufftab);
++      free(hufftab);
++      return NULL;
++    }
++
++    /*
++     * walk the whole set of codes
++     */
++    huffptr = 0;
++    for(j = 0; j < 16; ++j, codeword *= 2) {
++      /*
++       * choose the child node
++       */
++      if(codeword & 0x8000)
++        ++huffptr;
++
++      /*
++       * store value at end-of-code
++       */
++      if(j == length) {
++        /*
++         * more sanity
++         */
++        if((codeword *= 2) & 0xffff) {
++          fprintf(stderr,
++            "gethufftable: "
++            ":probable invalid code @ %d\n",
++              i);
++          dumphufftab(num, huf,
++              hufftop/2, hufftab);
++          free(hufftab);
++          return NULL;
++        }
++        hufftab[huffptr] = 1 + (int) huf[4*i + 3];
++        break;
++      }
++
++      /*
++       * otherwise, follow the tree to date
++       */
++      if(hufftab[huffptr] < 0) {
++        huffptr -= hufftab[huffptr];
++        continue;
++      } else if(hufftab[huffptr] > 0) {
++        fprintf(stderr, "duplicate code %d %d/%d\n",
++          huffptr, i, num);
++        dumphufftab(num, huf, hufftop/2, hufftab);
++        free(hufftab);
++        return NULL;
++      }
++
++      /*
++       * and if necessary, make the tree bigger
++       */
++      if((hufftop += 2) >= N) {
++        int oldN = N;
++#if TRACE
++        dumphufftab(num, huf, hufftop/2, hufftab);
++#endif
++        N *= 2;
++        bufsize = N*sizeof(int);
++        if (N/2 != oldN || bufsize/N != sizeof(int)) {
++          SetISTR(ISTR_WARNING,
++            "new Huffman table is too large");
++          free(hufftab);
++          return NULL;
++        }
++        h = (int *)realloc(hufftab, bufsize);
++        if(h == NULL) {
++          fprintf(stderr,
++            "Table overflow %d/%d\n",
++                 i, num);
++          dumphufftab(num, huf,
++              hufftop/2, hufftab);
++          free(hufftab);
++          FatalError(
++            "couldn't realloc Huffman table");
++        }
++        hufftab = h;
++      }
++
++      /*
++       * then add new ptr
++       */
++      hufftab[huffptr] = huffptr - hufftop;
++      huffptr = hufftop;
++      hufftab[huffptr + 0] =
++      hufftab[huffptr + 1] = 0;
++    }
++  }
++  return hufftab;
++}
++
++/* WORDTYPE & char buffer must be unsigned else */
++/* fills with sign bit not 0 on right shifts */
++typedef unsigned int WORDTYPE;
++typedef int SWORDTYPE;
++#define WORDSIZE sizeof(WORDTYPE)
++#define NBYTESINBUF 0x800
++
++static byte buffer[NBYTESINBUF];
++static int bitsleft=0;
++static int bytesleft=0;
++static byte *bufptr;
++static WORDTYPE word;
++
++#if 0
++static void
++dumpbuffer(void)
++{
++  int i,left;
++  byte *ptr=buffer;
++
++  fprintf(stderr,"dumpbuffer: bytesleft=%d bitsleft= %d word=0x%08lx\n",
++    bytesleft,bitsleft,(unsigned long)word);
++  for (left=NBYTESINBUF; left>0; left-=16) {
++    fprintf(stderr,"%05d  ",left);
++    for (i=0; i<8; i++) {
++      fprintf(stderr,"%02x",*ptr++);
++      fprintf(stderr,"%02x ",*ptr++);
++    }
++    fprintf(stderr,"\n");
++  }
++}
++#endif /* 0 */
++
++static void
++loadbuffer(void)
++{
++  if ((bytesleft=fread(buffer,1,NBYTESINBUF,fp)) == 0) {
++    fprintf(stderr,"Truncation error\n");
++    exit(1);
++  }
++  bufptr=buffer;
++  /* dumpbuffer(); */
++}
++
++static void
++loadbyte(void)
++{
++  if (bytesleft <= 0) loadbuffer();
++  --bytesleft;
++  word|=(WORDTYPE)(*bufptr++)<<(sizeof(WORDTYPE)*8-8-bitsleft);
++  bitsleft+=8;
++}
++
++static int
++getbit(void)
++{
++  int bit;
++
++  while (bitsleft <= 0) loadbyte();
++  --bitsleft;
++  bit=(SWORDTYPE)(word)<0;  /* assumes word is signed */
++  /* bit=word>>(sizeof(WORDTYPE)*8-1); */
++  word<<=1;
++  return bit;
++}
++
++static WORDTYPE
++getnn(int nn)
++{
++  WORDTYPE value;
++
++  while (bitsleft <= nn) loadbyte();
++  bitsleft-=nn;
++  value=word>>(sizeof(WORDTYPE)*8-nn);
++  word<<=nn;
++  return value;
++}
++
++static WORDTYPE
++isnn(int nn)
++{
++  WORDTYPE value;
++
++  while (bitsleft <= nn) loadbyte();
++  value=word>>(sizeof(WORDTYPE)*8-nn);
++  return value;
++}
++
++static void
++skipnn(int nn)
++{
++  while (bitsleft <= nn) loadbyte();
++  bitsleft-=nn;
++  word<<=nn;
++}
++
++#define get1()    (getbit())
++#define get2()    (getnn(2))
++#define get8()    (getnn(8))
++#define get13()    (getnn(13))
++#define get16()    (getnn(16))
++#define get24()    (getnn(24))
++
++#define is24()    (isnn(24))
++
++#define skip1()    (skipnn(1))
++#define skip24()  (skipnn(24))
++
++static int
++gethuffdata(  byte *luma,
++    byte *chroma1,
++    byte *chroma2,
++    int realrowwidth,
++    int maxrownumber)
++{
++static  byte  clip[3*256];
++  int  *hufftable[3], *huffstart = NULL, *huffptr = NULL;
++  int  row, col, plane, i, result = 1;
++#if TRACE
++  int  uflow = 0, oflow = 0;
++#endif
++  byte  *pixelptr = NULL;
++
++  trace((stderr,"gethuffdata: start @ 0x%08lx (sector %ld.%ld)\n",
++      ftell(fp), ftell(fp)/0x800, ftell(fp) % 0x800));
++
++  /*
++   * correction clipping
++   */
++  if(clip[256+255] == 0) {
++    for(i = 0; i < 256; ++i)
++      clip[i +   0] = 0x00,
++      clip[i + 256] = (byte) i,
++      clip[i + 512] = 0xff;
++  }
++
++  /*
++   * should really only look for luma plane for 4base, but the
++   * there are zeroes in the rest of the sector that give both
++   * chroma tables 0 length
++   */
++  for(i = 0; i < 3; ++i)
++    hufftable[i] = NULL;
++  for(i = 0; i < 3; ++i) {
++    if((hufftable[i] = gethufftable()) == NULL) {
++      result = 0;
++      break;
++    }
++  }
++  if(result == 0)
++    goto oops;
++
++  /*
++   * skip remainder of current sector
++   */
++  i = (ftell(fp) | 0x7ff) + 1;
++  if(fseek(fp, i, SEEK_SET) < 0) {
++    fprintf(stderr, "gethuffdata: sector skip failed\n");
++    return 0;
++  }
++
++  /*
++   * skip remainder of "sector"
++   */
++  i = 0;
++  while (is24() != 0xfffffe) {
++    (void)get24();
++    if(++i == 1)
++      trace((stderr,"gethuffdata: skipping for sync ..."));
++  }
++  if(i != 0)
++    trace((stderr, " %d times\n", i));
++
++  while(result) {
++    if(is24() == 0xfffffe) {
++      skip24();
++      plane = get2();
++      row = get13(); col = 0;
++      skip1();
++      if(row >= maxrownumber) {
++        trace((stderr,
++          "gethuffdata: stopping at row %d\n",
++                row));
++        break;
++      }
++      switch (plane) {
++      case  0:
++        huffstart = hufftable[0];
++        pixelptr  = luma + row*realrowwidth;
++        break;
++
++      case  2:
++        huffstart = hufftable[1];
++        pixelptr  = chroma1 + row/2*realrowwidth/2;
++        break;
++
++      case  3:
++        huffstart = hufftable[2];
++        pixelptr  = chroma2 + row/2*realrowwidth/2;
++        break;
++
++      default:
++        fprintf(stderr, "gethuffdata: bad plane %d\n",
++                  plane);
++        result = 0;
++        break;
++      }
++      WaitCursor();
++      continue;
++    }
++
++    /*
++     * locate correction in huffman tree
++     */
++    for(huffptr = huffstart;;) {
++      huffptr += get1();
++      if(*huffptr < 0) {
++        huffptr -= *huffptr;
++      } else if(*huffptr == 0) {
++        fprintf(stderr,
++          "gethuffdata: invalid code: "
++            "image quality reduced\n");
++        result = 0;
++        break;
++      } else
++        break;
++    }
++    if(!result)
++      break;
++
++    /*
++     * apply correction to the pixel
++     *
++     * eeeek!!  the corrections can sometimes over or underflow!
++     * this strongly suggested that the 'magnify' method was in
++     * some way wrong.  however, experiments showed that the
++     * over/under flows even occured for the pixels that are
++     * copied through magnify without change (ie, the even
++     * row/even column case).  curiously, though, the odd
++     * column and odd row cases were about 3x more likely to have
++     * the over/underflow, and the odd row/odd column case was
++     * about 5x higher, so maybe the use of a bi-linear
++     * interpolation is not correct -- just *close*?
++     *
++     * the other clue in this area is that the overflows are
++     * by far most frequenct along edges of very bright
++     * areas -- rarely in the interior of such regions.
++     */
++    i = (int) *pixelptr + (signed char) (*huffptr - 1);
++#if TRACE
++    if(i > 255)
++      ++oflow;
++/*      trace((stderr,
++        "gethuffdata: oflow %d %d %d\n", row, col, i));*/
++    else if(i < 0)
++      ++uflow;
++/*      trace((stderr,
++        "gethuffdata: uflow %d %d %d\n", row, col, i));*/
++    ++col;
++#endif
++    *pixelptr++ = clip[i + 256];
++  }
++
++oops:
++  for(i = 0; i < 3; ++i)
++    free(hufftable[i]);
++  trace((stderr, "gethuffdata: uflow=%d oflow=%d\n", uflow, oflow));
++  trace((stderr, "gethuffdata: done @ 0x%08lx (sector %ld.%d)\n",
++        ftell(fp), ftell(fp)/0x800, 0x800 - bytesleft));
++  return result;
++}
++
++#endif /* HAVE_PCD */
+diff -Naru xv-3.10a/xvpi.c xv-3.10a.jumbo/xvpi.c
+--- xv-3.10a/xvpi.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvpi.c	2005-04-18 07:57:04.000000000 +0200
+@@ -0,0 +1,1060 @@
++/*
++ * xvpi.c - load routine for `Pi' format pictures.
++ *
++ * The `Pi' format is made by Yanagisawa.
++ * It is common among many Japanese personal computer users.
++ *
++ */
++
++#include "xv.h"
++#include <setjmp.h>
++
++#ifdef HAVE_PI
++
++typedef unsigned short data16;
++typedef unsigned int data32;
++
++struct pi_info {
++    jmp_buf jmp;
++    FILE *fp;
++    struct {
++	int rest;
++	byte cur;
++    }bs;
++    long fsize;
++    byte mode;
++    int width, height;
++    float aspect;
++    int cbits;
++    int numcols;
++    byte *cmap;
++    struct ct_t{
++	struct elt_t *top;
++	struct elt_t{
++	    struct elt_t *old, *recent;
++	    byte val;
++	} *elt;
++    }*ct;
++    int defcmap;
++    int writing_grey;
++};
++
++static void pi_open_file         PARM((struct pi_info*, char*));
++static void pi_read_header       PARM((struct pi_info*, char**));
++static void pi_check_id          PARM((struct pi_info*));
++static void pi_read_comment      PARM((struct pi_info*, char**));
++static void pi_read_palette      PARM((struct pi_info*));
++static void pi_expand            PARM((struct pi_info*, byte**));
++static byte pi_read_color        PARM((struct pi_info*, int));
++static int pi_read_position      PARM((struct pi_info*));
++static data32 pi_read_length     PARM((struct pi_info*));
++static int pi_copy_pixels        PARM((struct pi_info*,
++				     byte*, int, int, data32));
++
++static void pi_write_header      PARM((struct pi_info*,
++				       char*, byte*, byte*, byte*));
++static void pi_write_id          PARM((struct pi_info*));
++static void pi_write_comment     PARM((struct pi_info*, char*));
++static void pi_write_palette     PARM((struct pi_info*, byte*, byte*, byte*));
++static void pi_compress          PARM((struct pi_info*, byte*));
++static void pi_write_gabage      PARM((struct pi_info*));
++static void pi_write_color       PARM((struct pi_info*, int, int));
++static int pi_test_matching      PARM((struct pi_info*,
++				       byte*, int, int, data32*));
++static void pi_write_position    PARM((struct pi_info*, int));
++static void pi_write_length      PARM((struct pi_info*, data32));
++
++static void pi_table_create      PARM((struct pi_info*));
++static byte pi_table_get_value   PARM((struct pi_info*, int, int));
++static int pi_table_lookup_value PARM((struct pi_info*, int, int));
++static data32 pi_read_bits       PARM((struct pi_info*, int));
++static void pi_write_bits        PARM((struct pi_info*, data32, int));
++static void pi_init_pi_info      PARM((struct pi_info*));
++static void pi_cleanup_pi_info   PARM((struct pi_info*, int));
++static void pi_cleanup_pinfo     PARM((PICINFO*));
++static void pi_memory_error      PARM((char*, char*));
++static void pi_error             PARM((struct pi_info*, int));
++static void pi_file_error        PARM((struct pi_info*, int));
++static void pi_file_warning      PARM((struct pi_info*, int));
++static void pi_show_pi_info      PARM((struct pi_info*));
++static void *pi_malloc           PARM((size_t, char*));
++static void *pi_realloc          PARM((void*, size_t, char*));
++
++
++static char *pi_id = "Pi";
++static char *pi_msgs[] = {
++    NULL,
++#define PI_OPEN 1
++    "couldn't open.",
++#define PI_CORRUPT 2
++    "file corrupted.",
++#define PI_FORMAT 3
++    "not PI format.",
++#define PI_PLANES 4
++    "bad number of planes.",
++#define PI_WRITE 5
++    "write failed.",
++};
++
++
++/* The main routine of `Pi' loader. */
++int LoadPi(fname, pinfo)
++    char *fname;
++    PICINFO *pinfo;
++{
++    struct pi_info pi;
++    int e;
++    int i;
++    if(DEBUG) fputs("LoadPi:\n", stderr);
++
++    pinfo->comment = NULL;
++    pi_init_pi_info(&pi);
++    if((e = setjmp(pi.jmp)) != 0){
++	/* When an error occurs, comes here. */
++	pi_cleanup_pi_info(&pi, 0);
++	pi_cleanup_pinfo(pinfo);
++	if(DEBUG) fputs("\n", stderr);
++	return 0;
++    }
++
++    pi_open_file(&pi, fname);
++    pi_read_header(&pi, &pinfo->comment);
++    pi_expand(&pi, &pinfo->pic);
++
++    pinfo->normw = pinfo->w = pi.width;
++    pinfo->normh = pinfo->h = pi.height;
++    pinfo->type = PIC8;
++    if(pi.numcols > 256)	/* shouldn't happen. */
++	pi.numcols = 256;
++    for(i = 0; i < pi.numcols; i++){
++	pinfo->r[i] = pi.cmap[i * 3    ];
++	pinfo->g[i] = pi.cmap[i * 3 + 1];
++	pinfo->b[i] = pi.cmap[i * 3 + 2];
++    }
++    pinfo->frmType = F_PI;
++    pinfo->colType = F_FULLCOLOR;
++    sprintf(pinfo->fullInfo, "Pi, %d colors (%ld bytes)",
++	    pi.numcols, pi.fsize);
++    sprintf(pinfo->shrtInfo, "%dx%d Pi.", pi.width, pi.height);
++    normaspect = pi.aspect;
++
++    pi_cleanup_pi_info(&pi, 0);
++    if(DEBUG) fputs("\n", stderr);
++    return 1;
++}
++
++static void pi_open_file(pi, fname)
++    struct pi_info *pi;
++    char *fname;
++{
++    if((pi->fp = fopen(fname, "rb")) == NULL)
++	pi_file_error(pi, PI_OPEN);
++    fseek(pi->fp, (size_t) 0, SEEK_END);
++    pi->fsize = ftell(pi->fp);
++    fseek(pi->fp, (size_t) 0, SEEK_SET);
++}
++
++static void pi_read_header(pi, comm)
++    struct pi_info *pi;
++    char **comm;
++{
++    byte buf[10];
++    int mda;
++    int i;
++
++    pi_check_id(pi);
++    pi_read_comment(pi, comm);
++
++    if(fread(buf, (size_t) 10, (size_t) 1, pi->fp) != 1)
++	pi_file_error(pi, PI_CORRUPT);
++
++    pi->mode = buf[0];
++    pi->defcmap = pi->mode & 0x80;
++    if(buf[1] != 0 && buf[2] != 0)
++	pi->aspect = (float) buf[2] / (int) buf[1];
++    pi->cbits = buf[3];
++    pi->numcols = 1 << pi->cbits;
++
++    if(pi->cbits != 4 && pi->cbits != 8)
++	pi_error(pi, PI_PLANES);
++
++    mda = (int) buf[8] << 8 | (int) buf[9];
++    for(i = 0; i < mda; i++){
++	if(fgetc(pi->fp) == EOF)
++	    pi_file_error(pi, PI_CORRUPT);
++    }
++
++    if(fread(buf, (size_t) 4, (size_t) 1, pi->fp) != 1)
++	pi_file_error(pi, PI_CORRUPT);
++    pi->width  = (int) buf[0] << 8 | (int) buf[1];
++    pi->height = (int) buf[2] << 8 | (int) buf[3];
++
++    pi_read_palette(pi);
++
++    if(DEBUG) pi_show_pi_info(pi);
++}
++
++static void pi_check_id(pi)
++    struct pi_info *pi;
++{
++    char buf[2];
++
++    if(fread(buf, (size_t) 2, (size_t) 1, pi->fp) != 1)
++	pi_file_error(pi, PI_CORRUPT);
++    if(strncmp(buf, pi_id, (size_t) 2) != 0)
++	pi_error(pi, PI_FORMAT);
++}
++
++static void pi_read_comment(pi, comm)
++    struct pi_info *pi;
++    char **comm;
++{
++/*
++ * The comment format is like:
++ *   comment string `^Z' dummy string `\0'
++ */
++    int max = -1, i = 0;
++    int c;
++
++    while(1){
++	if((c = fgetc(pi->fp)) == EOF)
++	    pi_file_error(pi, PI_CORRUPT);
++	if(c == '\032')		/* 0x1a, '^Z' */
++	    break;
++	if(max < i){
++	    max += 32;
++	    *comm = pi_realloc(*comm, (size_t) max + 1, "pi_read_comment(1)");
++	}
++	(*comm)[i++] = c;
++    }
++    if(max < i){
++	max++;
++	*comm = pi_realloc(*comm, (size_t) max + 1, "pi_read_comment(2)");
++    }
++    (*comm)[i] = '\0';
++
++    while((c = fgetc(pi->fp)) != '\0'){		/* skip the dummy area */
++	if(c == EOF)
++	    pi_file_error(pi, PI_CORRUPT);
++    }
++}
++
++static void pi_read_palette(pi)
++    struct pi_info *pi;
++{
++    pi->cmap = pi_malloc((size_t) pi->numcols * 3, "pi_read_palette");
++    if(pi->mode & 0x80){
++	if(pi->numcols == 16){
++	    int i;
++	    byte on;
++
++	    on = 0x77;
++	    for(i = 0; i < 8; i++){
++		pi->cmap[i * 3    ] = i & 2 ? on : 0;
++		pi->cmap[i * 3 + 1] = i & 4 ? on : 0;
++		pi->cmap[i * 3 + 2] = i & 1 ? on : 0;
++	    }
++	    on = 0xff;
++	    for(; i < 16; i++){
++		pi->cmap[i * 3    ] = i & 2 ? on : 0;
++		pi->cmap[i * 3 + 1] = i & 4 ? on : 0;
++		pi->cmap[i * 3 + 2] = i & 1 ? on : 0;
++	    }
++	}else{	/* pi->numcols == 256 */
++	    int i;
++	    byte r, g, b;
++	    r = g = b = 0;
++	    for(i = 0; i < 256; i++){
++		pi->cmap[i * 3    ] = r;
++		pi->cmap[i * 3 + 1] = g;
++		pi->cmap[i * 3 + 2] = b;
++		if((b += 0x40) == 0){
++		    if((r += 0x20) == 0)
++			g += 0x20;
++		}
++	    }
++	}
++    }else{
++	if(fread(pi->cmap, (size_t) pi->numcols * 3, (size_t) 1, pi->fp) != 1)
++	    pi_file_error(pi, PI_CORRUPT);
++    }
++}
++
++/* The main routine to expand `Pi' file. */
++static void pi_expand(pi, pic)
++    struct pi_info *pi;
++    byte **pic;
++{
++    byte prev_col = 0;
++    int prev_pos = -1;
++    int cnt = 0, max_cnt = pi->width * pi->height;
++
++    *pic = pi_malloc((size_t) max_cnt, "pi_expand");   // GRR POSSIBLE OVERFLOW / FIXME
++
++    pi_table_create(pi);
++
++    if(pi->width > 2){
++	(*pic)[0] = pi_read_color(pi, 0);
++	(*pic)[1] = pi_read_color(pi, (*pic)[0]);
++
++	while(cnt < max_cnt){
++	    int pos = pi_read_position(pi);
++	    if(pos != prev_pos){
++		data32 len = pi_read_length(pi);
++		cnt = pi_copy_pixels(pi, *pic, cnt, pos, len);
++		prev_col = (*pic)[cnt - 1];
++		prev_pos = pos;
++	    }else{
++		do{
++		    prev_col = pi_read_color(pi, (int) prev_col);
++		    (*pic)[cnt++] = prev_col;
++		    prev_col = pi_read_color(pi, (int) prev_col);
++		    (*pic)[cnt++] = prev_col;
++		}while(pi_read_bits(pi, 1) == 1);
++
++		prev_pos = -1;
++	    }
++	}
++    }else{
++	while(cnt < max_cnt){
++	    prev_col = pi_read_color(pi, (int) prev_col);
++	    (*pic)[cnt++] = prev_col;
++	}
++    }
++}
++
++static byte pi_read_color(pi, prev)
++    struct pi_info *pi;
++    int prev;
++{
++    byte n;
++    if(pi->cbits == 4){
++	if(pi_read_bits(pi, 1) == 1)
++	    n = pi_read_bits(pi, 1);			/* 1x */
++	else{
++	    if(pi_read_bits(pi, 1) == 0)
++		n = pi_read_bits(pi, 1) + 2;		/* 00x */
++	    else{
++		if(pi_read_bits(pi, 1) == 0)
++		    n = pi_read_bits(pi, 2) + 4;	/* 010xx */
++		else
++		    n = pi_read_bits(pi, 3) + 8;	/* 011xxx */
++	    }
++	}
++    }else{	/* cbits == 8 */
++	if(pi_read_bits(pi, 1) == 1)
++	    n = pi_read_bits(pi, 1);
++	else{
++	    int bits = 0;
++	    byte base = 2;
++	    while(bits < 6){
++		if(pi_read_bits(pi, 1) == 0)
++		    break;
++		bits++;
++		base <<= 1;
++	    }
++	    n = pi_read_bits(pi, bits + 1) + base;
++	}
++    }
++
++    return pi_table_get_value(pi, prev, (int) n);
++}
++
++static int pi_read_position(pi)
++    struct pi_info *pi;
++{
++    byte r;
++    if((r = pi_read_bits(pi, 2)) != 3)
++	return (int) r;
++    else
++	return (int) pi_read_bits(pi, 1) + 3;
++}
++
++static data32 pi_read_length(pi)
++    struct pi_info *pi;
++{
++    data32 r = 1;
++    int bits = 0;
++    while(pi_read_bits(pi, 1) == 1){
++	r <<= 1;
++	bits++;
++    }
++    if(bits > 0)
++	return r + pi_read_bits(pi, bits);
++    return 1;
++}
++
++static int pi_copy_pixels(pi, pic, cnt, pos, len)
++    struct pi_info *pi;
++    byte *pic;
++    int cnt, pos;
++    data32 len;
++{
++    int s = 0, d = cnt;
++    int max = pi->width * pi->height;
++    switch(pos){
++    case 0:
++	if(cnt < 2){
++	    if(pic[0] == pic[1])
++		s = cnt - 2;
++	    else
++		s = cnt - 4;
++	}else{
++	    if(pic[cnt - 2] == pic[cnt - 1])
++		s = cnt - 2;
++	    else
++		s = cnt - 4;
++	}
++	break;
++    case 1:
++	s = cnt - pi->width;
++	break;
++    case 2:
++	s = cnt - pi->width * 2;
++	break;
++    case 3:
++	s = cnt - pi->width + 1;
++	break;
++    case 4:
++	s = cnt - pi->width - 1;
++    }
++
++    len *= 2;
++    while(s < 0 && len != 0 && d < max){
++	pic[d++] = pic[-(s++) % 2];
++	len--;
++    }
++    while(len != 0 && d < max){
++	pic[d++] = pic[s++];
++	len--;
++    }
++    return d;
++}
++
++/* The main routine of `Pi' saver. */
++int WritePi(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
++	    comment)
++    FILE *fp;
++    byte *pic;
++    int ptype, w, h;
++    byte *rmap, *gmap, *bmap;
++    int numcols, colorstyle;
++    char *comment;
++{
++    byte rtemp[256], gtemp[256], btemp[256];
++    struct pi_info pi;
++    int e;
++
++    if(DEBUG) fputs("WritePi\n", stderr);
++    pi_init_pi_info(&pi);
++    pi.fp = fp;
++    pi.width  = w;
++    pi.height = h;
++    pi.writing_grey = (colorstyle == F_GREYSCALE);
++    if(ptype == PIC24){
++	if(!(pic = Conv24to8(pic, w, h, 256, rtemp, gtemp, btemp)))
++	    pi_memory_error("Conv24to8", "WritePi");
++	rmap = rtemp;
++	gmap = gtemp;
++	bmap = btemp;
++	numcols = 256;
++    }
++
++    if((e = setjmp(pi.jmp)) != 0){
++	/* When an error occurs, comes here. */
++	pi_cleanup_pi_info(&pi, 1);
++	if(DEBUG) fputs("\n", stderr);
++	return -1;
++    }
++
++    pi.numcols = numcols;
++    pi_write_header(&pi, comment,  rmap, gmap, bmap);
++    pi_compress(&pi, pic);
++    pi_write_gabage(&pi);
++
++    pi_cleanup_pi_info(&pi, 1);
++    if(DEBUG) fputs("\n", stderr);
++    return 0;
++}
++
++static void pi_write_header(pi, comm, r, g, b)
++    struct pi_info *pi;
++    char *comm;
++    byte *r, *g, *b;
++{
++    byte buf[14];
++
++    if(DEBUG) pi_show_pi_info(pi);
++
++    pi_write_id(pi);
++    pi_write_comment(pi, comm);
++
++    buf[0] = buf[1] = buf[2] = 0;
++    buf[3] = pi->cbits = pi->numcols > 16 ? 8 : 4;
++    buf[4] = 'X';
++    buf[5] = 'V';
++    buf[6] = ' ';
++    buf[7] = ' ';
++    buf[8] = buf[9] = 0;
++    buf[10] = pi->width >> 8;
++    buf[11] = pi->width;
++    buf[12] = pi->height >> 8;
++    buf[13] = pi->height;
++    if(fwrite(buf, (size_t) 14, (size_t) 1, pi->fp) != 1)
++	pi_file_error(pi, PI_WRITE);
++
++    pi_write_palette(pi, r, g, b);
++}
++
++static void pi_write_id(pi)
++    struct pi_info *pi;
++{
++    if(fwrite(pi_id, (size_t) 2, (size_t) 1, pi->fp) != 1)
++	pi_file_error(pi, PI_WRITE);
++}
++
++static void pi_write_comment(pi, comm)
++    struct pi_info *pi;
++    char *comm;
++{
++    if(comm){
++	int i;
++	for(i = 0; comm[i]; i++){
++	    if(comm[i] == '\032')	/* 0x1a, '^Z' */
++		comm[i] = ' ';
++	}
++	if(i > 0){
++	    if(fwrite(comm, (size_t) i, (size_t) 1, pi->fp) != 1)
++		pi_file_error(pi, PI_WRITE);
++	}
++    }
++
++    if(fwrite("\032\0", (size_t) 2, (size_t) 1, pi->fp) != 1)
++	pi_file_error(pi, PI_WRITE);
++}
++
++static void pi_write_palette(pi, r, g, b)
++    struct pi_info *pi;
++    byte *r, *g, *b;
++{
++    int i;
++    int pinum = 1 << pi->cbits;
++    char buf[3];
++
++    for(i = 0; i < pi->numcols; i++){
++	buf[0] = *r++;
++	buf[1] = *g++;
++	buf[2] = *b++;
++	if(pi->writing_grey)
++	    buf[0] = buf[1] = buf[2] = MONO(buf[0], buf[1], buf[2]);
++	if(fwrite(buf, (size_t) 3, (size_t) 1, pi->fp) != 1)
++	    pi_file_error(pi, PI_WRITE);
++    }
++    for( ; i < pinum; i++){
++	if(fwrite(buf, (size_t) 3, (size_t) 1, pi->fp) != 1)
++	    pi_file_error(pi, PI_WRITE);
++    }
++    pi->numcols = pinum;
++}
++
++/* The main routine to compress `Pi' format. */
++static void pi_compress(pi, pic)
++    struct pi_info *pi;
++    byte *pic;
++{
++    byte prev_col = 0;
++    int prev_pos = -1;
++    int cnt = 0, max_cnt = pi->width * pi->height;
++    pi_table_create(pi);
++
++    if(pi->width > 2){
++	int pos;
++	data32 len;
++
++	pi_write_color(pi, 0,      pic[0]);
++	pi_write_color(pi, pic[0], pic[1]);
++	pos = pi_test_matching(pi, pic, prev_pos, cnt, &len);
++	while(cnt < max_cnt){
++	    if(pos >= 0){
++		pi_write_position(pi, pos);
++		pi_write_length(pi, len);
++		if((cnt += len * 2) >= max_cnt)
++		    break;
++		prev_col = pic[cnt - 1];
++		prev_pos = pos;
++		pos = pi_test_matching(pi, pic, prev_pos, cnt, &len);
++	    }else{
++		pi_write_position(pi, prev_pos);
++		prev_pos = -1;
++		while(pos < 0){
++		    pi_write_color(pi, (int) prev_col, pic[cnt]);
++		    prev_col = pic[cnt];
++		    if(++cnt >= max_cnt)
++			break;
++		    pi_write_color(pi, (int) prev_col, pic[cnt]);
++		    prev_col = pic[cnt];
++		    if(++cnt >= max_cnt)
++			break;
++		    pos = pi_test_matching(pi, pic, -1, cnt, &len);
++		    if(pos < 0)
++			pi_write_bits(pi, 1, 1);
++		    else
++			pi_write_bits(pi, 0, 1);
++		}
++	    }
++	}
++    }else{
++	while(cnt < max_cnt){
++	    pi_write_color(pi, (int) prev_col, pic[cnt]);
++	    prev_col = pic[cnt++];
++	}
++    }
++}
++
++static void pi_write_gabage(pi)
++    struct pi_info *pi;
++{
++    pi_write_bits(pi, 0, 32);
++}
++
++static void pi_write_color(pi, prev, col)
++    struct pi_info *pi;
++    int prev, col;
++{
++    int n = pi_table_lookup_value(pi, prev, col);
++
++    if(pi->cbits == 4){
++	if(n < 2)
++	    pi_write_bits(pi, (data32) n | 2, 2);
++	else if(n < 4)
++	    pi_write_bits(pi, (data32) n - 2, 3);
++	else if(n < 8)
++	    pi_write_bits(pi, (data32) (n - 4) | 8, 5);
++	else
++	    pi_write_bits(pi, (data32) (n - 8) | 24, 6);
++    }else{	/* cbits == 8 */
++	if(n < 2){
++	    pi_write_bits(pi, (data32) n | 2, 2);
++	}else{
++	    int bits = 0;
++	    byte base = 2;
++	    while(bits < 6){
++		if(n < (int) base * 2)
++		    break;
++		bits++;
++		base <<= 1;
++	    }
++	    pi_write_bits(pi, 0, 1);
++	    if(bits > 0)
++		pi_write_bits(pi, 0xffffffff, bits);
++	    if(bits < 6)
++		pi_write_bits(pi, 0, 1);
++	    pi_write_bits(pi, (data32) n - base, bits + 1);
++	}
++    }
++}
++
++static int pi_test_matching(pi, pic, prev, cnt, len)
++    struct pi_info *pi;
++    byte *pic;
++    int prev, cnt;
++    data32 *len;
++{
++    data32 lens[5];
++    int pos, p;
++    int s, d = 0;
++    int max = pi->width * pi->height;
++
++    for(pos = 0; pos < 5; pos++){
++	switch(pos){
++	case 0:
++	    if(cnt < 2){
++		if(pic[0] == pic[1])
++		    d = cnt - 2;
++		else
++		    d = cnt - 4;
++	    }else{
++		if(pic[cnt - 2] == pic[cnt - 1])
++		    d = cnt - 2;
++		else
++		    d = cnt - 4;
++	    }
++	    break;
++	case 1:
++	    d = cnt - pi->width;
++	    break;
++	case 2:
++	    d = cnt - pi->width * 2;
++	    break;
++	case 3:
++	    d = cnt - pi->width + 1;
++	    break;
++	case 4:
++	    d = cnt - pi->width - 1;
++	}
++	s = cnt;
++	lens[pos] = 0;
++
++	if(prev == 0 && pos == 0)
++	    continue;
++
++	while(d < max){
++	    if(pic[(d < 0) ? (-d) % 2 : d] != pic[s])
++		break;
++	    lens[pos]++;
++	    d++;
++	    s++;
++	}
++
++    }
++
++    for(pos = 0, p = 1; p < 5; p++){
++	if(lens[p] >= lens[pos])
++	    pos = p;
++    }
++
++    if(lens[pos] / 2 == 0)
++	return -1;
++    *len = lens[pos] / 2;
++    return pos;
++}
++
++static void pi_write_position(pi, pos)
++    struct pi_info *pi;
++    int pos;
++{
++    switch(pos){
++    case 0:
++	pi_write_bits(pi, 0, 2);
++	break;
++    case 1:
++	pi_write_bits(pi, 1, 2);
++	break;
++    case 2:
++	pi_write_bits(pi, 2, 2);
++	break;
++    case 3:
++	pi_write_bits(pi, 6, 3);
++	break;
++    case 4:
++	pi_write_bits(pi, 7, 3);
++	break;
++    }
++}
++
++static void pi_write_length(pi, len)
++    struct pi_info *pi;
++    data32 len;
++{
++    int bits = 0;
++    data32 base = 1;
++
++    while(len >= base * 2){
++	bits++;
++	base <<= 1;
++    }
++    if(bits > 0){
++	pi_write_bits(pi, 0xffffffff, bits);
++	pi_write_bits(pi, 0, 1);
++	pi_write_bits(pi, len - base, bits);
++    }else
++	pi_write_bits(pi, 0, 1);
++}
++
++/*
++ * These pi_table_* functions manipulate the color table.
++ * pi_table_create:
++ *	allocates and initializes a color table.
++ * pi_table_get_value:
++ *	get the specified value, and move it to the top of the list.
++ * pi_table_lookup_value:
++ *	look up the specified value, and move it to the top of the list.
++ */
++static void pi_table_create(pi)
++    struct pi_info *pi;
++{
++    struct ct_t *t;
++    int i;
++    byte mask = pi->numcols - 1;
++    pi->ct = pi_malloc(sizeof *pi->ct * pi->numcols, "pi_table_create(1)");
++    for(i = 0, t = pi->ct; i < pi->numcols; i++, t++){
++	int j;
++	byte v = i;
++	t->elt = pi_malloc(sizeof *t->elt * pi->numcols, "pi_table_create(2)");
++	t->top = &t->elt[pi->numcols - 1];
++	for(j = 0; j < pi->numcols; j++){
++	    v = (v + 1) & mask;
++	    if(j > 0)
++		t->elt[j].old    = &t->elt[j - 1];
++	    else
++		t->elt[0].old    = t->top;
++	    if(j < pi->numcols - 1)
++		t->elt[j].recent = &t->elt[j + 1];
++	    else
++		t->elt[j].recent = &t->elt[0];
++	    t->elt[j].val    = v;
++	}
++	t->elt[0].old = t->top;
++	t->top->recent = &t->elt[0];
++    }
++}
++
++static byte pi_table_get_value(pi, left, num)
++    struct pi_info *pi;
++    int left, num;
++{
++    struct ct_t *t = &pi->ct[left];
++    struct elt_t *e = t->top;
++    if(left >= pi->numcols || num >= pi->numcols)
++	abort();
++    if(num != 0){
++	do {
++	    e = e->old;
++	}while(--num != 0);
++
++	e->old->recent = e->recent;
++	e->recent->old = e->old;
++
++	e->recent = t->top->recent;
++	e->recent->old = e;
++	e->old = t->top;
++	t->top->recent = e;
++
++	t->top = e;
++    }
++    return e->val;
++}
++
++static int pi_table_lookup_value(pi, left, v)
++    struct pi_info *pi;
++    int left, v;
++{
++    struct ct_t *t = &pi->ct[left];
++    struct elt_t *e = t->top;
++    int num = 0;
++
++    if(left >= pi->numcols || v >= pi->numcols)
++	abort();
++
++    while(e->val != v){
++	e = e->old;
++	num++;
++    }
++
++    if(num != 0){
++	e->old->recent = e->recent;
++	e->recent->old = e->old;
++
++	e->recent = t->top->recent;
++	e->recent->old = e;
++	e->old = t->top;
++	t->top->recent = e;
++
++	t->top = e;
++    }
++
++    return num;
++}
++
++/*
++ * These 2 functions read or write to a bit stream.
++ * pi_read_bits:
++ *	reads a specified-bit data from the bit stream.
++ * pi_write_bits:
++ *	writes a specified-bit data to the bit stream.
++ */
++static data32 pi_read_bits(pi, numbits)
++    struct pi_info *pi;
++    int numbits;
++{
++    data32 r = 0;
++
++    while(numbits > 0){
++	while(pi->bs.rest > 0 && numbits > 0){
++	    r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0);
++	    pi->bs.cur <<= 1;
++	    pi->bs.rest--;
++	    numbits--;
++	}
++	if(numbits > 0){
++	    int c;
++	    if((c = fgetc(pi->fp)) == EOF)
++		pi_file_warning(pi, PI_CORRUPT);
++	    pi->bs.cur  = c;
++	    pi->bs.rest = 8;
++	}
++    }
++
++    return r;
++}
++
++static void pi_write_bits(pi, dat, bits)
++    struct pi_info *pi;
++    data32 dat;
++    int bits;
++{
++    data32 dat_mask = 1 << (bits - 1);
++    while(bits > 0){
++	while(pi->bs.rest < 8 && bits > 0){
++	    pi->bs.cur <<= 1;
++	    if(dat & dat_mask)
++		pi->bs.cur |= 1;
++	    pi->bs.rest++;
++	    bits--;
++	    dat_mask >>= 1;
++	}
++	if(pi->bs.rest >= 8){
++	    if(fputc((int)pi->bs.cur, pi->fp) == EOF)
++		pi_file_error(pi, PI_WRITE);
++	    pi->bs.cur  = 0;
++	    pi->bs.rest = 0;
++	}
++    }
++}
++
++/*
++ * The routines to initialize or clean up.
++ * pi_inif_pi_info:
++ *	initializes a pi_info structure.
++ * pi_cleanup_pi_info:
++ *	cleanup pi_info structure. It frees allocated memories.
++ * pi_cleanup_pinfo:
++ *	cleanup PICINFO structure when an error occurs.
++ */
++static void pi_init_pi_info(pi)
++    struct pi_info *pi;
++{
++    pi->fp = NULL;
++    pi->bs.rest = 0;
++    pi->bs.cur = 0;
++    pi->fsize = 0;
++    pi->mode = 0;
++    pi->width = pi->mode = 0;
++    pi->aspect = 1.0;
++    pi->cbits = 0;
++    pi->numcols = 0;
++    pi->cmap = NULL;
++    pi->ct = NULL;
++    pi->defcmap = 0;
++    pi->writing_grey = 0;
++}
++
++static void pi_cleanup_pi_info(pi, writing)
++    struct pi_info *pi;
++    int writing;
++{
++    if(pi->fp && !writing){
++	fclose(pi->fp);
++	pi->fp = NULL;
++    }
++    if(pi->cmap){
++	free(pi->cmap);
++	pi->cmap = NULL;
++    }
++    if(pi->ct){
++	int i;
++	for(i = 0; i < pi->numcols; i++)
++	    free(pi->ct[i].elt);
++	free(pi->ct);
++	pi->ct = NULL;
++    }
++}
++
++static void pi_cleanup_pinfo(pinfo)
++    PICINFO *pinfo;
++{
++    if(pinfo->pic){
++	free(pinfo->pic);
++	pinfo->pic = NULL;
++    }
++    if(pinfo->comment){
++	free(pinfo->comment);
++	pinfo->comment = NULL;
++    }
++}
++
++/*
++ * Error handling routins.
++ * pi_memory_error:
++ *	shows a error message, and terminates.
++ * pi_error:
++ *	shows a non-file error message.
++ * pi_file_error:
++ *	shows a file error message.
++ */
++static void pi_memory_error(scm, fn)
++    char *scm, *fn;
++{
++    char buf[128];
++    sprintf(buf, "%s: couldn't allocate memory. (%s)", scm ,fn);
++    FatalError(buf);
++}
++
++static void pi_error(pi, mn)
++    struct pi_info *pi;
++    int mn;
++{
++    SetISTR(ISTR_WARNING, "%s", pi_msgs[mn]);
++    longjmp(pi->jmp, 1);
++}
++
++static void pi_file_error(pi, mn)
++    struct pi_info *pi;
++    int mn;
++{
++    if(feof(pi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", pi_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", pi_msgs[mn], ERRSTR(errno));
++    longjmp(pi->jmp, 1);
++}
++
++static void pi_file_warning(pi, mn)
++    struct pi_info *pi;
++    int mn;
++{
++    if(feof(pi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", pi_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", pi_msgs[mn], ERRSTR(errno));
++}
++
++static void pi_show_pi_info(pi)
++    struct pi_info *pi;
++{
++    fprintf(stderr, "  file size: %ld.\n", pi->fsize);
++    fprintf(stderr, "  mode: 0x%02x.\n", pi->mode);
++    fprintf(stderr, "  image size: %dx%d.\n", pi->width, pi->height);
++    fprintf(stderr, "  aspect: %f.\n", pi->aspect);
++    fprintf(stderr, "  number of color bits: %d.\n", pi->cbits);
++    fprintf(stderr, "  number of colors: %d.\n", pi->numcols);
++    fprintf(stderr, "  using default colormap: %s.\n",
++	    pi->defcmap ? "true" : "false");
++    fprintf(stderr, "  writing greyscale image: %s.\n",
++	    pi->writing_grey ? "true" : "false");
++}
++
++/*
++ * Memory related routines.  If failed, they calls pi_memory_error.
++ */
++static void *pi_malloc(n, fn)
++    size_t n;
++    char *fn;
++{
++    void *r = (void *) malloc(n);
++    if(r == NULL)
++	pi_memory_error("malloc", fn);
++    return r;
++}
++
++static void *pi_realloc(p, n, fn)
++    void *p;
++    size_t n;
++    char *fn;
++{
++    void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n);
++    if(r == NULL)
++	pi_memory_error("realloc", fn);
++    return r;
++}
++#endif /* HAVE_PI */
+diff -Naru xv-3.10a/xvpic2.c xv-3.10a.jumbo/xvpic2.c
+--- xv-3.10a/xvpic2.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvpic2.c	2007-04-16 00:02:32.000000000 +0200
+@@ -0,0 +1,3608 @@
++/*
++ * $Id: xvpic2.c,v 2.9.1.14 1995/04/24 15:34:15 ikeyan Exp $
++ * xvpic2.c - load and save routines for `PIC2' format pictures.
++ *
++ *
++ * Outline
++ * =======
++ * xvpic2.c supports the PIC2 format image file. It is used some
++ * Japanese personal computer users.
++ *
++ * The PIC2 format is designed by A.Yanagisawa. It is an excellent
++ * format except for its encode/decode speed. ;-)
++ *
++ * The features of the PIC2 format:
++ * - Powerful header information (included author, filename, title,
++ *   saver, product number, created date and comment).
++ * - Reversible compression, and very high compression ratio (in many
++ *   cases, a higher compression ratio than the JPEG compression;
++ *   because of its compression method, PIC2 is especially good at
++ *   pictures like cell animation).
++ * - Can handle full-color (24 bits) image.
++ * - Can include multi image blocks into one PIC2 file.
++ * - Have four different block format (P2SS, P2SF, P2BM and
++ *   P2BI). P2SS format uses arithmetic compression for storing
++ *   data. P2SF uses normal run-length compression. P2BM and P2BI is
++ *   raw image format. Select any one according to the situation.
++ *
++ * Explanation of the PIC2 compression:
++
++ * - In the first place, try to record pixel color, uses color caches
++ *   which keep some recent colors, and formed according to color's
++ *   frequency.  PIC2 has some color cache spaces that are switched by
++ *   upper pixel value of current pixel.  If cache is hit, record
++ *   that.
++ * - Unfortunately, in the case of color cache didn't hit, record the
++ *   difference from the value estimated with the value of upper and
++ *   left pixel of current pixel (similar to PNG's AVG predictor).
++ * - And extract image's color chain if exist, and record that (it
++ *   results in image's outline).
++ * - In all cases, arithmetic compression is used in the final stage
++ *   before writing the file, which in theory produces the ideal
++ *   compression ratio (P2SS).
++ *
++ * Features
++ * ========
++ * - Support 3,6,9,12,15,18,21,24bit PIC2 format (Load/Save).
++ * - Support all image block formats of PIC2 (Load/Save).
++ * - Support multi block PIC2 file (Load/Save).
++ *
++ *
++ * Bugs
++ * ====
++ * - Unsupport 8bit PIC2 image file.
++ *
++ * If you find other bugs (surely exist :-)), send me bug-report.
++ *
++ *
++ * Author
++ * ======
++ * IKEMOTO Masahiro <ikeyan at airlab.cs.ritsumei.ac.jp>
++ */
++
++#define PIC2_IGNORE_UNUSED_FUNCTIONS
++#define NEEDSDIR
++
++#include "xv.h"
++#include <setjmp.h>
++
++#ifdef HAVE_PIC2
++
++typedef unsigned long pixel;
++
++#define pic2_cextoshort(addr) ( \
++    (((short) (((byte *) addr)[0])) <<  8) | \
++    ( (short) (((byte *) addr)[1])) \
++)
++#define pic2_cextolong(addr) ( \
++    (((long)  (((byte *) addr)[0])) << 24) | \
++    (((long)  (((byte *) addr)[1])) << 16) | \
++    (((long)  (((byte *) addr)[2])) <<  8) | \
++    ( (long)  (((byte *) addr)[3])) \
++)
++#define pic2_shorttocex(addr, n) { \
++    ((byte *) addr)[0] = (((unsigned short) (n) >>  8) & 0xff); \
++    ((byte *) addr)[1] = ( (unsigned short) (n)        & 0xff); \
++}
++#define pic2_longtocex(addr, n) { \
++    ((byte *) addr)[0] = (((unsigned long)  (n) >> 24) & 0xff); \
++    ((byte *) addr)[1] = (((unsigned long)  (n) >> 16) & 0xff); \
++    ((byte *) addr)[2] = (((unsigned long)  (n) >>  8) & 0xff); \
++    ((byte *) addr)[3] = ( (unsigned long)  (n)        & 0xff); \
++}
++#define pic2_shift_bits(b, n) (((n) > 0) ? ((b) << (n)) : ((b) >> -(n)))
++
++#define PIC2_READ_MODE		0
++#define PIC2_WRITE_MODE		1
++
++#define PIC2_ARITH_CACHE	32
++#define PIC2_ARITH_CONTEXT	128
++#define PIC2_FAST_CACHE		64
++
++#define PIC2_HEADER_SIZE	124
++#define PIC2_BLOCK_HEADER_SIZE	26
++
++struct pic2_header {
++    char magic[4];
++    char name[18];
++    char subtitle[8];
++    char crlf0[2];
++    char title[30];
++    char crlf1[2];
++    char saver[30];
++    char crlf2[2];
++    char eof[1];
++    char reserve0[1];
++    short flag;
++    short no;
++    long time;
++    long size;
++    short depth;
++    short x_aspect;
++    short y_aspect;
++    short x_max;
++    short y_max;
++    long reserve1;
++};
++
++struct pic2_block {
++    char id[4];
++    long size;
++    short flag;
++    short x_wid;
++    short y_wid;
++    short x_offset;
++    short y_offset;
++    long opaque;
++    long reserve;
++};
++
++struct pic2_info {
++    jmp_buf jmp;
++    FILE *fp;
++    struct {
++	int rest;
++	byte cur;
++	int bits;
++	char zero;
++    }bs;
++    long fsize;
++    struct pic2_header *header;
++    struct pic2_block *block;
++    int n_pal;
++    int pal_bits;
++    byte pal[256][3];
++    char *comment;
++    char mode;
++    long next_pos;
++    long block_pos;
++    short x_max;
++    short y_max;
++    int ynow;
++    byte *buf;
++    pixel *vram_prev;
++    pixel *vram_now;
++    pixel *vram_next;
++    short *flag_now;
++    short *flag_next;
++    short *flag2_now;
++    short *flag2_next;
++    short *flag2_next2;
++    pixel (*cache)[PIC2_ARITH_CACHE];
++    unsigned short *cache_pos;
++    unsigned short *mulu_tab;
++    long aa;
++    long cc;
++    long dd;
++    char cache_hit_c;
++    int (*next_line) PARM((struct pic2_info *, pixel **));
++    char writing_grey;
++    char pagebname[64];
++    int pnum;
++};
++
++static void pic2_open_file             PARM((struct pic2_info*,char*));
++static void pic2_read_header           PARM((struct pic2_info*));
++static void pic2_read_block_header1    PARM((struct pic2_info*));
++static void pic2_read_block_header2    PARM((struct pic2_info*));
++static short pic2_arith_decode_bit     PARM((struct pic2_info*,int));
++static short pic2_arith_decode_nn      PARM((struct pic2_info*,int));
++static void pic2_arith_expand_chain    PARM((struct pic2_info*,int,int,pixel));
++static short pic2_arith_get_number     PARM((struct pic2_info*,int,int));
++static pixel pic2_arith_read_color     PARM((struct pic2_info*,int));
++static int pic2_arith_expand_line      PARM((struct pic2_info*,pixel**));
++static int pic2_arith_loader_init      PARM((struct pic2_info*));
++static int pic2_fast_read_length       PARM((struct pic2_info*));
++static void pic2_fast_expand_chain     PARM((struct pic2_info*,int,pixel));
++static pixel pic2_fast_read_color      PARM((struct pic2_info*,pixel));
++static int pic2_fast_expand_line       PARM((struct pic2_info*,pixel**));
++static int pic2_fast_loader_init       PARM((struct pic2_info*));
++static int pic2_beta_expand_line       PARM((struct pic2_info*,pixel**));
++static int pic2_beta_loader_init       PARM((struct pic2_info*));
++static void pic2_make_xvpic            PARM((struct pic2_info*,byte**,
++					     byte*,byte*,byte*));
++static void pic2_make_pagefile         PARM((struct pic2_info*,char*,int));
++static void pic2_setup_pic2_info       PARM((struct pic2_info*,
++					     char*,char*,char*,char*,
++					     int,int,int,int,int,int,char *));
++static void pic2_append                PARM((struct pic2_info*));
++static void pic2_write_header1         PARM((struct pic2_info*));
++static void pic2_write_header2         PARM((struct pic2_info*));
++static void pic2_write_block_header    PARM((struct pic2_info*));
++static void pic2_arith_write_zero_bit  PARM((struct pic2_info*));
++static void pic2_arith_flush_bit_buf   PARM((struct pic2_info*));
++static void pic2_arith_carry_bit       PARM((struct pic2_info*));
++static void pic2_arith_encode_bit      PARM((struct pic2_info*,int,int));
++static void pic2_arith_encode_nbyte    PARM((struct pic2_info*,int,int,int));
++static void pic2_arith_encode_nn       PARM((struct pic2_info*,int,int));
++static void pic2_arith_press_chain     PARM((struct pic2_info*,int));
++static void pic2_arith_put_number      PARM((struct pic2_info*,int,int,int));
++static void pic2_arith_write_color     PARM((struct pic2_info*,int));
++static void pic2_arith_press_line2     PARM((struct pic2_info*));
++static int pic2_arith_press_line       PARM((struct pic2_info*,pixel**));
++static int pic2_arith_saver_init       PARM((struct pic2_info*,pixel**));
++static void pic2_fast_write_length     PARM((struct pic2_info*,int));
++static void pic2_fast_press_chain      PARM((struct pic2_info*,int));
++static void pic2_fast_press_chain2     PARM((struct pic2_info*,int));
++static void pic2_fast_flush_chain      PARM((struct pic2_info*));
++static void pic2_fast_write_color      PARM((struct pic2_info*,int));
++static void pic2_fast_press_line2      PARM((struct pic2_info*));
++static int pic2_fast_press_line        PARM((struct pic2_info*,pixel**));
++static int pic2_fast_saver_init        PARM((struct pic2_info*,pixel**));
++static int pic2_beta_press_line        PARM((struct pic2_info*,pixel**));
++static int pic2_beta_saver_init        PARM((struct pic2_info*,pixel**));
++static void pic2_write_data            PARM((struct pic2_info*,byte*,
++					     int,int,int,int,int,
++					     byte*,byte*,byte*,int,int));
++static int pic2_next_line              PARM((struct pic2_info*,pixel**));
++static int pic2_next_block             PARM((struct pic2_info*));
++static int pic2_find_block             PARM((struct pic2_info*));
++static int pic2_load_block             PARM((struct pic2_info*));
++static int pic2_save_block             PARM((struct pic2_info*,pixel**,
++					     int,int,int,int,char*,pixel));
++#ifndef PIC2_IGNORE_UNUSED_FUNCTIONS
++static void pic2_read_palette          PARM((struct pic2_info*,
++					     byte*,byte*,byte*));
++static void pic2_write_palette         PARM((struct pic2_info*,int,int,
++					     byte*,byte*,byte*));
++#endif /* !PIC2_IGNORE_UNUSED_FUNCTIONS */
++static byte pic2_convert_color_bits    PARM((int,int,int));
++static byte pic2_pad_color_bits        PARM((int,int,int));
++static byte pic2_reduce_color_bits     PARM((int,int,int));
++static pixel pic2_exchange_rg          PARM((pixel,int));
++static void pic2_handle_para           PARM((struct pic2_info*,int));
++static int pic2_alloc_buffer           PARM((struct pic2_info*));
++static void pic2_free_buffer           PARM((struct pic2_info*));
++static long pic2_seek_file             PARM((struct pic2_info*,long,int));
++static long pic2_tell_file             PARM((struct pic2_info*));
++static int pic2_read_file              PARM((struct pic2_info*,void*,size_t));
++static long pic2_read_long             PARM((struct pic2_info*));
++static short pic2_read_short           PARM((struct pic2_info*));
++static char pic2_read_char             PARM((struct pic2_info*));
++static int pic2_write_file             PARM((struct pic2_info*,void*,size_t));
++static int pic2_write_long             PARM((struct pic2_info*,long));
++static int pic2_write_short            PARM((struct pic2_info*,int));
++static int pic2_write_char             PARM((struct pic2_info*,int));
++static unsigned long pic2_read_bits    PARM((struct pic2_info*,int));
++static void pic2_write_bits            PARM((struct pic2_info*,
++					     unsigned long,int));
++static void pic2_flush_bits            PARM((struct pic2_info*));
++static void pic2_memory_error          PARM((char*,char*));
++static void pic2_error                 PARM((struct pic2_info*,int));
++static void pic2_file_error            PARM((struct pic2_info*,int));
++static void pic2_init_info             PARM((struct pic2_info*));
++static void pic2_cleanup_pic2_info     PARM((struct pic2_info*,int));
++static void pic2_cleanup_pinfo         PARM((PICINFO*));
++static void pic2_show_pic2_info        PARM((struct pic2_info*));
++static char *pic2_strncpy              PARM((char*,char*,size_t));
++static void *pic2_malloc               PARM((size_t,char*));
++static void *pic2_new                  PARM((size_t,char*));
++
++static int WritePIC2                   PARM((FILE*,byte*,int,int,int,
++					     byte*,byte*,byte*,int,int,char*,
++					     int,int,int,int,int,char*));
++
++static char *pic2_id = "P2DT";
++
++/* Error Messages */
++static char *pic2_msgs[] = {
++    NULL,
++#define PIC2_OPEN 1
++    "can't open file.",
++#define PIC2_CORRUPT 2
++    "file corrupted.",
++#define PIC2_FORMAT 3
++    "not PIC2 format.",
++#define PIC2_DEPTH 4
++    "bit depths not divisible by 3 are unsupported.",
++#define PIC2_TMPFILE 5
++    "unable to create temporary filename???",
++#define PIC2_PAGE 6
++    "couldn't load the page.",
++#define PIC2_APPEND 7
++    "cannot append.",
++#define PIC2_WRITE 8
++    "write failed.",
++};
++
++struct _form_tab {
++    char *id;
++    int (*loader_init) PARM((struct pic2_info *));
++    int (*saver_init) PARM((struct pic2_info *, pixel **));
++} form_tab[] = {
++	{ "P2SS", pic2_arith_loader_init, pic2_arith_saver_init},
++	{ "P2SF", pic2_fast_loader_init, pic2_fast_saver_init},
++	{ "P2BM", pic2_beta_loader_init, pic2_beta_saver_init},
++	{ "P2BI", pic2_beta_loader_init, pic2_beta_saver_init},
++};
++#define	n_form_tab (sizeof(form_tab) / sizeof(struct _form_tab))
++#define P2SS 0
++#define P2SF 1
++#define P2BM 2
++#define P2BI 3
++
++/* The main routine to load a PIC2 file. */
++int LoadPIC2(fname, pinfo, quick)
++char *fname;
++PICINFO *pinfo;
++int quick;
++{
++    int e, i, block;
++    struct pic2_info pic2;
++
++    if (DEBUG)
++	fputs("LoadPIC2:\n", stderr);
++
++    pic2_init_info(&pic2);
++
++    if ((e = setjmp(pic2.jmp)) != 0){
++	/* When an error occurs, comes here. */
++	pic2_free_buffer(&pic2);
++	pic2_cleanup_pic2_info(&pic2, 0);
++	pic2_cleanup_pinfo(pinfo);
++	if (pic2split)
++	    KillPageFiles(pic2.pagebname, pic2.pnum);
++	SetCursors(-1);
++	if (DEBUG)
++	    fputs("\n", stderr);
++	return (0);
++    }
++    pic2_open_file(&pic2, fname);
++    pic2_read_header(&pic2);
++
++    if ((i = pic2_find_block(&pic2)) == 0)
++	pic2_file_error(&pic2, PIC2_CORRUPT);
++
++    block = 1;
++    while(i == 2) {
++	SetISTR(ISTR_WARNING, "unknown or invalid block #%d.", block);
++	i = pic2_next_block(&pic2);
++	block++;
++    }
++
++    if (pic2split && !quick) {
++	char firstpage[512];
++	struct stat st;
++#ifndef USE_MKSTEMP
++	int tmpfd;
++#endif
++
++#ifndef VMS
++	sprintf(pic2.pagebname, "%s/xvpic2XXXXXX", tmpdir);
++#else
++	sprintf(pic2.pagebname, "Sys$Scratch:xvpic2XXXXXX");
++#endif
++#ifdef USE_MKSTEMP
++	close(mkstemp(pic2.pagebname));
++#else
++	mktemp(pic2.pagebname);
++	tmpfd = open(pic2.pagebname, O_WRONLY|O_CREAT|O_EXCL, S_IRWUSR);
++	if (tmpfd < 0) FatalError("LoadPIC2(): can't create temporary file");
++	close(tmpfd);
++#endif
++	if (pic2.pagebname[0] == '\0')
++	    pic2_error(&pic2, PIC2_TMPFILE);
++	strcat(pic2.pagebname, ".");
++
++	sprintf(firstpage, "%s%d", pic2.pagebname, 1);
++	if (stat(firstpage, &st)) {
++	    for (pic2.pnum = 1; i >= 1; pic2.pnum++) {
++		pic2_load_block(&pic2);
++		pic2_make_pagefile(&pic2, pic2.pagebname, pic2.pnum);
++		while(block++, (i = pic2_next_block(&pic2)) == 2)
++		    SetISTR(ISTR_WARNING,
++			    "unknown or invalid block #%d.", block);
++	    }
++            pinfo->numpages = --pic2.pnum;
++            if (!LoadPIC2(firstpage, pinfo, 1))
++		pic2_error(&pic2, PIC2_PAGE);
++	    if (pic2.pnum == 1)
++		unlink(firstpage);
++	    else
++		strcpy(pinfo->pagebname, pic2.pagebname);
++	} else
++            if (!LoadPIC2(fname, pinfo, 1))
++		pic2_error(&pic2, PIC2_PAGE);
++    } else {
++	char buf[128], format[64];
++	int j;
++
++	pinfo->w = pic2.x_max;
++	pinfo->h = pic2.y_max;
++	pinfo->normw = pinfo->w;
++	pinfo->normh = pinfo->h;
++	pinfo->type = PIC24;
++	for (j = 0; j < n_form_tab; j++) {
++	    if (xvbcmp(pic2.block->id, form_tab[j].id, (size_t) 4) == 0)
++		break;
++	}
++	pinfo->frmType = F_PIC2;
++	pinfo->colType = F_FULLCOLOR;
++	pinfo->comment = pic2.comment;
++
++	if (pic2split) {
++	    pic2_make_xvpic(&pic2, &pinfo->pic, pinfo->r, pinfo->g, pinfo->b);
++	    strcpy(format, form_tab[j].id);
++	} else {
++	    for (pic2.pnum = 1; i >= 1; pic2.pnum++) {
++		SetISTR(ISTR_INFO, "composing block #%d", block);
++		pic2_make_xvpic(&pic2, &pinfo->pic,
++				pinfo->r, pinfo->g, pinfo->b);
++		while(block++, (i = pic2_next_block(&pic2)) == 2)
++		    SetISTR(ISTR_WARNING,
++			    "unknown or invalid block #%d.", block);
++	    }
++	    if (--block > 1)
++		if (block != --pic2.pnum)
++		    sprintf(format, "MultiBlock[%d/%d]", block, pic2.pnum);
++		else
++		    sprintf(format, "MultiBlock[%d]", block);
++	    else
++		strcpy(format, form_tab[j].id);
++	}
++	sprintf(buf, "PIC2(%s). %d colors (%ld bytes)", format,
++		(int) 1 << pic2.header->depth, pic2.fsize);
++	strcat(pinfo->fullInfo, buf);
++	sprintf(pinfo->shrtInfo, "%dx%d(aspect %4.2f) PIC2(%s).",
++		pinfo->w, pinfo->h,
++		(float) pic2.header->x_aspect / (float) pic2.header->y_aspect,
++		format);
++	if (!nopicadjust)
++	    normaspect = (float) pic2.header->x_aspect
++			 / (float) pic2.header->y_aspect;
++    }
++    pic2_cleanup_pic2_info(&pic2, 0);
++    SetCursors(-1);
++    if (DEBUG)
++	fputs("\n", stderr);
++    return (1);
++}
++
++/*
++ * This function opens the file, and set its size.
++ */
++static void pic2_open_file(pi, fname)
++    struct pic2_info *pi;
++    char *fname;
++{
++    if ((pi->fp = fopen(fname, "rb")) == NULL)
++	pic2_file_error(pi, PIC2_OPEN);
++    fseek(pi->fp, (size_t) 0, SEEK_END);
++    pi->fsize = ftell(pi->fp);
++    fseek(pi->fp, (size_t) 0, SEEK_SET);
++}
++
++/*
++ * These functions read the PIC2 header informations.
++ * pic2_read_header:
++ *	reads the PIC2 header.
++ * pic2_read_block_header1:
++ *	reads the id number of block header and the size of block.
++ * pic2_read_block_header2:
++ *	reads the rest of block header.
++ */
++static void pic2_read_header(pi)
++struct pic2_info *pi;
++{
++    long s_comment;
++
++    pi->mode = PIC2_READ_MODE;
++
++    /* read header image */
++    pic2_read_file(pi, pi->header->magic, 4);
++    pic2_read_file(pi, pi->header->name, 18);
++    pic2_read_file(pi, pi->header->subtitle, 8);
++    pic2_read_file(pi, pi->header->crlf0, 2);
++    pic2_read_file(pi, pi->header->title, 30);
++    pic2_read_file(pi, pi->header->crlf1, 2);
++    pic2_read_file(pi, pi->header->saver, 30);
++    pic2_read_file(pi, pi->header->crlf2, 2);
++    pic2_read_file(pi, pi->header->eof, 1);
++    pic2_read_file(pi, pi->header->reserve0, 1);
++    pi->header->flag = pic2_read_short(pi);
++    pi->header->no = pic2_read_short(pi);
++    pi->header->time = pic2_read_long(pi);
++    pi->header->size = pic2_read_long(pi);
++    pi->header->depth = pic2_read_short(pi);
++    pi->header->x_aspect = pic2_read_short(pi);
++    pi->header->y_aspect = pic2_read_short(pi);
++    pi->header->x_max = pic2_read_short(pi);
++    pi->header->y_max = pic2_read_short(pi);
++    pi->header->reserve1 = pic2_read_long(pi);
++
++    /* check magic number */
++    if (strncmp(pi->header->magic, pic2_id, (size_t) 4) != 0)
++        pic2_error(pi, PIC2_FORMAT);
++
++    /* read palette data, if exists */
++    if (pi->header->flag & 1) {
++	pi->pal_bits = pic2_read_char(pi);
++	pi->n_pal = pic2_read_short(pi);
++	pic2_read_file(pi, pi->pal, (size_t) (pi->n_pal * 3));
++    }
++
++    /* read comments */
++    s_comment = pi->header->size - pic2_tell_file(pi);
++    pi->comment = pic2_new(s_comment + 1, "pic2_read_header");
++    pic2_read_file(pi, pi->comment, (size_t) s_comment);
++    pi->comment[s_comment] = '\0';
++
++    pi->x_max = pi->header->x_max;
++    pi->y_max = pi->header->y_max;
++
++    /* set initial block point */
++    pi->next_pos = pic2_tell_file(pi);
++}
++
++static void pic2_read_block_header1(pi)
++struct pic2_info *pi;
++{
++    pic2_read_file(pi, pi->block->id, 4);
++    pi->block->size = pic2_read_long(pi);
++}
++
++static void pic2_read_block_header2(pi)
++struct pic2_info *pi;
++{
++    pi->block->flag = pic2_read_short(pi);
++    pi->block->x_wid = pic2_read_short(pi);
++    pi->block->y_wid = pic2_read_short(pi);
++    pi->block->x_offset = pic2_read_short(pi);
++    pi->block->y_offset = pic2_read_short(pi);
++    pi->block->opaque = pic2_read_long(pi);
++    pi->block->reserve = pic2_read_long(pi);
++}
++
++/*
++ * These functions are arithmetic pic2 format extractor.
++ */
++static short pic2_arith_decode_bit(pi, c)
++struct pic2_info *pi;
++int c;
++{
++    unsigned short pp;
++
++    pp = pi->mulu_tab[(pi->aa & 0x7f00) / 2 + c];
++    if (pi->dd >= (int) pp) {
++	pi->dd -= pp;
++	pi->aa -= pp;
++
++	while ((short) pi->aa >= 0) {
++	    pi->dd *= 2;
++	    if (pic2_read_bits(pi, 1))
++		pi->dd++;
++	    pi->aa *= 2;
++	}
++	return (1);
++    } else {
++	pi->aa = pp;
++
++	while ((short) pi->aa >= 0) {
++	    pi->dd *= 2;
++	    if (pic2_read_bits(pi, 1))
++		pi->dd++;
++	    pi->aa *= 2;
++	}
++	return (0);
++    }
++}
++
++static short pic2_arith_decode_nn(pi, c)
++struct pic2_info *pi;
++int c;
++{
++    int n;
++
++    if (pic2_arith_decode_bit(pi, c)) {
++	/* n < 1 */
++	n = 0;
++    } else if (pic2_arith_decode_bit(pi, c + 1)) {
++	/* n < 1 + 2 */
++	n = 1;
++	if (pic2_arith_decode_bit(pi, c + 8))
++	    n += 1;
++    } else if (pic2_arith_decode_bit(pi, c + 2)) {
++	/* n < 1 + 2 + 4 */
++	n = 1 + 2;
++	if (pic2_arith_decode_bit(pi,  c + 8))
++	    n += 1;
++	if (pic2_arith_decode_bit(pi,  c + 9))
++	    n += 2;
++    } else if (pic2_arith_decode_bit(pi, c + 3)) {
++	/* n < 1 + 2 + 4 + 8 */
++	n = 1 + 2 + 4;
++	if (pic2_arith_decode_bit(pi, c + 8))
++	    n += 1;
++	if (pic2_arith_decode_bit(pi, c + 9))
++	    n += 2;
++	if (pic2_arith_decode_bit(pi, c + 10))
++	    n += 4;
++    } else if (pic2_arith_decode_bit(pi, c + 4)) {
++	/* n < 1 + 2 + 4 + 8 + 16 */
++	n = 1 + 2 + 4 + 8;
++	if (pic2_arith_decode_bit(pi, c + 8))
++	    n += 1;
++	if (pic2_arith_decode_bit(pi, c + 9))
++	    n += 2;
++	if (pic2_arith_decode_bit(pi, c + 10))
++	    n += 4;
++	if (pic2_arith_decode_bit(pi, c + 11))
++	    n += 8;
++    } else if (pic2_arith_decode_bit(pi,  c + 5)) {
++	/* n < 1 + 2 + 4 + 8 + 16 + 32 */
++	n = 1 + 2 + 4 + 8 + 16;
++	if (pic2_arith_decode_bit(pi, c + 8))
++	    n += 1;
++	if (pic2_arith_decode_bit(pi, c + 9))
++	    n += 2;
++	if (pic2_arith_decode_bit(pi, c + 10))
++	    n += 4;
++	if (pic2_arith_decode_bit(pi, c + 11))
++	    n += 8;
++	if (pic2_arith_decode_bit(pi, c + 12))
++	    n += 16;
++
++    } else if (pic2_arith_decode_bit(pi, c + 6)) {
++	/* n < 1 + 2 + 4 + 8 + 16 + 32 + 64 */
++	n = 1 + 2 + 4 + 8 + 16 + 32;
++	if (pic2_arith_decode_bit(pi, c + 8))
++	    n += 1;
++	if (pic2_arith_decode_bit(pi, c + 9))
++	    n += 2;
++	if (pic2_arith_decode_bit(pi, c + 10))
++	    n += 4;
++	if (pic2_arith_decode_bit(pi, c + 11))
++	    n += 8;
++	if (pic2_arith_decode_bit(pi, c + 12))
++	    n += 16;
++	if (pic2_arith_decode_bit(pi, c + 13))
++	    n += 32;
++
++    } else if (pic2_arith_decode_bit(pi, c + 7)) {
++	/* n < 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 */
++	n = 1 + 2 + 4 + 8 + 16 + 32 + 64;
++	if (pic2_arith_decode_bit(pi, c + 8))
++	    n += 1;
++	if (pic2_arith_decode_bit(pi, c + 9))
++	    n += 2;
++	if (pic2_arith_decode_bit(pi, c + 10))
++	    n += 4;
++	if (pic2_arith_decode_bit(pi, c + 11))
++	    n += 8;
++	if (pic2_arith_decode_bit(pi, c + 12))
++	    n += 16;
++	if (pic2_arith_decode_bit(pi, c + 13))
++	    n += 32;
++	if (pic2_arith_decode_bit(pi, c + 14))
++	    n += 64;
++
++    } else {
++	n = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128;
++    }
++    return (n);
++}
++
++static void pic2_arith_expand_chain(pi, x, y, cc)
++struct pic2_info *pi;
++int x, y;
++pixel cc;
++{
++    static const unsigned short c_tab[] = {
++	80 + 6 * 5,	/* -5 */
++	80 + 6 * 4,
++	80 + 6 * 3,
++	80 + 6 * 2,
++	80 + 6 * 1,
++	80 + 6 * 0,	/* 0  */
++	80 + 6 * 0,	/* 1  */
++    };
++    unsigned short b;
++
++    b = c_tab[pi->flag_now[x] + 5];
++    if (!pic2_arith_decode_bit(pi, b++)) {
++	if (pic2_arith_decode_bit(pi, b++))      {	/* down */
++	    pi->vram_next[x    ] = cc;
++	    pi->flag_next[x    ] = -1;
++	} else if (pic2_arith_decode_bit(pi, b++)) {	/* left */
++	    pi->vram_next[x - 1] = cc;
++	    pi->flag_next[x - 1] = -2;
++	} else if (pic2_arith_decode_bit(pi, b++)) {	/* right */
++	    pi->vram_next[x + 1] = cc;
++	    pi->flag_next[x + 1] = -3;
++	} else if (pic2_arith_decode_bit(pi, b++)) {	/* left2 */
++	    pi->vram_next[x - 2] = cc;
++	    pi->flag_next[x - 2] = -4;
++	} else {					/* right2 */
++	    pi->vram_next[x + 2] = cc;
++	    pi->flag_next[x + 2] = -5;
++	}
++    }
++}
++
++static short pic2_arith_get_number(pi, c, bef)
++struct pic2_info *pi;
++int c, bef;
++{
++    unsigned short n;
++    byte maxcol;
++
++    maxcol = 0xff >> (8 - pi->header->depth / 3);
++
++    n = pic2_arith_decode_nn(pi, c);
++    if (bef > ((int) maxcol >> 1)) {
++	if (n > ((int) maxcol - bef) * 2)
++	    n = maxcol - n;
++	else if (n & 1)
++	    n = n / 2 + bef + 1;
++	else
++	    n = bef - n / 2;
++    } else {
++	if ((int) n > (bef * 2))
++	    n = n;
++	else if (n & 1)
++	    n = n / 2 + bef + 1;
++	else
++	    n = bef - n / 2;
++    }
++    return (n);
++}
++
++static pixel pic2_arith_read_color(pi, x)
++struct pic2_info *pi;
++int x;
++{
++    pixel c1, c2, cc;
++    unsigned short i, j, k, m;
++    short r, g, b, r0, g0, b0;
++    short colbits;
++    pixel rmask, gmask, bmask;
++    byte maxcol;
++
++    colbits = pi->header->depth / 3;
++    rmask = (0xff >> (8 - colbits)) << (colbits * 2);
++    gmask = (0xff >> (8 - colbits)) <<  colbits;
++    bmask = (0xff >> (8 - colbits));
++    maxcol = (byte) bmask;
++
++    c1 = pi->vram_prev[x];
++    k = ((c1 >> ((colbits - 3) * 3)) & 0x1c0)
++      | ((c1 >> ((colbits - 3) * 2)) & 0x038)
++      | ((c1 >>  (colbits - 3)     ) & 0x007);
++    if (colbits == 5)
++	k = pic2_exchange_rg(k, 3);
++
++    if (pic2_arith_decode_bit(pi, pi->cache_hit_c)) {	/* ouch */
++	pi->cache_hit_c = 16;
++
++        c2 = pi->vram_now[x - 1];
++	r = ((c1 & rmask) + (c2 & rmask)) >> (colbits * 2 + 1);
++	g = ((c1 & gmask) + (c2 & gmask)) >> (colbits     + 1);
++	b = ((c1 & bmask) + (c2 & bmask)) >> (              1);
++
++	g0 = pic2_arith_get_number(pi, 32, g);
++        r = r + g0 - g;
++	if (r > (short) maxcol)
++	    r = maxcol;
++	else if (r < 0)
++	    r = 0;
++
++        b = b + g0 - g;
++	if (b > (short) maxcol)
++	    b = maxcol;
++	else if (b < 0)
++	    b = 0;
++
++	r0 = pic2_arith_get_number(pi, 48, r);
++	b0 = pic2_arith_get_number(pi, 64, b);
++
++	pi->cache_pos[k] = j = (pi->cache_pos[k] - 1) & (PIC2_ARITH_CACHE - 1);
++	pi->cache[k][j] = cc = (r0 << (colbits * 2)) | (g0 << colbits) | b0;
++    } else {
++	pi->cache_hit_c = 15;
++
++	j = pic2_arith_decode_nn(pi, 17);
++	m = pi->cache_pos[k];
++	i = (m + j / 2) & (PIC2_ARITH_CACHE - 1);
++	j = (m + j) & (PIC2_ARITH_CACHE - 1);
++
++	cc = pi->cache[k][j];
++	pi->cache[k][j] = pi->cache[k][i];
++	pi->cache[k][i] = pi->cache[k][m];
++	pi->cache[k][m] = cc;
++    }
++    return (cc);
++}
++
++static int pic2_arith_expand_line(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    int ymax;
++    int x, xw;
++    pixel cc;
++
++    pic2_handle_para(pi, 0);
++
++    xw = pi->block->x_wid;
++    ymax = pi->block->y_wid - 1;
++
++    if (pi->ynow > ymax)
++	return (-2);					/* end */
++
++    /* set right end of previous line before left end of current line. */
++    if (pi->ynow == 0) {
++	cc = 0;
++    } else
++	cc = pi->vram_prev[xw - 1];
++    pi->vram_now[-1] = cc;
++
++    /* clear flag for change point */
++    xvbzero((char *) pi->flag_next, xw * sizeof(pi->flag_next[0]));
++
++    /* clear flag for position probability space */
++    xvbzero((char *) pi->flag2_next2, xw * sizeof(pi->flag2_next2[0]));
++
++    for (x = 0; x < xw; x++) {
++	if (pi->flag_now[x] < 0) {
++	    cc = pi->vram_now[x];
++	    if (pi->ynow < ymax)
++		pic2_arith_expand_chain(pi, x, pi->ynow, cc);
++	} else if (pic2_arith_decode_bit(pi, pi->flag2_now[x])) {
++	    /* ajust probability space around of change point */
++	    pi->flag2_now  [x + 1]++;
++	    pi->flag2_now  [x + 2]++;
++	    pi->flag2_next [x - 1]++;
++	    pi->flag2_next [x    ]++;
++	    pi->flag2_next [x + 1]++;
++	    pi->flag2_next2[x - 1]++;
++	    pi->flag2_next2[x    ]++;
++	    pi->flag2_next2[x + 1]++;
++
++	    pi->vram_now[x] = cc = pic2_arith_read_color(pi, x);
++	    if (pi->ynow < ymax)
++		pic2_arith_expand_chain(pi, x, pi->ynow, cc);
++	} else
++	    pi->vram_now[x] = cc;
++    }
++    if (line != NULL)
++	*line = pi->vram_now;
++    pi->ynow++;
++
++    pic2_handle_para(pi, 1);
++
++    return (pi->ynow - 1);
++}
++
++static int pic2_arith_loader_init(pi)
++struct pic2_info *pi;
++{
++    unsigned short p2b[256];
++    int i, xw;
++
++    pi->ynow = 0;
++
++    /* check the color depth */
++    if (pi->header->depth % 3)
++	pic2_error(pi, PIC2_DEPTH);
++
++    /* set function for extract next line */
++    pi->next_line = pic2_arith_expand_line;
++
++    /* clear cache and flags */
++    xw = pi->block->x_wid;
++    xvbzero((char *) pi->cache, 8 * 8 * 8 * sizeof(pi->cache[0]));
++    xvbzero((char *) pi->cache_pos, 8 * 8 * 8 * sizeof(pi->cache_pos[0]));
++
++    xvbzero((char *) pi->flag_now, xw * sizeof(pi->flag_now[0]));
++    xvbzero((char *) pi->flag2_now, 8 + xw * sizeof(pi->flag2_now[0]));
++    xvbzero((char *) pi->flag2_next, 8 + xw * sizeof(pi->flag2_next[0]));
++
++    /* go to picture data field */
++    pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
++
++    /* clear bit field marker */
++    pi->bs.rest = 0;
++    pi->bs.cur = 0;
++
++    /* read probability table */
++    for (i = 0; i < PIC2_ARITH_CONTEXT; i++)
++	p2b[i] = pic2_read_short(pi);
++
++    /* make multiplication table */
++    for (i = 0; i < 16384; i++) {
++	pi->mulu_tab[i] = (long) (i / 128 + 128) * (int) p2b[i & 127] / 256;
++	if (pi->mulu_tab[i] == 0) pi->mulu_tab[i] = 1;
++    }
++    /* initialize some valuables */
++    pi->aa = 0xffff;
++    pi->dd = 0;
++    for (i = 0; i < 16; i++) {
++	pi->dd *= 2;
++	if (pic2_read_bits(pi, 1))
++	    pi->dd |= 1;
++    }
++    pi->cache_hit_c = 16;
++
++    return (0);
++}
++
++/*
++ * These functions are fast pic2 compression extractor.
++ */
++static int pic2_fast_read_length(pi)
++struct pic2_info *pi;
++{
++    int a;
++
++    a = 0;
++    while (pic2_read_bits(pi, 1)) {
++	a++;
++    }
++    if (a == 0)
++	return (0);
++    return (pic2_read_bits(pi, a) + (1 << a) - 1);
++}
++
++static void pic2_fast_expand_chain(pi, x, cc)
++struct pic2_info *pi;
++int x;
++pixel cc;
++{
++    if (pic2_read_bits(pi, 1) != 0) {
++	if (pic2_read_bits(pi, 1) != 0) {		/* down */
++	    pi->vram_next[x] = cc;
++	    pi->flag_next[x] = -1;
++	} else if (pic2_read_bits(pi, 1) != 0) {
++	    if (pic2_read_bits(pi, 1) == 0) {		/* left2down */
++		pi->vram_next[x - 2] = cc;
++		pi->flag_next[x - 2] = -1;
++	    } else {					/* left1down */
++		pi->vram_next[x - 1] = cc;
++		pi->flag_next[x - 1] = -1;
++	    }
++	} else {
++	    if (pic2_read_bits(pi, 1) == 0) {		/* right2down */
++		pi->vram_next[x + 2] = cc;
++		pi->flag_next[x + 2] = -1;
++	    } else {					/* left1down */
++		pi->vram_next[x + 1] = cc;
++		pi->flag_next[x + 1] = -1;
++	    }
++	}
++    }
++}
++
++static pixel pic2_fast_read_color(pi, bc)
++struct pic2_info *pi;
++pixel bc;
++{
++    pixel cc;
++    unsigned short j, k, m;
++    short depth, colbits;
++    pixel (*cache)[PIC2_FAST_CACHE];
++
++    depth = pi->header->depth;
++    colbits = depth / 3;
++    cache = (pixel (*)[PIC2_FAST_CACHE]) pi->cache;
++
++    bc = pic2_exchange_rg(bc, colbits);
++    k = pic2_shift_bits(bc, 8 - depth);
++    if (pic2_read_bits(pi, 1) == 0) {
++	pi->cache_pos[k] = m = (pi->cache_pos[k] - 1) & (PIC2_FAST_CACHE - 1);
++	cc = pic2_read_bits(pi, depth);
++	cc = pic2_exchange_rg(cc, colbits);
++	cache[k][m] = cc;
++    } else {
++	j = pic2_read_bits(pi, 6);		/* 6= log2(PIC2_FAST_CACHE) */
++	m = pi->cache_pos[k];
++	cc = cache[k][(m + j) & (PIC2_FAST_CACHE - 1)];
++    }
++    return (cc);
++}
++
++static int pic2_fast_expand_line(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    int ymax;
++    int x, xw;
++    pixel cc;
++
++    pic2_handle_para(pi, 0);
++
++    xw = pi->block->x_wid;
++    ymax = pi->block->y_wid - 1;
++
++    if (pi->ynow > ymax)
++	return (-2);
++
++    if (pi->ynow == 0) {
++	pi->dd = 0;
++	pi->aa = pic2_fast_read_length(pi);
++	if (pi->aa == 1023)
++	    pi->dd = 1023;
++	else if (pi->aa > 1023)
++	    pi->aa--;
++	cc = 0;
++    } else
++	cc = pi->vram_prev[xw - 1];
++
++    xvbzero((char *) pi->flag_next, xw * sizeof(pi->flag_next[0]));
++
++    for (x = 0; x < xw; x++) {
++	if (pi->dd > 0) {
++	    if (pi->flag_now[x] < 0) {			/* on chain ? */
++		cc = pi->vram_now[x];
++		pic2_fast_expand_chain(pi, x, cc);
++		if (--pi->dd == 0) {
++		    pi->aa = pic2_fast_read_length(pi);
++		    if (pi->aa == 1023)
++			pi->dd = 1023;
++		    else if (pi->aa > 1023)
++			pi->aa--;
++		}
++	    } else
++		pi->vram_now[x] = cc;
++	} else {
++	    if (pi->flag_now[x] < 0) {			/* on chain ? */
++		cc = pi->vram_now[x];
++		pic2_fast_expand_chain(pi, x, cc);
++	    } else if (--pi->aa < 0) {
++		cc = pi->vram_now[x] = pic2_fast_read_color(pi, cc);
++		pic2_fast_expand_chain(pi, x, cc);
++		pi->aa = pic2_fast_read_length(pi);
++		if (pi->aa == 1023)
++		    pi->dd = 1023;
++		else if (pi->aa > 1023)
++		    pi->aa--;
++	    } else
++		pi->vram_now[x] = cc;
++	}
++    }
++    if (line != NULL)
++	*line = pi->vram_now;
++    pi->ynow++;
++
++    pic2_handle_para(pi, 1);
++
++    return (pi->ynow - 1);
++}
++
++static int pic2_fast_loader_init(pi)
++struct pic2_info *pi;
++{
++    int xw;
++
++    pi->ynow = 0;
++
++    /* check the color depth */
++    if (pi->header->depth % 3)
++	pic2_error(pi, PIC2_DEPTH);
++
++    /* set function for extract next line */
++    pi->next_line = pic2_fast_expand_line;
++
++    /* clear cache and flags */
++    xw = pi->block->x_wid;
++    xvbzero((char *) pi->cache, sizeof(pi->cache[0]) * 256);
++    xvbzero((char *) pi->cache_pos, sizeof(pi->cache_pos[0]) * 8 * 8 * 8);
++    xvbzero((char *) pi->flag_now, (xw + 8) * sizeof(pi->flag_now[0]));
++    xvbzero((char *) pi->flag_next, (xw + 8) * sizeof(pi->flag_next[0]));
++
++    /* go to picture data field */
++    pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
++
++    /* clear bit field marker */
++    pi->bs.rest = 0;
++    pi->bs.cur = 0;
++
++    return (0);
++}
++
++/*
++ * These functions are beta pic2 format extractor.
++ */
++static int pic2_beta_expand_line(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    int i, xw, ymax;
++    byte a, b, c, *p;
++    pixel *pc;
++    short depth, pixbyte, colbits;
++
++    depth = pi->header->depth;
++    pixbyte = depth / 8 + ((depth % 8) > 0);
++    colbits = depth / 3;
++
++    xw = pi->block->x_wid;
++    ymax = pi->block->y_wid - 1;
++
++    if (pi->ynow > ymax)
++	return (-2);					/* end */
++
++    pc = pi->vram_now;
++    p = (byte *) pi->vram_prev;
++    if (pixbyte == 3) {
++	pic2_read_file(pi, pi->vram_prev, (size_t) (xw * pixbyte));
++	for (i = 0; i < xw; i++, pc++) {
++	    a = *p++;
++	    b = *p++;
++	    c = *p++;
++	    *pc = ((pixel) a << 16) | ((pixel) b << 8) | (pixel) c;
++	}
++    } else if (pixbyte == 2) {
++	pic2_read_file(pi, pi->vram_prev, (size_t) (xw * 2));
++	if (strncmp(pi->block->id, "P2BM", 4) == 0) {
++	    for (i = 0; i < xw; i++, pc++) {
++		a = *p++;
++		b = *p++;
++		*pc = ((pixel) a << 8) | (pixel) b;
++		if (colbits == 5) {
++		    *pc >>= 1;
++		    *pc = pic2_exchange_rg(*pc, colbits);
++		}
++	    }
++	} else {
++	    for (i = 0; i < xw; i++, pc++) {
++		a = *p++;
++		b = *p++;
++		*pc = ((pixel) b << 8) | (pixel) a;
++		if (colbits == 5) {
++		    *pc >>= 1;
++		    *pc = pic2_exchange_rg(*pc, colbits);
++		}
++	    }
++	}
++    } else {
++	pic2_read_file(pi, pi->vram_prev, (size_t) xw);
++	for (i = 0; i < xw; i++)
++	    *pc++ = *p++;
++    }
++    if (line != NULL)
++	*line = pi->vram_now;
++
++    pc = pi->vram_prev;
++    pi->vram_prev = pi->vram_now;
++    pi->vram_now = pi->vram_next;
++    pi->vram_next = pc;
++
++    pi->ynow++;
++    return (pi->ynow - 1);
++}
++
++static int pic2_beta_loader_init(pi)
++struct pic2_info *pi;
++{
++    pi->ynow = 0;
++    pi->next_line = pic2_beta_expand_line;
++    pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
++    return (0);
++}
++
++/*
++ * Make a picture from the expanded data.
++ */
++static void pic2_make_xvpic(pi, xp, rp, gp, bp)
++struct pic2_info *pi;
++byte **xp, *rp, *gp, *bp;
++{
++    int line, i;
++    pixel *linep, opaque;
++    short colbits;
++    byte colmask;
++
++    if (*xp == NULL)
++	*xp = pic2_new((size_t) pi->x_max * pi->y_max * 3, "pic2_make_xvpic");   // GRR POSSIBLE OVERFLOW / FIXME
++
++    if (pi->block->flag & 1)
++	opaque = pi->block->opaque;
++    else
++	opaque = 0xffffffff;
++
++    colbits = pi->header->depth / 3;
++    colmask = 0xff >> (8 - colbits);
++
++    line = pic2_load_block(pi);
++    for (;;) {
++	int pic_idx;
++
++	line = pic2_next_line(pi, &linep);
++	if (line < 0)
++	    break;
++	pic_idx = ((line + pi->block->y_offset) * pi->x_max
++		   + pi->block->x_offset) * 3;
++
++	for (i = 0; i < pi->block->x_wid; i++, linep++) {
++	    byte r, g, b;
++
++	    if (*linep != opaque) {
++		r = ((*linep >> (colbits * 2)) & colmask);
++		r = pic2_convert_color_bits(r, colbits, 8);
++		g = ((*linep >>  colbits     ) & colmask);
++		g = pic2_convert_color_bits(g, colbits, 8);
++		b = ( *linep                   & colmask);
++		b = pic2_convert_color_bits(b, colbits, 8);
++		(*xp)[pic_idx++] = r;
++		(*xp)[pic_idx++] = g;
++		(*xp)[pic_idx++] = b;
++	    } else
++	        pic_idx += 3;
++
++	    WaitCursor();
++	}
++    }
++}
++
++/*
++ * This function splits a multiblock PIC2 file into several pages.
++ */
++static void pic2_make_pagefile(pi, pagebname, pnum)
++struct pic2_info *pi;
++char *pagebname;
++int pnum;
++{
++    struct pic2_info pic2;
++    FILE *fp;
++    char pagefile[64], *buf;
++    size_t imagesize;
++
++    sprintf(pagefile, "%s%d", pagebname, pnum);
++    if ((fp = fopen(pagefile, "wb")) == NULL)
++	pic2_error(pi, PIC2_WRITE);
++
++    xvbcopy((char *) pi, (char *) &pic2, sizeof(struct pic2_info));
++    pic2.fp = fp;
++
++    pic2_write_header1(&pic2);
++
++    pic2_write_block_header(&pic2);
++
++    imagesize = pi->block->size - PIC2_BLOCK_HEADER_SIZE;
++    buf = (char *) pic2_malloc(imagesize, "pic2_make_pagefile");
++
++    pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
++    if (fread(buf, (size_t) 1, imagesize, pi->fp) < imagesize) {
++	free(buf);
++	pic2_file_error(pi, PIC2_CORRUPT);
++    }
++    if (fwrite(buf, (size_t) 1, imagesize, fp) < imagesize) {
++	free(buf);
++	pic2_error(pi, PIC2_WRITE);
++    }
++    free(buf);
++
++    pic2.next_pos = pic2_tell_file(&pic2);
++    pic2_write_header2(&pic2);
++
++    fclose(fp);
++}
++
++/* The main routine to save a PIC2 file. */
++static int WritePIC2(fp, pic0, ptype, w, h, rmap, gmap, bmap, numcols,
++		     colorstyle, fname, type, depth, x_offset, y_offset,
++		     append, comment)
++FILE *fp;
++byte *pic0;
++int ptype, w, h;
++byte *rmap, *gmap, *bmap;
++int numcols, colorstyle;
++char *fname;
++int type, depth;
++int x_offset, y_offset;
++int append;
++char *comment;
++{
++    struct pic2_info pic2;
++    char creator[256], title[256], saver[256];
++    int e;
++
++    if (DEBUG)
++	fputs("WritePIC2:\n", stderr);
++
++    pic2_init_info(&pic2);
++    pic2.fp = fp;
++    pic2.writing_grey = (colorstyle == F_GREYSCALE);
++
++    if ((e = setjmp(pic2.jmp)) != 0){
++	/* When an error occurs while writing, comes here. */
++	pic2_free_buffer(&pic2);
++	pic2_cleanup_pic2_info(&pic2, 1);
++	SetCursors(-1);
++	if (DEBUG)
++	    fputs("\n", stderr);
++	return (-1);
++    }
++    sprintf(creator, "XV Version %s", VERSTR);
++    pic2_strncpy(title, comment, 30);
++    sprintf(saver, "XV %s/UNIX/Bradley", VERSTR);
++
++    if (!append) {
++	pic2_setup_pic2_info(&pic2, creator, fname, title, saver,
++			     0, depth, 1, 1, w, h, comment);
++	pic2_write_header1(&pic2);
++    } else {
++	pic2_read_header(&pic2);
++	pic2_append(&pic2);
++	free(pic2.comment);
++	pic2_setup_pic2_info(&pic2, creator, fname, title, saver,
++			     0, depth, 1, 1, w, h, comment);
++    }
++
++    pic2_write_data(&pic2, pic0, ptype, x_offset, y_offset, w, h,
++		    rmap, gmap, bmap, type, depth);
++    pic2_write_header2(&pic2);
++
++    pic2_cleanup_pic2_info(&pic2, 1);
++    SetCursors(-1);
++    if (DEBUG)
++	fputs("\n", stderr);
++    return (0);
++}
++
++/*
++ * This function initializes pic2_info.
++ */
++static void pic2_setup_pic2_info(pi, name, fname, title, saver, no, depth,
++			      x_aspect, y_aspect, x_max, y_max, comment)
++struct pic2_info *pi;
++char *name, *fname, *title, *saver;
++int no, depth;
++int x_aspect, y_aspect;
++int x_max, y_max;
++char *comment;
++{
++    char basename[256], *suffix;
++
++    pi->mode = PIC2_WRITE_MODE;
++
++    /* set magic number */
++    strncpy(pi->header->magic, pic2_id, 4);
++
++    /* set creator's name */
++    pic2_strncpy(pi->header->name, (char *) name, 18);
++
++    /* set title and subtitle */
++    pic2_strncpy(pi->header->title, (char *) title, 30);
++    strcpy(basename, BaseName(fname));
++    suffix = (char *) rindex(basename, '.');
++    if (suffix) {
++	suffix++;
++	if (!strcmp(suffix, "p2") || !strcmp(suffix, "P2"))
++	    *(suffix - 1) = '\0';
++    }
++    pic2_strncpy(pi->header->subtitle, basename, 8);
++
++    /* set saver */
++    pic2_strncpy(pi->header->saver, saver, 30);
++
++    /* set picture number */
++    pi->header->no = no;
++
++    /* import comment */
++    pi->comment = comment;
++
++    /* set some picture's info */
++    pi->header->depth = depth;
++    pi->header->x_aspect = x_aspect;
++    pi->header->y_aspect = y_aspect;
++    pi->header->x_max = x_max;
++    pi->header->y_max = y_max;
++
++    /* set some gaps */
++    pi->header->crlf0[0] = pi->header->crlf1[0] = pi->header->crlf2[0] = 0x0d;
++    pi->header->crlf0[1] = pi->header->crlf1[1] = pi->header->crlf2[1] = 0x0a;
++
++    pi->header->eof[0] = 0x1a;
++    pi->header->reserve0[0] = 0;
++    pi->header->reserve1 = 0;
++
++    /* set palettes */
++    if (pi->n_pal > 0)
++	pi->header->flag = 1;
++    else
++	pi->header->flag = 0;
++}
++
++/*
++ * This function appends to existing pic2 file.
++ */
++static void pic2_append(pi)
++struct pic2_info *pi;
++{
++    int block;
++
++    block = pic2_find_block(pi);
++    while (block > 0)
++	block = pic2_next_block(pi);
++
++    if (block != 0)
++	pic2_error(pi, PIC2_APPEND);
++}
++
++/*
++ * These functions write the PIC2 header.
++ * pic2_write_header1:
++ *	write palette data and comment.
++ * pic2_write_header2:
++ *	write the terminate block and rest header.
++ * pic2_write_block_header:
++ *	write the block header.
++ */
++static void pic2_write_header1(pi)
++struct pic2_info *pi;
++{
++    char *comment;
++
++    /* seek to block start position */
++    pic2_seek_file(pi, PIC2_HEADER_SIZE, SEEK_SET);
++
++    /* write palette */
++    if (pi->n_pal > 0) {
++	pic2_write_char(pi, pi->pal_bits);
++	pic2_write_short(pi, pi->n_pal);
++	pic2_write_file(pi, pi->pal, (size_t) (pi->n_pal * 3));
++    }
++    /* save comment */
++    comment = pi->comment;
++    if (pi->comment != NULL) {
++	for (comment = pi->comment; *comment; comment++) {
++	    if (*comment == '\n') {
++		pic2_write_char(pi, '\r');
++		pic2_write_char(pi, '\n');
++	    } else if (*comment != '\r')
++		pic2_write_char(pi, *comment);
++	}
++	pic2_write_char(pi, 0);
++    }
++    /* set the next block position */
++    pi->next_pos = pic2_tell_file(pi);
++    pi->header->size = pi->next_pos;
++}
++
++static void pic2_write_header2(pi)
++struct pic2_info *pi;
++{
++    pic2_seek_file(pi, pi->next_pos, SEEK_SET);
++
++    /* write terminate block */
++    pic2_write_long(pi, 0);
++    pic2_write_long(pi, 0);
++
++    /* set some header information */
++    if (pi->header->x_max < pi->x_max)
++	pi->header->x_max = pi->x_max;
++    if (pi->header->y_max < pi->x_max)
++	pi->header->y_max = pi->y_max;
++
++    pi->header->time = time(NULL);
++    pic2_seek_file(pi, 0, SEEK_SET);
++
++    /* write header image */
++    pic2_write_file(pi, pi->header->magic, 4);
++    pic2_write_file(pi, pi->header->name, 18);
++    pic2_write_file(pi, pi->header->subtitle, 8);
++    pic2_write_file(pi, pi->header->crlf0, 2);
++    pic2_write_file(pi, pi->header->title, 30);
++    pic2_write_file(pi, pi->header->crlf1, 2);
++    pic2_write_file(pi, pi->header->saver, 30);
++    pic2_write_file(pi, pi->header->crlf2, 2);
++    pic2_write_file(pi, pi->header->eof, 1);
++    pic2_write_file(pi, pi->header->reserve0, 1);
++    pic2_write_short(pi, pi->header->flag);
++    pic2_write_short(pi, pi->header->no);
++    pic2_write_long(pi, pi->header->time);
++    pic2_write_long(pi, pi->header->size);
++    pic2_write_short(pi, pi->header->depth);
++    pic2_write_short(pi, pi->header->x_aspect);
++    pic2_write_short(pi, pi->header->y_aspect);
++    pic2_write_short(pi, pi->header->x_max);
++    pic2_write_short(pi, pi->header->y_max);
++    pic2_write_long(pi, pi->header->reserve1);
++}
++
++static void pic2_write_block_header(pi)
++struct pic2_info *pi;
++{
++    pic2_write_file(pi, pi->block->id, 4);
++    pic2_write_long(pi, pi->block->size);
++    pic2_write_short(pi, pi->block->flag);
++    pic2_write_short(pi, pi->block->x_wid);
++    pic2_write_short(pi, pi->block->y_wid);
++    pic2_write_short(pi, pi->block->x_offset);
++    pic2_write_short(pi, pi->block->y_offset);
++    pic2_write_long(pi, pi->block->opaque);
++    pic2_write_long(pi, pi->block->reserve);
++}
++
++/*
++ * These functions implement the arithmetic-format compressor.
++ */
++#define	pic2_arith_write_one_bit(pi)	(pi->bs.bits++)
++
++static void pic2_arith_write_zero_bit(pi)
++struct pic2_info *pi;
++{
++    if (pi->bs.zero)
++	pic2_write_bits(pi, 0, 1);
++
++    while (pi->bs.bits--)
++	pic2_write_bits(pi, 1, 1);
++
++    pi->bs.bits = 0;
++    pi->bs.zero = 1;
++}
++
++static void pic2_arith_flush_bit_buf(pi)
++struct pic2_info *pi;
++{
++    int	i;
++
++    for (i = 0; i < 16; i++) {
++	if (pi->cc & 0x8000)
++	    pic2_arith_write_one_bit(pi);
++	else
++	    pic2_arith_write_zero_bit(pi);
++	pi->cc <<= 1;
++    }
++    pic2_arith_write_zero_bit(pi);
++    pic2_flush_bits(pi);
++}
++
++static void pic2_arith_carry_bit(pi)
++struct pic2_info *pi;
++{
++    pic2_write_bits(pi, 1, 1);
++
++    if (pi->bs.bits == 0) {
++	pi->bs.zero = 0;
++    } else {
++	while (--pi->bs.bits)
++	    pic2_write_bits(pi, 0, 1);
++	pi->bs.zero = 1;
++    }
++}
++
++static void pic2_arith_encode_bit(pi, n, c)
++struct pic2_info *pi;
++int n, c;
++{
++    int	pp;
++    long *c_sum, *c_0_sum;
++
++    c_sum = (long *) pi->mulu_tab;
++    c_0_sum = c_sum + PIC2_ARITH_CONTEXT + 1;
++
++    if (pi->dd  == 0) {
++	c_sum[c]++;
++	if (n == 0)
++	    c_0_sum[c]++;
++	return;
++    }
++    pp = pi->mulu_tab[(pi->aa & 0x7f00) / 2 + c];
++    if (n != 0) {
++	pi->cc = pi->cc + pp;
++	if (pi->cc > 0xffff) {
++	    pic2_arith_carry_bit(pi);
++	    pi->cc = pi->cc & 0xffff;
++	}
++	pi->aa = pi->aa - pp;
++	while (pi->aa < 0x8000) {
++	    if (pi->cc & 0x8000)
++		pic2_arith_write_one_bit(pi);
++	    else
++		pic2_arith_write_zero_bit(pi);
++	    pi->cc = (pi->cc * 2) & 0xffff;
++	    pi->aa = pi->aa * 2;
++	}
++    } else {
++	pi->aa = pp;
++
++	while (pi->aa < 0x8000) {
++	    if (pi->cc & 0x8000)
++		pic2_arith_write_one_bit(pi);
++	    else
++		pic2_arith_write_zero_bit(pi);
++	    pi->cc = (pi->cc * 2) & 0xffff;
++	    pi->aa = pi->aa * 2;
++	}
++    }
++}
++
++static void pic2_arith_encode_nbyte(pi, n, c, max)
++struct pic2_info *pi;
++int n, c, max;
++{
++    short i;
++
++    for (i = 0; i < n; i++) {
++	pic2_arith_encode_bit(pi, 0, c + i);
++    }
++    if (n < max)
++	pic2_arith_encode_bit(pi, 1, c + n);
++}
++
++static void pic2_arith_encode_nn(pi, n, c)
++struct pic2_info *pi;
++int n, c;
++{
++    if (n < 1) {
++	pic2_arith_encode_bit(pi, 1, c);
++    } else if (n < 1 + 2) {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 1, c + 1);
++	n -= 1;
++	pic2_arith_encode_bit(pi, n & 1, c + 8);
++    } else if (n < 1 + 2 + 4) {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 0, c + 1);
++	pic2_arith_encode_bit(pi, 1, c + 2);
++	n -= 1 + 2;
++	pic2_arith_encode_bit(pi, n & 1, c + 8);
++	pic2_arith_encode_bit(pi, n & 2, c + 9);
++    } else if (n < 1 + 2 + 4 + 8) {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 0, c + 1);
++	pic2_arith_encode_bit(pi, 0, c + 2);
++	pic2_arith_encode_bit(pi, 1, c + 3);
++	n -= 1 + 2 + 4;
++	pic2_arith_encode_bit(pi, n & 1, c + 8);
++	pic2_arith_encode_bit(pi, n & 2, c + 9);
++	pic2_arith_encode_bit(pi, n & 4, c + 10);
++    } else if (n < 1 + 2 + 4 + 8 + 16) {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 0, c + 1);
++	pic2_arith_encode_bit(pi, 0, c + 2);
++	pic2_arith_encode_bit(pi, 0, c + 3);
++	pic2_arith_encode_bit(pi, 1, c + 4);
++	n -= 1 + 2 + 4 + 8;
++	pic2_arith_encode_bit(pi, n & 1, c + 8);
++	pic2_arith_encode_bit(pi, n & 2, c + 9);
++	pic2_arith_encode_bit(pi, n & 4, c + 10);
++	pic2_arith_encode_bit(pi, n & 8, c + 11);
++    } else if (n < 1 + 2 + 4 + 8 + 16 + 32) {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 0, c + 1);
++	pic2_arith_encode_bit(pi, 0, c + 2);
++	pic2_arith_encode_bit(pi, 0, c + 3);
++	pic2_arith_encode_bit(pi, 0, c + 4);
++	pic2_arith_encode_bit(pi, 1, c + 5);
++	n -= 1 + 2 + 4 + 8 + 16;
++	pic2_arith_encode_bit(pi, n & 1, c + 8);
++	pic2_arith_encode_bit(pi, n & 2, c + 9);
++	pic2_arith_encode_bit(pi, n & 4, c + 10);
++	pic2_arith_encode_bit(pi, n & 8, c + 11);
++	pic2_arith_encode_bit(pi, n & 16, c + 12);
++    } else if (n < 1 + 2 + 4 + 8 + 16 + 32 + 64) {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 0, c + 1);
++	pic2_arith_encode_bit(pi, 0, c + 2);
++	pic2_arith_encode_bit(pi, 0, c + 3);
++	pic2_arith_encode_bit(pi, 0, c + 4);
++	pic2_arith_encode_bit(pi, 0, c + 5);
++	pic2_arith_encode_bit(pi, 1, c + 6);
++	n -= 1 + 2 + 4 + 8 + 16 + 32;
++	pic2_arith_encode_bit(pi, n & 1, c + 8);
++	pic2_arith_encode_bit(pi, n & 2, c + 9);
++	pic2_arith_encode_bit(pi, n & 4, c + 10);
++	pic2_arith_encode_bit(pi, n & 8, c + 11);
++	pic2_arith_encode_bit(pi, n & 16, c + 12);
++	pic2_arith_encode_bit(pi, n & 32, c + 13);
++    } else if (n < 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128) {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 0, c + 1);
++	pic2_arith_encode_bit(pi, 0, c + 2);
++	pic2_arith_encode_bit(pi, 0, c + 3);
++	pic2_arith_encode_bit(pi, 0, c + 4);
++	pic2_arith_encode_bit(pi, 0, c + 5);
++	pic2_arith_encode_bit(pi, 0, c + 6);
++	pic2_arith_encode_bit(pi, 1, c + 7);
++	n -= 1 + 2 + 4 + 8 + 16 + 32 + 64;
++	pic2_arith_encode_bit(pi, n & 1, c + 8);
++	pic2_arith_encode_bit(pi, n & 2, c + 9);
++	pic2_arith_encode_bit(pi, n & 4, c + 10);
++	pic2_arith_encode_bit(pi, n & 8, c + 11);
++	pic2_arith_encode_bit(pi, n & 16, c + 12);
++	pic2_arith_encode_bit(pi, n & 32, c + 13);
++	pic2_arith_encode_bit(pi, n & 64, c + 14);
++    } else {
++	pic2_arith_encode_bit(pi, 0, c);
++	pic2_arith_encode_bit(pi, 0, c + 1);
++	pic2_arith_encode_bit(pi, 0, c + 2);
++	pic2_arith_encode_bit(pi, 0, c + 3);
++	pic2_arith_encode_bit(pi, 0, c + 4);
++	pic2_arith_encode_bit(pi, 0, c + 5);
++	pic2_arith_encode_bit(pi, 0, c + 6);
++	pic2_arith_encode_bit(pi, 0, c + 7);
++    }
++}
++
++static void pic2_arith_press_chain(pi, x)
++struct pic2_info *pi;
++int x;
++{
++    int b, d;
++    pixel c;
++
++    b = -(pi->flag_now[x]);
++    c = pi->vram_now[x];
++    d = 0;
++
++    if (b < 0)
++	b = 0;
++
++    if (pi->flag_next[x] == 1 && pi->vram_next[x] == c) {
++	d = 1;
++	pi->flag_next[x] = -1;
++    } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == c) {
++	d = 2;
++	pi->flag_next[x - 1] = -2;
++    } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == c) {
++	d = 3;
++	pi->flag_next[x + 1] = -3;
++    } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == c) {
++	d = 4;
++	pi->flag_next[x - 2] = -4;
++    } else if (pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == c) {
++	if ((pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == c)
++	    || (pi->flag_now[x + 1] != 0 && pi->vram_now[x + 1] == c)
++	    || (pi->flag_now[x + 3] != 0 && pi->vram_now[x + 3] == c)) {
++	    pic2_arith_encode_nbyte(pi, 0, 80 + 6 * b, 5);
++	    return;
++	}
++	d = 5;
++	pi->flag_next[x + 2] = -5;
++    }
++    pic2_arith_encode_nbyte(pi, d, 80 + 6 * b, 5);
++}
++
++static void pic2_arith_put_number(pi, xn, xa, xb)
++struct pic2_info *pi;
++int xn, xa, xb;
++{
++    short n;
++    byte maxcol;
++
++    maxcol = 0xff >> (8 - pi->header->depth / 3);
++
++    if (xa > ((int) maxcol >> 1)) {
++	if (xb > xa)
++	    n = (xb - xa) * 2 - 1;
++	else if (xa - ((int) maxcol - xa)  > xb)
++	    n = maxcol - xb;
++	else
++	    n = (xa - xb) * 2;
++    } else {
++	if (xb <= xa)
++	    n = (xa - xb) * 2;
++	else if (2 * xa < xb)
++	    n = xb;
++ 	else
++	    n = (xb - xa) * 2 - 1;
++    }
++    pic2_arith_encode_nn(pi, n, xn);
++}
++
++static void pic2_arith_write_color(pi, x)
++struct pic2_info *pi;
++int x;
++{
++    pixel c1, c2, cc;
++    short g0, r0, b0, r, g, b;
++    int i, j;
++    unsigned short k;
++    pixel *p, *pp;
++    short colbits;
++    pixel rmask, gmask, bmask;
++    byte maxcol;
++
++    colbits = pi->header->depth / 3;
++    rmask = (0xff >> (8 - colbits)) << (colbits * 2);
++    gmask = (0xff >> (8 - colbits)) <<  colbits;
++    bmask = (0xff >> (8 - colbits));
++    maxcol = (byte) bmask;
++
++    cc = pi->vram_now[x];
++    c1 = pi->vram_prev[x];
++    k = ((c1 >> ((colbits - 3) * 3)) & 0x1c0)
++      | ((c1 >> ((colbits - 3) * 2)) & 0x038)
++      | ((c1 >>  (colbits - 3)     ) & 0x007);
++    if (colbits == 5)
++	k = pic2_exchange_rg(k, 3);
++
++    p = pi->cache[k];
++    for (i = 0; i < (PIC2_ARITH_CACHE - 1); i++) {
++	if (cc == *p++)
++	    break;
++    }
++    if (i == (PIC2_ARITH_CACHE - 1)) {
++	pp = p - 1;
++	for (j = i; j > 0; j--) {
++	    *--p = *--pp;
++	}
++	pi->cache[k][0] = cc;
++	pic2_arith_encode_bit(pi, 1, pi->cache_hit_c);
++	pi->cache_hit_c = 16;
++
++	c2 = pi->vram_now[x - 1];
++	r = ((c1 & rmask) + (c2 & rmask)) >> (colbits * 2 + 1);
++	g = ((c1 & gmask) + (c2 & gmask)) >> (colbits     + 1);
++	b = ((c1 & bmask) + (c2 & bmask)) >> (              1);
++
++	r0 = (cc >> (colbits * 2)) & maxcol;
++	g0 = (cc >>  colbits     ) & maxcol;
++	b0 =  cc                   & maxcol;
++
++	r = r + g0 - g;
++	if (r < 0)
++	    r = 0;
++	else if (r > (short) maxcol)
++	    r = maxcol;
++
++	b = b + g0 - g;
++	if (b < 0)
++	    b = 0;
++	else if (b > (short) maxcol)
++	    b = maxcol;
++
++	pic2_arith_put_number(pi, 32, g, g0);
++	pic2_arith_put_number(pi, 48, r, r0);
++	pic2_arith_put_number(pi, 64, b, b0);
++    } else {
++	*--p = pi->cache[k][i / 2];
++	pi->cache[k][i / 2] = pi->cache[k][0];
++	pi->cache[k][0] = cc;
++
++	pic2_arith_encode_bit(pi, 0, pi->cache_hit_c);
++	pi->cache_hit_c = 15;
++	pic2_arith_encode_nn(pi, i, 17);
++    }
++}
++
++static void pic2_arith_press_line2(pi)
++struct pic2_info *pi;
++{
++    int x, xw, ymax;
++    pixel cc;
++
++    xw = pi->block->x_wid;
++    ymax = pi->block->y_wid -1;
++    cc = pi->vram_now[xw - 1];			/* last color */
++    pi->vram_next[-1] = cc;
++
++    /* mark change point */
++    for (x = 0; x < xw; x++)
++	if (cc != pi->vram_next[x]) {
++	    pi->flag_next[x] = 1;
++	    cc = pi->vram_next[x];
++	} else
++	    pi->flag_next[x] = 0;
++
++    for (x = 0; x < xw; x++) {
++	if (pi->flag_now[x] == 1) {			/* change point */
++	    pi->flag2_now  [x + 1]++;
++	    pi->flag2_now  [x + 2]++;
++	    pi->flag2_next [x - 1]++;
++	    pi->flag2_next [x    ]++;
++	    pi->flag2_next [x + 1]++;
++	    pi->flag2_next2[x - 1]++;
++	    pi->flag2_next2[x    ]++;
++	    pi->flag2_next2[x + 1]++;
++
++	    /* write change point */
++	    pic2_arith_encode_bit(pi, 1, pi->flag2_now[x]);
++
++	    /* write color */
++	    pic2_arith_write_color(pi, x);
++
++	    /* if not last line, write chain */
++	    if (pi->ynow - 1 < ymax)
++		pic2_arith_press_chain(pi, x);
++	} else if (pi->flag_now[x] == 0)		/* not on chain */
++	    /* write change point */
++	    pic2_arith_encode_bit(pi, 0, pi->flag2_now[x]);
++	else				/* on chain */
++	     /* if not on last line, write next chain */
++	     if (pi->ynow - 1 < ymax)
++		 pic2_arith_press_chain(pi, x);
++    }
++}
++
++static int pic2_arith_press_line(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    int i, xw, ymax;
++    long *c_sum, *c_0_sum;
++
++    xw = pi->block->x_wid;
++    ymax = pi->block->y_wid -1;
++    c_sum = (long *) pi->mulu_tab;
++    c_0_sum = c_sum + PIC2_ARITH_CONTEXT +1;
++
++    pic2_handle_para(pi, 0);
++
++    xvbzero((char *) pi->flag2_next2 - 4,
++	    (8 + xw) * sizeof(pi->flag2_next2[0]));
++
++    if (pi->ynow == 0) {			/* first line */
++	int x;
++	pixel cc = 0;
++
++	if (pi->dd != 0) {			/* compress pass */
++	    unsigned short c_tab[PIC2_ARITH_CONTEXT];
++
++	    for (i = 0; i < PIC2_ARITH_CONTEXT; i++) {
++		unsigned long a, b;
++		a = c_0_sum[i];
++		b = c_sum[i];
++		while (a > 32767) {
++		    a /= 2;
++		    b /= 2;
++		}
++		if (a == b)
++		    c_tab[i] = 0xffff;		/* b==0 here, too */
++		else
++		    c_tab[i] = (65536 * a) / b; /* a < b, so less 65536 */
++	    }
++	    for (i = 0; i < 16384; i++) {
++		pi->mulu_tab[i] = (long) (i / 128 + 128) * (int) c_tab[i & 127] / 256;
++		if (pi->mulu_tab[i] == 0)
++		    pi->mulu_tab[i] = 1;	/* 0 is wrong */
++	    }
++	    for (i = 0; i < PIC2_ARITH_CONTEXT; i++)
++		pic2_write_short(pi, c_tab[i]);
++
++	    xvbzero((char *) pi->vram_now, xw * sizeof(pi->vram_now[0]));
++	} else {				/* statistical pass */
++	    xvbzero((char *) c_0_sum, PIC2_ARITH_CONTEXT * sizeof(c_0_sum[0]));
++	    xvbzero((char *) c_sum, PIC2_ARITH_CONTEXT * sizeof(c_sum[0]));
++	}
++
++	/* initialize flags */
++	xvbzero((char *) pi->cache, 8 * 8 * 8 * sizeof(pi->cache[0]));
++	xvbzero((char *) pi->cache_pos, 8 * 8 * 8 * sizeof(pi->cache_pos[0]));
++
++	xvbzero((char *) pi->flag2_next - 4,
++		(8 + xw) * sizeof(pi->flag2_next[0]));
++	xvbzero((char *) pi->flag2_next2 - 4,
++		(8 + xw) * sizeof(pi->flag2_next2[0]));
++
++	pi->vram_next[-1] = cc;
++	for (x = 0; x < xw; x++)
++	    if (cc != pi->vram_next[x]) {
++		pi->flag_next[x] = 1;
++		cc = pi->vram_next[x];
++	    } else
++		pi->flag_next[x] = 0;
++
++	pi->aa = 0xffff;
++	cc = 0;
++	pi->cache_hit_c = 16;
++    } else					/* after second line */
++	pic2_arith_press_line2(pi);
++
++    if (pi->ynow ==  ymax) {
++	pi->ynow++;
++	pic2_handle_para(pi, 1);
++	pic2_handle_para(pi, 0);
++	pic2_arith_press_line2(pi);
++    }
++    /* line buffer for next data */
++    if (line != NULL)
++	*line = pi->vram_prev;
++
++    pi->ynow++;
++
++    if (pi->ynow - 1 < ymax) {
++	pic2_handle_para(pi, 1);
++	return (pi->ynow);
++    } else {					/* end */
++	if (pi->dd == 0) {			/* statistical pass */
++	    pi->dd = 1;
++	    pi->ynow = 0;
++	    pic2_handle_para(pi, 1);
++	    return (0);
++	} else {
++	    pic2_handle_para(pi, 1);
++	    pic2_arith_flush_bit_buf(pi);
++	    return (-2);			/* end */
++	}
++    }
++}
++
++static int pic2_arith_saver_init(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    pi->ynow = 0;
++
++    /* check the color depth */
++    if (pi->header->depth % 3)
++	pic2_error(pi, PIC2_DEPTH);
++
++    /* set next line function */
++    pi->next_line = pic2_arith_press_line;
++
++    if (line != NULL)
++	*line = pi->vram_next + 4;
++
++    pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
++
++    /* clear bit field marker */
++    pi->bs.rest = 0;
++    pi->bs.cur = 0;
++    pi->bs.zero = 0;
++    pi->bs.bits = 0;
++
++    return (0);
++}
++
++/*
++ * These functions are fast pic2 format compressor.
++ */
++static void pic2_fast_write_length(pi, n)
++struct pic2_info *pi;
++int n;
++{
++    int	a, b;
++    static const unsigned short len_data[8][2] = {
++	{1, 0},
++	{1, 0},
++	{3, 4},
++	{3, 5},
++	{5, 24},
++	{5, 25},
++	{5, 26},
++	{5, 27},
++    };
++
++    n++;
++    if (n < 8)
++	pic2_write_bits(pi, len_data[n][1], len_data[n][0]);
++    else {
++	a = 0;
++	b = 2;
++	while (n > b - 1) {
++	    a = a + 1;
++	    b = b * 2;
++	}
++	pic2_write_bits(pi, 0xfffffffe, a + 1);
++	if (a > 0)
++	    pic2_write_bits(pi, n - b / 2, a);
++    }
++}
++
++static void pic2_fast_press_chain(pi, x)
++struct pic2_info *pi;
++int x;
++{
++    int ymax;
++    pixel cc;
++
++    ymax = pi->block->y_wid -1;
++    cc = pi->vram_now[x];
++
++    if (pi->ynow - 1 == ymax) {
++	pic2_write_bits(pi, 0, 1);
++	return;
++    }
++    if (pi->flag_next[x] == 1 && pi->vram_next[x] == cc) {
++	pi->flag_next[x] = -1;
++	pic2_write_bits(pi, 3, 2);
++    } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == cc) {
++	pi->flag_next[x - 1] = -1;
++	pic2_write_bits(pi, 11, 4);
++    } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == cc) {
++	pi->flag_next[x + 1] = -1;
++	pic2_write_bits(pi, 9, 4);
++    } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == cc) {
++	pi->flag_next[x - 2] = -1;
++	pic2_write_bits(pi, 10, 4);
++    } else if ((pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == cc)
++		&& !(pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == cc)) {
++	pi->flag_next[x + 2] = -1;
++	pic2_write_bits(pi, 8, 4);
++    } else
++	pic2_write_bits(pi, 0, 1);
++}
++
++static void pic2_fast_press_chain2(pi, x)
++struct pic2_info *pi;
++int x;
++{
++    int ymax;
++    pixel cc;
++    char *chain_buff;
++
++    ymax = pi->block->y_wid -1;
++    chain_buff = (char *) pi->mulu_tab;
++    cc = pi->vram_now[x];
++
++    if (pi->ynow - 1 == ymax) {
++	chain_buff[pi->cc++] = 0;
++	return;
++    }
++    if (pi->flag_next[x] == 1 && pi->vram_next[x] == cc) {
++	pi->flag_next[x] = -1;
++	chain_buff[pi->cc++] = 1;
++    } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == cc) {
++	pi->flag_next[x - 1] = -1;
++	chain_buff[pi->cc++] = 2;
++    } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == cc) {
++	pi->flag_next[x + 1] = -1;
++	chain_buff[pi->cc++] = 3;
++    } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == cc) {
++	pi->flag_next[x - 2] = -1;
++	chain_buff[pi->cc++] = 4;
++    } else if ((pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == cc)
++	       && !(pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == cc)) {
++	pi->flag_next[x + 2] = -1;
++	chain_buff[pi->cc++] = 5;
++    } else
++	chain_buff[pi->cc++] = 0;
++}
++
++static void pic2_fast_flush_chain(pi)
++struct pic2_info *pi;
++{
++    int i;
++    char *chain_buf;
++
++    chain_buf = (char *) pi->mulu_tab;
++    for (i = 0; i < pi->cc; i++){
++	switch (chain_buf[i]) {
++	case 0:
++	    pic2_write_bits(pi, 0, 1);
++	    break;
++	case 1:
++	    pic2_write_bits(pi, 3, 2);
++	    break;
++	case 2:
++	    pic2_write_bits(pi, 11, 4);
++	    break;
++	case 3:
++	    pic2_write_bits(pi, 9, 4);
++	    break;
++	case 4:
++	    pic2_write_bits(pi, 10, 4);
++	    break;
++	case 5:
++	    pic2_write_bits(pi, 8, 4);
++	    break;
++	}
++    }
++    pi->cc = 0;
++}
++
++static void pic2_fast_write_color(pi, x)
++struct pic2_info *pi;
++int x;
++{
++    pixel cc, bc;
++    unsigned short j, k, m;
++    short depth, colbits;
++    pixel (*cache)[PIC2_FAST_CACHE];
++
++    depth = pi->header->depth;
++    colbits = depth / 3;
++    cache = (pixel (*)[PIC2_FAST_CACHE]) pi->cache;
++
++    bc = pi->vram_now[x - 1];
++    bc = pic2_exchange_rg(bc, colbits);
++    k = pic2_shift_bits(bc, 8 - depth);
++    cc = pi->vram_now[x];
++    m = pi->cache_pos[k];
++
++    for (j = 0; j < PIC2_FAST_CACHE; j++)
++	if (cache[k][(m + j) & (PIC2_FAST_CACHE - 1)] == cc)
++	    break;
++
++    if (j == PIC2_FAST_CACHE) {
++	m = (m - 1) & (PIC2_FAST_CACHE - 1);
++	pi->cache_pos[k] = m;
++	cache[k][m] = cc;
++
++	cc = pic2_exchange_rg(cc, colbits);
++	pic2_write_bits(pi, 0, 1);
++	pic2_write_bits(pi, cc, depth);
++    } else {
++	pic2_write_bits(pi, 1, 1);
++	pic2_write_bits(pi, j, 6);
++    }
++}
++
++static void pic2_fast_press_line2(pi)
++struct pic2_info *pi;
++{
++    int x, xw;
++    pixel cc;
++
++    xw = pi->block->x_wid;
++    cc = pi->vram_now[xw - 1];			/* last color */
++    pi->vram_next[-1] = cc;
++
++    /* mark change point */
++    for (x = 0; x < xw; x++)
++	if (cc != pi->vram_next[x]) {
++	    pi->flag_next[x] = 1;
++	    cc = pi->vram_next[x];
++	} else
++	    pi->flag_next[x] = 0;
++
++    for (x = 0; x < xw; x++)
++	if (pi->flag_now[x] == 1) {			/* change point */
++	    if (pi->aa >= 1023)
++		pi->aa++;
++	    pic2_fast_write_length(pi, pi->aa);
++	    pic2_fast_flush_chain(pi);
++	    pi->aa = 0;
++	    pic2_fast_write_color(pi, x);
++	    pic2_fast_press_chain(pi, x);
++	} else if (pi->flag_now[x] == 0) {
++	    pi->aa++;
++	} else {
++	    pic2_fast_press_chain2(pi, x);
++	    if (pi->cc == 1023) {
++		pic2_fast_write_length(pi, 1023);
++		pic2_fast_flush_chain(pi);
++		pi->aa = 0;
++	    }
++	}
++}
++
++static int pic2_fast_press_line(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    int xw, ymax;
++
++    xw = pi->block->x_wid;
++    ymax = pi->block->y_wid -1;
++
++    pic2_handle_para(pi, 0);
++
++    if (pi->ynow == 0) {			/* first line */
++	int x;
++	pixel cc = 0;
++
++	/* initialize flags */
++	xvbzero((char *) pi->cache, 256 * sizeof(pi->cache[0]));
++	xvbzero((char *) pi->cache_pos,
++		PIC2_FAST_CACHE * sizeof(pi->cache_pos[0]));
++
++	/* mark change point */
++	pi->vram_next[-1] = cc;
++	for (x = 0; x < xw; x++)
++	    if (cc != pi->vram_next[x]) {
++		pi->flag_next[x] = 1;
++		cc = pi->vram_next[x];
++	    } else
++		pi->flag_next[x] = 0;
++
++	pi->cc = 0;
++	pi->aa = 0;
++    } else					/* after second line */
++	pic2_fast_press_line2(pi);
++
++    if (pi->ynow ==  ymax) {
++	pi->ynow++;
++	pic2_handle_para(pi, 1);
++	pic2_handle_para(pi, 0);
++	pic2_fast_press_line2(pi);
++    }
++    /* line buffer for next data */
++    if (line != NULL)
++	*line = pi->vram_prev;
++
++    pi->ynow++;
++
++    if (pi->ynow - 1 < ymax) {
++	pic2_handle_para(pi, 1);
++	return (pi->ynow);
++    } else {					/* end */
++	pic2_handle_para(pi, 1);
++	if (pi->aa >= 1023)
++	    pi->aa++;
++	pic2_fast_write_length(pi, pi->aa);
++	pic2_fast_flush_chain(pi);
++	return (-2);				/* end */
++    }
++}
++
++static int pic2_fast_saver_init(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    pi->ynow = 0;
++
++    /* check the color depth */
++    if (pi->header->depth % 3)
++	pic2_error(pi, PIC2_DEPTH);
++
++    /* set next line function */
++    pi->next_line = pic2_fast_press_line;
++    if (line != NULL)
++	*line = pi->vram_next + 4;
++
++    pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
++
++    /* clear bit field marker */
++    pi->bs.rest = 0;
++    pi->bs.cur = 0;
++
++    return (0);
++}
++
++/*
++ * These functions are beta pic2 format compressor.
++ */
++static int pic2_beta_press_line(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    int i, xw, ymax;
++    byte *p;
++    pixel *pc;
++    short depth, pixbyte, colbits;
++
++    depth = pi->header->depth;
++    pixbyte = depth / 8 + ((depth % 8) > 0);
++    colbits = depth / 3;
++
++    xw = pi->block->x_wid;
++    ymax = pi->block->y_wid - 1;
++
++    pc = pi->vram_now;
++    p = (byte *) pi->vram_prev;
++    if (pixbyte == 3) {
++	for (i = 0; i < xw; i++, pc++) {
++	    *p++ = *pc >> 16;
++	    *p++ = *pc >>  8;
++	    *p++ = *pc;
++	}
++	pic2_write_file(pi, pi->vram_prev, (size_t) (xw * 3));
++    } else if (pixbyte == 2) {
++	if (strncmp(pi->block->id, "P2BM", 4) == 0)
++	    for (i = 0; i < xw; i++, pc++) {
++		if (colbits == 5) {
++		    *pc = pic2_exchange_rg(*pc, colbits);
++		    *pc <<= 1;
++		}
++		*p++ = *pc >> 8;
++		*p++ = *pc;
++	    }
++	else
++	    for (i = 0; i < xw; i++, pc++) {
++		if (colbits == 5) {
++		    *pc = pic2_exchange_rg(*pc, colbits);
++		    *pc <<= 1;
++		}
++		*p++ = *pc;
++		*p++ = *pc >> 8;
++	    }
++	pic2_write_file(pi, pi->vram_prev, (size_t) (xw * 2));
++    } else {
++	for (i = 0; i < xw; i++, pc++)
++	    *p++ = *pc;
++	pic2_write_file(pi, pi->vram_prev, (size_t) xw);
++    }
++    if (line != NULL)
++	*line = pi->vram_now;
++
++    pi->ynow++;
++    if (pi->ynow > ymax)
++	return (-2);
++    return (pi->ynow);
++}
++
++static int pic2_beta_saver_init(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    pi->ynow = 0;
++
++    *line = pi->vram_now;
++    pi->next_line = pic2_beta_press_line;
++    pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET);
++    return (0);
++}
++
++/*
++ * This function saves compressed data.
++ */
++static void pic2_write_data(pi, data, ptype, x_offset, y_offset, w, h,
++			    rmap, gmap, bmap, type, depth)
++struct pic2_info *pi;
++byte *data;
++int ptype;
++int x_offset, y_offset;
++int w, h;
++byte *rmap, *gmap, *bmap;
++int type, depth;
++{
++    int i, line;
++    pixel *linep;
++    short colbits;
++
++    colbits = pi->header->depth / 3;
++
++    line = pic2_save_block(pi, &linep, x_offset, y_offset, w, h,
++			   form_tab[type].id, 0xffffffff);
++    while (line >= 0) {
++	byte r, g, b;
++	int pic_idx;
++
++	pic_idx = line * w * ((ptype == PIC24) ? 3 : 1);
++
++	for (i = 0; i < w; i++) {
++	    if (ptype != PIC24) {
++		r = rmap[data[pic_idx]];
++		g = gmap[data[pic_idx]];
++		b = bmap[data[pic_idx]];
++		pic_idx++;
++	    } else {
++		r = data[pic_idx++];
++		g = data[pic_idx++];
++		b = data[pic_idx++];
++	    }
++	    if (pi->writing_grey)
++		r = g = b = MONO(r, g, b);
++
++	    r = pic2_convert_color_bits(r, 8, colbits);
++	    g = pic2_convert_color_bits(g, 8, colbits);
++	    b = pic2_convert_color_bits(b, 8, colbits);
++
++	    linep[i] = ((pixel) r << (colbits * 2))
++		     | ((pixel) g <<  colbits     )
++		     | ((pixel) b                 );
++	}
++	line = pic2_next_line(pi, &linep);
++	WaitCursor();
++    }
++}
++
++/*
++ * This function compresses/extracts one line buffer.
++ */
++static int pic2_next_line(pi, line)
++struct pic2_info *pi;
++pixel **line;
++{
++    int res;
++
++    res = pi->next_line(pi, line);
++    if (res == -2) {
++	if (pi->mode == PIC2_WRITE_MODE) {
++	    long new_pos;
++
++	    new_pos = pic2_tell_file(pi);
++	    pi->block->size = new_pos - pi->next_pos;
++	    pic2_seek_file(pi, pi->next_pos, SEEK_SET);
++	    pic2_write_block_header(pi);
++	    pi->next_pos = new_pos;
++	    if (DEBUG)
++		pic2_show_pic2_info(pi);
++	}
++	pic2_free_buffer(pi);
++    }
++    return (res);
++}
++
++/*
++ * These functions find the pic2 image block.
++ * pic2_next_block:
++ *	moves the file pointer to the next image block.
++ * pic2_find_block:
++ *	finds the first image block and moves the file pointer there.
++ */
++static int pic2_next_block(pi)
++struct pic2_info *pi;
++{
++    int i;
++
++    if (pi->mode != PIC2_READ_MODE)
++	return (-1);
++
++    /* go to block for read */
++    pic2_seek_file(pi, pi->next_pos, SEEK_SET);
++
++    /* read the head of block header */
++    pic2_read_block_header1(pi);
++
++    /* end block ? */
++    if (pi->block->id[0] == 0)
++	return (0);
++
++    /* set current block */
++    pi->block_pos = pi->next_pos;
++
++    /* set next block */
++    pi->next_pos += pi->block->size;
++
++   /* check block id */
++    for (i = 0; i < n_form_tab; i++) {
++	if (xvbcmp(pi->block->id, form_tab[i].id, (size_t) 4) == 0)
++	    break;
++    }
++    if (i == n_form_tab)
++	return (2);
++
++    /* read the rest of block header */
++    pic2_read_block_header2(pi);
++
++    if (pi->block->x_offset + pi->block->x_wid > pi->x_max)
++	pi->x_max = pi->block->x_offset + pi->block->x_wid;
++
++    if (pi->block->y_offset + pi->block->y_wid > pi->y_max)
++	pi->y_max = pi->block->y_offset + pi->block->y_wid;
++
++    if (DEBUG)
++	pic2_show_pic2_info(pi);
++    return (1);
++}
++
++static int pic2_find_block(pi)
++struct pic2_info *pi;
++{
++    if (pi->mode != PIC2_READ_MODE)
++	return (-1);
++
++    pi->next_pos = pi->header->size;
++    return (pic2_next_block(pi));
++}
++
++/*
++ * These functions load/save the pic2 image block.
++ * pic2_load_block:
++ *	initializes loader information with current block information.
++ * pic2_save_block:
++ *	initializes saver information.
++ */
++static int pic2_load_block(pi)
++struct pic2_info *pi;
++{
++    int i;
++
++    for (i = 0; i < n_form_tab; i++) {
++	if (xvbcmp(pi->block->id, form_tab[i].id, (size_t) 4) == 0)
++	    break;
++    }
++    if (i == n_form_tab)
++	return (2);
++
++    pic2_alloc_buffer(pi);
++    return (form_tab[i].loader_init(pi));
++}
++
++static int pic2_save_block(pi, line, x, y, xw, yw, id, opaque)
++struct pic2_info *pi;
++pixel **line;
++int x, y, xw, yw;
++char *id;
++pixel opaque;
++{
++    int i;
++
++    for (i = 0; i < n_form_tab; i++) {
++	if (xvbcmp(id, form_tab[i].id, (size_t) 4) == 0)
++	    break;
++    }
++    if (i == n_form_tab)
++	return (2);
++
++    strncpy(pi->block->id, id, 4);
++    pi->block->x_wid = xw;
++    pi->block->y_wid = yw;
++    pi->block->x_offset = x;
++    pi->block->y_offset = y;
++    pi->block->reserve = 0;
++
++    if (x < 0)
++	x = 0;
++    if (y < 0)
++	y = 0;
++    if (x + xw > pi->x_max)
++	pi->x_max = x + xw;
++    if (y + yw > pi->y_max)
++	pi->y_max = y + yw;
++
++    if (opaque != 0xffffffff) {
++	pi->block->flag = 1;
++	pi->block->opaque = opaque;
++    } else {
++	pi->block->flag = 0;
++	pi->block->opaque = 0;
++    }
++    pic2_alloc_buffer(pi);
++
++    return (form_tab[i].saver_init(pi, line));
++}
++
++/*
++ * These functions set/get palettes.
++ * pic2_read_palette:
++ *	copy the palettes from pic2_info to PICINFO.
++ * pic2_write_palette:
++ *	copy the palettes from PICINFO to pic2_info.
++ */
++#ifndef PIC2_IGNORE_UNUSED_FUNCTIONS
++static void pic2_read_palette(pi, r, g, b)
++struct pic2_info *pi;
++byte *r, *g, *b;
++{
++    int i;
++
++    if (pi->n_pal > 256)
++	pi->n_pal = 256;
++
++    if (pi->pal_bits > 8)
++	pi->pal_bits = 8;
++
++    for (i = 0; i < pi->n_pal; i++) {
++	*r++ =pic2_convert_color_bits(pi->pal[i][0] >> (8 - pi->pal_bits),
++				      pi->pal_bits, 8);
++	*g++ =pic2_convert_color_bits(pi->pal[i][1] >> (8 - pi->pal_bits),
++				      pi->pal_bits, 8);
++	*b++ =pic2_convert_color_bits(pi->pal[i][2] >> (8 - pi->pal_bits),
++				      pi->pal_bits, 8);
++    }
++}
++
++static void pic2_write_palette(pi, n_pal, pal_bits, r, g, b)
++struct pic2_info *pi;
++int n_pal, pal_bits;
++byte *r, *g, *b;
++{
++    int i;
++
++    if (n_pal > 256)
++	pi->n_pal = 256;
++    else
++	pi->n_pal = n_pal;
++
++    if (pal_bits > 8)
++	pi->pal_bits = 8;
++    else
++	pi->pal_bits = pal_bits;
++
++    for (i = 0; i < n_pal; i++) {
++	pi->pal[i][0] = pic2_convert_color_bits(*r++, 8, pal_bits)
++	    << (8 - pal_bits);
++	pi->pal[i][1] = pic2_convert_color_bits(*g++, 8, pal_bits)
++	    << (8 - pal_bits);
++	pi->pal[i][2] = pic2_convert_color_bits(*b++, 8, pal_bits)
++	    << (8 - pal_bits);
++    }
++}
++#endif /* PIC2_IGNORE_UNUSED_FUNCTIONS */
++
++/*
++ * These functions handle color bits.
++ * pic2_convert_color_bits:
++ *	converts color bits.
++ * pic2_pad_color_bits:
++ *	pads color bits.
++ * pic2_reduce_color_bits:
++ *	reduces color bits.
++ * pic2_exchange_rg:
++ *      exchanges red and green values.
++ */
++static byte pic2_convert_color_bits(c, from, to)
++int c, from, to;
++{
++    if (from == to)
++	return ((byte) c);
++    else if (from < to)
++	return (pic2_pad_color_bits(c, from, to));
++    else
++	return (pic2_reduce_color_bits(c, from, to));
++}
++
++static byte pic2_pad_color_bits(c, from, to)
++int c, from, to;
++{
++    byte p = 0;
++
++    do {
++	to -= from;
++	p |= pic2_shift_bits(c, to);
++    } while (to >= 0);
++    return (p);
++}
++
++static byte pic2_reduce_color_bits(c, from, to)
++int c, from, to;
++{
++    return ((byte) (c >> (from - to)));
++}
++
++static pixel pic2_exchange_rg(p, colbits)
++pixel p;
++int colbits;
++{
++    pixel rmask, gmask, bmask;
++
++    rmask = (0xff >> (8 - colbits)) << (colbits * 2);
++    gmask = (0xff >> (8 - colbits)) <<  colbits;
++    bmask = (0xff >> (8 - colbits));
++
++    p = ((p << colbits) & rmask)
++      | ((p >> colbits) & gmask)
++      | ( p             & bmask);
++    return (p);
++}
++
++/*
++ * This function handles work memory buffer.
++ */
++static void pic2_handle_para(pi, mode)
++struct pic2_info *pi;
++int mode;
++{
++    static pixel *vram_prev, *vram_now, *vram_next;
++    static short *flag_now, *flag_next;
++    static short *flag2_now, *flag2_next, *flag2_next2;
++
++    switch (mode) {
++    case 0:
++	vram_prev = pi->vram_prev;
++	vram_now = pi->vram_now;
++	vram_next = pi->vram_next;
++	flag_now = pi->flag_now;
++	flag_next = pi->flag_next;
++	flag2_now = pi->flag2_now;
++	flag2_next = pi->flag2_next;
++	flag2_next2 = pi->flag2_next2;
++	pi->vram_prev += 4;
++	pi->vram_now += 4;
++	pi->vram_next += 4;
++	pi->flag_now += 4;
++	pi->flag_next += 4;
++	pi->flag2_now += 4;
++	pi->flag2_next += 4;
++	pi->flag2_next2 += 4;
++	break;
++    case 1:
++	pi->vram_prev = vram_now;
++	pi->vram_now = vram_next;
++	pi->vram_next = vram_prev;
++	pi->flag_now = flag_next;
++	pi->flag_next = flag_now;
++	pi->flag2_now = flag2_next;
++	pi->flag2_next = flag2_next2;
++	pi->flag2_next2 = flag2_now;
++	break;
++    }
++}
++
++/*
++ * These functions alloc/free work memory.
++ * pic2_alloc_buffer:
++ *	alloc work memory buffer.
++ * pic2_free_buffer:
++ *	free work memory buffer.
++ */
++static int pic2_alloc_buffer(pi)
++struct pic2_info *pi;
++{
++    int wid;
++    byte *p;
++
++    if (pi->buf != NULL)
++	return (-1);
++
++    wid = pi->block->x_wid;
++
++    p = pi->buf = (byte *) pic2_new((wid + 8) * sizeof(pixel) * 3   // GRR POSSIBLE OVERFLOW / FIXME
++				    + sizeof(pi->cache[0]) * 8 * 8 * 8
++				    + sizeof(pi->cache_pos[0]) * 8 * 8 * 8
++				    + sizeof(pi->mulu_tab[0]) * 16384
++				    + sizeof(pi->flag_now[0]) * ((wid+8) * 5),
++				    "pic2_alloc_buffer");
++
++    pi->vram_prev = (pixel *) p;
++    p += (wid + 8) * sizeof(pixel);
++    pi->vram_now = (pixel *) p;
++    p += (wid + 8) * sizeof(pixel);
++    pi->vram_next = (pixel *) p;
++    p += (wid + 8) * sizeof(pixel);
++    pi->cache = (pixel (*)[PIC2_ARITH_CACHE]) p;
++    p += sizeof(pi->cache[0]) * 8 * 8 * 8;
++    pi->cache_pos = (unsigned short *) p;
++    p += sizeof(pi->cache_pos[0]) * 8 * 8 * 8;
++    pi->mulu_tab = (unsigned short *) p;
++    p += sizeof(pi->mulu_tab[0]) * 16384;
++    pi->flag_now = (short *) p;
++    p += sizeof(pi->flag_now[0]) * (wid + 8);
++    pi->flag_next = (short *) p;
++    p += sizeof(pi->flag_next[0]) * (wid + 8);
++    pi->flag2_now = (short *) p;
++    p += sizeof(pi->flag2_now[0]) * (wid + 8);
++    pi->flag2_next = (short *) p;
++    p += sizeof(pi->flag2_next[0]) * (wid + 8);
++    pi->flag2_next2 = (short *) p;
++    p += sizeof(pi->flag2_next2[0]) * (wid + 8);
++    return (0);
++}
++
++static void pic2_free_buffer(pi)
++struct pic2_info *pi;
++{
++    free(pi->buf);
++    pi->buf = NULL;
++}
++
++/*
++ * These functions handle the file pointer.
++ * pic2_seek_file:
++ *	moves the file pointer.
++ * pic2_tell_file:
++ *	tells the location of the file pointer.
++ */
++static long pic2_seek_file(pi, offset, whence)
++struct pic2_info *pi;
++long offset;
++int whence;
++{
++    long n;
++
++    n = fseek(pi->fp, offset, whence);
++    if (n < 0)
++	pic2_file_error(pi, PIC2_CORRUPT);
++
++    return (n);
++}
++
++static long pic2_tell_file(pi)
++struct pic2_info *pi;
++{
++    return (ftell(pi->fp));
++}
++
++/*
++ * These functions handle file.
++ * pic2_read_file:
++ *	reads data from the file.
++ * pic2_read_long:
++ *	reads long word data from the file and converts to internal expression.
++ * pic2_read_short:
++ *	reads word data from the file and converts to internal expression.
++ * pic2_read_char:
++ *	reads byte data from the file.
++ * pic2_write_file:
++ *	writes data to the file.
++ * pic2_write_long:
++ *	converts long word data to common expression and writes to the file.
++ * pic2_write_short:
++ *	converts word data to common expression and writes to the file.
++ * pic2_write_char:
++ *	writes byte data to the file.
++ */
++static int pic2_read_file(pi, buf, size)
++struct pic2_info *pi;
++void *buf;
++size_t size;
++{
++    if (fread(buf, (size_t) 1, size, pi->fp) < size)
++	pic2_file_error(pi, PIC2_CORRUPT);
++    return (0);
++}
++
++static long pic2_read_long(pi)
++struct pic2_info *pi;
++{
++    byte buf[4];
++
++    if (fread(buf, (size_t) 4, (size_t) 1, pi->fp) < 1)
++	pic2_file_error(pi, PIC2_CORRUPT);
++    return (pic2_cextolong(buf));
++}
++
++static short pic2_read_short(pi)
++struct pic2_info *pi;
++{
++    byte buf[2];
++
++    if (fread(buf, (size_t) 2, (size_t) 1, pi->fp) < 1)
++	pic2_file_error(pi, PIC2_CORRUPT);
++    return (pic2_cextoshort(buf));
++}
++
++static char pic2_read_char(pi)
++struct pic2_info *pi;
++{
++    int c;
++
++    if ((c = fgetc(pi->fp)) == EOF)
++	pic2_file_error(pi, PIC2_CORRUPT);
++    return ((char) c);
++}
++
++static int pic2_write_file(pi, buf, size)
++struct pic2_info *pi;
++void *buf;
++size_t size;
++{
++    if (fwrite(buf, (size_t) 1, size, pi->fp) < size)
++	pic2_error(pi, PIC2_WRITE);
++    return (0);
++}
++
++static int pic2_write_long(pi, n)
++struct pic2_info *pi;
++long n;
++{
++    byte buf[4];
++
++    pic2_longtocex(buf, n);
++    if (fwrite(buf, (size_t) 4, (size_t) 1, pi->fp) < 1)
++	pic2_error(pi, PIC2_WRITE);
++    return (0);
++}
++
++static int pic2_write_short(pi, n)
++struct pic2_info *pi;
++int n;
++{
++    byte buf[2];
++
++    pic2_shorttocex(buf, n);
++    if (fwrite(buf, (size_t) 2, (size_t) 1, pi->fp) < 1)
++	pic2_error(pi, PIC2_WRITE);
++    return (0);
++}
++
++static int pic2_write_char(pi, c)
++struct pic2_info *pi;
++int c;
++{
++    if (fputc(c, pi->fp) == EOF)
++	pic2_error(pi, PIC2_WRITE);
++    return (0);
++}
++
++/*
++ * These functions access the bit stream.
++ * pic2_read_bits:
++ *	reads the specified bits from the file.
++ * pic2_write_bits:
++ *	writes the specified bits to the file.
++ * pic2_flush_bits:
++ *	flushes bit buffer to the file.
++ */
++static unsigned long pic2_read_bits(pi, bits)
++struct pic2_info *pi;
++int bits;
++{
++    unsigned long r = 0;
++
++    while (bits > 0) {
++	while (pi->bs.rest > 0 && bits > 0) {
++	    r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0);
++	    pi->bs.cur <<= 1;
++	    pi->bs.rest--;
++	    bits--;
++	}
++	if (bits > 0) {
++	    int c;
++	    if ((c = fgetc(pi->fp)) == EOF)
++		pic2_file_error(pi, PIC2_CORRUPT);
++	    pi->bs.cur  = (byte) c;
++	    pi->bs.rest = 8;
++	}
++    }
++    return r;
++}
++
++static void pic2_write_bits(pi, dat, bits)
++struct pic2_info *pi;
++unsigned long dat;
++int bits;
++{
++    unsigned long dat_mask = 1 << (bits - 1);
++
++    while (bits > 0) {
++	while (pi->bs.rest < 8 && bits > 0) {
++	    pi->bs.cur <<= 1;
++	    if (dat & dat_mask)
++		pi->bs.cur |= 1;
++	    pi->bs.rest++;
++	    bits--;
++	    dat_mask >>= 1;
++	}
++	if (pi->bs.rest >= 8) {
++	    if ((fputc((int) pi->bs.cur, pi->fp)) == EOF)
++		pic2_error(pi, PIC2_WRITE);
++	    pi->bs.cur  = 0;
++	    pi->bs.rest = 0;
++	}
++    }
++}
++
++static void pic2_flush_bits(pi)
++struct pic2_info *pi;
++{
++    if (pi->bs.rest < 8) {
++	pi->bs.cur <<= 8 - pi->bs.rest;
++	if (fputc((int) pi->bs.cur, pi->fp) == EOF)
++		pic2_error(pi, PIC2_WRITE);
++	pi->bs.cur  = 0;
++	pi->bs.rest = 0;
++    }
++}
++
++/*
++ * These functions initialize or clean up structures.
++ * pic2_init_info:
++ *	initializes a pic2_info structure.
++ * pic2_cleanup_pic2_info:
++ *	cleans up a pic_info structure.
++ * pic2_cleanup_pinfo:
++ *	cleans up a PICINFO structure.
++ */
++static void pic2_init_info(pi)
++struct pic2_info *pi;
++{
++    xvbzero((char *) pi, sizeof(struct pic2_info));
++    pi->header = pic2_new(sizeof(struct pic2_header), "pic2_init_info#1");
++    pi->block = pic2_new(sizeof(struct pic2_block), "pic2_init_info#2");
++}
++
++static void pic2_cleanup_pic2_info(pi, writing)
++struct pic2_info *pi;
++int writing;
++{
++    if (!writing && pi->fp)
++	fclose(pi->fp);
++    if (pi->header)
++	free(pi->header);
++    if (pi->block)
++	free(pi->block);
++    pi->fp = NULL;
++    pi->header = NULL;
++    pi->block = NULL;
++    pi->comment = NULL;
++}
++
++static void pic2_cleanup_pinfo(pinfo)
++PICINFO *pinfo;
++{
++    if (pinfo->pic){
++	free(pinfo->pic);
++	pinfo->pic = NULL;
++    }
++    if (pinfo->comment){
++	free(pinfo->comment);
++	pinfo->comment = NULL;
++    }
++}
++
++/*
++ * Error Handlers.
++ * pic2_memory_error:
++ *	shows an error message and terminates.
++ * pic2_error:
++ *	shows a non-file error message and jumps to the entry for errors.
++ * pic2_file_error:
++ *	shows a file error message and jumps to the entry for errors.
++ */
++static void pic2_memory_error(scm, fn)
++char *scm, *fn;
++{
++    char buf[128];
++    sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn);
++    FatalError(buf);
++}
++
++static void pic2_error(pi, mn)
++struct pic2_info *pi;
++int mn;
++{
++    SetISTR(ISTR_WARNING, "%s", pic2_msgs[mn]);
++    longjmp(pi->jmp, 1);
++}
++
++static void pic2_file_error(pi, mn)
++    struct pic2_info *pi;
++    int mn;
++{
++    if (feof(pi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", pic2_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", pic2_msgs[mn], ERRSTR(errno));
++    longjmp(pi->jmp, 1);
++}
++
++static void pic2_show_pic2_info(pi)
++    struct pic2_info *pi;
++{
++    fprintf(stderr, "file size: %ld.\n", pi->fsize);
++    fprintf(stderr, "full image size: %dx%d\n", pi->x_max, pi->y_max);
++    fprintf(stderr, "number of palettes: %d\n", pi->n_pal);
++    fprintf(stderr, "depth of palettes: %d\n", pi->pal_bits);
++    fprintf(stderr, "current block position: %ld\n", pi->block_pos);
++    fprintf(stderr, "next block position: %ld\n\n", pi->next_pos);
++
++    fprintf(stderr, "header flag: %x\n", pi->header->flag);
++    fprintf(stderr, "header size: %ld\n", pi->header->size);
++    fprintf(stderr, "x_aspect: %d, y_aspect: %d\n",
++	    pi->header->x_aspect, pi->header->y_aspect);
++    fprintf(stderr, "number of color bits: %d\n\n", pi->header->depth);
++
++    fprintf(stderr, "image block id: %s\n", pi->block->id);
++    fprintf(stderr, "image block size: %ld\n", pi->block->size);
++    fprintf(stderr, "block flag: %x\n", pi->block->flag);
++
++    fprintf(stderr, "block image size: %dx%d\n",
++	    pi->block->x_wid, pi->block->y_wid);
++    fprintf(stderr, "x_offset: %d\n", pi->block->x_offset);
++    fprintf(stderr, "y_offset: %d\n", pi->block->y_offset);
++    fprintf(stderr, "opaque color: %lx\n\n", pi->block->opaque);
++}
++
++/*
++ * This function is similar to strncpy.
++ * But this pads with whitespace after the null character.
++ */
++static char *pic2_strncpy(dest, src, n)
++char *dest, *src;
++size_t n;
++{
++    char *r;
++
++    r = dest;
++    while (n--)
++	if ((src != NULL) && (*src != '\r') && (*src != '\n') && *src)
++	    *dest++ = *src++;
++	else
++	    *dest++ = ' ';
++    return (r);
++}
++
++/*
++ * These functions create a memory block.
++ */
++static void *pic2_malloc(size, fn)
++size_t size;
++char *fn;
++{
++    void *p;
++
++    p = (void *) malloc(size);
++    if (p == NULL)
++	pic2_memory_error("malloc", fn);
++    return (p);
++}
++
++static void *pic2_new(size, fn)
++size_t size;
++char *fn;
++{
++    void *p;
++
++    p = (void *) pic2_malloc(size, fn);
++    xvbzero((char *) p, size);
++    return (p);
++}
++
++
++
++
++/**** Stuff for PIC2Dialog box ****/
++
++#define TWIDE    320
++#define THIGH	 178
++#define T_NBUTTS 2
++#define T_BOK    0
++#define T_BCANC  1
++#define BUTTH    24
++
++static void drawTD    PARM((int,int,int,int));
++static void clickTD   PARM((int,int));
++static void doCmd     PARM((int));
++static void writePIC2 PARM((void));
++
++/* local variables */
++static FILE  *fp;
++static char  *filename;
++static int   colorType;
++static int   append;
++static int   x_offset;
++static int   y_offset;
++static BUTT  tbut[T_NBUTTS];
++static RBUTT *typeRB;
++static RBUTT *depthRB;
++
++
++
++/***************************************************/
++void CreatePIC2W()
++{
++    int	     y;
++
++    pic2W = CreateWindow("xv pic2", "XVpic2", NULL,
++			TWIDE, THIGH, infofg, infobg, 0);
++    if (!pic2W)
++	FatalError("can't create pic2 window!");
++
++    XSelectInput(theDisp, pic2W,
++		 ExposureMask | ButtonPressMask | KeyPressMask);
++
++    BTCreate(&tbut[T_BOK], pic2W, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH,
++	     "Ok", infofg, infobg, hicol, locol);
++
++    BTCreate(&tbut[T_BCANC], pic2W, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH,
++	     "Cancel", infofg, infobg, hicol, locol);
++
++    y = 55;
++    typeRB = RBCreate(NULL, pic2W, 36, y,          "P2SS",
++		      infofg, infobg,hicol,locol);
++    RBCreate(typeRB, pic2W, 36, y+18,              "P2SF",
++	     infofg, infobg,hicol,locol);
++    RBCreate(typeRB, pic2W, 36, y+36,              "P2BM",
++	     infofg, infobg, hicol, locol);
++    RBCreate(typeRB, pic2W, 36, y+54,              "P2BI",
++	     infofg, infobg, hicol, locol);
++
++    depthRB = RBCreate(NULL, pic2W, TWIDE/2-16, y, "  3bit",
++		       infofg, infobg,hicol,locol);
++    RBCreate(depthRB, pic2W, TWIDE/2-16, y+18,     "  6bit",
++	     infofg, infobg,hicol,locol);
++    RBCreate(depthRB, pic2W, TWIDE/2-16, y+36,     "  9bit",
++	     infofg, infobg, hicol, locol);
++    RBCreate(depthRB, pic2W, TWIDE/2-16, y+54,     "12bit",
++	     infofg, infobg, hicol, locol);
++    RBCreate(depthRB, pic2W, TWIDE/4*3-16, y,      "15bit",
++	     infofg, infobg, hicol, locol);
++    RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+18,   "18bit",
++	     infofg, infobg, hicol, locol);
++    RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+36,   "21bit",
++	     infofg, infobg, hicol, locol);
++    RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+54,   "24bit",
++	     infofg, infobg, hicol, locol);
++
++    XMapSubwindows(theDisp, pic2W);
++}
++
++
++/***************************************************/
++void PIC2Dialog(vis)
++int vis;
++{
++    if (vis) {
++	CenterMapWindow(pic2W, tbut[T_BOK].x + tbut[T_BOK].w/2,
++			tbut[T_BOK].y + tbut[T_BOK].h/2, TWIDE, THIGH);
++    }
++    else     XUnmapWindow(theDisp, pic2W);
++    pic2Up = vis;
++}
++
++
++/***************************************************/
++int PIC2CheckEvent(xev)
++XEvent *xev;
++{
++    /* check event to see if it's for one of our subwindows.  If it is,
++       deal accordingly and return '1'.  Otherwise, return '0'. */
++
++    int rv;
++    rv = 1;
++
++    if (!pic2Up)
++	return (0);
++
++    if (xev->type == Expose) {
++	int x,y,w,h;
++	XExposeEvent *e = (XExposeEvent *) xev;
++	x = e->x;  y = e->y;  w = e->width;  h = e->height;
++
++	if (e->window == pic2W)       drawTD(x, y, w, h);
++	else rv = 0;
++    }
++
++    else if (xev->type == ButtonPress) {
++	XButtonEvent *e = (XButtonEvent *) xev;
++	int x,y;
++	x = e->x;  y = e->y;
++
++	if (e->button == Button1) {
++	    if      (e->window == pic2W)     clickTD(x,y);
++	    else rv = 0;
++	}  /* button1 */
++	else rv = 0;
++    }  /* button press */
++
++
++    else if (xev->type == KeyPress) {
++	XKeyEvent *e = (XKeyEvent *) xev;
++	char buf[128];  KeySym ks;  XComposeStatus status;
++	int stlen;
++
++	stlen = XLookupString(e,buf,128,&ks,&status);
++	buf[stlen] = '\0';
++
++	if (e->window == pic2W) {
++	    if (stlen) {
++		if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
++		    FakeButtonPress(&tbut[T_BOK]);
++		}
++		else if (buf[0] == '\033') {            /* ESC */
++		    FakeButtonPress(&tbut[T_BCANC]);
++		}
++	    }
++	}
++	else rv = 0;
++    }
++    else rv = 0;
++
++    if (rv == 0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
++	XBell(theDisp, 50);
++	rv = 1;   /* eat it */
++    }
++
++    return (rv);
++}
++
++
++/***************************************************/
++int PIC2SaveParams(fname, col)
++char *fname;
++int col;
++{
++    filename = fname;
++    colorType = col;
++
++    /* see if we can open the output file before proceeding */
++    fp = pic2_OpenOutFile(filename, &append);
++    if (!fp)
++	return (-1);
++
++    RBSetActive(typeRB,0,1);
++    RBSetActive(typeRB,1,1);
++    RBSetActive(typeRB,2,1);
++    RBSetActive(typeRB,3,1);
++    RBSelect(typeRB,0);
++
++
++    if (append) {
++	struct pic2_info pic2;
++
++	pic2_init_info(&pic2);
++	pic2.fp = fp;
++	pic2_read_header(&pic2);
++
++	RBSetActive(depthRB,0,0);
++	RBSetActive(depthRB,1,0);
++	RBSetActive(depthRB,2,0);
++	RBSetActive(depthRB,3,0);
++	RBSetActive(depthRB,4,0);
++	RBSetActive(depthRB,5,0);
++	RBSetActive(depthRB,6,0);
++	RBSetActive(depthRB,7,0);
++
++	switch (pic2.header->depth) {
++	case  3:
++	    RBSetActive(depthRB,0,1);
++	    RBSelect(depthRB,0);
++	    RBSetActive(typeRB,3,0);
++	    break;
++	case  6:
++	    RBSetActive(depthRB,1,1);
++	    RBSelect(depthRB,1);
++	    RBSetActive(typeRB,3,0);
++	    break;
++	case  9:
++	    RBSetActive(depthRB,2,1);
++	    RBSelect(depthRB,2);
++	    break;
++	case 12:
++	    RBSetActive(depthRB,3,1);
++	    RBSelect(depthRB,3);
++	    break;
++	case 15:
++	    RBSetActive(depthRB,4,1);
++	    RBSelect(depthRB,4);
++	    break;
++	case 18:
++	    RBSetActive(depthRB,5,1);
++	    RBSelect(depthRB,5);
++	    RBSetActive(typeRB,3,0);
++	    break;
++	case 21:
++	    RBSetActive(depthRB,6,1);
++	    RBSelect(depthRB,6);
++	    RBSetActive(typeRB,3,0);
++	    break;
++	case 24:
++	    RBSetActive(depthRB,7,1);
++	    RBSelect(depthRB,7);
++	    RBSetActive(typeRB,3,0);
++	    break;
++	default: {
++	    char str[512];
++	    sprintf(str, "unsupported PIC2 file '%s'.", filename);
++	    ErrPopUp(str, "\nBummer");
++	    CloseOutFile(fp, filename, 0);
++	    fp = OpenOutFile(fname);
++	    if (!fp)
++		return (-1);
++	    break;
++	}
++	}
++	pic2_seek_file(&pic2, 0, SEEK_SET);
++	pic2_cleanup_pic2_info(&pic2, 1);
++    } else {
++	RBSetActive(depthRB,0,1);
++	RBSetActive(depthRB,1,1);
++	RBSetActive(depthRB,2,1);
++	RBSetActive(depthRB,3,1);
++	RBSetActive(depthRB,4,1);
++	RBSetActive(depthRB,5,1);
++	RBSetActive(depthRB,6,1);
++	RBSetActive(depthRB,7,1);
++	RBSelect(depthRB,7);
++	RBSetActive(typeRB,3,0);
++    }
++    return (0);
++}
++
++
++/***************************************************/
++static void drawTD(x,y,w,h)
++int x,y,w,h;
++{
++    char *title  = "Save PIC2 file...";
++    int  i;
++    XRectangle xr;
++
++    xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
++    XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
++
++    XSetForeground(theDisp, theGC, infofg);
++    XSetBackground(theDisp, theGC, infobg);
++
++    for (i = 0; i < T_NBUTTS; i++)
++	BTRedraw(&tbut[i]);
++
++    ULineString(pic2W, typeRB->x-16, typeRB->y-3-DESCENT,   "FormatType");
++    ULineString(pic2W, depthRB->x-16, depthRB->y-3-DESCENT, "ColorDepth");
++    RBRedraw(typeRB, -1);
++    RBRedraw(depthRB, -1);
++
++    DrawString(pic2W, 20, 29, title);
++
++    XSetClipMask(theDisp, theGC, None);
++}
++
++static void clickTD(x,y)
++int x,y;
++{
++    int i;
++    BUTT *bp;
++
++    /* check BUTTs */
++
++    /* check the RBUTTS first, since they don't DO anything */
++    if ((i = RBClick(typeRB, x,y)) >= 0) {
++	(void) RBTrack(typeRB, i);
++	return;
++    } else if ((i = RBClick(depthRB, x,y)) >= 0) {
++	(void) RBTrack(depthRB, i);
++	if ((2 <= i) && (i <= 4))
++	    RBSetActive(typeRB,3,1);
++	else {
++	    RBSetActive(typeRB,3,0);
++	    if (RBWhich(typeRB) == 3)
++		RBSelect(typeRB,0);
++	return;
++	}
++    }
++    for (i = 0; i < T_NBUTTS; i++) {
++	bp = &tbut[i];
++	if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h))
++	    break;
++    }
++    if (i < T_NBUTTS)  /* found one */
++	if (BTTrack(bp))
++	    doCmd(i);
++}
++
++
++
++/***************************************************/
++static void doCmd(cmd)
++int cmd;
++{
++    switch (cmd) {
++    case T_BOK: {
++	char              *fullname;
++	char               buf[64], *x_offsetp, *y_offsetp;
++	static const char *labels[] = { "\nOk", "\033Cancel" };
++        XEvent             event;
++	int                i;
++
++	strcpy(buf, "0,0");
++	i = GetStrPopUp("Enter offset (x,y):", labels, 2, buf, 64,
++			"01234567890,", 1);
++
++	if (i)
++	    return;
++	if (strlen(buf)==0)
++	    return;
++
++	x_offsetp = buf;
++	y_offsetp = index(buf, ',');
++	if (!y_offsetp)
++	    return;
++	*(y_offsetp++) = '\0';
++	if ((*x_offsetp == '\0') || (*y_offsetp == '\0'))
++	    return;
++	x_offset = atoi(x_offsetp);
++	y_offset = atoi(y_offsetp);
++
++        XNextEvent(theDisp, &event);
++	HandleEvent(&event, &i);
++
++	writePIC2();
++	PIC2Dialog(0);
++
++	fullname = GetDirFullName();
++	if (!ISPIPE(fullname[0])) {
++	    XVCreatedFile(fullname);
++	    StickInCtrlList(0);
++	}
++    }
++	break;
++    case T_BCANC:
++	pic2_KillNullFile(fp);
++	PIC2Dialog(0);
++	break;
++    default:
++	break;
++    }
++}
++
++
++/*******************************************/
++static void writePIC2()
++{
++    int   w, h, nc, rv, type, depth, ptype, pfree;
++    byte *inpix, *rmap, *gmap, *bmap;
++
++
++    WaitCursor();
++    inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap);
++
++    if (colorType == F_REDUCED)
++	colorType = F_FULLCOLOR;
++
++    switch (RBWhich(typeRB)) {
++    case 0: type = P2SS;  break;
++    case 1: type = P2SF;  break;
++    case 2: type = P2BM;  break;
++    case 3: type = P2BI;  break;
++    default: type = P2SS; break;
++    }
++    switch (RBWhich(depthRB)) {
++    case 0: depth =  3;  break;
++    case 1: depth =  6;  break;
++    case 2: depth =  9;  break;
++    case 3: depth = 12;  break;
++    case 4: depth = 15;  break;
++    case 5: depth = 18;  break;
++    case 6: depth = 21;  break;
++    case 7: depth = 24;  break;
++    default: depth = 24; break;
++    }
++    rv = WritePIC2(fp, inpix, ptype, w, h,
++		   rmap, gmap, bmap, nc, colorType, filename,
++		   type, depth, x_offset, y_offset, append, picComments);
++
++    if (CloseOutFile(fp, filename, rv) == 0)
++	DirBox(0);
++
++    if (pfree)
++	free(inpix);
++}
++#endif /* HAVE_PIC2 */
+diff -Naru xv-3.10a/xvpic.c xv-3.10a.jumbo/xvpic.c
+--- xv-3.10a/xvpic.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvpic.c	2005-04-18 07:57:08.000000000 +0200
+@@ -0,0 +1,1285 @@
++/*
++ * xvpic.c - load routine for `PIC' format pictures.
++ *
++ * The `PIC' format is used by many Japanese personal computer users.
++ */
++
++#include "xv.h"
++#include <setjmp.h>
++
++#ifdef HAVE_PIC
++
++typedef unsigned short data16;
++typedef unsigned int data32;
++
++struct pic_info {
++    jmp_buf jmp;
++    FILE *fp;
++    struct {
++	int rest;
++	byte cur;
++    }bs;
++    long fsize;
++    int type, mode;
++    int width, height;
++    float aspect;
++    int cbits;
++    int cmapped;
++    byte *cmap;
++    int cached;
++    struct cache_t {
++	int newest;
++	struct cachenode_t {
++	    data32 dat;
++	    int newer, older;
++	} *node;
++    } cache;
++    int g_bits, r_bits, b_bits, i_bits;
++    int inv_gr;
++    int tiled256;
++    int numcols;
++    int writing_grey;
++    data32 *data;
++};
++
++static void pic_open_file              PARM((struct pic_info*,char*));
++static void pic_check_id               PARM((struct pic_info*));
++static void pic_read_comment           PARM((struct pic_info*, char**));
++static void pic_read_header            PARM((struct pic_info*));
++static void pic_expand_data            PARM((struct pic_info*));
++static int pic_expanding_read_len      PARM((struct pic_info*));
++static data32 pic_expanding_read_color PARM((struct pic_info*));
++static void pic_expanding_read_chain
++			PARM((struct pic_info*, int, int, data32));
++static void pic_make_xvpic
++			PARM((struct pic_info*, byte**, byte*, byte*, byte*));
++
++static void pic_write_id               PARM((struct pic_info*));
++static void pic_write_comment          PARM((struct pic_info*, char*));
++static void pic_write_header           PARM((struct pic_info*));
++static void pic_write_palette
++			PARM((struct pic_info*, byte*, byte*, byte*));
++static void pic_make_sparse_data       PARM((struct pic_info*, byte*));
++static void pic_write_data             PARM((struct pic_info*));
++static void pic_write_length           PARM((struct pic_info*, data32));
++static void pic_write_color            PARM((struct pic_info*, data32));
++static void pic_write_chain
++			PARM((struct pic_info*, int, int, data32));
++
++static data32 pic_read_rgb             PARM((struct pic_info*));
++static data32 pic_read_color_code      PARM((struct pic_info*));
++static void pic_write_rgb              PARM((struct pic_info*, data32));
++static void pic_write_color_code       PARM((struct pic_info*, data32));
++
++static void pic_cache_init             PARM((struct pic_info*));
++static data32 pic_cache_get_value      PARM((struct pic_info*, int));
++static void pic_cache_add_value        PARM((struct pic_info*, data32));
++static int pic_cache_lookup            PARM((struct pic_info*, data32));
++
++static data32 pic_read_bits            PARM((struct pic_info*, int));
++static void pic_write_bits             PARM((struct pic_info*, data32, int));
++static byte pic_pad_bit                PARM((int, data32));
++
++static void pic_init_info              PARM((struct pic_info*));
++static void pic_cleanup_pic_info       PARM((struct pic_info*, int));
++static void pic_cleanup_pinfo          PARM((PICINFO*));
++static void pic_memory_error           PARM((char*, char*));
++static void pic_error                  PARM((struct pic_info*, int));
++static void pic_file_error             PARM((struct pic_info*, int));
++static void pic_file_warning           PARM((struct pic_info*, int));
++static void pic_show_pic_info          PARM((struct pic_info*));
++static void *pic_malloc                PARM((size_t, char*));
++static void *pic_realloc               PARM((void*, size_t, char*));
++
++
++static char *pic_id = "PIC";
++
++/* Error Messages */
++static char *pic_msgs[] = {
++    NULL,
++#define PIC_OPEN 1
++    "can't open file.",
++#define PIC_CORRUPT 2
++    "file corrupted.",
++#define PIC_FORMAT 3
++    "not PIC format.",
++#define PIC_SUPPORT 4
++    "unsupported type.",
++#define PIC_COMMENT 5
++    "can't read comment.",
++#define PIC_TYPE 6
++    "bad machine type.",
++#define PIC_MODE 7
++    "bad machine-dependent mode.",
++#define PIC_NUM_COLORS 8
++    "bad number of colors.",
++#define PIC_SIZE 9
++    "bad size.",
++#define PIC_ASPECT 10
++    "bad aspect.",
++#define PIC_WRITE 11
++    "write failed.",
++};
++
++#define H4(b) (((b) >> 4) & 0x0f)
++#define L4(b) ( (b)       & 0x0f)
++
++
++/* The main routine to load a PIC file. */
++int LoadPIC(fname, pinfo)
++    char *fname;
++    PICINFO *pinfo;
++{
++    int e;
++    struct pic_info pic;
++    char buf[128];
++
++    if(DEBUG) fputs("LoadPIC:\n", stderr);
++
++    pic_init_info(&pic);
++
++    pinfo->comment = NULL;
++    if((e = setjmp(pic.jmp)) != 0){
++	/* When an error occurs, comes here. */
++	pic_cleanup_pic_info(&pic, 0);
++	pic_cleanup_pinfo(pinfo);
++	if(DEBUG) fputs("\n", stderr);
++	return 0;
++    }
++
++    pic_open_file(&pic, fname);
++    pic_check_id(&pic);
++    pic_read_comment(&pic, &pinfo->comment);
++    pic_read_header(&pic);
++    pic_expand_data(&pic);
++    pic_make_xvpic(&pic, &pinfo->pic, pinfo->r, pinfo->g, pinfo->b);
++
++    pinfo->w = pic.width;
++    if(pic.tiled256)
++	pinfo->h = pic.height * 2;
++    else
++	pinfo->h = pic.height;
++    pinfo->normw = pinfo->w;
++    pinfo->normh = pinfo->h;
++    pinfo->type = pic.cmapped ? PIC8 : PIC24;
++    pinfo->frmType = F_PIC;
++    pinfo->colType = F_FULLCOLOR;
++    strcpy(pinfo->fullInfo, "PIC");
++    switch(pic.type){
++    case 0x0:
++	strcat(pinfo->fullInfo, ", X68k");
++	break;
++    case 0x1:
++	strcat(pinfo->fullInfo, ", PC-88VA");
++	if(pic.mode & 1)
++	    strcat(pinfo->fullInfo, ", HR");
++	if(pic.mode & 2)
++	    strcat(pinfo->fullInfo, ", tiled 256");
++	break;
++    case 0x2:
++	strcat(pinfo->fullInfo, ", FM-TOWNS");
++	if(pic.mode == 0x5){
++	    strcat(pinfo->fullInfo, ", low-resolution");
++	}else{
++	    strcat(pinfo->fullInfo, ", high-resolution");
++	}
++	break;
++    case 0x3:
++	strcat(pinfo->fullInfo, ", Macintosh");
++	break;
++    case 0xf:
++	;
++    }
++    sprintf(buf, " (%ld bytes)", pic.fsize);
++    strcat(pinfo->fullInfo, buf);
++    sprintf(pinfo->shrtInfo, "%dx%d(aspect %4.2f) PIC.",
++	    pinfo->w, pinfo->h, pic.aspect);
++    if (!nopicadjust)
++	normaspect = pic.aspect;
++
++    pic_cleanup_pic_info(&pic, 0);
++    if(DEBUG) fputs("\n", stderr);
++    return 1;
++}
++
++static void pic_open_file(pi, fname)
++    struct pic_info *pi;
++    char *fname;
++{
++    if((pi->fp = fopen(fname, "rb")) == NULL)
++	pic_file_error(pi, PIC_OPEN);
++    fseek(pi->fp, (size_t) 0, SEEK_END);
++    pi->fsize = ftell(pi->fp);
++    fseek(pi->fp, (size_t) 0, SEEK_SET);
++}
++
++static void pic_check_id(pi)
++    struct pic_info *pi;
++{
++    char buf[3];
++    if(fread(buf, (size_t) 3, (size_t) 1, pi->fp) != 1)
++	pic_file_error(pi, PIC_CORRUPT);
++    if(strncmp(buf, pic_id, (size_t) 3) != 0)
++	pic_error(pi, PIC_FORMAT);
++}
++
++static void pic_read_comment(pi, comm)
++    struct pic_info *pi;
++    char **comm;
++{
++    /* The comment field is like:
++     * comment-string ^Z dummy \0 \0
++     */
++    int max = -1, i = 0;
++    int c;
++
++    while(1){
++	if((c = fgetc(pi->fp)) == EOF)
++	    pic_file_error(pi, PIC_CORRUPT);
++	if(c == '\032')			/* 0x1a, '^Z' */
++	    break;
++	if(max < i){
++	    max += 32;
++	    *comm = pic_realloc(*comm, (size_t) max + 1, "pic_read_comment#1");
++	}
++	(*comm)[i++] = c;
++    }
++
++    if(max < i){
++	max++;
++	*comm = pic_realloc(*comm, (size_t) max + 1, "pic_read_comment#2");
++    }
++    (*comm)[i] = '\0';
++
++    while((c = fgetc(pi->fp)) != '\0'){	/* skip the dummy area */
++	if(c == EOF)
++	    pic_file_error(pi, PIC_CORRUPT);
++    }
++
++    if(fgetc(pi->fp) != '\0')		/* check the reserved byte */
++	pic_error(pi, PIC_SUPPORT);
++}
++
++static void pic_read_header(pi)
++    struct pic_info *pi;
++{
++    pi->mode   = pic_read_bits(pi, 4);
++    pi->type   = pic_read_bits(pi, 4);
++    pi->cbits  = pic_read_bits(pi, 16);
++    pi->width  = pic_read_bits(pi, 16);
++    pi->height = pic_read_bits(pi, 16);
++
++    /* machine-dependent setup. */
++    switch(pi->type){
++    case 0x0:				/* X68K */
++	if(pi->mode != 0)
++	    pic_error(pi, PIC_MODE);
++	switch(pi->cbits){
++	case 4:
++	    pi->aspect = 1.0;
++	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
++	    pi->i_bits = 1;
++	    pi->cmapped = 1;
++	    break;
++
++	case 8:
++	    pi->aspect = 4.0 / 3.0;
++	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
++	    pi->i_bits = 1;
++	    pi->cmapped = 1;
++	    break;
++
++	case 15:
++	    pi->aspect = 4.0 / 3.0;
++	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
++	    pi->cached = 1;
++	    break;
++
++	case 16:
++	    pi->aspect = 4.0 / 3.0;
++	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
++	    pi->i_bits = 1;
++	    pi->cached = 1;
++	    break;
++
++	default:
++	    pic_error(pi, PIC_NUM_COLORS);
++	}
++	break;
++
++    case 0x1:				/* PC-88VA */
++	if(pi->height > 1000)
++	    pic_error(pi, PIC_SIZE);
++	switch(pi->width * 1000 + pi->height){
++	case 640400:
++	case 640204:
++	case 640200:
++	case 320408:
++	case 320400:
++	case 320200:
++	    break;
++	default:
++	    pic_error(pi, PIC_SIZE);
++	}
++	pi->aspect = 400.0 / pi->height;
++	pi->aspect *= pi->width / 640.0;
++	if(pi->mode & 0x1)		/* HR mode */
++	    pi->aspect *= 2.0;
++	if(pi->mode & 0x2){		/* tiled 256 format */
++	    if(pi->cbits != 16)
++		pic_error(pi, PIC_NUM_COLORS);
++	    pi->tiled256 = 1;
++	}
++	switch(pi->cbits){
++	case 8:
++	    pi->g_bits = pi->r_bits = 3;
++	    pi->b_bits = 2;
++	    break;
++
++	case 12:
++	    pi->g_bits = pi->r_bits = pi->b_bits = 4;
++	    pi->cached = 1;
++	    break;
++
++	case 16:
++	    pi->g_bits = 6;
++	    pi->r_bits = pi->b_bits = 5;
++	    pi->cached = 1;
++	    break;
++
++	default:
++	    pic_error(pi, PIC_NUM_COLORS);
++	}
++	break;
++
++    case 0x2:				/* FM-TOWNS */
++	if(pi->cbits != 15)
++	    pic_error(pi, PIC_NUM_COLORS);
++	switch(pi->mode){
++	case 0x5:
++	case 0xc:
++	    break;
++	default:
++	    pic_error(pi, PIC_MODE);
++	}
++	pi->g_bits = pi->r_bits = pi->b_bits = 5;
++	pi->cached = 1;
++	break;
++
++    case 0x3:				/* MAC */
++	if(pi->cbits != 15)
++	    pic_error(pi, PIC_NUM_COLORS);
++	pi->r_bits = pi->g_bits = pi->b_bits = 5;
++	pi->inv_gr = 1;
++	break;
++
++    case 0xf:				/* misc */
++	{
++	    byte ah, al;
++
++	    switch(pi->mode){
++	    case 0x0:
++		break;
++	    case 0x1:
++		pi->aspect = 4.0 / 3.0;
++		break;
++	    case 0xf:
++		break;
++	    default:
++		pic_error(pi, PIC_MODE);
++	    }
++	    pic_read_bits(pi, 16);	/* x */
++	    pic_read_bits(pi, 16);	/* y */
++	    ah = pic_read_bits(pi, 8);
++	    al = pic_read_bits(pi, 8);
++	    if(ah > 0 && al > 0)
++		pi->aspect = (float) al / (int) ah;
++	    else if(pi->mode == 0xf)
++		pic_error(pi, PIC_ASPECT);
++	    switch(pi->cbits){
++	    case 4:
++	    case 8:
++		pi->g_bits = pi->r_bits = pi->b_bits = pic_read_bits(pi, 8);
++		pi->cmapped = 1;
++		break;
++
++	    case 12:
++		pi->g_bits = pi->r_bits = pi->b_bits = 4;
++		pi->cached = 1;
++		break;
++
++	    case 15:
++		pi->g_bits = pi->r_bits = pi->b_bits = 5;
++		pi->cached = 1;
++		break;
++
++	    case 16:
++		pi->g_bits = pi->r_bits = pi->b_bits = 5;
++		pi->i_bits = 1;
++		pi->cached = 1;
++		break;
++
++	    case 24:
++		pi->g_bits = pi->r_bits = pi->b_bits = 8;
++		pi->cached = 1;
++		break;
++
++	    case 32:
++		pic_error(pi, PIC_SUPPORT);
++		break;
++
++	    default:
++		pic_error(pi, PIC_NUM_COLORS);
++	    }
++	}
++	break;
++
++    default:
++	pic_error(pi, PIC_TYPE);
++    }
++
++    pi->numcols = 1 << pi->cbits;
++
++    /* read palette data */
++    if(pi->cmapped){
++	int i;
++	pi->cmap = pic_malloc((size_t) 3 * pi->numcols, "pic_read_header#1");
++	for(i = 0; i < pi->numcols; i++){
++	    data32 c = pic_read_rgb(pi);
++	    pi->cmap[i * 3    ] = c >> 16 & 0xff;
++	    pi->cmap[i * 3 + 1] = c >>  8 & 0xff;
++	    pi->cmap[i * 3 + 2] = c       & 0xff;
++	}
++    }
++
++    /* setup color code cache */
++    if(pi->cached)
++	pic_cache_init(pi);
++
++
++    pi->data = pic_malloc(sizeof(data32) * pi->width * pi->height,   // GRR POSSIBLE OVERFLOW / FIXME
++			  "pic_read_header#2");
++    {
++	int i;
++	for(i = 0; i < pi->width * pi->height; i++)
++	    pi->data[i] = 0xffffffff;
++    }
++
++    if(DEBUG)
++	pic_show_pic_info(pi);
++}
++
++/* The main routine to expand a PIC file. */
++static void pic_expand_data(pi)
++    struct pic_info *pi;
++{
++    int cnt;
++    data32 c;
++    pi->data[0] = c = 0;
++    for(cnt = -1; cnt < pi->width * pi->height; ){
++	int len = pic_expanding_read_len(pi);
++	cnt += len;
++	if(cnt < pi->width * pi->height){
++	    int x = cnt % pi->width;
++	    int y = cnt / pi->width;
++	    data32 c = pic_expanding_read_color(pi);
++	    pic_expanding_read_chain(pi, x, y, c);
++	}
++    }
++}
++
++static int pic_expanding_read_len(pi)
++    struct pic_info *pi;
++{
++    int len;
++    byte bits;
++    for(len = 2, bits = 1; pic_read_bits(pi, 1) == 1; bits++)
++	len <<= 1;
++    return len - 1 + pic_read_bits(pi, bits);
++}
++
++static data32 pic_expanding_read_color(pi)
++    struct pic_info *pi;
++{
++    if(pi->cached){
++	byte b = pic_read_bits(pi, 1);
++	if(b){
++	    return pic_cache_get_value(pi, (int) pic_read_bits(pi, 7));
++	}else{
++	    data32 c = pic_read_color_code(pi);
++	    pic_cache_add_value(pi, c);
++	    return c;
++	}
++    }
++    return pic_read_color_code(pi);
++}
++
++static void pic_expanding_read_chain(pi, x, y, c)
++    struct pic_info *pi;
++    int x, y;
++    data32 c;
++{
++    pi->data[y * pi->width + x] = c;
++    if(pic_read_bits(pi, 1) == 1){
++	int fin = 0;
++	while(!fin){
++	    switch(pic_read_bits(pi, 2)){
++	    case 1:	/* left */
++		pi->data[(++y) * pi->width + (--x)] = c;
++		break;
++	    case 2:	/* middle */
++		pi->data[(++y) * pi->width +    x ] = c;
++		break;
++	    case 3:	/* right */
++		pi->data[(++y) * pi->width + (++x)] = c;
++		break;
++	    case 0:	/* far or nothing */
++		if(pic_read_bits(pi, 1) == 0)
++		    fin = 1;
++		else{
++		    if(pic_read_bits(pi, 1) == 0)
++			pi->data[(++y) * pi->width + (x -= 2)] = c;
++		    else
++			pi->data[(++y) * pi->width + (x += 2)] = c;
++		}
++	    }
++	}
++    }
++}
++
++/*
++ * Make a picture from the expanded data.
++ */
++static void pic_make_xvpic(pi, xp, rp, gp, bp)
++    struct pic_info *pi;
++    byte **xp, *rp, *gp, *bp;
++{
++    if(pi->cmapped){
++	if(pi->tiled256)
++	    *xp = pic_malloc((size_t) pi->width * pi->height * 2,   // GRR POSSIBLE OVERFLOW / FIXME
++			     "pic_make_xvpic#1");
++	else
++	    *xp = pic_malloc((size_t) pi->width * pi->height,   // GRR POSSIBLE OVERFLOW / FIXME
++			     "pic_make_xvpic#2");
++    }else
++	*xp = pic_malloc((size_t) pi->width * pi->height * 3,   // GRR POSSIBLE OVERFLOW / FIXME
++			 "pic_make_xvpic#3");
++
++    if(pi->cmapped){
++	int i;
++
++	for(i = 0; i < pi->numcols; i++){
++	    rp[i] = pi->cmap[i * 3    ];
++	    gp[i] = pi->cmap[i * 3 + 1];
++	    bp[i] = pi->cmap[i * 3 + 2];
++	}
++
++	if(pi->tiled256){
++	    int pic_idx = 0, dat_idx;
++	    data16 col = 0;
++	    for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){
++		if(pi->data[dat_idx] != 0xffffffff)
++		    col = pi->data[dat_idx];
++		(*xp)[pic_idx++] = col      & 0xff;
++		(*xp)[pic_idx++] = col >> 8 & 0xff;
++		dat_idx++;
++	    }
++	}else{
++	    int pic_idx = 0, dat_idx;
++	    byte col = 0;
++	    for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){
++		if(pi->data[dat_idx] != 0xffffffff)
++		    col = pi->data[dat_idx];
++		(*xp)[pic_idx++] = col;
++	    }
++	}
++    }else{
++	int pic_idx = 0, dat_idx;
++	byte r = 0, g = 0, b = 0;
++	for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){
++	    if(pi->data[dat_idx] != 0xffffffff){
++		data32 col = pi->data[dat_idx];
++		r = col >> 16 & 0xff;
++		g = col >>  8 & 0xff;
++		b = col       & 0xff;
++	    }
++	    (*xp)[pic_idx++] = r;
++	    (*xp)[pic_idx++] = g;
++	    (*xp)[pic_idx++] = b;
++	}
++    }
++}
++
++
++/* The main routine to write PIC file. */
++int WritePIC(fp, pic0, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
++	     comment)
++    FILE *fp;
++    byte *pic0;
++    int ptype, w, h;
++    byte *rmap, *gmap, *bmap;
++    int numcols, colorstyle;
++    char *comment;
++{
++    struct pic_info pic;
++    int e;
++
++    if(DEBUG) fputs("WritePIC:\n", stderr);
++
++    pic_init_info(&pic);
++    pic.fp = fp;
++    pic.width  = w;
++    pic.height = h;
++    pic.writing_grey = (colorstyle == F_GREYSCALE);
++    if(ptype != PIC24){		/* PIC8  */
++	pic.cmapped = 1;
++	pic.cached  = 0;
++	pic.cbits   = 8;
++	pic.g_bits  =
++	pic.r_bits  =
++	pic.b_bits  = 8;
++	pic.i_bits  = 0;
++	pic.numcols = numcols;
++    }else{			/* PIC24 */
++	pic.cmapped = 0;
++	pic.cached  = 1;
++	pic.cbits   = 24;
++	pic.g_bits  =
++	pic.r_bits  =
++	pic.b_bits  = 8;
++	pic.i_bits  = 0;
++	pic.numcols = 1 << 24;
++	pic_cache_init(&pic);
++    }
++
++    if((e = setjmp(pic.jmp)) != 0){
++	/* When an error occurs while writing, comes here. */
++	pic_cleanup_pic_info(&pic, 1);
++	if(DEBUG) fputs("\n", stderr);
++	return -1;
++    }
++
++    pic_write_id(&pic);
++    pic_write_comment(&pic, comment);
++    pic_write_header(&pic);
++    if(pic.cmapped)
++	pic_write_palette(&pic, rmap, gmap, bmap);
++    pic_make_sparse_data(&pic, pic0);
++    pic_write_data(&pic);
++    pic_write_bits(&pic, 0, 8);
++
++    pic_cleanup_pic_info(&pic, 1);
++    if(DEBUG) fputs("\n", stderr);
++    return 0;
++}
++
++static void pic_write_id(pi)
++    struct pic_info *pi;
++{
++    if(fwrite("PIC", (size_t) 3, (size_t) 1, pi->fp) != 1)
++	pic_file_error(pi, PIC_WRITE);
++}
++
++static void pic_write_comment(pi, comm)
++    struct pic_info *pi;
++    char *comm;
++{
++    if(comm){
++	while(*comm){
++	    int c = *comm;
++	    if(c == '\032')
++		c = ' ';
++	    if(fputc(*comm, pi->fp) == EOF)
++		pic_file_error(pi, PIC_WRITE);
++	    comm++;
++	}
++    }
++    /* write ^Z, 0, and reserved. */
++    if(fwrite("\032\0\0", (size_t)3, (size_t) 1, pi->fp) != 1)
++	pic_file_error(pi, PIC_WRITE);
++}
++
++static void pic_write_header(pi)
++    struct pic_info *pi;
++{
++    if(DEBUG) pic_show_pic_info(pi);
++    pic_write_bits(pi, (data32) 0, 4);			/* mode:  1:1 */
++    pic_write_bits(pi, (data32) 0xf, 4);		/* type: misc */
++    pic_write_bits(pi, (data32) pi->cbits, 16);		/* bits */
++    pic_write_bits(pi, (data32) pi->width, 16);		/* width */
++    pic_write_bits(pi, (data32) pi->height, 16);	/* height */
++    pic_write_bits(pi, (data32) 0xffff, 16);		/* x: unused */
++    pic_write_bits(pi, (data32) 0xffff, 16);		/* y: unused */
++    pic_write_bits(pi, (data32) 0x0101, 16);		/* real aspect */
++}
++
++static void pic_write_palette(pi, r, g, b)
++    struct pic_info *pi;
++    byte *r, *g, *b;
++{
++    int i;
++    data32 rgb = 0;
++    pic_write_bits(pi, (data32) pi->g_bits, 8);
++    for(i = 0; i < pi->numcols; i++){
++	rgb = (data32) *r++ << 16 | (data32) *g++ << 8 | (data32) *b++;
++	pic_write_rgb(pi, rgb);
++    }
++    for( ; i < 256; i++)
++	pic_write_rgb(pi, rgb);
++}
++
++static void pic_make_sparse_data(pi, dat)
++    struct pic_info *pi;
++    byte *dat;
++{
++    int i;
++    data32 c;
++
++    pi->data = pic_malloc(sizeof(data32) * pi->width * pi->height,   // GRR POSSIBLE OVERFLOW / FIXME
++			  "pic_make_sparse_data");
++
++    if(pi->cmapped){
++	c = 0;
++	for(i = 0; i < pi->width * pi->height; i++){
++	    if(c != dat[i])
++		c = pi->data[i] = dat[i];
++	    else
++		pi->data[i] = 0xffffffff;
++	}
++    }else{
++	int j = 0;
++	c = 0;
++	for(i = 0; i < pi->width * pi->height; i++){
++	    data32 r, g, b, t;
++	    r = dat[j++];
++	    g = dat[j++];
++	    b = dat[j++];
++	    t = r << 16 | g << 8 | b;
++	    if(c != t)
++		c = pi->data[i] = t;
++	    else
++		pi->data[i] = 0xffffffff;
++	}
++    }
++}
++
++static void pic_write_data(pi)
++    struct pic_info *pi;
++{
++    int i;
++    int max = pi->width * pi->height;
++    data32 c = 0;
++
++    i = -1;
++    while(i < max){
++	int j;
++	for(j = i + 1; j < max; j++){
++	    if(pi->data[j] != 0xffffffff)
++		break;
++	}
++	pic_write_length(pi, (data32) j - i);
++	i = j;
++	if(i < max){
++	    pic_write_color(pi, c = pi->data[i]);
++	    pic_write_chain(pi, i % pi->width, i / pi->width, c);
++	}
++    }
++}
++
++static void pic_write_length(pi, len)
++    struct pic_info *pi;
++    data32 len;
++{
++    int bits = 0;	/* leading 1's */
++    int max = 2;
++
++    while(len > max){
++	max = (max + 1) * 2;
++	bits++;
++    }
++    pic_write_bits(pi, 0xffffffff, bits);
++    pic_write_bits(pi, 0, 1);
++    pic_write_bits(pi, len - max / 2, bits + 1);
++}
++
++static void pic_write_color(pi, c)
++    struct pic_info *pi;
++    data32 c;
++{
++    if(pi->cached){
++	int idx = pic_cache_lookup(pi, c);
++	if(idx < 0){	/* not found */
++	    pic_write_bits(pi, 0, 1);
++	    pic_write_color_code(pi, c);
++	    pic_cache_add_value(pi, c);
++	}else{		/* found */
++	    pic_write_bits(pi, (data32) 0xffffffff, 1);
++	    pic_write_bits(pi, (data32) idx, 7);
++	}
++    }else
++	pic_write_color_code(pi, c);
++}
++
++static void pic_write_chain(pi, x, y, c)
++    struct pic_info *pi;
++    int x, y;
++    data32 c;
++{
++    int ctr = (y + 1) * pi->width + x;
++
++    if(y < pi->height - 1 &&
++       (                      pi->data[ctr    ] == c  ||
++	(x > 0             && pi->data[ctr - 1] == c) ||
++	(x < pi->width - 1 && pi->data[ctr + 1] == c) ||
++	(x > 1             && pi->data[ctr - 2] == c) ||
++	(x < pi->width - 2 && pi->data[ctr + 2] == c))){
++	pic_write_bits(pi, 1, 1);
++	while(++y < pi->height){
++	    if(pi->data[ctr] == c){				  /* center */
++		pic_write_bits(pi, 2, 2);
++		pi->data[ctr] = 0xffffffff;
++		ctr += pi->width;
++	    }else if(x > 0 && pi->data[ctr - 1] == c){		  /* left */
++		pic_write_bits(pi, 1, 2);
++		pi->data[ctr - 1] = 0xffffffff;
++		ctr += pi->width - 1;
++	    }else if(x < pi->width - 1 && pi->data[ctr + 1] == c){/* right */
++		pic_write_bits(pi, 3, 2);
++		pi->data[ctr + 1] = 0xffffffff;
++		ctr += pi->width + 1;
++	    }else if(x > 1 && pi->data[ctr - 2] == c){		  /* 2-left */
++		pic_write_bits(pi, 2, 4);
++		pi->data[ctr - 2] = 0xffffffff;
++		ctr += pi->width - 2;
++	    }else if(x < pi->width - 2 && pi->data[ctr + 2] == c){/* 2-right */
++		pic_write_bits(pi, 3, 4);
++		pi->data[ctr + 2] = 0xffffffff;
++		ctr += pi->width + 2;
++	    }else						  /* nothing */
++		break;
++	}
++	pic_write_bits(pi, 0, 3);
++    }else
++	pic_write_bits(pi, 0, 1);
++}
++
++
++/*
++ * These 4 functions read or write a color.
++ *
++ * pic_read_rgb:
++ *	reads an RGB. Each bit length is [rgb]_bits, but
++ *	it is expanded to 8bits when returned.
++ *
++ * pic_read_color_code:
++ *	reads a color code, whose length is cbits.
++ *	It is the index to the colormap or RGB itself.
++ *
++ * pic_write_rgb:
++ *	writes an RGB value.
++ *
++ * pic_write_color_code:
++ *	writes a color code.
++ */
++static data32 pic_read_rgb(pi)
++    struct pic_info *pi;
++{
++    int rb = pi->r_bits, gb = pi->g_bits, bb = pi->b_bits;
++    byte r, g, b;
++    if(pi->inv_gr){
++	r = pic_read_bits(pi, rb);
++	g = pic_read_bits(pi, gb);
++    }else{
++	g = pic_read_bits(pi, gb);
++	r = pic_read_bits(pi, rb);
++    }
++    b = pic_read_bits(pi, bb);
++    if(pi->i_bits){
++	byte i;
++	i = pic_read_bits(pi, pi->i_bits);
++	r = r << pi->i_bits | i;
++	g = g << pi->i_bits | i;
++	b = b << pi->i_bits | i;
++	rb += pi->i_bits;
++	gb += pi->i_bits;
++	bb += pi->i_bits;
++    }
++    r = pic_pad_bit(rb, r);
++    g = pic_pad_bit(gb, g);
++    b = pic_pad_bit(bb, b);
++
++    return (data32) r << 16 | (data32) g << 8 | (data32) b;
++}
++
++static data32 pic_read_color_code(pi)
++    struct pic_info *pi;
++{
++    if(pi->cmapped)
++	return pic_read_bits(pi, pi->cbits);
++    return pic_read_rgb(pi);
++}
++
++static void pic_write_rgb(pi, rgb)
++    struct pic_info *pi;
++    data32 rgb;
++{
++    byte r = rgb >> 16;
++    byte g = rgb >> 8;
++    byte b = rgb;
++    if(pi->writing_grey)
++	r = g = b = MONO(r, g, b);
++    pic_write_bits(pi, g, pi->g_bits);
++    pic_write_bits(pi, r, pi->r_bits);
++    pic_write_bits(pi, b, pi->b_bits);
++}
++
++static void pic_write_color_code(pi, code)
++    struct pic_info *pi;
++    data32 code;
++{
++    if(pi->cmapped){
++	pic_write_bits(pi, code, pi->cbits);
++    }else{
++	pic_write_rgb(pi, code);
++    }
++}
++
++
++/*
++ * These pic_cache_* functions are an implementation of the color cache.
++ *
++ * pic_cache_init:
++ *	initializes the cache.
++ *
++ * pic_cache_get_value:
++ *	gets a color indexed by the argument `idx'.
++ *	It updates the `most recently used' time.
++ *
++ * pic_cache_add_value:
++ *	adds a color to the top of the cache list.
++ */
++static void pic_cache_init(pi)
++    struct pic_info *pi;
++{
++    int i;
++    pi->cache.node = pic_malloc(sizeof(struct cachenode_t) * 128,
++				"pic_cache_init");
++    for(i = 0; i < 128; i++){
++	pi->cache.node[i].newer = i + 1;
++	pi->cache.node[i].older = i - 1;
++	pi->cache.node[i].dat = 0;
++    }
++    pi->cache.node[  0].older = 127;
++    pi->cache.node[127].newer = 0;
++    pi->cache.newest = 0;
++}
++
++static data32 pic_cache_get_value(pi, idx)
++    struct pic_info *pi;
++    int idx;
++{
++    struct cachenode_t *p = pi->cache.node;
++    int n = pi->cache.newest;
++    if(n != idx){
++	p[p[idx].newer].older = p[idx].older;
++	p[p[idx].older].newer = p[idx].newer;
++
++	p[p[n].newer].older = idx;
++	p[idx].newer = p[n].newer;
++	p[n].newer = idx;
++	p[idx].older = n;
++
++	pi->cache.newest = idx;
++    }
++    return pi->cache.node[idx].dat;
++}
++
++static void pic_cache_add_value(pi, dat)
++    struct pic_info *pi;
++    data32 dat;
++{
++    pi->cache.newest = pi->cache.node[pi->cache.newest].newer;
++    pi->cache.node[pi->cache.newest].dat = dat;
++}
++
++static int pic_cache_lookup(pi, dat)
++    struct pic_info *pi;
++    data32 dat;
++{
++    int i;
++    for(i = 0; i < 128; i++){
++	if(pi->cache.node[i].dat == dat){
++	    pic_cache_get_value(pi, i);
++	    return i;
++	}
++    }
++    return -1;
++}
++
++
++/*
++ * These pic_{read,write}_bits functions access the bit stream.
++ * pic_read_bits:
++ *	reads the specified bits from the file.
++ *
++ * pic_write_bits:
++ *	writes the specified bits to the file.
++ */
++static data32 pic_read_bits(pi, bits)
++    struct pic_info *pi;
++    int bits;
++{
++    data32 r = 0;
++
++    while(bits > 0){
++	while(pi->bs.rest > 0 && bits > 0){
++	    r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0);
++	    pi->bs.cur <<= 1;
++	    pi->bs.rest--;
++	    bits--;
++	}
++	if(bits > 0){
++	    int c;
++	    if((c = fgetc(pi->fp)) == EOF){
++		pic_file_warning(pi, PIC_CORRUPT);
++		c = 0;
++	    }
++	    pi->bs.cur  = c;
++	    pi->bs.rest = 8;
++	}
++    }
++
++    return r;
++}
++
++static void pic_write_bits(pi, dat, bits)
++    struct pic_info *pi;
++    data32 dat;
++    int bits;
++{
++    data32 dat_mask = 1 << (bits - 1);
++    while(bits > 0){
++	while(pi->bs.rest < 8 && bits > 0){
++	    pi->bs.cur <<= 1;
++	    if(dat & dat_mask)
++		pi->bs.cur |= 1;
++	    pi->bs.rest++;
++	    bits--;
++	    dat_mask >>= 1;
++	}
++	if(pi->bs.rest >= 8){
++	    if(fputc((int)pi->bs.cur, pi->fp) == EOF)
++		pic_error(pi, PIC_WRITE);
++	    pi->bs.cur  = 0;
++	    pi->bs.rest = 0;
++	}
++    }
++}
++
++
++/*
++ * This function extends sub-8-bit data to 8-bit data using bit-replication.
++ */
++static byte pic_pad_bit(bits, dat)
++    int bits;
++    data32 dat;
++{
++    switch(bits){
++    case 1:
++	if(dat & 1)
++	    dat = 0xff;
++	else
++	    dat = 0;
++	break;
++    case 2:
++	dat = dat << 6 | dat << 4 | dat << 2 | dat;
++	break;
++    case 3:
++	dat = dat << 5 | dat << 2 | dat >> 1;
++	break;
++    case 4:
++	dat = dat << 4 | dat;
++	break;
++    case 5:
++	dat = dat << 3 | dat >> 2;
++	break;
++    case 6:
++	dat = dat << 2 | dat >> 4;
++	break;
++    case 7:
++	dat = dat << 1 | dat >> 6;
++    }
++
++    return dat;
++}
++
++/*
++ * These functions initialize or clean up structures.
++ * pic_init_info:
++ *	initializes a pic_info structure.
++ * pic_cleanup_pic_info:
++ *	cleans up a pic_info structure.
++ * pic_cleanup_pinfo:
++ *	cleans up a PICINFO structure.
++ */
++static void pic_init_info(pi)
++    struct pic_info *pi;
++{
++    pi->fp = NULL;
++    pi->bs.rest = 0;
++    pi->bs.cur = '\0';
++    pi->type = pi->mode = 0;
++    pi->width = pi->height = 0;
++    pi->aspect = 1.0;
++    pi->cbits = 0;
++    pi->cmapped = pi->cached = 0;
++    pi->cache.node = NULL;
++    pi->cmap = NULL;
++    pi->g_bits = pi->r_bits = pi->b_bits = pi->i_bits = 0;
++    pi->inv_gr = 0;
++    pi->tiled256 = 0;
++    pi->numcols = 0;
++    pi->writing_grey = 0;
++}
++
++static void pic_cleanup_pic_info(pi, writing)
++    struct pic_info *pi;
++    int writing;
++{
++    if(!writing && pi->fp)
++	fclose(pi->fp);
++    if(pi->cmap)
++	free(pi->cmap);
++    if(pi->cache.node)
++	free(pi->cache.node);
++    if(pi->data)
++	free(pi->data);
++    pi->fp = NULL;
++    pi->cmap = NULL;
++    pi->cache.node = NULL;
++    pi->data = NULL;
++}
++
++static void pic_cleanup_pinfo(pinfo)
++    PICINFO *pinfo;
++{
++    if(pinfo->pic){
++	free(pinfo->pic);
++	pinfo->pic = NULL;
++    }
++    if(pinfo->comment){
++	free(pinfo->comment);
++	pinfo->comment = NULL;
++    }
++}
++
++/*
++ * Error Handlers.
++ * pic_memory_error:
++ *	shows an error message and terminates.
++ * pic_error:
++ *	shows a non-file error message and jumps to the entry for errors.
++ * pic_file_error:
++ *	shows a file error message and jumps to the entry for errors.
++ * pic_file_warning:
++ *	shows a file warning message.
++ */
++static void pic_memory_error(scm, fn)
++    char *scm, *fn;
++{
++    char buf[128];
++    sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn);
++    FatalError(buf);
++}
++
++static void pic_error(pi, mn)
++    struct pic_info *pi;
++    int mn;
++{
++    SetISTR(ISTR_WARNING, "%s", pic_msgs[mn]);
++    longjmp(pi->jmp, 1);
++}
++
++static void pic_file_error(pi, mn)
++    struct pic_info *pi;
++    int mn;
++{
++    if(feof(pi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", pic_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", pic_msgs[mn], ERRSTR(errno));
++    longjmp(pi->jmp, 1);
++}
++
++static void pic_file_warning(pi, mn)
++    struct pic_info *pi;
++    int mn;
++{
++    if(feof(pi->fp))
++	SetISTR(ISTR_WARNING, "%s (end of file)", pic_msgs[mn]);
++    else
++	SetISTR(ISTR_WARNING, "%s (%s)", pic_msgs[mn], ERRSTR(errno));
++}
++
++static void pic_show_pic_info(pi)
++    struct pic_info *pi;
++{
++    fprintf(stderr, "  file size: %ld.\n", pi->fsize);
++
++    fputs("  machine: ", stderr);
++    switch(pi->type){
++    case 0x0:
++	fputs("X68k", stderr);
++	break;
++    case 0x1:
++	fputs("PC-88VA", stderr);
++	if(pi->mode & 1)
++	    fputs(",HR", stderr);
++	if(pi->mode & 2)
++	    fputs(",tiled256", stderr);
++	break;
++    case 0x2:
++	fprintf(stderr,
++		"FM-TOWNS,%s-resolution", pi->mode == 5 ? "low" : "high");
++	break;
++    case 0x3:
++	fputs("Macintosh", stderr);
++	break;
++    case 0xf:
++	fputs("misc", stderr);
++    }
++    fputs("\n", stderr);
++
++    fprintf(stderr, "  image size: %dx%d\n", pi->width, pi->height);
++    fprintf(stderr, "  aspect: %f\n", pi->aspect);
++    fprintf(stderr, "  cache: %s\n", pi->cached ? "on" : "off");
++    fprintf(stderr, "  colormap: %s\n", pi->cmapped ? "on" : "off");
++    fprintf(stderr, "  number of color bits: %d\n", pi->cbits);
++    fprintf(stderr, "  number of RGB bits: R%d,G%d,B%d,I%d\n",
++	   pi->r_bits, pi->g_bits, pi->b_bits, pi->i_bits);
++    fprintf(stderr, "  inverted G&R: %s\n", pi->inv_gr ? "true" : "false");
++    fprintf(stderr, "  number of colors: %d\n", pi->numcols);
++}
++
++/* Memory related routines. */
++static void *pic_malloc(n, fn)
++    size_t n;
++    char *fn;
++{
++    void *r = (void *) malloc(n);
++    if(r == NULL)
++	pic_memory_error("malloc", fn);
++    return r;
++}
++
++static void *pic_realloc(p, n, fn)
++    void *p;
++    size_t n;
++    char *fn;
++{
++    void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n);
++    if(r == NULL)
++	pic_memory_error("realloc", fn);
++    return r;
++}
++#endif /* HAVE_PIC */
+diff -Naru xv-3.10a/xvpng.c xv-3.10a.jumbo/xvpng.c
+--- xv-3.10a/xvpng.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvpng.c	2007-05-14 02:53:28.000000000 +0200
+@@ -0,0 +1,1173 @@
++/*
++ * xvpng.c - load and write routines for 'PNG' format pictures
++ *
++ * callable functions
++ *
++ *    CreatePNGW()
++ *    PNGDialog(vis)
++ *    PNGCheckEvent(xev)
++ *    PNGSaveParams(fname, col)
++ *    LoadPNG(fname, pinfo)
++ *    VersionInfoPNG()
++ */
++
++/*#include "copyright.h"*/
++
++/* (c) 1995 by Alexander Lehmann <lehmann at mathematik.th-darmstadt.de>
++ *   This file is a suplement to xv and is supplied under the same copying
++ *   conditions (except the shareware part).
++ *   The copyright will be passed on to JB at some future point if he
++ *   so desires.
++ *
++ * Modified by Andreas Dilger <adilger at enel.ucalgary.ca> to fix
++ *   error handling for bad PNGs, add dialogs for interlacing and
++ *   compression selection, and upgrade to libpng-0.89.
++ *
++ * Modified by Greg Roelofs, TenThumbs and others to fix bugs and add
++ *   features.  See README.jumbo for details.
++ */
++
++#include "xv.h"
++
++#ifdef HAVE_PNG
++
++#include "png.h"
++
++/*** Stuff for PNG Dialog box ***/
++#define PWIDE 318
++#define PHIGH 215
++
++#define DISPLAY_GAMMA 2.20  /* default display gamma */
++#define COMPRESSION   6     /* default zlib compression level, not max
++                               (Z_BEST_COMPRESSION) */
++
++#define HAVE_tRNS  (info_ptr->valid & PNG_INFO_tRNS)
++
++#define DWIDE    86
++#define DHIGH    104
++#define PFX      (PWIDE-93)
++#define PFY      44
++#define PFH      20
++
++#define P_BOK    0
++#define P_BCANC  1
++#define P_NBUTTS 2
++
++#define BUTTH    24
++
++#define LF       10   /* a.k.a. '\n' on ASCII machines */
++#define CR       13   /* a.k.a. '\r' on ASCII machines */
++
++/*** local functions ***/
++static    void drawPD         PARM((int, int, int, int));
++static    void clickPD        PARM((int, int));
++static    void doCmd          PARM((int));
++static    void writePNG       PARM((void));
++static    int  WritePNG       PARM((FILE *, byte *, int, int, int,
++                                    byte *, byte *, byte *, int));
++
++static    void png_xv_error   PARM((png_structp png_ptr,
++                                    png_const_charp message));
++static    void png_xv_warning PARM((png_structp png_ptr,
++                                    png_const_charp message));
++
++/*** local variables ***/
++static char *filename;
++static const char *fbasename;
++static int   colorType;
++static int   read_anything;
++static double Display_Gamma = DISPLAY_GAMMA;
++
++static DIAL  cDial, gDial;
++static BUTT  pbut[P_NBUTTS];
++static CBUTT interCB;
++static CBUTT FdefCB, FnoneCB, FsubCB, FupCB, FavgCB, FPaethCB;
++
++
++#ifdef PNG_NO_STDIO
++/* NOTE:  Some sites configure their version of the PNG Library without
++ *        Standard I/O Library interfaces in order to avoid unnecessary inter-
++ * library dependencies at link time for applications that don't need Standard
++ * I/O.  If your site is one of these, the following skeletal stubs, copied
++ * from libpng code, should be enough for this module.  --Scott B. Marovich,
++ * Hewlett-Packard Laboratories, March 2001.
++ */
++static void
++png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
++{
++
++   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
++    * instead of an int, which is what fread() actually returns.
++    */
++   if (fread(data,1,length,(FILE *)png_ptr->io_ptr) != length)
++     png_error(png_ptr, "Read Error");
++}
++
++static void
++png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
++{
++   if (fwrite(data, 1, length, (FILE *)png_ptr->io_ptr) != length)
++     png_error(png_ptr, "Write Error");
++}
++#endif /* PNG_NO_STDIO */
++
++
++/**************************************************************************/
++/* PNG SAVE DIALOG ROUTINES ***********************************************/
++/**************************************************************************/
++
++
++/*******************************************/
++void CreatePNGW()
++{
++  pngW = CreateWindow("xv png", "XVPNG", NULL,
++                      PWIDE, PHIGH, infofg, infobg, 0);
++  if (!pngW) FatalError("can't create PNG window!");
++
++  XSelectInput(theDisp, pngW, ExposureMask | ButtonPressMask | KeyPressMask);
++
++  DCreate(&cDial, pngW,  12, 25, DWIDE, DHIGH, (double)Z_NO_COMPRESSION,
++          (double)Z_BEST_COMPRESSION, COMPRESSION, 1.0, 3.0,
++          infofg, infobg, hicol, locol, "Compression", NULL);
++
++  DCreate(&gDial, pngW, DWIDE+27, 25, DWIDE, DHIGH, 1.0, 3.5,DISPLAY_GAMMA,0.01,0.2,
++          infofg, infobg, hicol, locol, "Disp. Gamma", NULL);
++
++  CBCreate(&interCB, pngW,  DWIDE+30, DHIGH+3*LINEHIGH+2, "interlace",
++           infofg, infobg, hicol, locol);
++
++  CBCreate(&FdefCB,   pngW, PFX, PFY, "Default",
++           infofg, infobg, hicol, locol);
++  FdefCB.val = 1;
++
++  CBCreate(&FnoneCB,  pngW, PFX, FdefCB.y + PFH + 4, "none",
++           infofg, infobg, hicol, locol);
++  CBCreate(&FsubCB,   pngW, PFX, FnoneCB.y + PFH, "sub",
++           infofg, infobg, hicol, locol);
++  CBCreate(&FupCB,    pngW, PFX, FsubCB.y  + PFH, "up",
++           infofg, infobg, hicol, locol);
++  CBCreate(&FavgCB,   pngW, PFX, FupCB.y   + PFH, "average",
++           infofg, infobg, hicol, locol);
++  CBCreate(&FPaethCB, pngW, PFX, FavgCB.y  + PFH, "Paeth",
++           infofg, infobg, hicol, locol);
++
++  FnoneCB.val = FsubCB.val = FupCB.val = FavgCB.val = FPaethCB.val = 1;
++  CBSetActive(&FnoneCB, !FdefCB.val);
++  CBSetActive(&FsubCB, !FdefCB.val);
++  CBSetActive(&FupCB, !FdefCB.val);
++  CBSetActive(&FavgCB, !FdefCB.val);
++  CBSetActive(&FPaethCB, !FdefCB.val);
++
++  BTCreate(&pbut[P_BOK], pngW, PWIDE-180-1, PHIGH-10-BUTTH-1, 80, BUTTH,
++          "Ok", infofg, infobg, hicol, locol);
++  BTCreate(&pbut[P_BCANC], pngW, PWIDE-90-1, PHIGH-10-BUTTH-1, 80, BUTTH,
++          "Cancel", infofg, infobg, hicol, locol);
++
++  XMapSubwindows(theDisp, pngW);
++}
++
++
++/*******************************************/
++void PNGDialog(vis)
++     int vis;
++{
++  if (vis) {
++    CenterMapWindow(pngW, pbut[P_BOK].x + (int) pbut[P_BOK].w/2,
++                          pbut[P_BOK].y + (int) pbut[P_BOK].h/2,
++                    PWIDE, PHIGH);
++  }
++  else XUnmapWindow(theDisp, pngW);
++  pngUp = vis;
++}
++
++
++/*******************************************/
++int PNGCheckEvent(xev)
++     XEvent *xev;
++{
++  /* check event to see if it's for one of our subwindows.  If it is,
++     deal accordingly, and return '1'.  Otherwise, return '0' */
++
++  int rv;
++  rv = 1;
++
++  if (!pngUp) return 0;
++
++  if (xev->type == Expose) {
++    int x,y,w,h;
++    XExposeEvent *e = (XExposeEvent *) xev;
++    x = e->x; y = e->y; w = e->width; h = e->height;
++
++    /* throw away excess expose events for 'dumb' windows */
++    if (e->count > 0 && (e->window == cDial.win)) {}
++
++    else if (e->window == pngW)        drawPD(x, y, w, h);
++    else if (e->window == cDial.win)   DRedraw(&cDial);
++    else if (e->window == gDial.win)   DRedraw(&gDial);
++    else rv = 0;
++  }
++
++  else if (xev->type == ButtonPress) {
++    XButtonEvent *e = (XButtonEvent *) xev;
++    int x,y;
++    x = e->x;  y = e->y;
++
++    if (e->button == Button1) {
++      if      (e->window == pngW)       clickPD(x,y);
++      else if (e->window == cDial.win)  DTrack(&cDial,x,y);
++      else if (e->window == gDial.win)  DTrack(&gDial,x,y);
++      else rv = 0;
++    }  /* button1 */
++    else rv = 0;
++  }  /* button press */
++
++  else if (xev->type == KeyPress) {
++    XKeyEvent *e = (XKeyEvent *) xev;
++    char buf[128];  KeySym ks;
++    int stlen;
++
++    stlen = XLookupString(e,buf,128,&ks,(XComposeStatus *) NULL);
++    buf[stlen] = '\0';
++
++    RemapKeyCheck(ks, buf, &stlen);
++
++    if (e->window == pngW) {
++      if (stlen) {
++        if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
++          FakeButtonPress(&pbut[P_BOK]);
++        }
++        else if (buf[0] == '\033') {            /* ESC */
++          FakeButtonPress(&pbut[P_BCANC]);
++        }
++      }
++    }
++    else rv = 0;
++  }
++  else rv = 0;
++
++  if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
++    XBell(theDisp, 50);
++    rv = 1;   /* eat it */
++  }
++
++  return rv;
++}
++
++
++/*******************************************/
++void PNGSaveParams(fname, col)
++     char *fname;
++     int col;
++{
++  filename = fname;
++  colorType = col;
++}
++
++
++/*******************************************/
++static void drawPD(x, y, w, h)
++     int x, y, w, h;
++{
++  const char *title   = "Save PNG file...";
++
++  char ctitle1[20];
++  const char *ctitle2 = "Useful range";
++  const char *ctitle3 = "is 2 - 7.";
++  const char *ctitle4 = "Uncompressed = 0";
++
++  const char *ftitle  = "Row Filters:";
++
++  char gtitle[20];
++
++  int i;
++  XRectangle xr;
++
++  xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
++  XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
++
++  XSetForeground(theDisp, theGC, infofg);
++  XSetBackground(theDisp, theGC, infobg);
++
++  for (i=0; i<P_NBUTTS; i++) BTRedraw(&pbut[i]);
++
++  DrawString(pngW,       15,  6+ASCENT,                          title);
++
++  sprintf(ctitle1, "Default = %d", COMPRESSION);
++  DrawString(pngW,       18,  6+DHIGH+cDial.y+ASCENT,            ctitle1);
++  DrawString(pngW,       17,  6+DHIGH+cDial.y+ASCENT+LINEHIGH,   ctitle2);
++  DrawString(pngW,       17,  6+DHIGH+cDial.y+ASCENT+2*LINEHIGH, ctitle3);
++  DrawString(pngW,       17,  6+DHIGH+cDial.y+ASCENT+3*LINEHIGH, ctitle4);
++
++  sprintf(gtitle, "Default = %g", DISPLAY_GAMMA);
++  DrawString(pngW, DWIDE+30,  6+DHIGH+gDial.y+ASCENT,            gtitle);
++
++  ULineString(pngW, FdefCB.x, FdefCB.y-3-DESCENT, ftitle);
++  XDrawRectangle(theDisp, pngW, theGC, FdefCB.x-11, FdefCB.y-LINEHIGH-3,
++                                       93, 8*LINEHIGH+15);
++  CBRedraw(&FdefCB);
++  XDrawLine(theDisp, pngW, theGC, FdefCB.x-11, FdefCB.y+LINEHIGH+4,
++                                  FdefCB.x+82, FdefCB.y+LINEHIGH+4);
++
++  CBRedraw(&FnoneCB);
++  CBRedraw(&FupCB);
++  CBRedraw(&FsubCB);
++  CBRedraw(&FavgCB);
++  CBRedraw(&FPaethCB);
++
++  CBRedraw(&interCB);
++
++  XSetClipMask(theDisp, theGC, None);
++}
++
++
++/*******************************************/
++static void clickPD(x,y)
++     int x,y;
++{
++  int i;
++  BUTT *bp;
++
++  /* check BUTTs */
++
++  for (i=0; i<P_NBUTTS; i++) {
++    bp = &pbut[i];
++    if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
++  }
++
++  if (i<P_NBUTTS) {  /* found one */
++    if (BTTrack(bp)) doCmd(i);
++  }
++
++  /* check CBUTTs */
++
++  else if (CBClick(&FdefCB,x,y)) {
++    int oldval = FdefCB.val;
++
++    CBTrack(&FdefCB);
++
++    if (oldval != FdefCB.val)
++    {
++      CBSetActive(&FnoneCB, !FdefCB.val);
++      CBSetActive(&FsubCB, !FdefCB.val);
++      CBSetActive(&FupCB, !FdefCB.val);
++      CBSetActive(&FavgCB, !FdefCB.val);
++      CBSetActive(&FPaethCB, !FdefCB.val);
++
++      CBRedraw(&FnoneCB);
++      CBRedraw(&FupCB);
++      CBRedraw(&FsubCB);
++      CBRedraw(&FavgCB);
++      CBRedraw(&FPaethCB);
++    }
++  }
++  else if (CBClick(&FnoneCB,x,y))  CBTrack(&FnoneCB);
++  else if (CBClick(&FsubCB,x,y))   CBTrack(&FsubCB);
++  else if (CBClick(&FupCB,x,y))    CBTrack(&FupCB);
++  else if (CBClick(&FavgCB,x,y))   CBTrack(&FavgCB);
++  else if (CBClick(&FPaethCB,x,y)) CBTrack(&FPaethCB);
++  else if (CBClick(&interCB,x,y))  CBTrack(&interCB);
++}
++
++
++/*******************************************/
++static void doCmd(cmd)
++     int cmd;
++{
++  switch (cmd) {
++    case P_BOK:
++      {
++        char *fullname;
++
++        writePNG();
++        PNGDialog(0);
++
++        fullname = GetDirFullName();
++        if (!ISPIPE(fullname[0])) {
++          XVCreatedFile(fullname);
++          StickInCtrlList(0);
++        }
++      }
++      break;
++
++    case P_BCANC:
++      PNGDialog(0);
++      break;
++
++    default:
++      break;
++  }
++}
++
++
++/*******************************************/
++static void writePNG()
++{
++  FILE       *fp;
++  int         w, h, nc, rv, ptype, pfree;
++  byte       *inpix, *rmap, *gmap, *bmap;
++
++  fp = OpenOutFile(filename);
++  if (!fp) return;
++
++  fbasename = BaseName(filename);
++
++  WaitCursor();
++  inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap);
++
++  rv = WritePNG(fp, inpix, ptype, w, h, rmap, gmap, bmap, nc);
++
++  SetCursors(-1);
++
++  if (CloseOutFile(fp, filename, rv) == 0) DirBox(0);
++
++  if (pfree) free(inpix);
++}
++
++
++/*******************************************/
++int WritePNG(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols)
++     FILE *fp;
++     byte *pic;
++     int   ptype, w, h;
++     byte *rmap, *gmap, *bmap;
++     int   numcols;
++     /* FIXME?  what's diff between picComments and WriteGIF's comment arg? */
++{
++  png_struct *png_ptr;
++  png_info   *info_ptr;
++  png_color   palette[256];
++  png_textp   text;
++  byte        r1[256], g1[256], b1[256];  /* storage for deduped palette */
++  byte        pc2nc[256];  /* for duplicated-color remapping (1st level) */
++  byte        remap[256];  /* for bw/grayscale remapping (2nd level) */
++  int         i, j, numuniqcols=0, filter, linesize, pass;
++  byte       *p, *png_line;
++  char        software[256];
++  char       *savecmnt;
++
++  if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
++       png_xv_error, png_xv_warning)) == NULL) {
++    sprintf(software, "png_create_write_struct() failure in WritePNG");
++    FatalError(software);
++  }
++
++  if ((info_ptr = png_create_info_struct(png_ptr)) == NULL)
++  {
++    png_destroy_write_struct(&png_ptr, &info_ptr);
++    sprintf(software, "png_create_info_struct() failure in WritePNG");
++    FatalError(software);
++  }
++
++  if (setjmp(png_ptr->jmpbuf)) {
++    png_destroy_write_struct(&png_ptr, &info_ptr);
++    return -1;
++  }
++
++#ifdef PNG_NO_STDIO
++  png_set_write_fn(png_ptr, fp, png_default_write_data, NULL);
++  png_set_error_fn(png_ptr, NULL, png_xv_error, png_xv_warning);
++#else
++  png_init_io(png_ptr, fp);
++#endif
++
++  png_set_compression_level(png_ptr, (int)cDial.val);
++
++  /* Don't bother filtering if we aren't compressing the image */
++  if (FdefCB.val)
++  {
++    if ((int)cDial.val == 0)
++      png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
++  }
++  else
++  {
++    filter  = FnoneCB.val  ? PNG_FILTER_NONE  : 0;
++    filter |= FsubCB.val   ? PNG_FILTER_SUB   : 0;
++    filter |= FupCB.val    ? PNG_FILTER_UP    : 0;
++    filter |= FavgCB.val   ? PNG_FILTER_AVG   : 0;
++    filter |= FPaethCB.val ? PNG_FILTER_PAETH : 0;
++
++    png_set_filter(png_ptr, 0, filter);
++  }
++
++  info_ptr->width = w;
++  info_ptr->height = h;
++  if (w <= 0 || h <= 0) {
++    SetISTR(ISTR_WARNING, "%s:  image dimensions out of range (%dx%d)",
++      fbasename, w, h);
++    png_destroy_write_struct(&png_ptr, &info_ptr);
++    return -1;
++  }
++
++  info_ptr->interlace_type = interCB.val ? 1 : 0;
++
++  linesize = 0;   /* quiet a compiler warning */
++
++
++  /* GRR 20070331:  remap palette to eliminate duplicated colors (as in
++   *   xvgifwr.c) */
++  if (ptype == PIC8) {
++    for (i=0; i<256; ++i) {
++      pc2nc[i] = r1[i] = g1[i] = b1[i] = 0;
++    }
++
++    /* compute number of unique colors */
++    numuniqcols = 0;
++
++    for (i=0; i<numcols; ++i) {
++      /* see if color #i is already used */
++      for (j=0; j<i; ++j) {
++        if (rmap[i] == rmap[j]  &&  gmap[i] == gmap[j]  &&  bmap[i] == bmap[j])
++          break;
++      }
++
++      if (j==i) {  /* wasn't found */
++        pc2nc[i] = numuniqcols;
++        r1[numuniqcols] = rmap[i];  /* i.e., r1[pc2nc[i]] == rmap[i] */
++        g1[numuniqcols] = gmap[i];
++        b1[numuniqcols] = bmap[i];
++        ++numuniqcols;
++      }
++      else pc2nc[i] = pc2nc[j];
++    }
++  }
++
++
++  /* Appendix G.2 of user manual claims colorType will never be F_REDUCED... */
++  if (colorType == F_FULLCOLOR || colorType == F_REDUCED) {
++    if (ptype == PIC24) {
++      linesize = 3*w;
++      if (linesize/3 < w) {
++        SetISTR(ISTR_WARNING, "%s:  image dimensions too large (%dx%d)",
++          fbasename, w, h);
++        png_destroy_write_struct(&png_ptr, &info_ptr);
++        return -1;
++      }
++      info_ptr->color_type = PNG_COLOR_TYPE_RGB;
++      info_ptr->bit_depth = 8;
++    } else /* ptype == PIC8 */ {
++      linesize = w;
++      info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
++      if (numuniqcols <= 2)
++        info_ptr->bit_depth = 1;
++      else
++      if (numuniqcols <= 4)
++        info_ptr->bit_depth = 2;
++      else
++      if (numuniqcols <= 16)
++        info_ptr->bit_depth = 4;
++      else
++        info_ptr->bit_depth = 8;
++
++      for (i = 0; i < numuniqcols; i++) {
++        palette[i].red   = r1[i];
++        palette[i].green = g1[i];
++        palette[i].blue  = b1[i];
++      }
++      info_ptr->num_palette = numuniqcols;
++      info_ptr->palette = palette;
++      info_ptr->valid |= PNG_INFO_PLTE;
++    }
++  }
++
++  else if (colorType == F_GREYSCALE || colorType == F_BWDITHER) {
++    info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
++    if (colorType == F_BWDITHER) {
++      /* shouldn't happen */
++      if (ptype == PIC24) FatalError("PIC24 and B/W Stipple in WritePNG()");
++
++      info_ptr->bit_depth = 1;
++      if (MONO(r1[0], g1[0], b1[0]) > MONO(r1[1], g1[1], b1[1])) {
++        remap[0] = 1;
++        remap[1] = 0;
++      }
++      else {
++        remap[0] = 0;
++        remap[1] = 1;
++      }
++      linesize = w;
++    }
++    else /* F_GREYSCALE */ {
++      if (ptype == PIC24) {
++        linesize = 3*w;
++        if (linesize/3 < w) {
++          SetISTR(ISTR_WARNING, "%s:  image dimensions too large (%dx%d)",
++            fbasename, w, h);
++          png_destroy_write_struct(&png_ptr, &info_ptr);
++          return -1;
++        }
++        info_ptr->bit_depth = 8;
++      }
++      else /* ptype == PIC8 */ {
++        int low_precision;
++
++        linesize = w;
++
++        /* NOTE:  currently remap[] is the _secondary_ remapping of "palette"
++         *   colors; its values are the final color/grayscale values, and,
++         *   like r1/g1/b1[], it is _indexed_ by pc2nc[] (which is why its
++         *   values come from r1/g1/b1[] and not from rmap/gmap/bmap[]).
++         *
++         * FIXME (probably):  MONO() will create new duplicates; ideally should
++         *   do extra round of dup-detection (and preferably collapse all
++         *   remapping levels into single LUT).  This stuff is a tad confusing.
++         */
++        for (i = 0; i < numuniqcols; i++)
++          remap[i] = MONO(r1[i], g1[i], b1[i]);
++
++        for (; i < 256; i++)
++          remap[i]=0;  /* shouldn't be necessary, but... */
++
++        info_ptr->bit_depth = 8;
++
++        /* Note that this fails most of the time because of gamma */
++           /* (and that would be a bug:  GRR FIXME) */
++        /* try to adjust to 4-bit precision grayscale */
++
++        low_precision=1;
++
++        for (i = 0; i < numuniqcols; i++) {
++          if ((remap[i] & 0x0f) * 0x11 != remap[i]) {
++            low_precision = 0;
++            break;
++          }
++        }
++
++        if (low_precision) {
++          for (i = 0; i < numuniqcols; i++) {
++            remap[i] &= 0xf;
++          }
++          info_ptr->bit_depth = 4;
++
++          /* try to adjust to 2-bit precision grayscale */
++
++          for (i = 0; i < numuniqcols; i++) {
++            if ((remap[i] & 0x03) * 0x05 != remap[i]) {
++              low_precision = 0;
++              break;
++            }
++          }
++        }
++
++        if (low_precision) {
++          for (i = 0; i < numuniqcols; i++) {
++            remap[i] &= 3;
++          }
++          info_ptr->bit_depth = 2;
++
++          /* try to adjust to 1-bit precision grayscale */
++
++          for (i = 0; i < numuniqcols; i++) {
++            if ((remap[i] & 0x01) * 0x03 != remap[i]) {
++              low_precision = 0;
++              break;
++            }
++          }
++        }
++
++        if (low_precision) {
++          for (i = 0; i < numuniqcols; i++) {
++            remap[i] &= 1;
++          }
++          info_ptr->bit_depth = 1;
++        }
++      }
++    }
++  }
++
++  else
++    png_error(png_ptr, "Unknown colorstyle in WritePNG");
++
++  if ((text = (png_textp)malloc(sizeof(png_text)))) {
++    sprintf(software, "XV %s", REVDATE);
++
++    text->compression = -1;
++    text->key = "Software";
++    text->text = software;
++    text->text_length = strlen(text->text);
++
++    info_ptr->max_text = 1;
++    info_ptr->num_text = 1;
++    info_ptr->text = text;
++  }
++
++  Display_Gamma = gDial.val;  /* Save the current gamma for loading */
++
++// GRR FIXME:  add .Xdefaults option to omit writing gamma (size, cumulative errors when editing)--alternatively, modify save box to include "omit" checkbox
++  info_ptr->gamma = 1.0/gDial.val;
++  info_ptr->valid |= PNG_INFO_gAMA;
++
++  png_write_info(png_ptr, info_ptr);
++
++  if (info_ptr->bit_depth < 8)
++    png_set_packing(png_ptr);
++
++  pass=png_set_interlace_handling(png_ptr);
++
++  if ((png_line = malloc(linesize)) == NULL)
++    png_error(png_ptr, "cannot allocate temp image line");
++    /* FIXME:  should be FatalError() */
++
++  for (i = 0; i < pass; ++i) {
++    int j;
++    p = pic;
++    for (j = 0; j < h; ++j) {
++      if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
++        int k;
++        for (k = 0; k < w; ++k)
++          png_line[k] = ptype==PIC24 ? MONO(p[k*3], p[k*3+1], p[k*3+2]) :
++                                       remap[pc2nc[p[k]]];
++        png_write_row(png_ptr, png_line);
++      } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
++        int k;
++        for (k = 0; k < w; ++k)
++          png_line[k] = pc2nc[p[k]];
++        png_write_row(png_ptr, png_line);
++      } else {  /* PNG_COLOR_TYPE_RGB */
++        png_write_row(png_ptr, p);
++      }
++      if ((j & 0x1f) == 0) WaitCursor();
++      p += linesize;
++    }
++  }
++
++  free(png_line);
++
++  savecmnt = NULL;   /* quiet a compiler warning */
++
++  if (text) {
++    if (picComments && strlen(picComments) &&
++        (savecmnt = (char *)malloc((strlen(picComments) + 1)*sizeof(char)))) {
++      png_textp tp;
++      char *comment, *key;
++
++      strcpy(savecmnt, picComments);
++      key = savecmnt;
++      tp = text;
++      info_ptr->num_text = 0;
++
++      comment = strchr(key, ':');
++
++      do  {
++        /* Allocate a larger structure for comments if necessary */
++        if (info_ptr->num_text >= info_ptr->max_text)
++        {
++          if ((tp =
++              realloc(text, (info_ptr->num_text + 2)*sizeof(png_text))) == NULL)
++          {
++            break;
++          }
++          else
++          {
++            text = tp;
++            tp = &text[info_ptr->num_text];
++            info_ptr->max_text += 2;
++          }
++        }
++
++        /* See if it looks like a PNG keyword from LoadPNG */
++        /* GRR: should test for strictly < 80, right? (key = 1-79 chars only) */
++        if (comment && comment[1] == ':' && comment - key <= 80) {
++          *(comment++) = '\0';
++          *(comment++) = '\0';
++
++          /* If the comment is the 'Software' chunk XV writes, we remove it,
++             since we have already stored one */
++          if (strcmp(key, "Software") == 0 && strncmp(comment, "XV", 2) == 0) {
++            key = strchr(comment, '\n');
++            if (key)
++              key++; /* skip \n */
++            comment = strchr(key, ':');
++          }
++          /* We have another keyword and/or comment to write out */
++          else {
++            tp->key = key;
++            tp->text = comment;
++
++            /* We have to find the end of this comment, and the next keyword
++               if there is one */
++            for (; NULL != (key = comment = strchr(comment, ':')); comment++)
++              if (key[1] == ':')
++                break;
++
++            /* It looks like another keyword, go backward to the beginning */
++            if (key) {
++              while (key > tp->text && *key != '\n')
++                key--;
++
++              if (key > tp->text && comment - key <= 80) {
++                *key = '\0';
++                key++;
++              }
++            }
++
++            tp->text_length = strlen(tp->text);
++
++            /* We don't have another keyword, so remove the last newline */
++            if (!key && tp->text[tp->text_length - 1] == '\n')
++            {
++              tp->text[tp->text_length] = '\0';
++              tp->text_length--;
++            }
++
++            tp->compression = tp->text_length > 640 ? 0 : -1;
++            info_ptr->num_text++;
++            tp++;
++          }
++        }
++        /* Just a generic comment:  make sure line-endings are valid for PNG */
++        else {
++          char *p=key, *q=key;     /* only deleting chars, not adding any */
++
++          while (*p) {
++            if (*p == CR) {        /* lone CR or CR/LF:  EOL either way */
++              *q++ = LF;           /* LF is the only allowed PNG line-ending */
++              if (p[1] == LF)      /* get rid of any original LF */
++                ++p;
++            } else if (*p == LF)   /* lone LF */
++              *q++ = LF;
++            else
++              *q++ = *p;
++            ++p;
++          }
++          *q = '\0';               /* unnecessary...but what the heck */
++          tp->key = "Comment";
++          tp->text = key;
++          tp->text_length = q - key;
++          tp->compression = tp->text_length > 750 ? 0 : -1;
++          info_ptr->num_text++;
++          key = NULL;
++        }
++      } while (key && *key);
++    }
++    else {
++      info_ptr->num_text = 0;
++    }
++  }
++  info_ptr->text = text;
++
++  png_convert_from_time_t(&(info_ptr->mod_time), time(NULL));
++  info_ptr->valid |= PNG_INFO_tIME;
++
++  png_write_end(png_ptr, info_ptr);
++  fflush(fp);   /* just in case we core-dump before finishing... */
++
++  if (text) {
++    free(text);
++    /* must do this or png_destroy_write_struct() 0.97+ will free text again: */
++    info_ptr->text = (png_textp)NULL;
++    if (savecmnt)
++    {
++      free(savecmnt);
++      savecmnt = (char *)NULL;
++    }
++  }
++
++  png_destroy_write_struct(&png_ptr, &info_ptr);
++
++  return 0;
++}
++
++
++/*******************************************/
++int LoadPNG(fname, pinfo)
++     char    *fname;
++     PICINFO *pinfo;
++/*******************************************/
++{
++  /* returns '1' on success */
++
++  FILE  *fp;
++  png_struct *png_ptr;
++  png_info *info_ptr;
++  png_color_16 my_background;
++  int i,j;
++  int linesize, bufsize;
++  int filesize;
++  int pass;
++  int gray_to_rgb;
++  size_t commentsize;
++
++  fbasename = BaseName(fname);
++
++  pinfo->pic     = (byte *) NULL;
++  pinfo->comment = (char *) NULL;
++
++  read_anything=0;
++
++  /* open the file */
++  fp = xv_fopen(fname,"r");
++  if (!fp) {
++    SetISTR(ISTR_WARNING,"%s:  can't open file", fname);
++    return 0;
++  }
++
++  /* find the size of the file */
++  fseek(fp, 0L, 2);
++  filesize = ftell(fp);
++  fseek(fp, 0L, 0);
++
++  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
++                                   png_xv_error, png_xv_warning);
++  if (!png_ptr) {
++    fclose(fp);
++    FatalError("malloc failure in LoadPNG");
++  }
++
++  info_ptr = png_create_info_struct(png_ptr);
++
++  if (!info_ptr) {
++    fclose(fp);
++    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
++    FatalError("malloc failure in LoadPNG");
++  }
++
++  if (setjmp(png_ptr->jmpbuf)) {
++    fclose(fp);
++    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
++    if (!read_anything) {
++      if (pinfo->pic) {
++        free(pinfo->pic);
++        pinfo->pic = NULL;
++      }
++      if (pinfo->comment) {
++        free(pinfo->comment);
++        pinfo->comment = NULL;
++      }
++    }
++    return read_anything;
++  }
++
++#ifdef PNG_NO_STDIO
++  png_set_read_fn(png_ptr, fp, png_default_read_data);
++  png_set_error_fn(png_ptr, NULL, png_xv_error, png_xv_warning);
++#else
++  png_init_io(png_ptr, fp);
++#endif
++  png_read_info(png_ptr, info_ptr);
++
++  pinfo->w = pinfo->normw = info_ptr->width;
++  pinfo->h = pinfo->normh = info_ptr->height;
++  if (pinfo->w <= 0 || pinfo->h <= 0) {
++    SetISTR(ISTR_WARNING, "%s:  image dimensions out of range (%dx%d)",
++      fbasename, pinfo->w, pinfo->h);
++    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
++    return read_anything;
++  }
++
++  pinfo->frmType = F_PNG;
++
++  sprintf(pinfo->fullInfo, "PNG, %d bit ",
++          info_ptr->bit_depth * info_ptr->channels);
++
++  switch(info_ptr->color_type) {
++    case PNG_COLOR_TYPE_PALETTE:
++      strcat(pinfo->fullInfo, "palette color");
++      break;
++
++    case PNG_COLOR_TYPE_GRAY:
++      strcat(pinfo->fullInfo, "grayscale");
++      break;
++
++    case PNG_COLOR_TYPE_GRAY_ALPHA:
++      strcat(pinfo->fullInfo, "grayscale+alpha");
++      break;
++
++    case PNG_COLOR_TYPE_RGB:
++      strcat(pinfo->fullInfo, "truecolor");
++      break;
++
++    case PNG_COLOR_TYPE_RGB_ALPHA:
++      strcat(pinfo->fullInfo, "truecolor+alpha");
++      break;
++  }
++
++  sprintf(pinfo->fullInfo + strlen(pinfo->fullInfo),
++	  ", %sinterlaced. (%d bytes)",
++	  info_ptr->interlace_type ? "" : "non-", filesize);
++
++  sprintf(pinfo->shrtInfo, "%lux%lu PNG", info_ptr->width, info_ptr->height);
++
++  if (info_ptr->bit_depth < 8)
++      png_set_packing(png_ptr);
++
++  if (info_ptr->valid & PNG_INFO_gAMA)
++    png_set_gamma(png_ptr, Display_Gamma, info_ptr->gamma);
++/*
++ *else
++ *  png_set_gamma(png_ptr, Display_Gamma, 0.45);
++ */
++
++  gray_to_rgb = 0;   /* quiet a compiler warning */
++
++  if (have_imagebg) {
++    if (info_ptr->bit_depth == 16) {
++      my_background.red   = imagebgR;
++      my_background.green = imagebgG;
++      my_background.blue  = imagebgB;
++      my_background.gray = imagebgG;   /* used only if all three equal... */
++    } else {
++      my_background.red   = (imagebgR >> 8);
++      my_background.green = (imagebgG >> 8);
++      my_background.blue  = (imagebgB >> 8);
++      my_background.gray = my_background.green;
++    }
++    png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN,
++                       0, Display_Gamma);
++    if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
++         (info_ptr->color_type == PNG_COLOR_TYPE_GRAY && HAVE_tRNS)) &&
++        (imagebgR != imagebgG || imagebgR != imagebgB))  /* i.e., colored bg */
++    {
++      png_set_gray_to_rgb(png_ptr);
++      png_set_expand(png_ptr);
++      gray_to_rgb = 1;
++    }
++  } else {
++    if (info_ptr->valid & PNG_INFO_bKGD) {
++      png_set_background(png_ptr, &info_ptr->background,
++                         PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
++    } else {
++      my_background.red = my_background.green = my_background.blue =
++        my_background.gray = 0;
++      png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN,
++                         0, Display_Gamma);
++    }
++  }
++
++  if (info_ptr->bit_depth == 16)
++    png_set_strip_16(png_ptr);
++
++  if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
++      info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
++  {
++    if (info_ptr->bit_depth == 1)
++      pinfo->colType = F_BWDITHER;
++    else
++      pinfo->colType = F_GREYSCALE;
++    png_set_expand(png_ptr);
++  }
++
++  pass=png_set_interlace_handling(png_ptr);
++
++  png_read_update_info(png_ptr, info_ptr);
++
++  if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
++     info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || gray_to_rgb)
++  {
++    linesize = 3 * pinfo->w;
++    if (linesize/3 < pinfo->w) {   /* know pinfo->w > 0 (see above) */
++      SetISTR(ISTR_WARNING, "%s:  image dimensions too large (%dx%d)",
++        fbasename, pinfo->w, pinfo->h);
++      png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
++      return read_anything;
++    }
++    pinfo->colType = F_FULLCOLOR;
++    pinfo->type = PIC24;
++  } else {
++    linesize = pinfo->w;
++    pinfo->type = PIC8;
++    if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
++       info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
++      for (i = 0; i < 256; i++)
++        pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
++    } else {
++      pinfo->colType = F_FULLCOLOR;
++      for (i = 0; i < info_ptr->num_palette; i++) {
++        pinfo->r[i] = info_ptr->palette[i].red;
++        pinfo->g[i] = info_ptr->palette[i].green;
++        pinfo->b[i] = info_ptr->palette[i].blue;
++      }
++    }
++  }
++
++  bufsize = linesize * pinfo->h;
++  if (bufsize/linesize < pinfo->h) {  /* know linesize, pinfo->h > 0 (above) */
++    SetISTR(ISTR_WARNING, "%s:  image dimensions too large (%dx%d)",
++      fbasename, pinfo->w, pinfo->h);
++    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
++    return read_anything;
++  }
++  pinfo->pic = calloc((size_t)bufsize, (size_t)1);
++
++  if (!pinfo->pic) {
++    png_error(png_ptr, "can't allocate space for PNG image");
++  }
++
++  png_start_read_image(png_ptr);
++
++  for (i = 0; i < pass; i++) {
++    byte *p = pinfo->pic;
++    for (j = 0; j < pinfo->h; j++) {
++      png_read_row(png_ptr, p, NULL);
++      read_anything = 1;
++      if ((j & 0x1f) == 0) WaitCursor();
++      p += linesize;
++    }
++  }
++
++  png_read_end(png_ptr, info_ptr);
++
++  if (info_ptr->num_text > 0) {
++    commentsize = 1;
++
++    for (i = 0; i < info_ptr->num_text; i++)
++      commentsize += strlen(info_ptr->text[i].key) + 1 +
++                     info_ptr->text[i].text_length + 2;
++
++    if ((pinfo->comment = malloc(commentsize)) == NULL) {
++      png_warning(png_ptr,"can't allocate comment string");
++    }
++    else {
++      pinfo->comment[0] = '\0';
++      for (i = 0; i < info_ptr->num_text; i++) {
++        strcat(pinfo->comment, info_ptr->text[i].key);
++        strcat(pinfo->comment, "::");
++        strcat(pinfo->comment, info_ptr->text[i].text);
++        strcat(pinfo->comment, "\n");
++      }
++    }
++  }
++
++  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
++
++  fclose(fp);
++
++  return 1;
++}
++
++
++/*******************************************/
++static void
++png_xv_error(png_ptr, message)
++     png_structp png_ptr;
++     png_const_charp message;
++{
++  SetISTR(ISTR_WARNING,"%s:  libpng error: %s", fbasename, message);
++
++  longjmp(png_ptr->jmpbuf, 1);
++}
++
++
++/*******************************************/
++static void
++png_xv_warning(png_ptr, message)
++     png_structp png_ptr;
++     png_const_charp message;
++{
++  if (!png_ptr)
++    return;
++
++  SetISTR(ISTR_WARNING,"%s:  libpng warning: %s", fbasename, message);
++}
++
++
++/*******************************************/
++void
++VersionInfoPNG()	/* GRR 19980605 */
++{
++  fprintf(stderr, "   Compiled with libpng %s; using libpng %s.\n",
++    PNG_LIBPNG_VER_STRING, png_libpng_ver);
++  fprintf(stderr, "   Compiled with zlib %s; using zlib %s.\n",
++    ZLIB_VERSION, zlib_version);
++}
++
++#endif /* HAVE_PNG */
+diff -Naru xv-3.10a/xvvd.c xv-3.10a.jumbo/xvvd.c
+--- xv-3.10a/xvvd.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvvd.c	2007-04-16 06:30:19.000000000 +0200
+@@ -0,0 +1,1101 @@
++
++/*
++ * xvvd.c - extract archived file automatically and regard it as a
++ *          (virtual) directory.
++ */
++
++#define NEEDSDIR
++
++#include "xv.h"
++
++#ifdef AUTO_EXPAND
++
++static void  vd_Dirtovd    		PARM((char *));
++static void  vd_Vdtodir    		PARM((char *));
++static int   vd_Mkvdir    		PARM((char *));
++static int   vd_Rmvdir     		PARM((char *));
++static int   vd_Movevdir  		PARM((char *, char *));
++static void  vd_addvdtable		PARM((char *));
++static void  vd_packvdtable		PARM((void));
++static int   vd_recursive_mkdir		PARM((char *));
++static int   vd_recursive_rmdir		PARM((char *));
++static void  vd_optimize_path		PARM((char *));
++static int   vd_ftype			PARM((char *));
++static int   vd_compp			PARM((char *, char *));
++static int   vd_UncompressFile		PARM((char *, char *));
++static int   vd_tarc			PARM((char *));
++static u_int vd_tar_sumchk		PARM((char *));
++
++#define VD_VDTABLESIZE	100
++
++#define VD_ERR -2
++#define VD_UKN -1
++
++static char *ext_command[] = {
++/* KEEP 0 */
++    NULL,
++#define VD_ARC 1
++    "arc xo %s",
++#define VD_ARJ 2
++    "unarj x %s",
++#define VD_LZH 3
++    "lha -xf %s",
++#define VD_TAR 4
++    "tar xvf %s",
++#define VD_ZIP 5
++    "unzip -xo %s",
++#define VD_ZOO 6
++    "zoo xOS %s",
++};
++
++int vdcount = 0;
++
++static char vdroot[MAXPATHLEN+1];
++static char *vdtable[VD_VDTABLESIZE];
++
++/*
++ * These functions initialize and settle virtual directory system.
++ * Vdinit:
++ *	creates root of virtual directory.
++ * Vdsettle:
++ *	sweeps virtual directories.
++ */
++void Vdinit()
++{
++#ifndef VMS
++    char tmp[MAXPATHLEN+1];
++
++    xv_getwd(tmp, MAXPATHLEN+1);
++    if (chdir(tmpdir)) {
++	fprintf(stderr, "Warning: cannot chdir to tmpdir = '%s'.\n", tmpdir);
++	fprintf(stderr,
++		"         I will use current directory '%s' instead of tmpdir.\n",
++		tmp);
++    }
++    xv_getwd(vdroot, MAXPATHLEN+1);
++    strcat(vdroot, "/.xvvdXXXXXX");
++    chdir(tmp);
++#else
++    sprintf(vdroot, "Sys$Scratch:xvvdXXXXXX");
++#endif /* VMS */
++#ifdef USE_MKSTEMP
++    close(mkstemp(vdroot));
++#else
++    mktemp(vdroot);
++#endif
++
++    if (!vd_recursive_mkdir(vdroot))
++	tmpdir = vdroot;
++}
++
++void Vdsettle()
++{
++    int i;
++
++    for (i = 0; i < vdcount; i++)
++	free(vdtable[i]);
++
++    vdcount = 0;
++
++    vd_recursive_rmdir(vdroot);
++}
++
++/*
++ * This function chdir to virtual directory, if specified path is in
++ * virtual directlry.
++ */
++int Chvdir(dir)
++char *dir;
++{
++    char buf[MAXPATHLEN+1];
++
++    if (Mkvdir(dir) == VD_ERR)
++	return -1;
++
++    strcpy(buf, dir);
++    Dirtovd(buf);
++
++    return (chdir(buf));
++}
++
++/*
++ * These functions convert directory <-> virtual directory.
++ * Dirtovd:
++ *	front interface of vd_Dirtovd.
++ * vd_Dirtovd:
++ *	converts directory to virtual directory.
++ * Vdtodir:
++ *	front interface of vd_Vdtodir.
++ * vd_Vdtodir:
++ *	converts virtual directory to normal directory.
++ * Dirtosubst:
++ *	converts directory to substance of archive.
++ */
++void Dirtovd(dir)
++char *dir;
++{
++    vd_optimize_path(dir);
++
++    vd_Dirtovd(dir);
++}
++
++static void vd_Dirtovd(dir)
++char *dir;
++{
++    int i;
++
++    for (i = 0; i < vdcount; i++)
++	if (!strncmp(dir, vdtable[i], strlen(vdtable[i]))) {
++	    char tmp[MAXPATHLEN+1];
++
++	    sprintf(tmp, "%s%s", vdroot, dir);
++	    strcpy(dir, tmp);
++	    Dirtovd(dir);
++	}
++}
++
++void Vdtodir(dir)
++char *dir;
++{
++    vd_optimize_path(dir);
++
++    vd_Vdtodir(dir);
++}
++
++static void vd_Vdtodir(vd)
++char *vd;
++{
++    int i;
++    char tmp[MAXPATHLEN+1];
++
++    for (i = vdcount-1; i >= 0; i--) {
++	sprintf(tmp, "%s%s", vdroot, vdtable[i]);
++	if(!strncmp(vd, tmp, strlen(tmp))) {
++	    strcpy(tmp, vd+strlen(vdroot));
++	    strcpy(vd, tmp);
++	    Vdtodir(vd);
++	}
++    }
++}
++
++void Dirtosubst(dir)
++char *dir;
++{
++    char tmp[MAXPATHLEN+1];
++
++    Dirtovd(dir);
++
++    strcpy(tmp, dir+strlen(vdroot));
++
++    if (Isarchive(tmp))
++	strcpy(dir, tmp);
++}
++
++/*
++ * These functions make virtual directory and extracts archive, if
++ * specified path is archive.
++ * Mkvdir:
++ *	front interface of vd_Mkvdir.
++ * vd_Mkvdir:
++ *	does real work.
++ * Mkvdir_force: (used by makeThumbDir(in xvbrowse.c) only)
++ *	make virtual directory by force.
++ */
++int Mkvdir(dir)
++char *dir;
++{
++    char dir1[MAXPATHLEN+1], dir2[MAXPATHLEN+1];
++    char *d1, *d2;
++    int rv;
++
++#if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
++    sighold(SIGHUP);
++    sighold(SIGCHLD);
++#else
++    int mask;
++    mask = sigblock(sigmask(SIGHUP)|sigmask(SIGCHLD));
++#endif
++
++    strcpy(dir1, dir);
++    vd_optimize_path(dir1);
++
++    if ((rv = vd_Mkvdir(dir1)) != VD_ERR)
++	goto MKVDIR_END;
++
++    strcpy(dir2, dir1);
++    d2 = dir2 + strlen(dir2);
++    while (rv == VD_ERR) {
++	d2--;
++	while (*d2 != '/')
++	    d2--;
++	*d2 = '\0';
++	rv = vd_Mkvdir(dir2);
++    }
++    d1 = dir1 + strlen(dir2);
++    while ((rv != VD_ERR) && (*d1 != '\0')) {
++	*d2++ = *d1++;
++	while ((*d1 != '/') && (*d1 != '\0'))
++	    *d2++ = *d1++;
++	*d2 = '\0';
++	rv = vd_Mkvdir(dir2);
++    }
++
++MKVDIR_END:
++#if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
++    sigrelse(SIGHUP);
++    sigrelse(SIGCHLD);
++#else
++    sigsetmask(mask);
++#endif
++
++    return rv;
++}
++
++static int vd_Mkvdir(dir)
++char *dir;
++{
++    char dir1[MAXPATHLEN+1], dir2[MAXPATHLEN+1], tmp[MAXPATHLEN+1];
++    int ftype, i;
++    struct stat st;
++    FILE *pfp;
++
++    strcpy(dir1, dir);
++    Dirtovd(dir1);
++    strcpy(dir2, dir1);
++
++    WaitCursor();
++
++    if ((ftype = vd_ftype(dir1)) < 0) {
++	SetCursors(-1);
++	return ftype;
++    }
++    if (ftype == RFT_COMPRESS) {
++	if (!(ftype = vd_compp(dir1, tmp))) {
++	    SetCursors(-1);
++	    return ftype;
++	}
++	strcpy(dir1, tmp);
++    }
++
++    if (!stat(dir1, &st)) {
++	for(i = 0; i < vdcount; i++)
++	    if (!strcmp(vdtable[i], dir2)) {
++		SetCursors(-1);
++		return 0;
++	    }
++
++	if (!S_ISDIR(st.st_mode)) {
++	    char origdir[MAXPATHLEN+1], buf[MAXPATHLEN+10], buf1[100];
++
++	    if (vdcount >= VD_VDTABLESIZE) {
++		ErrPopUp("Sorry, you can't make virtual directory any more.",
++			 "\nBummer!");
++		goto VD_MKVDIR_ERR;
++	    }
++
++	    WaitCursor();
++
++	    xv_getwd(origdir, MAXPATHLEN+1);
++
++	    sprintf(tmp, "%s%s", vdroot, dir2);
++	    if (vd_recursive_mkdir(tmp) || chdir(tmp)) {
++		SetISTR(ISTR_INFO, "fail to make virtual directory.");
++		Warning();
++		goto VD_MKVDIR_ERR;
++	    }
++	    sprintf(buf, ext_command[ftype], dir1);
++
++	    WaitCursor();
++
++	    if((pfp = popen(buf, "r")) == NULL) {
++		SetISTR(ISTR_INFO, "fail to extract archive '%s'.",
++			BaseName(dir2));
++		Warning();
++		goto VD_MKVDIR_ERR;
++	    }
++	    while (1) {
++		if (fread(buf1, 1, sizeof(buf1), pfp) < sizeof(buf1))
++		    break;
++		WaitCursor();
++	    }
++	    if (!feof(pfp)) {
++		SetISTR(ISTR_INFO, "Pipe was broken.");
++		Warning();
++		pclose(pfp);
++		goto VD_MKVDIR_ERR;
++	    }
++	    pclose(pfp);
++
++	    if (strcmp(dir1, dir2))
++		unlink(dir1);
++
++	    vd_addvdtable(dir2);
++	    Dirtovd(origdir);
++	    chdir(origdir);
++	    SetCursors(-1);
++	    return 0;
++
++VD_MKVDIR_ERR:
++	    if (strcmp(dir1, dir2))
++		unlink(dir1);
++	    SetCursors(-1);
++	    return VD_ERR;
++	}
++    }
++    SetCursors(-1);
++    return VD_ERR;
++}
++
++#ifdef VIRTUAL_TD
++void Mkvdir_force(dir)
++char *dir;
++{
++    char tmp[MAXPATHLEN+1];
++
++    if (vdcount >= VD_VDTABLESIZE) {
++      ErrPopUp("Sorry, you can't make virtual directory any more.",
++	       "\nBummer!");
++      return;
++    }
++
++    sprintf(tmp, "%s%s", vdroot, dir);
++    if (vd_recursive_mkdir(tmp)) {
++      SetISTR(ISTR_INFO, "Failed to make virtual directory.");
++      Warning();
++      return;
++    }
++
++    vd_addvdtable(dir);
++}
++#endif /* VIRTUAL_TD */
++
++/*
++ * These functions remove virtual directory, if exists.
++ * Rmvdir:
++ *	front interface of vd_Rmvdir.
++ * vd_Rmvdir:
++ *	remove virtual directory function.
++ */
++int Rmvdir(dir)
++char *dir;
++{
++    int rv;
++    char buf[MAXPATHLEN+1];
++
++    strcpy(buf, dir);
++    vd_optimize_path(buf);
++
++    rv = vd_Rmvdir(buf);
++    vd_packvdtable();
++    return rv;
++}
++
++static int vd_Rmvdir(dir)
++char *dir;
++{
++    int i;
++    char tmp[MAXPATHLEN+1];
++
++    for(i = 0; i < vdcount; i++)
++	if (!strncmp(dir, vdtable[i], strlen(dir))) {
++	    sprintf(tmp, "%s%s", vdroot, vdtable[i]);
++	    if (vd_Rmvdir(tmp))
++		return 1;
++	    if (vd_recursive_rmdir(tmp))
++		return 1;
++	    vdtable[i][0] = '\0';
++	}
++    return 0;
++}
++
++/*
++ * These functions move virtual directory, if exists.
++ * Movevdir:
++ *	front interface of move virtual directory function.
++ * vd_Movevdir:
++ *	does real work.
++ */
++int Movevdir(src, dst)
++char *src, *dst;
++{
++/*
++    char sbuf[MAXPATHLEN+1], dbuf[MAXPATHLEN+1];
++
++    strcpy(sbuf, src);
++    vd_optimize_path(sbuf);
++
++    strcpy(dbuf, dst);
++    vd_optimize_path(dbuf);
++
++    return (vd_Movevdir(sbuf, dbuf));
++*/
++    return (vd_Movevdir(src, dst));
++}
++
++static int vd_Movevdir(src, dst)
++char *src, *dst;
++{
++    int i;
++    char *p, *pp;
++    char tmp[MAXPATHLEN+1], tmps[MAXPATHLEN+1], tmpd[MAXPATHLEN+1];
++
++    for (i = 0; i < vdcount; i++)
++	if (!strncmp(src, vdtable[i], strlen(src))) {
++	    sprintf(tmps, "%s%s", vdroot, vdtable[i]);
++	    sprintf(tmp, "%s%s", dst, vdtable[i]+strlen(src));
++	    sprintf(tmpd, "%s%s", vdroot, tmp);
++
++	    if (vd_Movevdir(tmps, tmpd))
++		return 1;
++
++	    pp = vdtable[i];
++	    p = (char *) malloc(strlen(tmp)+1);
++	    strcpy(p, tmp);
++	    vdtable[i] = p;
++
++	    strcpy(tmp, tmpd);
++	    for (p = tmp+strlen(tmp); *p != '/'; p--)
++		;
++	    *p = '\0';
++
++	    if (vd_recursive_mkdir(tmp))
++		goto VD_MOVEVDIR_ERR;
++
++	    if (rename(tmps, tmpd) < 0)
++		goto VD_MOVEVDIR_ERR;
++
++	    free(pp);
++	}
++    return 0;
++
++VD_MOVEVDIR_ERR:
++    free(vdtable[i]);
++    vdtable[i] = pp;
++    return 1;
++}
++
++/*
++ * These functions handle table of virtual directories.
++ * vd_addvdtable:
++ *	adds virtual directory to table.
++ * vd_packvdtable:
++ *	removes disused virtual directories from table.
++ */
++static void vd_addvdtable(vd)
++char *vd;
++{
++    char *p;
++    p = (char *) malloc(strlen(vd)+1);
++    strcpy(p, vd);
++    vdtable[vdcount] = p;
++    vdcount++;
++}
++
++static void vd_packvdtable()
++{
++    int i, j;
++
++    for (i = j = 0; i < vdcount; i++)
++	if (vdtable[i][0] != '\0')
++	    vdtable[j++] = vdtable[i];
++	else
++	    free(vdtable[i]);
++
++    vdcount = j;
++}
++
++/*
++ * These are utility functions.
++ * vd_recursive_mkdir:
++ *	makes directories recursively.
++ * vd_recursive_rmdir
++ *	removes directories recursively.
++ */
++static int vd_recursive_mkdir(dir)
++char *dir;
++{
++    char buf[MAXPATHLEN+1], *p;
++    struct stat st;
++
++    strcpy(buf, dir);
++
++    if (buf[strlen(buf) - 1] == '/')
++	buf[strlen(buf) - 1] = '\0';
++
++    p = rindex(buf, '/');
++    *p = '\0';
++
++    if (stat(buf, &st) < 0)
++	if (vd_recursive_mkdir(buf) < 0)
++	    return (-1);
++
++    *p = '/';
++    if (mkdir(buf, 0700) < 0)
++	return (-1);
++
++    return (0);
++}
++
++static int vd_recursive_rmdir(dir)
++char *dir;
++{
++    char buf[MAXPATHLEN+1], buf2[MAXPATHLEN+1];
++    DIR *dp;
++    struct dirent *di;
++
++    strcpy(buf, dir);
++
++    if (buf[strlen(buf) - 1] == '/')
++	buf[strlen(buf) - 1] = '\0';
++
++    if ((dp = opendir(buf)) == NULL)
++	return (-1);
++
++    while ((di = readdir(dp)) != NULL) {
++	struct stat st;
++
++	if (!strcmp(di->d_name, ".") || !strcmp(di->d_name, ".."))
++	    continue;
++
++	sprintf(buf2, "%s/%s", dir, di->d_name);
++
++	stat(buf2, &st);
++	if (S_ISDIR(st.st_mode)) {
++	    if (vd_recursive_rmdir(buf2) < 0)
++		goto VD_RECURSIVE_RMDIR_ERR;
++	} else
++	    unlink(buf2);
++    }
++    if (rmdir(buf) < 0)
++	goto VD_RECURSIVE_RMDIR_ERR;
++
++    closedir(dp);
++    return (0);
++
++VD_RECURSIVE_RMDIR_ERR:
++    closedir(dp);
++    return (-1);
++}
++
++/*
++ * These functions test specified path.
++ * Isarchive:
++ *	tests whether it's an archive?
++ * Isvdir:
++ *	tests whether it's in the virtual directory?
++ */
++int Isarchive(path)
++char *path;
++{
++    int ftype;
++
++    if ((ftype = vd_ftype(path)) < 0)
++	return 0;
++
++    if (ftype == RFT_COMPRESS)
++	if (!(ftype = vd_compp(path, NULL)))
++	    return 0;
++
++    return ftype;
++}
++
++int Isvdir(path)
++char *path;
++{
++    int rv = 0;
++    char tmp1[MAXPATHLEN+1], tmp2[MAXPATHLEN+1];
++    int archive1, archive2;
++
++    strcpy(tmp1, path);
++    strcpy(tmp2, path);
++
++    vd_optimize_path(tmp1);
++    Dirtovd(tmp2);
++
++    archive1 = Isarchive(tmp1);
++    archive2 = Isarchive(tmp2);
++
++    if (strcmp(tmp1, tmp2)) {
++	char tmp3[MAXPATHLEN+1], tmp4[MAXPATHLEN+1];
++	int archive3, archive4;
++
++	sprintf(tmp3, "%s%s", vdroot, tmp1);
++	strcpy(tmp4, tmp2+strlen(vdroot));
++
++	archive3 = Isarchive(tmp3);
++	archive4 = Isarchive(tmp4);
++
++	if (archive4 && !strcmp(tmp1, tmp4)) {
++	    rv |= 06;
++	    return rv;
++	}
++	rv |= 01;
++	if (archive2)
++	    rv |= 02;
++	else if (archive4)
++	    rv |= 06;
++	return rv;
++    }
++    if (archive1)
++	rv |= 02;
++
++    return rv;
++}
++
++/*
++ * This function optimizes given path.
++ * Expand '~' to home directory and removes '.', and treat '..'.
++ */
++static void vd_optimize_path(path)
++char *path;
++{
++    char *tmp, *reserve;
++
++    if (!strcmp(path, STDINSTR))
++	return;
++
++    if (*path == '\0') {
++	xv_getwd(path, MAXPATHLEN+1);
++	return;
++    }
++    if (*path == '~')
++	Globify(path);
++    if (*path != '/') {
++	char tmp[MAXPATHLEN+1];
++
++	strcpy(tmp, path);
++	xv_getwd(path, MAXPATHLEN+1);
++	strcat(path, "/");
++	strcat(path, tmp);
++    }
++
++    reserve = tmp = path;
++    while(*path != '\0') {
++	if (*path == '/') {
++	    *tmp++ = *path;
++	    while (*++path == '/')
++		;
++	    continue;
++	}
++	if ((*path == '.') && (*(path-1) == '/')) {
++	    if (*(path+1) == '/') {
++		tmp--;
++		path++;
++		continue;
++	    } else if (*(path+1) == '\0') {
++		tmp--;
++		break;
++	    } else if (*(path+1) == '.') {
++		if (*(path+2) == '/') {
++		    if ((tmp - reserve) > 1)
++			for (tmp-=2; (*tmp != '/'); tmp--)
++			    ;
++		    else
++			tmp = reserve;
++		    path+=2;
++		    continue;
++		} else if (*(path+2) == '\0') {
++		    if ((tmp - reserve) > 1)
++			for (tmp-=2; (*tmp != '/'); tmp--)
++			    ;
++		    else
++			tmp = reserve+1;
++		    break;
++		}
++	    }
++	}
++	*tmp++ = *path++;
++    }
++    if (((tmp - reserve) > 1) && *(tmp-1) == '/')
++	tmp--;
++    if (tmp == reserve)
++	*tmp++ = '/';
++
++    *tmp = '\0';
++}
++
++/*
++ * These functions detect file type.
++ */
++static int vd_ftype(fname)
++char *fname;
++{
++    /* check archive type */
++
++    FILE *fp;
++    byte  magicno[30];    /* first 30 bytes of file */
++    int   rv, n;
++    struct stat st;
++
++    if (!fname) return VD_ERR;   /* shouldn't happen */
++
++    if ((!stat(fname, &st)) && (st.st_mode & S_IFMT) == S_IFDIR)
++	return VD_UKN;
++    fp = xv_fopen(fname, "r");
++    if (!fp) return VD_ERR;
++
++    n = fread(magicno, (size_t) 1, (size_t) 30, fp);
++    fclose(fp);
++
++    if (n<30) return VD_UKN;    /* files less than 30 bytes long... */
++
++    rv = VD_UKN;
++
++    if (magicno[0] == 0x60 && magicno[1]==0xea) rv = VD_ARJ;
++
++    else if (magicno[2] == '-' && magicno[3] == 'l' &&
++	     magicno[4] == 'h') rv = VD_LZH;
++
++    else if (strncmp((char *) magicno,"PK", (size_t) 2)==0) rv = VD_ZIP;
++
++    else if (magicno[20]==0xdc && magicno[21]==0xa7 &&
++	     magicno[22]==0xc4 && magicno[23]==0xfd) rv = VD_ZOO;
++
++    else if (vd_tarc(fname)) rv = VD_TAR;
++
++    else if (magicno[0]==0x1f && magicno[1]==0x9d) rv = RFT_COMPRESS;
++
++    else if (!strncmp((char *) &magicno[11], "MAJYO", (size_t) 5))
++	     rv = VD_UKN; /* XXX */
++
++    else if (magicno[0] == 26) rv = VD_ARC;
++
++#ifdef GUNZIP
++    else if (magicno[0]==0x1f && magicno[1]==0x8b) rv = RFT_COMPRESS;/* gzip */
++    else if (magicno[0]==0x1f && magicno[1]==0x9e) rv = RFT_COMPRESS;/*  old */
++    else if (magicno[0]==0x1f && magicno[1]==0x1e) rv = RFT_COMPRESS;/* pack */
++#endif
++
++    return rv;
++}
++
++static int vd_compp(path, newpath)
++char *path, *newpath;
++{
++    /*
++     * uncompress and check archive type.
++     *
++     * If newpath is NULL, uncompress only 512 byte of 'path' and
++     * check archive type, so it is for SPEED-UP strategy.
++     * In this case, caller this function does not have to unlink
++     * tempoary file.
++     * Unfortunately it does not work in VMS system.
++     */
++
++    int file_type, r;
++    char uncompname[128], basename[128];
++    int comptype;
++
++    if (newpath) *newpath = '\0';
++    strncpy(basename, path, 127);
++    comptype = ReadFileType(path);
++#if (defined(VMS) && !defined(GUNZIP))
++    /* VMS decompress doesn't like the file to have a trailing .Z in fname
++    however, GUnZip is OK with it, which we are calling UnCompress */
++    *rindex (basename, '.') = '\0';
++#endif
++#ifdef VMS
++    if (UncompressFile(basename, uncompname)) {
++#else
++    if (newpath == NULL)
++	r = vd_UncompressFile(basename, uncompname);
++    else
++	r = UncompressFile(basename, uncompname, comptype);
++    if (r) {
++#endif
++	if ((file_type = vd_ftype(uncompname)) < 0) {
++	    unlink(uncompname);
++	    return 0;
++	}
++	if (newpath) strcpy(newpath, uncompname);
++	else unlink(uncompname);
++    } else {
++	return 0;
++    }
++    return file_type;
++}
++
++#define HEADERSIZE 512
++
++static void  vd_Dirtovd    		PARM((char *));
++static int   stderr_on			PARM((void));
++static int   stderr_off			PARM((void));
++static FILE  *popen_nul			PARM((char *, char *));
++
++static int vd_UncompressFile(name, uncompname)
++char *name, *uncompname;
++{
++    /* Yap, I`m nearly same as original `UncompnameFile' function, but,
++       1) I extract `name' file ONLY first 512 byte.
++       2) I'm called only from UNIX and UNIX like OS, *NOT* VMS */
++    /* returns '1' on success, with name of uncompressed file in uncompname
++       returns '0' on failure */
++
++    char namez[128], *fname, buf[512], tmp[HEADERSIZE];
++    int n, tmpfd;
++    FILE *pfp, *tfp;
++
++    fname = name;
++    namez[0] = '\0';
++
++
++#ifndef GUNZIP
++    /* see if compressed file name ends with '.Z'.  If it *doesn't*, we need
++       to temporarily rename it so it *does*, uncompress it, and rename it
++       *back* to what it was.  necessary because uncompress doesn't handle
++       files that don't end with '.Z' */
++
++    if (strlen(name) >= (size_t) 2            &&
++	strcmp(name + strlen(name)-2,".Z")!=0 &&
++	strcmp(name + strlen(name)-2,".z")!=0) {
++	strcpy(namez, name);
++	strcat(namez,".Z");
++
++	if (rename(name, namez) < 0) {
++	    sprintf(buf, "Error renaming '%s' to '%s':  %s",
++		    name, namez, ERRSTR(errno));
++	    ErrPopUp(buf, "\nBummer!");
++	    return 0;
++	}
++
++	fname = namez;
++    }
++#endif   /* not GUNZIP */
++
++    sprintf(uncompname, "%s/xvuXXXXXX", tmpdir);
++#ifdef USE_MKSTEMP
++    tmpfd = mkstemp(uncompname);
++#else
++    mktemp(uncompname);
++#endif
++
++    sprintf(buf,"%s -c %s", UNCOMPRESS, fname);
++    SetISTR(ISTR_INFO, "Uncompressing Header '%s'...", BaseName(fname));
++    if ((pfp = popen_nul(buf, "r")) == NULL) {
++	SetISTR(ISTR_INFO, "Cannot extract for archive '%s'.",
++		BaseName(fname));
++	Warning();
++#ifdef USE_MKSTEMP
++	if (tmpfd >= 0)
++	    close(tmpfd);
++#endif
++	return 0;
++    }
++#ifdef USE_MKSTEMP
++    if (tmpfd < 0)
++#else
++    if ((tmpfd = open(uncompname,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR)) < 0)
++#endif
++    {
++	SetISTR(ISTR_INFO, "Unable to create temporary file.",
++		BaseName(uncompname));
++	Warning();
++	pclose(pfp);
++    }
++    if ((tfp = fdopen(tmpfd, "w")) == NULL) {
++	SetISTR(ISTR_INFO, "Unable to create temporary file.",
++		BaseName(uncompname));
++	Warning();
++	close(tmpfd);
++	pclose(pfp);
++	return 0;
++    }
++    if ((n = fread(tmp, 1, sizeof(tmp), pfp)) != HEADERSIZE) {
++	SetISTR(ISTR_INFO, "Unable to read '%s'.",
++		BaseName(fname));
++	Warning();
++	pclose(pfp);
++	fflush(tfp);
++	fclose(tfp);
++	close(tmpfd);
++	return 0;
++    }
++    fwrite(tmp, 1, n, tfp);
++    fflush(tfp);
++    fclose(tfp);
++    close(tmpfd);
++    pclose(pfp);
++
++    /* if we renamed the file to end with a .Z for the sake of 'uncompress',
++       rename it back to what it once was... */
++
++    if (strlen(namez)) {
++	if (rename(namez, name) < 0) {
++	    sprintf(buf, "Error renaming '%s' to '%s':  %s",
++		    namez, name, ERRSTR(errno));
++	    ErrPopUp(buf, "\nBummer!");
++	}
++    }
++
++    return 1;
++}
++
++#define TARBLOCK 512
++#define CKSTART 148 /* XXX */
++#define CKSIZE 8
++
++/*
++ * Tar file: 1, other: 0
++ */
++static int vd_tarc(fname)
++char *fname;
++{
++    FILE *fp;
++    unsigned int sum;
++    char *ckp, buf[TARBLOCK];
++
++    if ((fp = fopen(fname, "r")) == NULL)
++	return 0;
++
++    fread(buf, TARBLOCK, 1, fp);
++    fclose(fp);
++
++    for (sum = 0, ckp = buf + CKSTART;
++	 (ckp < buf + CKSTART + CKSIZE) && *ckp != '\0';
++	 ckp++) {
++	sum *= 8;
++	if (*ckp == ' ')
++	    continue;
++	if (*ckp < '0' || '7' < *ckp)
++	    return 0;
++	sum += *ckp - '0';
++    }
++    if (sum != vd_tar_sumchk(buf))
++	return 0;
++
++    return 1;
++}
++
++static unsigned int vd_tar_sumchk(buf)
++char *buf;
++{
++    int i;
++    unsigned int sum = 0;
++
++    for (i = 0; i < CKSTART; i++) {
++	sum += *(buf + i);
++    }
++    sum += ' ' * 8;
++    for (i += 8; i < TARBLOCK; i++) {
++	sum += *(buf + i);
++    }
++    return sum;
++}
++
++
++static int stde = -1;        /*  fd of stderr    */
++static int nul = -1;         /*  fd of /dev/null */
++
++/*
++ * switch off the output to stderr(bypass to /dev/null).
++ */
++static int stderr_off()
++{
++    if (nul < 0)
++      nul = open("/dev/null", O_RDONLY);
++    if (nul < 0) {
++	fprintf(stderr, "/dev/null open failure\n");
++	return -1;
++    }
++    if (stde < 0)
++	stde = dup(2);
++    if (stde < 0) {
++	fprintf(stderr, "duplicate stderr failure\n");
++	return -1;
++    }
++    close(2);
++    dup(nul);
++    return 0;
++}
++
++/*
++ * turn on stderr output.
++ */
++static int stderr_on()
++{
++    if ((stde < 0) || (nul < 0)) {
++	fprintf(stderr, "stderr_on should call after stderr_off\n");
++	return -1;
++    }
++    close(2);
++    dup(stde);
++    return 0;
++}
++
++/*
++ * popen with no output to stderr.
++ */
++static FILE *popen_nul(prog, mode)
++char *prog, *mode;
++{
++    FILE *fp;
++
++    stderr_off();
++    fp = popen(prog, mode);
++    stderr_on();
++    return fp;
++}
++
++/*
++ * These functions are for SIGNAL.
++ * If XV end by C-c, there are dust of directory which name is .xvvd???,
++ * made by xvvd. Then, I handle SIGINT, and add good finish.
++ */
++void vd_HUPhandler()
++{
++#if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
++    sighold(SIGHUP);
++#else
++    int mask;
++    mask = sigblock(sigmask(SIGHUP));
++#endif
++
++  Vdsettle();
++
++#if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
++    sigrelse(SIGHUP);
++    signal(SIGHUP, (void (*)PARM((int))) vd_HUPhandler);
++#else
++    sigsetmask(mask);
++#endif
++}
++
++void vd_handler(sig)
++int sig;
++{
++#if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
++    sighold(sig);
++#else
++    sigblock(sigmask(sig));
++#endif
++
++    Quit(1); /*exit(1);*/
++}
++
++int vd_Xhandler(disp,event)
++Display *disp;
++XErrorEvent *event;
++{
++    Quit(1); /*exit(1);*/
++    return (1); /* Not reached */
++}
++
++int vd_XIOhandler(disp)
++Display *disp;
++{
++    fprintf(stderr, "XIO  fatal IO error ? (?) on X server\n");
++    fprintf(stderr, "You must exit normally in xv usage.\n");
++    Quit(1); /*exit(1);*/
++    return (1); /* Not reached */
++}
++
++void vd_handler_setup()
++{
++    signal(SIGHUP, (void (*)PARM((int))) vd_HUPhandler);
++    signal(SIGINT, (void (*)PARM((int))) vd_handler);
++    signal(SIGTERM,(void (*)PARM((int))) vd_handler);
++
++    (void)XSetErrorHandler(vd_Xhandler);
++    (void)XSetIOErrorHandler(vd_XIOhandler);
++}
++#endif /* AUTO_EXPAND */
+diff -Naru xv-3.10a/xvwbmp.c xv-3.10a.jumbo/xvwbmp.c
+--- xv-3.10a/xvwbmp.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvwbmp.c	2007-04-16 06:38:05.000000000 +0200
+@@ -0,0 +1,345 @@
++/*
++ * xvwbmp.c - i/o routings for WBMP files
++ * defined by OMA (http://www.openmobilealliance.com)
++ * as a standard for images for micro devices.
++ *
++ * exports :
++ *
++ * LoadWBMP(fname, numcols);
++ * WriteWBMP(fp, pic, ptype, w, h, r, g, b, numcols, style);
++ *
++ * author: Pawel S. Veselov <vps at manticore.2y.net>
++ *	      http://manticore.2y.net/
++ *
++ */
++
++#include "xv.h"
++
++typedef	short int16;
++typedef unsigned char uint8;
++typedef	unsigned short uint16;	/* sizeof (uint16) must == 2 */
++#if defined(__alpha) || _MIPS_SZLONG == 64
++typedef	int int32;
++typedef	unsigned int uint32;	/* sizeof (uint32) must == 4 */
++#else
++typedef	long int32;
++typedef	unsigned long uint32;	/* sizeof (uint32) must == 4 */
++#endif
++
++#define MUST(a)	            if (!(a)) {\
++				close(fd); \
++				return fail(st_fname, st_err); }
++#define READU8(fd,u)	    if ((read(fd, &u, 1)<1)) {\
++				myfree(); \
++				close(fd); \
++				return fail(st_fname, err_ueof); }
++#define SREADU8(fd, u)	    if ((read(fd, &u, 1,)<1)) {\
++				{ st_err = err_ueof; return 0; }
++
++#define SREADC(fd, str, l)  {	\
++    str = (char*)mymalloc(l);	\
++    if (!str) {			\
++	myfree();		\
++	FatalError("LoadWBMP: can't malloc extension buffer");	\
++    }				\
++    if (read(fd, str, l)<l) {	\
++	st_err = err_ueof;	\
++	return 0;		\
++    }
++
++static const char err_ueof[] = "Unexpected EOF";
++static const char err_unst[] = "Unsupported image type";
++static const char err_extf[] = "Extensions are forbidden";
++static const char err_inmb[] = "Invalid multibyte integer";
++
++static const char *st_fname;
++static const char *st_err;
++
++static int    fail	PARM((const char *, const char *));
++static int    read_mb	PARM((int *, int));
++static void   write_mb	PARM((uint32, FILE *));
++static int    read_ext	PARM((int, uint8));
++static void  *mymalloc	PARM((int));
++static void   myfree	PARM((void));
++static uint8 *render1	PARM((uint8 *, int, int));
++
++static void **mymem = NULL;
++static int    mymems = 0;
++
++
++int LoadWBMP(fname, pinfo)
++     char *fname;
++     PICINFO *pinfo;
++{
++    int fd;
++    int im_type;	/* image type (only type 0 supported) */
++    uint8 fix_header;	/* fixed header field */
++    int width, height;
++    int npixels, raw_size, aux;
++    uint8 * raw;
++
++    st_fname = fname;
++
++    fd = open(fname, O_RDONLY);
++    if (fd < 0) {
++	return fail(fname, "Couldn't open the file");
++    }
++
++    MUST(read_mb(&im_type, fd));
++    if (im_type) {
++	return fail(fname, err_unst);
++    }
++
++    READU8(fd, fix_header);
++
++    MUST(read_ext(fd, fix_header));
++
++    MUST(read_mb(&width, fd));
++    MUST(read_mb(&height, fd));
++
++    npixels = width * height;
++    raw_size = (npixels+7) / 8;
++    if (width <= 0 || height <= 0 || npixels/width != height ||
++        npixels+7 < npixels)
++    {
++	return fail(fname, "image dimensions out of range");
++    }
++
++    raw = mymalloc(raw_size);
++    if (!raw) {
++	myfree();
++	FatalError("LoadWBMP: can't malloc image buffer");
++    }
++
++    aux = read(fd, raw, raw_size);
++    if (aux < raw_size) {
++	fail(fname, "Image size shrank");
++	raw_size = aux;
++    }
++
++    pinfo->r[0] = 0;
++    pinfo->g[0] = 0;
++    pinfo->b[0] = 0;
++    pinfo->r[1] = 255;
++    pinfo->g[1] = 255;
++    pinfo->b[1] = 255;
++
++    pinfo->pic = render1(raw, raw_size, npixels);
++    pinfo->type = PIC8;
++
++    pinfo->w = pinfo->normw = width;
++    pinfo->h = pinfo->normh = height;
++    pinfo->frmType = F_BWDITHER;
++
++    sprintf(pinfo->fullInfo, "WBMP, 1 bit per pixel, %d bytes", raw_size);
++    sprintf(pinfo->shrtInfo, "%dx%d WBMP (WAP/OMA).", width, height);
++    pinfo->comment = (char*)NULL;
++
++    close(fd);
++
++    myfree();
++    return 1;
++}
++
++
++int WriteWBMP(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle)
++     FILE *fp;
++     byte *pic;
++     int ptype, w, h;
++     byte *rmap, *gmap, *bmap;
++     int numcols, colorstyle;
++{
++    int count = 0;
++    uint8 bit = 0;
++    int i;
++
++    write_mb(0, fp);	/* type : always 0 */
++    putc(0, fp);	/* fixed header : always 0 for type 0 */
++    write_mb((uint32)w, fp);
++    write_mb((uint32)h, fp);
++
++    /* ready to write data */
++
++    for (i=0; i<w*h; i++) {
++	bit |= (((pic[i]&1)<<(7-(count++))));
++	if (count == 8) {
++	    putc(bit, fp);
++	    count = 0;
++	}
++    }
++
++    if (!count) {
++	putc(bit, fp);
++    }
++
++    return 0;
++}
++
++
++static int fail(name, msg)
++     const char *name, *msg;
++{
++    SetISTR(ISTR_WARNING, "%s : %s", name, msg);
++    return 0;
++}
++
++
++static void write_mb(data, f)
++     uint32 data;
++     FILE *f;
++{
++    int i = 32;
++    uint32 aux = data;
++    int no;
++
++    if (!aux) {
++	i = 1;
++    } else {
++	while (!(aux & 0x80000000)) {
++	    aux <<= 1;
++	    i--;
++	}
++    }
++
++    /* i tells us how many bits are left to encode */
++
++    no = (i / 7 + ((i % 7)?1:0))-1;
++
++    /*
++    fprintf(stderr, "writing %x, bits to write=%d, passes=%d\n",
++	    data, i, no);
++    */
++
++    do {
++	uint8 value = no?0x80:0x0;
++	value |= ((data >> (no*7)) & 0x7f);
++	putc(value, f);
++    } while ((no--)>0);
++
++}
++
++
++static int read_mb(dst, fd)
++     int *dst, fd;
++{
++    int ac = 0;
++    int ct = 0;
++
++    while (1) {
++	uint8 bt;
++	if ((ct++)==6) {
++	    st_err = err_inmb;
++	    return 0;
++	}
++
++	if ((read(fd, &bt, 1)) < 1) {
++	    st_err = err_ueof;
++	    return 0;
++	}
++	ac = (ac << 7) | (bt & 0x7f);   /* accumulates up to 42 bits?? FIXME */
++	if (!(bt & 0x80))
++	    break;
++    }
++    *dst = ac;
++    return 1;
++}
++
++
++static int read_ext(fd, fixed)
++     int fd;
++     uint8 fixed;
++{
++    if (!(fixed&0x7f)) {    /* no extensions */
++	return 1;
++    }
++
++    /*
++     * The only described type is WBMP 0, that must not
++     * have extensions.
++     */
++
++    st_err = err_extf;
++    return 0;
++
++    /*
++
++    fixed = (fixed >> 5)&0x3;
++
++    switch (fixed) {
++    case 0:
++	while (true) {
++	    SREADU8(fd, fixed);
++	    if (!(fixed & 0x7f)) { break; }
++	}
++	break;
++    case 0x3:
++	{
++	    char * par;
++	    char * val;
++	    SREADU8(fd, fixed);
++	    SREADC(fd, par, (fixed>>4)&0x6);
++	    SREADC(fd, val, fixed&0xf);
++	}
++	break;
++    }
++    */
++}
++
++
++static void *mymalloc(numbytes)
++     int numbytes;
++{
++    mymem = (void**)realloc(mymem, mymems+1);
++    if (!mymem)
++	FatalError("LoadWBMP: can't realloc buffer");
++    return (mymem[mymems++] = malloc(numbytes));
++}
++
++
++static void myfree()
++{
++    int i;
++
++    if (mymem) {
++	for (i=0; i<mymems; i++) {
++	    if (mymem[i])
++	        free(mymem[i]);
++	}
++	free(mymem);
++    }
++    mymem = (void**)NULL;
++    mymems = 0;
++}
++
++
++static uint8 *render1(data, size, npixels)
++     uint8 *data;
++     int size, npixels;
++{
++    byte * pic;
++    int i;
++    int cnt = 0;
++    uint8 cb = *data;
++
++    pic = calloc(npixels,1);   /* checked for overflow by caller */
++    if (!pic) {
++	myfree();
++	FatalError("LoadWBMP: can't allocate 'pic' buffer");
++    }
++
++    /* expand bits into bytes */
++    /* memset(pic, 0, npixels); */
++
++    for (i=0; i<npixels; i++) {
++
++	pic[i] = (cb>>7)&1;
++
++	if ((++cnt)==8) {
++	    cb = *(++data);
++	    cnt = 0;
++	} else {
++	    cb <<=1;
++	}
++    }
++    return pic;
++}
+diff -Naru xv-3.10a/xvzx.c xv-3.10a.jumbo/xvzx.c
+--- xv-3.10a/xvzx.c	1970-01-01 01:00:00.000000000 +0100
++++ xv-3.10a.jumbo/xvzx.c	2007-05-14 02:53:46.000000000 +0200
+@@ -0,0 +1,349 @@
++/*
++ * xvzx.c - load routine for Spectrum screen$
++ *
++ * John Elliott, 7 August 1998
++ *
++ * LoadZX(fname, pinfo)  -  load file
++ * WriteZX(fp,pic,ptype,w,h,r,g,b,numcols,style,cmt,comment) - convert to
++ *                          256x192 SCREEN$ and save.
++ */
++
++#include "copyright.h"
++
++#include "xv.h"
++
++
++
++/*
++ * comments on error handling:
++ * a file with a bad header checksum is a warning error.
++ *
++ * not being able to malloc is a Fatal Error.  The program is aborted.
++ */
++
++
++#define TRUNCSTR "File appears to be truncated."
++
++static int zxError PARM((const char *, const char *));
++
++static const char *bname;
++
++/*******************************************/
++int LoadZX(fname, pinfo)
++     char    *fname;
++     PICINFO *pinfo;
++/*******************************************/
++{
++  /* returns '1' on success */
++
++  FILE  *fp;
++  unsigned int    c, c1;
++  int   x,y, trunc;
++  byte  *zxfile;
++
++  bname = BaseName(fname);
++
++  pinfo->pic     = (byte *) NULL;
++  pinfo->comment = (char *) NULL;
++
++  /* Allocate memory for a 256x192x8bit image */
++
++  pinfo->pic     = (byte *)malloc(256*192);
++  if (!pinfo->pic) FatalError("malloc failure in xvzx.c LoadZX");
++
++  /* Allocate 1B80h bytes and slurp the whole file into memory */
++
++  zxfile         = (byte *)malloc(7040);
++  if (!zxfile)     FatalError("malloc failure in xvzx.c LoadZX");
++
++  /* open the file */
++  fp = xv_fopen(fname,"r");
++  if (!fp) return (zxError(bname, "can't open file"));
++
++  /* Load it in en bloc */
++  memset(zxfile, 0, 7040);
++  if (fread(zxfile, 1, 7040, fp) < 7040) trunc = 1;
++
++  /* Transform to 8-bit */
++
++  for (y = 0; y < 192; y++) for (x = 0; x < 256; x++)
++  {
++     /* Spectrum screen layout: three 2k segments at y=0, y=64, y=128 */
++     /* In each segment: Scan lines 0,8,16,...,56,1,9,...,57 etc.  Each
++        scanline is 32 bytes, so line 1 is 256 bytes after line 0
++
++        So address of line start is ((y>>6) * 2048) + ((y & 7) * 256)
++        + ((y & 0x38) * 4)
++
++       The colour byte for a cell is at screen + 6k + (y >> 3)*32 + (x>>3)
++
++       */
++
++     int offset;
++     byte *dst  = pinfo->pic + 256*y + x;
++     byte attr, pt, mask;
++
++     offset  = (y >> 6)   * 2048;
++     offset += (y & 7)    * 256;
++     offset += (y & 0x38) * 4;
++     offset += (x >> 3);
++
++     pt = zxfile[offset + 128];	/* Ink/paper map */
++
++     offset = 0x1880;
++     offset += (y >> 3) * 32;
++     offset += (x >> 3);
++
++     attr = zxfile[offset]; 	/* Colours for cell */
++
++     mask = 0x80;
++
++     if (x & 7) mask >>= (x & 7);
++
++     if (pt & mask)  *dst = attr & 7;        /* Ink */
++     else            *dst = (attr >> 3) & 7; /* Paper */
++
++     if (attr & 0x40) *dst |= 8; /* High intensity */
++  }
++
++  /* Picture bytes converted; now build the colour maps */
++
++  pinfo->normw = pinfo->w = 256;
++  pinfo->normh = pinfo->h = 192;
++  pinfo->type = PIC8;
++
++  for (c = 0; c < 16; c++)
++  {
++    if (c < 8) c1 = 192; else c1 = 255;	/* low-intensity colours use 192 */
++					/* high-intensity colours use 255 */
++    pinfo->b[c] = (c & 1 ? c1 : 0);
++    pinfo->r[c] = (c & 2 ? c1 : 0);
++    pinfo->g[c] = (c & 4 ? c1 : 0);
++  }
++
++  pinfo->colType = F_FULLCOLOR;
++  pinfo->frmType = F_ZX;		/* Save as SCREEN$ */
++  sprintf(pinfo->fullInfo, "Spectrum SCREEN$, load address %04x",
++                                 zxfile[16]+256*zxfile[17]);
++  strcpy(pinfo->shrtInfo, "Spectrum SCREEN$.");
++
++  /* Almost as an afterthought, check that the +3DOS header is valid.
++
++     If it isn't, then odds are that the file isn't a graphic. But it
++     had the right magic number, so it might be. Let them see it anyway.
++
++     The check is: Byte 127 of the header should be the 8-bit sum of bytes
++                   0-126 of the header. The header should also have the
++                   +3DOS magic number, but we know it does or we wouldn't
++                   have got this far.
++  */
++
++  c1 = 0;
++  for (c1 = c = 0; c < 127; c++) c1 = ((c1 + zxfile[c]) & 0xFF);
++  if (c1 != zxfile[127]) zxError(bname, "Bad header checksum.");
++
++  fclose(fp);
++  free(zxfile);
++  return 1;
++}
++
++
++
++
++
++/*******************************************/
++static int zxError(fname, st)
++     const char *fname, *st;
++{
++  SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
++  return 0;
++}
++
++
++/* Spectrum screen file header. The first 18 bytes are used in the magic
++   number test */
++
++byte ZXheader[128] =
++{
++    'P', 'L', 'U', 'S', '3', 'D', 'O', 'S', 26,	 /* Spectrum +3DOS file */
++      1,   0, 					 /* Header type 1.0 */
++    128,  27,  0,   0,				 /* 7040 bytes */
++      3,	                                 /* Binary format */
++      0, 27,   					 /* 6912 data bytes */
++      0, 64					 /* load address 0x4000 */
++};
++
++
++
++/* Get the Spectrum colour/bright byte (0-15) from a pixel */
++
++static int PointZX(pic, w, h, rmap, gmap, bmap, x, y)
++	byte *pic;
++	int w,h;
++	byte *rmap, *gmap, *bmap;
++	int x,y;
++{
++	int index, r, g, b, zxc;
++
++	/* If the picture is smaller than the screen, pad out the edges
++           with "bright black" - a colour not otherwise returned */
++
++	if (x >= w || y >= h) return 8;
++
++	/* Get colour index */
++
++	index = pic[y*w + x];
++
++	/* Convert to rgb */
++
++	r = rmap[index];
++	g = gmap[index];
++	b = bmap[index];
++	zxc = 0;
++
++	/* Work out Spectrum colour by a simplistic "nearest colour" method */
++
++	if (b >= 160) zxc |= 1;	/* Blue */
++	if (r >= 160) zxc |= 2;	/* Red */
++	if (g >= 160) zxc |= 4;	/* Green */
++	if (r > 208 || g >= 208 || b >= 208) zxc |= 8; /* High intensity */
++
++	return zxc;
++}
++
++
++/* Work out what colours should be used in a cell */
++
++static void CellZX(pic, w, h, rmap, gmap, bmap, cx, cy, zxfile)
++        byte *pic;
++        int w,h;
++        byte *rmap, *gmap, *bmap;
++        int cx,cy;
++	byte *zxfile;
++{
++	byte counts[16];	/* Count of no. of colours */
++	int offset, ink, paper, n, m, x, y, x0, y0, di, dp;
++
++	x0 = cx * 8;		/* Convert from cell to pixel coords */
++	y0 = cy * 8;
++
++	for (n = 0; n < 16; n++) counts[n] = 0;	 /* Reset all counts */
++
++	/* Count no. of pixels of various colours */
++
++	for (y = y0; y < y0+8; y++) for (x = x0; x < x0+8; x++)
++	{
++		m = PointZX(pic, w, h, rmap, gmap, bmap, x, y);
++
++		counts[m]++;
++	}
++	counts[8] = 0;	/* Discard Bright Black (pixels not in the picture area)
++                         */
++
++	/* Assign the most popular colour as ink */
++	for (n = m = ink = 0; n < 16; n++) if (counts[n] > m)
++	{
++		ink = n;
++		m   = counts[n];
++	}
++	counts[ink] = 0;
++
++	/* Assign the next most popular colour as paper */
++	for (n = m = paper = 0; n < 16; n++) if (counts[n] > m)
++	{
++		paper = n;
++		m     = counts[n];
++	}
++	/* We have ink and paper. Set cell's attributes */
++
++	offset = cy*32 + cx + 0x1880;
++
++	/* Set the high-intensity bit if ink is high-intensity */
++	if (ink & 8) zxfile[offset] = 0x40; else zxfile[offset] = 0;
++	zxfile[offset] |= ((paper & 7) << 3);
++	zxfile[offset] |=  (ink & 7);
++
++	/* Plot the points */
++	for (y = y0; y < y0+8; y++)
++	{
++	     byte mask = 0x80;
++
++	     offset  = (y >> 6)   * 2048;
++	     offset += (y & 7)    * 256;
++	     offset += (y & 0x38) * 4;
++	     offset += (x0 >> 3);
++
++	     for (x = x0; x < x0+8; x++)
++	     {
++		/* Work out whether the point should be plotted as ink or
++                   paper */
++		m = PointZX(pic, w, h, rmap, gmap, bmap, x, y);
++
++		di = (ink & 7)   - (m & 7);	/* "Difference" from ink */
++		dp = (paper & 7) - (m & 7);	/* "Difference" from paper */
++
++		if (di < 0) di = -di;
++		if (dp < 0) dp = -dp;
++
++		if (di < dp)	/* Point is more like ink */
++			zxfile[offset+128] |= mask;
++
++		mask = (mask >> 1);
++             }
++	}
++
++}
++
++
++
++/*******************************************/
++int WriteZX(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,comment)
++     FILE *fp;
++     byte *pic;
++     int   ptype, w,h;
++     byte *rmap, *gmap, *bmap;
++     int   numcols, colorstyle;
++     char *comment;
++{
++	int rv, x, y;
++	byte *zxfile;
++	byte *pic8;
++	byte  rtemp[256],gtemp[256],btemp[256];
++
++	/* To simplify matters, reduce 24-bit to 8-bit. Since the Spectrum
++           screen is 3.5-bit anyway, it doesn't make much difference */
++
++	if (ptype == PIC24)
++	{
++		pic8 = Conv24to8(pic, w, h, 256, rtemp,gtemp,btemp);
++		if (!pic8) FatalError("Unable to malloc in WriteZX()");
++		rmap = rtemp;  gmap = gtemp;  bmap = btemp;  numcols=256;
++  	}
++	else pic8 = pic;
++
++	ZXheader[127] = 0x71;	/* The correct checksum. */
++
++	/* Create a memory image of the SCREEN$ */
++
++	zxfile         = (byte *)malloc(7040);
++	if (!zxfile)     FatalError("malloc failure in xvzx.c WriteZX");
++
++	memset(zxfile, 0, 7040);	/* Reset all points to black */
++	memcpy(zxfile, ZXheader, 128);	/* Create +3DOS header */
++
++        /* Convert the image, character cell by character cell */
++        for (y = 0; y < 24; y++) for (x = 0; x < 32; x++)
++        {
++                CellZX(pic8, w, h, rmap, gmap, bmap, x, y, zxfile);
++        }
++	rv = 0;
++	if (fwrite(zxfile, 1, 7040, fp) < 7040) rv = -1;
++
++	if (ptype == PIC24) free(pic8);
++	free(zxfile);
++
++	if (ferror(fp)) rv = -1;
++
++	return rv;
++}
++


Property changes on: dists/trunk/xv/debian/patches/02-xv-3.10a-jumbo-files-20070520.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: dists/trunk/xv/debian/patches/03-no-docs.dpatch
===================================================================
--- dists/trunk/xv/debian/patches/03-no-docs.dpatch	                        (rev 0)
+++ dists/trunk/xv/debian/patches/03-no-docs.dpatch	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,21 @@
+#!/bin/sh /usr/share/dpatch/dpatch-run
+## 03-no-docs.dpatch by Fabian Greffrath <fabian at debian-unofficial.org>
+##
+## DP: Disable installation of the documentation.
+
+ at DPATCH@
+diff -urNad xv-3.10a~/Makefile xv-3.10a/Makefile
+--- xv-3.10a~/Makefile	2008-01-12 17:55:36.000000000 +0100
++++ xv-3.10a/Makefile	2008-01-12 17:57:50.000000000 +0100
+@@ -418,9 +418,8 @@
+ 	  $(DESTDIR)$(MANDIR)/vdcomp.$(MANSUF)
+ #
+ 	$(MKDIR) $(DESTDIR)$(DOCDIR)		# or $(DESTDIR)$(LIBDIR)
+-	cp README.jumbo docs/xvdocs.pdf docs/xvdocs.ps $(DESTDIR)$(DOCDIR)/.
+-	chmod 644 $(DESTDIR)$(DOCDIR)/README.jumbo \
+-	  $(DESTDIR)$(DOCDIR)/xvdocs.pdf $(DESTDIR)$(DOCDIR)/xvdocs.ps
++	cp README.jumbo $(DESTDIR)$(DOCDIR)/.
++	chmod 644 $(DESTDIR)$(DOCDIR)/README.jumbo
+ #
+ 	#$(MKDIR) $(DESTDIR)$(SYSCONFDIR)
+ 	#cp xv_mgcsfx.sample $(DESTDIR)$(SYSCONFDIR)/xv_mgcsfx


Property changes on: dists/trunk/xv/debian/patches/03-no-docs.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: dists/trunk/xv/debian/patches/04-shared-libjasper.dpatch
===================================================================
--- dists/trunk/xv/debian/patches/04-shared-libjasper.dpatch	                        (rev 0)
+++ dists/trunk/xv/debian/patches/04-shared-libjasper.dpatch	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,26 @@
+#!/bin/sh /usr/share/dpatch/dpatch-run
+## 04-shared-libjasper.dpatch by Fabian Greffrath <fabian at debian-unofficial.org>
+##
+## DP: Link programs against shared libjasper.
+
+ at DPATCH@
+diff -urNad xv-3.10a~/Makefile xv-3.10a/Makefile
+--- xv-3.10a~/Makefile	2008-01-12 18:07:08.000000000 +0100
++++ xv-3.10a/Makefile	2008-01-12 18:07:08.000000000 +0100
+@@ -179,13 +179,13 @@
+ JP2K    = -DDOJP2K
+ ###
+ #JP2KDIR = ../../jasper
+-JP2KDIR = /usr/local/lib
++JP2KDIR = /usr
+ ###
+ #JP2KINC = -I$(JP2KDIR)
+-JP2KINC = -I/usr/local/include
++JP2KINC = -I$(JP2KDIR)/include
+ ###
+ #JP2KLIB = -L$(JP2KDIR) -ljasper
+-JP2KLIB = $(JP2KDIR)/libjasper.a
++JP2KLIB = -L$(JP2KDIR)/lib -ljasper
+ 
+ 
+ ###


Property changes on: dists/trunk/xv/debian/patches/04-shared-libjasper.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: dists/trunk/xv/debian/patches/05-override-cflags.dpatch
===================================================================
--- dists/trunk/xv/debian/patches/05-override-cflags.dpatch	                        (rev 0)
+++ dists/trunk/xv/debian/patches/05-override-cflags.dpatch	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,104 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 05-override-cflags.dpatch by Fabian Greffrath <fabian at debian-unofficial.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Make CFLAGS overridable.
+
+ at DPATCH@
+diff -urNad xv-3.10a~/Makefile xv-3.10a/Makefile
+--- xv-3.10a~/Makefile	2008-01-09 14:03:18.000000000 +0100
++++ xv-3.10a/Makefile	2008-01-09 14:04:23.000000000 +0100
+@@ -18,29 +18,29 @@
+ #       -Wuninitialized -Wparentheses
+ 
+ 
+-CCOPTS = -O
++CFLAGS = -O
+ #
+ # these are the usual optimization and warning options for gcc; all such
+ # warnings but one (mktemp() use) have been eliminated (at least on Linux):
+-#CCOPTS = -O3 -Wall
++#CFLAGS = -O3 -Wall
+ #
+ # slightly more warnings... older code often made non-const pointers to
+ # static strings (nothing should blow up unless something tries to write
+ # to them):
+-#CCOPTS = -O3 -Wall -Wpointer-arith -Wcast-align -Wwrite-strings -Wnested-externs
++#CFLAGS = -O3 -Wall -Wpointer-arith -Wcast-align -Wwrite-strings -Wnested-externs
+ #
+ # for the next step up in gcc noise, try adding -W (but note that it adds a
+ # huge number of unused-parameter and signed/unsigned comparison warnings):
+-#CCOPTS = -O3 -Wall -W
++#CFLAGS = -O3 -Wall -W
+ 
+ ### NOTE: Sun running OpenWindows:
+ ### if you're using a SUN running OPENWINDOWS, you need to add these two
+-### options to the CCOPTS line, so it finds the libs and include files
++### options to the ALL_CFLAGS line, so it finds the libs and include files
+ ###   -L/usr/openwin/lib -I/usr/openwin/include
+ ###
+ ### In general, if your X11 include files and libX11.a library aren't in the
+ ### 'standard' places in which the C compiler looks, you should add '-L' and
+-### '-I' options on the CCOPTS line to tell the compiler where said files are.
++### '-I' options on the ALL_CFLAGS line to tell the compiler where said files are.
+ 
+ 
+ # older Unixen don't support the -p option, but its lack may mean installation
+@@ -106,7 +106,7 @@
+ ### included in the "tiff" subdir of XV, not an arbitrary copy of libtiff:
+ ###
+ #$(TIFFLIB):
+-#	( cd $(TIFFDIR) ; make CC='$(CC)' COPTS='$(CCOPTS) $(MCHN)' )
++#	( cd $(TIFFDIR) ; make CC='$(CC)' CFLAGS='$(CFLAGS) $(MCHN)' )
+ 
+ 
+ ###
+@@ -335,11 +335,12 @@
+ 
+ 
+ 
+-CFLAGS = $(CCOPTS) $(PNG) $(PNGINC) $(ZLIBINC) $(JPEG) $(JPEGINC) \
++ALL_CFLAGS = $(PNG) $(PNGINC) $(ZLIBINC) $(JPEG) $(JPEGINC) \
+ 	$(TIFF) $(TIFFINC) $(PDS) $(JP2K) $(JP2KINC) $(TVL10N) $(MGCSFX) \
+ 	$(UNIX) $(BSDTYPES) $(RAND) $(MALLOC) $(DXWM) $(MCHN) $(NODIRENT) \
+ 	$(VPRINTF) $(TIMERS) -DDOCDIR=\"$(DOCDIR)\" \
+-	-DSYSCONFDIR=\"$(SYSCONFDIR)\" -DXVEXECPATH=\"$(LIBDIR)\"
++	-DSYSCONFDIR=\"$(SYSCONFDIR)\" -DXVEXECPATH=\"$(LIBDIR)\" \
++	$(CFLAGS)
+ 
+ ### remove -lm for BeOS:
+ LIBS = $(TIFFLIB) $(JPEGLIB) $(PNGLIB) $(ZLIBLIB) $(JP2KLIB) -L/usr/X11R6/lib -lX11 -lm
+@@ -359,7 +360,7 @@
+ 
+ 
+ 
+-.c.o:	; $(CC) $(CFLAGS) -c $*.c
++.c.o:	; $(CC) $(ALL_CFLAGS) -c $*.c
+ 
+ 
+ 
+@@ -369,19 +370,19 @@
+ 
+ #xv: $(OBJS) $(JPEGLIB) $(TIFFLIB)
+ xv: $(OBJS)
+-	$(CC) -o xv $(CFLAGS) $(OBJS) $(LIBS)
++	$(CC) -o xv $(ALL_CFLAGS) $(OBJS) $(LIBS)
+ 
+ bggen: bggen.c
+-	$(CC) $(CFLAGS) -o bggen bggen.c $(LIBS)
++	$(CC) $(ALL_CFLAGS) -o bggen bggen.c $(LIBS)
+ 
+ vdcomp: vdcomp.c
+-	$(CC) $(CFLAGS) -o vdcomp vdcomp.c
++	$(CC) $(ALL_CFLAGS) -o vdcomp vdcomp.c
+ 
+ xcmap:  xcmap.c
+-	$(CC) $(CFLAGS) -o xcmap xcmap.c $(LIBS)
++	$(CC) $(ALL_CFLAGS) -o xcmap xcmap.c $(LIBS)
+ 
+ xvpictoppm:  xvpictoppm.c
+-	$(CC) $(CFLAGS) -o xvpictoppm xvpictoppm.c
++	$(CC) $(ALL_CFLAGS) -o xvpictoppm xvpictoppm.c
+ 
+ 
+ 


Property changes on: dists/trunk/xv/debian/patches/05-override-cflags.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: dists/trunk/xv/debian/pixmap/xv.xpm
===================================================================
--- dists/trunk/xv/debian/pixmap/xv.xpm	                        (rev 0)
+++ dists/trunk/xv/debian/pixmap/xv.xpm	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,50 @@
+/* XPM */
+static char * xv_xpm[] = {
+"32 32 15 1",
+" 	c None",
+".	c #000000",
+"+	c #E1E100",
+"@	c #000068",
+"#	c #E1FF00",
+"$	c #FFE100",
+"%	c #FFFF00",
+"&	c #FFC000",
+"*	c #E1C000",
+"=	c #FF9900",
+"-	c #E19900",
+";	c #FF6800",
+">	c #E16800",
+",	c #FF0000",
+"'	c #E10000",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                      .         ",
+"         +       @+ ###@   +.   ",
+"       ###.    ++..#$++.  %+%   ",
+"       #+$.   ++ at .%%$%+. &*&@   ",
+"       $++. .#$+.  &&==. &-&.   ",
+"       &&&.@&$$.   =-=. --==.   ",
+"       &&*@-**.   =-;-. =>;@ ,  ",
+"       &&&--=.   @>;>.   >;,'@. ",
+"       ==;;;.    ,;>@.  @'';,.  ",
+"       ',',.    ''''.   ''...   ",
+"      ,,''..    ,,>@.  @,.      ",
+"     ',,,,.    ,,''.   ',.      ",
+"    '''>''.   '',',.  ''.       ",
+"   ,''>'''. ',''',@  ';@.       ",
+"  .'>'.'''@'''.,''' '''.        ",
+"  ','. ,>''''..@'>,,''.         ",
+" .,;.  ''',,..  ',;''.          ",
+"  ;@    ';,..   ;,,'..          ",
+"  .,     ...     ,'..           ",
+"    .             .             ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};

Deleted: dists/trunk/xv/debian/rules
===================================================================
--- dists/trunk/xv/debian/rules	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/rules	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,96 +0,0 @@
-#!/usr/bin/make -f
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-include /usr/share/dpatch/dpatch.make
-
-CFLAGS = -Wall -g
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -O0
-else
-	CFLAGS += -O2
-endif
-
-build: build-stamp
-build-stamp: patch-stamp
-	dh_testdir
-
-	# Building package
-	$(MAKE) CCOPTS="$(CFLAGS)" PREFIX=/usr
-
-	touch build-stamp
-
-clean: clean-patched unpatch
-clean-patched: patch-stamp
-	dh_testdir
-	dh_testroot
-	rm -f build-stamp
-
-	# Cleaning package
-	$(MAKE) clean
-
-	dh_clean
-
-install: build
-	dh_testdir
-	dh_testroot
-	dh_clean -k
-	dh_installdirs
-
-	# Installing package
-	$(MAKE) install PREFIX=/usr DESTDIR=$(CURDIR)/debian/xv
-
-	# Installing pixmap
-	install -D -m 0644 debian/pixmap/xv.xpm debian/xv/usr/share/pixmaps/xv.xpm
-
-	# Moving PostScript documentation to the xv-docs package
-	mv -f debian/xv/usr/share/doc/xv/xvdocs.ps debian/xv-doc/usr/share/doc/xv-doc/xvdocs.ps
-
-	# Uudecoding PDF documentation to the xv-docs package
-	uudecode -o debian/xv-doc/usr/share/doc/xv-doc/xvdocs.pdf debian/doc/xvdocs.pdf.uue
-
-	# Installing bug control
-	for BUG in debian/bug/*; \
-	do \
-		install -D -m 0644 $$BUG debian/`basename $$BUG`/usr/share/bug/`basename $$BUG`/control || exit 1; \
-	done
-
-	# Installing lintian overrides
-	for LINTIAN in debian/lintian/*; \
-	do \
-		install -D -m 0644 $$LINTIAN debian/`basename $$LINTIAN`/usr/share/lintian/overrides/`basename $$LINTIAN` || exit 1; \
-	done
-
-binary-indep: build install
-	dh_testdir -i
-	dh_testroot -i
-	dh_installchangelogs -i CHANGELOG
-	dh_installdocs -i
-	dh_compress -i
-	dh_fixperms -i
-	dh_installdeb -i
-	dh_gencontrol -i
-	dh_md5sums -i
-	dh_builddeb -i
-
-binary-arch: build install
-	dh_testdir -a
-	dh_testroot -a
-	dh_installchangelogs -a CHANGELOG
-	dh_installdocs -a
-	dh_installmenu -a
-	dh_installmime -a
-	dh_installman -a
-	dh_strip -a --dbg-package=xv-dbg
-	dh_compress -a
-	dh_fixperms -a
-	dh_installdeb -a
-	dh_shlibdeps -a
-	dh_gencontrol -a
-	dh_md5sums -a
-	dh_builddeb -a
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install

Added: dists/trunk/xv/debian/rules
===================================================================
--- dists/trunk/xv/debian/rules	                        (rev 0)
+++ dists/trunk/xv/debian/rules	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,23 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/makefile.mk
+include /usr/share/cdbs/1/rules/dpatch.mk
+
+DEB_MAKE_BUILD_TARGET += PREFIX=/usr
+DEB_MAKE_INSTALL_TARGET += install PREFIX=/usr DESTDIR=$(CURDIR)/debian/xv
+
+DEB_INSTALL_CHANGELOGS_ALL += CHANGELOG
+
+cleanbuilddir:: apply-dpatches
+
+common-install-impl::
+	# Installing bug control
+	for BUG in debian/bug/*; do \
+		install -D -m 0644 $$BUG debian/`basename $$BUG`/usr/share/bug/`basename $$BUG`/control || exit 1; \
+	done
+
+	# Installing lintian overrides
+	for LINTIAN in debian/lintian/*; do \
+		install -D -m 0644 $$LINTIAN debian/`basename $$LINTIAN`/usr/share/lintian/overrides/`basename $$LINTIAN` || exit 1; \
+	done

Deleted: dists/trunk/xv/debian/watch
===================================================================
--- dists/trunk/xv/debian/watch	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/watch	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,3 +0,0 @@
-version=3
-ftp://ftp.cis.upenn.edu/pub/xv/xv-(.*)\.tar\.gz
-http://sf.net/png-mng/xv-3.10a-jumbo-patches-(.*)\.tar\.gz

Added: dists/trunk/xv/debian/watch
===================================================================
--- dists/trunk/xv/debian/watch	                        (rev 0)
+++ dists/trunk/xv/debian/watch	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,3 @@
+version=3
+ftp://ftp.cis.upenn.edu/pub/xv/xv-(.*)\.tar\.gz
+http://sf.net/png-mng/xv-3.10a-jumbo-patches-(.*)\.tar\.gz

Deleted: dists/trunk/xv/debian/xv-doc.dirs
===================================================================
--- dists/trunk/xv/debian/xv-doc.dirs	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/xv-doc.dirs	2008-01-15 22:03:08 UTC (rev 163)
@@ -1 +0,0 @@
-/usr/share/doc/xv-doc

Deleted: dists/trunk/xv/debian/xv-doc.doc-base
===================================================================
--- dists/trunk/xv/debian/xv-doc.doc-base	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/xv-doc.doc-base	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,11 +0,0 @@
-Document: xv-doc
-Title: XV documentation
-Author: John Bradley <bradley at trilon.com>
-Abstract: This manual describes what XV is and how it can be used.
-Section: Apps/Graphics
-
-Format: postscript
-Files: /usr/share/doc/xv-doc/xvdocs.ps.gz
-
-Format: pdf
-Files: /usr/share/doc/xv-doc/xvdocs.pdf.gz

Added: dists/trunk/xv/debian/xv-doc.doc-base
===================================================================
--- dists/trunk/xv/debian/xv-doc.doc-base	                        (rev 0)
+++ dists/trunk/xv/debian/xv-doc.doc-base	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,8 @@
+Document: xv-doc
+Title: XV manual
+Author: John Bradley <bradley at trilon.com>
+Abstract: This manual describes what XV is and how it can be used.
+Section: Apps/Graphics
+
+Format: postscript
+Files: /usr/share/doc/xv-doc/xvdocs.ps.gz

Deleted: dists/trunk/xv/debian/xv-doc.docs
===================================================================
--- dists/trunk/xv/debian/xv-doc.docs	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/xv-doc.docs	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,3 +0,0 @@
-BUGS
-IDEAS
-README*

Added: dists/trunk/xv/debian/xv-doc.docs
===================================================================
--- dists/trunk/xv/debian/xv-doc.docs	                        (rev 0)
+++ dists/trunk/xv/debian/xv-doc.docs	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,4 @@
+BUGS
+IDEAS
+README*
+docs/xvdocs.ps

Deleted: dists/trunk/xv/debian/xv.docs
===================================================================
--- dists/trunk/xv/debian/xv.docs	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/xv.docs	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,3 +0,0 @@
-BUGS
-IDEAS
-README*

Added: dists/trunk/xv/debian/xv.docs
===================================================================
--- dists/trunk/xv/debian/xv.docs	                        (rev 0)
+++ dists/trunk/xv/debian/xv.docs	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,3 @@
+BUGS
+IDEAS
+README*

Added: dists/trunk/xv/debian/xv.install
===================================================================
--- dists/trunk/xv/debian/xv.install	                        (rev 0)
+++ dists/trunk/xv/debian/xv.install	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1 @@
+debian/pixmap/xv.xpm	/usr/share/pixmaps/

Deleted: dists/trunk/xv/debian/xv.menu
===================================================================
--- dists/trunk/xv/debian/xv.menu	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/xv.menu	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,3 +0,0 @@
-?package(xv):needs="X11" section="Applications/Graphics"\
-  title="XV" longtitle="image viewer and manipulator"\
-  command="/usr/bin/xv" icon="/usr/share/pixmaps/xv.xpm"

Added: dists/trunk/xv/debian/xv.menu
===================================================================
--- dists/trunk/xv/debian/xv.menu	                        (rev 0)
+++ dists/trunk/xv/debian/xv.menu	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,3 @@
+?package(xv):needs="X11" section="Applications/Graphics"\
+  title="XV" longtitle="image viewer and manipulator"\
+  command="/usr/bin/xv" icon="/usr/share/pixmaps/xv.xpm"

Deleted: dists/trunk/xv/debian/xv.mime
===================================================================
--- dists/trunk/xv/debian/xv.mime	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xv/debian/xv.mime	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,16 +0,0 @@
-image/gif; xv %s; description="GIF Image"; test=test "$DISPLAY"; priority=3
-image/jpeg; xv %s; description="JPEG Image"; test=test "$DISPLAY"; priority=3
-image/tiff; xv %s; description="TIFF Image"; test=test "$DISPLAY"; priority=3
-image/postscript; xv %s; description="Postscript Image"; test=test "$DISPLAY"; priority=3
-image/x-portable-bitmap; xv %s; description="PBM Image"; test=test "$DISPLAY"; priority=3
-image/x-portable-graymap; xv %s; description="PGM Image"; test=test "$DISPLAY"; priority=3
-image/x-portable-pixmap; xv %s; description="PPM Image"; test=test "$DISPLAY"; priority=3
-image/x-xbitmap; xv %s; description="XBM Image"; test=test "$DISPLAY"; priority=3
-image/x-xpixmap; xv %s; description="XPM Image"; test=test "$DISPLAY"; priority=3
-image/x-ms-bmp; xv %s; description="BMP Image"; test=test "$DISPLAY"; priority=3
-image/cmu-raster; xv %s; description="CMU-RasterFile Image"; test=test "$DISPLAY"; priority=3
-image/x-rgb; xv %s; description="RGB Image"; test=test "$DISPLAY"; priority=3
-image/targa; xv %s; description="TARGA Image"; test=test "$DISPLAY"; priority=3
-image/fits; xv %s; description="FITS Image"; test=test "$DISPLAY"; priority=3
-image/png; xv %s; description="PNG Image"; test=test "$DISPLAY"; priority=3
-image/pm; xv %s; description="PM Image"; test=test "$DISPLAY"; priority=3

Added: dists/trunk/xv/debian/xv.mime
===================================================================
--- dists/trunk/xv/debian/xv.mime	                        (rev 0)
+++ dists/trunk/xv/debian/xv.mime	2008-01-15 22:03:08 UTC (rev 163)
@@ -0,0 +1,16 @@
+image/gif; xv %s; description="GIF Image"; test=test "$DISPLAY"; priority=3
+image/jpeg; xv %s; description="JPEG Image"; test=test "$DISPLAY"; priority=3
+image/tiff; xv %s; description="TIFF Image"; test=test "$DISPLAY"; priority=3
+image/postscript; xv %s; description="Postscript Image"; test=test "$DISPLAY"; priority=3
+image/x-portable-bitmap; xv %s; description="PBM Image"; test=test "$DISPLAY"; priority=3
+image/x-portable-graymap; xv %s; description="PGM Image"; test=test "$DISPLAY"; priority=3
+image/x-portable-pixmap; xv %s; description="PPM Image"; test=test "$DISPLAY"; priority=3
+image/x-xbitmap; xv %s; description="XBM Image"; test=test "$DISPLAY"; priority=3
+image/x-xpixmap; xv %s; description="XPM Image"; test=test "$DISPLAY"; priority=3
+image/x-ms-bmp; xv %s; description="BMP Image"; test=test "$DISPLAY"; priority=3
+image/cmu-raster; xv %s; description="CMU-RasterFile Image"; test=test "$DISPLAY"; priority=3
+image/x-rgb; xv %s; description="RGB Image"; test=test "$DISPLAY"; priority=3
+image/targa; xv %s; description="TARGA Image"; test=test "$DISPLAY"; priority=3
+image/fits; xv %s; description="FITS Image"; test=test "$DISPLAY"; priority=3
+image/png; xv %s; description="PNG Image"; test=test "$DISPLAY"; priority=3
+image/pm; xv %s; description="PM Image"; test=test "$DISPLAY"; priority=3

Modified: dists/trunk/xvidcore/debian/control
===================================================================
--- dists/trunk/xvidcore/debian/control	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xvidcore/debian/control	2008-01-15 22:03:08 UTC (rev 163)
@@ -11,10 +11,10 @@
                debhelper (>= 5),
                dpatch,
                yasm
-Standards-Version: 3.7.2
-Homepage: http://www.xvid.org/
+Standards-Version: 3.7.3
 Vcs-Svn: svn://svn.debian.org/restricted/dists/trunk/xvidcore/
 Vcs-Browser: http://svn.debian.org/wsvn/restricted/dists/trunk/xvidcore/
+Homepage: http://www.xvid.org/
 
 Package: libxvidcore4
 Section: restricted/libs

Modified: dists/trunk/xvidcore/debian/copyright
===================================================================
--- dists/trunk/xvidcore/debian/copyright	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xvidcore/debian/copyright	2008-01-15 22:03:08 UTC (rev 163)
@@ -1,4 +1,4 @@
-This package was debianized by Daniel Baumann <panthera at debian-unofficial.org> on
+This package was debianized by Daniel Baumann <daniel at debian.org> on
 Sun,  1 Jan 2006 00:00:00 +0100.
 
 It was downloaded from <http://www.xvid.org/downloads.html>.
@@ -34,5 +34,5 @@
 On Debian systems, the complete text of the GNU General Public License
 can be found in the `/usr/share/common-licenses/GPL' file.
 
-The Debian packaging is (C) 2005-2007, Daniel Baumann <daniel at debian.org> and
+The Debian packaging is (C) 2005-2008, Daniel Baumann <daniel at debian.org> and
 is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

Modified: dists/trunk/xvidcore/debian/rules
===================================================================
--- dists/trunk/xvidcore/debian/rules	2007-12-13 22:41:52 UTC (rev 162)
+++ dists/trunk/xvidcore/debian/rules	2008-01-15 22:03:08 UTC (rev 163)
@@ -10,9 +10,9 @@
 DEB_INSTALL_CHANGELOGS_ALL += ChangeLog
 DEB_INSTALL_DOCS_ALL += AUTHORS README TODO
 
-DEB_DH_INSTALL_ARGS += --sourcedir=debian/tmp
+DEB_DH_INSTALL_SOURCEDIR := debian/tmp
 
-common-install-arch::
+common-install-impl::
 	# Installing bug control
 	for BUG in debian/bug/*; do \
 		install -D -m 0644 $$BUG debian/`basename $$BUG`/usr/share/bug/`basename $$BUG`/control || exit 1; \




More information about the Restricted-changes mailing list