summaryrefslogtreecommitdiffstats
path: root/source/xap/xv/xv-3.10a-jumbo-fix-enh-patch-20070520.txt
diff options
context:
space:
mode:
Diffstat (limited to 'source/xap/xv/xv-3.10a-jumbo-fix-enh-patch-20070520.txt')
-rw-r--r--source/xap/xv/xv-3.10a-jumbo-fix-enh-patch-20070520.txt42401
1 files changed, 42401 insertions, 0 deletions
diff --git a/source/xap/xv/xv-3.10a-jumbo-fix-enh-patch-20070520.txt b/source/xap/xv/xv-3.10a-jumbo-fix-enh-patch-20070520.txt
new file mode 100644
index 000000000..51ff30a98
--- /dev/null
+++ b/source/xap/xv/xv-3.10a-jumbo-fix-enh-patch-20070520.txt
@@ -0,0 +1,42401 @@
+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@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@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@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@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@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@frec.bull.fr (Marc Kossa) */
+ /* MSBFirst mods added by dale@ntg.com (Dale Luck) */
+- /* additional fixes by evol@infko.uni-koblenz.de
++ /* additional fixes by evol@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@frec.bull.fr (Marc Kossa) */
+ /* MSBFirst mods added by dale@ntg.com (Dale Luck) */
+- /* additional fixes by evol@infko.uni-koblenz.de
++ /* additional fixes by evol@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@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@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@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@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) */