diff options
author | Patrick J Volkerding <volkerdi@slackware.com> | 2010-05-19 08:58:23 +0000 |
---|---|---|
committer | Eric Hameleers <alien@slackware.com> | 2018-05-31 22:43:05 +0200 |
commit | b76270bf9e6dd375e495fec92140a79a79415d27 (patch) | |
tree | 3dbed78b2279bf9f14207a16dc634b90995cbd40 /source/xap/xv/xv-3.10a-jumbo-fix-enh-patch-20070520.txt | |
parent | 5a12e7c134274dba706667107d10d231517d3e05 (diff) | |
download | current-b76270bf9e6dd375e495fec92140a79a79415d27.tar.gz |
Slackware 13.1slackware-13.1
Wed May 19 08:58:23 UTC 2010
Slackware 13.1 x86_64 stable is released!
Lots of thanks are due -- see the RELEASE_NOTES and the rest of the
ChangeLog for credits. The ISOs are on their way to replication,
a 6 CD-ROM 32-bit set and a dual-sided 32-bit/64-bit x86/x86_64 DVD.
We are taking pre-orders now at store.slackware.com, and offering
a discount if you sign up for a subscription. Consider picking up
a copy to help support the project. Thanks again to the Slackware
community for testing, contributing, and generally holding us to a
high level of quality. :-)
Enjoy!
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.txt | 42401 |
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 00000000..51ff30a9 --- /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) */ |