diff options
author | Seemant Kulleen <seemant@gentoo.org> | 2002-04-30 05:47:38 +0000 |
---|---|---|
committer | Seemant Kulleen <seemant@gentoo.org> | 2002-04-30 05:47:38 +0000 |
commit | 208cc629627f9bd4c9b39f51db7daccbe2ccf376 (patch) | |
tree | 7a860d9ae5dc3ef35e43db42ad7b46ab11a73253 /media-gfx/xv/files | |
parent | xv masked until ibiblio mirror gets updatedwith naz's patch (diff) | |
download | gentoo-2-208cc629627f9bd4c9b39f51db7daccbe2ccf376.tar.gz gentoo-2-208cc629627f9bd4c9b39f51db7daccbe2ccf376.tar.bz2 gentoo-2-208cc629627f9bd4c9b39f51db7daccbe2ccf376.zip |
naz's new patch so that tcsh is not required any more
Diffstat (limited to 'media-gfx/xv/files')
-rw-r--r-- | media-gfx/xv/files/digest-xv-3.10a-r2 | 2 | ||||
-rw-r--r-- | media-gfx/xv/files/xv-naz-gentoo.patch | 14838 |
2 files changed, 2 insertions, 14838 deletions
diff --git a/media-gfx/xv/files/digest-xv-3.10a-r2 b/media-gfx/xv/files/digest-xv-3.10a-r2 new file mode 100644 index 000000000000..c1b66a0fab78 --- /dev/null +++ b/media-gfx/xv/files/digest-xv-3.10a-r2 @@ -0,0 +1,2 @@ +MD5 2d4fbeec1561304362781cc8e2f7f72d xv-3.10a.tar.gz 2259124 +MD5 df8d702d9c23f7f6c70e84e4d1d80da2 xv-png-patch.tar.bz2 97733 diff --git a/media-gfx/xv/files/xv-naz-gentoo.patch b/media-gfx/xv/files/xv-naz-gentoo.patch deleted file mode 100644 index 3c0edcc83d4c..000000000000 --- a/media-gfx/xv/files/xv-naz-gentoo.patch +++ /dev/null @@ -1,14838 +0,0 @@ -diff -urN xv-3.10a/Makefile xv-3.10apatched/Makefile ---- xv-3.10a/Makefile Mon Jan 23 12:20:54 1995 -+++ xv-3.10apatched/Makefile Tue Apr 30 00:12:54 2002 -@@ -1,8 +1,8 @@ - # Makefile for xv - - # your C compiler (and options) of choice --CC = cc --# CC = gcc -ansi -+#CC = cc -+CC = gcc -ansi - - # use this if you're using 'cc' on a DEC Alpha (OSF/1) or MIPS (Ultrix) system: - # CC = cc -std1 -Olimit 750 -@@ -14,7 +14,7 @@ - # -Wuninitialized -Wparentheses - - --CCOPTS = -O -+CCOPTS = -O -L/usr/X11R6/lib -D_BSD_SOURCE - - - ### NOTE: Sun running OpenWindows: -@@ -28,10 +28,10 @@ - - - ### Installation locations --BINDIR = /usr/local/bin --MANDIR = /usr/local/man/man1 -+BINDIR = /usr/X11R6/bin -+MANDIR = /usr/man/man1 - MANSUF = 1 --LIBDIR = /usr/local/lib -+LIBDIR = /usr/lib - - - buildit: all -@@ -46,13 +46,28 @@ - ### on your machine, *COMMENT OUT* the following lines - ### - 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 -+#JPEGINC = -I$(JPEGDIR) -+JPEGLIB = -ljpeg -+#$(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 PNG library to compile -+### on your machine, *COMMENT OUT* the following lines -+### -+PNG = -DDOPNG -+PNGLIB = -lpng -+ -+ -+### -+### if, for whatever reason, you're unable to get the PNG library to compile -+### on your machine, *COMMENT OUT* the following lines -+### -+ZLIBLIB = -lz - - - ### -@@ -102,7 +117,7 @@ - - - ### for LINUX, uncomment the following line --#MCHN = -DLINUX -+MCHN = -DLINUX - - - # For SCO 1.1 (UNIX 3.2v2) machines, uncomment the following: -@@ -144,7 +159,7 @@ - - # if your machine has the usleep() function, uncomment the following line: - # if it doesn't, or you're not sure, leave this line alone. --#TIMERS = -DUSLEEP -+TIMERS = -DUSLEEP - - - # if XV locks up whenever you click on *any* of the buttons, the Timer() -@@ -186,9 +201,9 @@ - - CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \ - $(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \ -- $(DXWM) $(MCHN) -+ $(DXWM) $(MCHN) $(PNG) $(PNGINC) $(ZLIBINC) - --LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) -lm -+LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) $(PNGLIB) $(ZLIBLIB) -lm - - 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 +211,7 @@ - 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 - - MISC = README INSTALL CHANGELOG IDEAS - -@@ -267,7 +282,7 @@ - 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_trash bits/fcurs bits/fccurs bits/fdcurs bits/fcursm --xvbrowse.o: bits/br_xwd -+xvbrowse.o: bits/br_xwd bits/br_png - - 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 -diff -urN xv-3.10a/Makefile.std xv-3.10apatched/Makefile.std ---- xv-3.10a/Makefile.std Mon Jan 23 17:06:26 1995 -+++ xv-3.10apatched/Makefile.std Tue Apr 30 00:10:16 2002 -@@ -56,6 +56,25 @@ - - - ### -+### if, for whatever reason, you're unable to get the PNG library to compile -+### on your machine, *COMMENT OUT* the following lines -+### -+PNG = -DDOPNG -+PNGDIR = /usr/local/src/libpng -+PNGINC = -I$(PNGDIR) -+PNGLIB = -L$(PNGDIR) -lpng -+ -+ -+### -+### if, for whatever reason, you're unable to get the PNG library to compile -+### on your machine, *COMMENT OUT* the following lines -+### -+ZLIBDIR = /usr/local/src/zlib -+ZLIBINC = -I$(ZLIBDIR) -+ZLIBLIB = -L$(ZLIBDIR) -lz -+ -+ -+### - ### if, for whatever reason, you're unable to get the TIFF library to compile - ### on your machine, *COMMENT OUT* the following lines - ### -@@ -186,9 +205,9 @@ - - CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \ - $(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \ -- $(DXWM) $(MCHN) -+ $(DXWM) $(MCHN) $(PNG) $(PNGINC) $(ZLIBINC) - --LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) -lm -+LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) $(PNGLIB) $(ZLIBLIB) -lm - - 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 +215,7 @@ - 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 - - MISC = README INSTALL CHANGELOG IDEAS - -@@ -267,7 +286,7 @@ - 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_trash bits/fcurs bits/fccurs bits/fdcurs bits/fcursm --xvbrowse.o: bits/br_xwd -+xvbrowse.o: bits/br_xwd bits/br_png - - 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 -diff -urN xv-3.10a/Makefile~ xv-3.10apatched/Makefile~ ---- xv-3.10a/Makefile~ Wed Dec 31 16:00:00 1969 -+++ xv-3.10apatched/Makefile~ Tue Apr 30 00:10:16 2002 -@@ -0,0 +1,338 @@ -+# Makefile for xv -+ -+# your C compiler (and options) of choice -+CC = cc -+# CC = gcc -ansi -+ -+# use this if you're using 'cc' on a DEC Alpha (OSF/1) or MIPS (Ultrix) system: -+# CC = cc -std1 -Olimit 750 -+ -+# this is what I personally use on an OSF Alpha. Not that I recommend it. -+# CC = gcc -g -ansi -pedantic -W -Wreturn-type -Wmissing-prototypes \ -+# -Wstrict-prototypes -Waggregate-return -Wconversion \ -+# -Wpointer-arith -Wcomment -Wformat -Wchar-subscripts \ -+# -Wuninitialized -Wparentheses -+ -+ -+CCOPTS = -O -+ -+ -+### NOTE: Sun running OpenWindows: -+### if you're using a SUN running OPENWINDOWS, you need to add these two -+### options to the CCOPTS line, so it finds the libs and include files -+### -L/usr/openwin/lib -I/usr/openwin/include -+### -+### In general, if your X11 include files and libX11.a library aren't in the -+### 'standard' places in which the C compiler looks, you should add '-L' and -+### '-I' options on the CCOPTS line to tell the compiler where said files are. -+ -+ -+### Installation locations -+BINDIR = /usr/local/bin -+MANDIR = /usr/local/man/man1 -+MANSUF = 1 -+LIBDIR = /usr/local/lib -+ -+ -+buildit: all -+ -+ -+########################### 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 JPEG library to compile -+### on your machine, *COMMENT OUT* the following lines -+### -+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 -+ -+ -+### -+### if, for whatever reason, you're unable to get the PNG library to compile -+### on your machine, *COMMENT OUT* the following lines -+### -+PNG = -DDOPNG -+PNGDIR = /usr/local/src/libpng -+PNGINC = -I$(PNGDIR) -+PNGLIB = -L$(PNGDIR) -lpng -+ -+ -+### -+### if, for whatever reason, you're unable to get the PNG library to compile -+### on your machine, *COMMENT OUT* the following lines -+### -+ZLIBDIR = /usr/local/src/zlib -+ZLIBINC = -I$(ZLIBDIR) -+ZLIBLIB = -L$(ZLIBDIR) -lz -+ -+ -+### -+### if, for whatever reason, you're unable to get the TIFF 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)' ) -+ -+ -+### -+### 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 -+### -+PDS = -DDOPDS -+ -+ -+#----------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 -+ -+ -+#----------Machine Specific Configurations---------- -+ -+### If you are using an SGI system, uncomment the following line -+#MCHN = -Dsgi -+ -+ -+### 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 -+# 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) -+# to whichever of those lines you used, as HP tends to store their X11 -+# include files in a non-standard place... -+ -+ -+### for LINUX, uncomment the following line -+#MCHN = -DLINUX -+ -+ -+# 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 -+# -+# 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) -+# No other switches should be necessary, or so I'm told... -+# -+#MCHN = -q extensions=pcc_c -D__UMAXV__ -L/usr2/usr/lib/X11 -DSVR4 -+ -+# For Interactive/SunSoft Unix ISC 4.0 (whatever *that* is!) -+#MCHN = -DSVR4 -DBSDTYPES -+ -+ -+#----------'Roll Your Own' Options---------- -+ -+ -+# if your machine doesn't have 'random()', but does have 'rand()', -+# uncomment the following line: -+# -+#RAND = -DNO_RANDOM -+ -+ -+# if your system *doesn't* have /usr/include/dirent.h, (ie, isn't POSIX -+# compliant, then you may have to uncomment the following line to use the -+# 'old-style' directory-handling structures -+# -+#NODIRENT = -DNODIRENT -+ -+ -+# if your machine has the usleep() function, uncomment the following line: -+# if it doesn't, or you're not sure, leave this line alone. -+#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 -+# uncomment the following line: -+#TIMERS = -DNOTIMER -+ -+ -+# if you are running under DXWM, I pity you. XV doesn't work correctly -+# under DXWM. You should probably be running MWM. However, if such is -+# not an option for you, try uncommenting the following line. The -+# behavior won't be 'right', but it will be less 'wrong'. -+#DXWM = -DDXWM -+ -+ -+# 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 -+ -+ -+# if your machine doesn't have 'vprintf()' or 'vsprintf()' -+# (see vprintf.c for more information, if needed) -+# -+# (for BSD 4.3 VAX, uncomment the following line) -+#VPRINTF = -DNEED_VPRINTF -DINTSPRINTF -DLONGINT -DNOVOID -+# (for (stock) IBM RT AOS 4.3, uncomment the following line) -+#VPRINTF = -DNEED_VPRINTF -DLONGINT -DNOSTDHDRS -+# (for Sequent running DYNIX 3.1.4, uncomment the following line) -+#VPRINTF = -DNEED_VPRINTF -DLONGINT -DNOSTDHDRS -+ -+ -+ -+ -+################ END OF CONFIGURATION OPTIONS ################# -+ -+ -+ -+ -+CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \ -+ $(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \ -+ $(DXWM) $(MCHN) $(PNG) $(PNGINC) $(ZLIBINC) -+ -+LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) $(PNGLIB) $(ZLIBLIB) -lm -+ -+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 \ -+ xvgifwr.o xvdir.o xvbutt.o xvpbm.o xvxbm.o xvgam.o xvbmp.o \ -+ 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 xvpng.o -+ -+MISC = README INSTALL CHANGELOG IDEAS -+ -+ -+ -+.c.o: ; $(CC) $(CFLAGS) -c $*.c -+ -+ -+ -+all: $(JPEGLIB) $(TIFFLIB) xv bggen vdcomp xcmap xvpictoppm -+ -+ -+xv: $(OBJS) $(JPEGLIB) $(TIFFLIB) -+ $(CC) -o xv $(CFLAGS) $(OBJS) $(LIBS) -+ -+bggen: bggen.c -+ $(CC) $(CFLAGS) -o bggen bggen.c $(LIBS) -+ -+vdcomp: vdcomp.c -+ $(CC) $(CFLAGS) -o vdcomp vdcomp.c -+ -+xcmap: xcmap.c -+ $(CC) $(CFLAGS) -o xcmap xcmap.c $(LIBS) -+ -+xvpictoppm: xvpictoppm.c -+ $(CC) $(CFLAGS) -o xvpictoppm xvpictoppm.c -+ -+ -+ -+xvclean: -+ rm -f $(OBJS) xv -+ -+clean: xvclean -+ rm -f bggen vdcomp xcmap xvpictoppm -+ ./cleandir $(JPEGDIR) -+ rm -f $(JPEGDIR)/jconfig.h $(JPEGDIR)/Makefile -+ ./cleandir $(TIFFDIR) -+ -+ -+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) -+ -+tar: -+ tar cvf xv.tar Makefile* Imakefile *.c *.h bits \ -+ docs unsupt vms $(JPEGDIR) $(TIFFDIR) $(MISC) -+ -+xvtar: -+ tar cvf xv.tar Makefile* Imakefile *.c *.h bits -+ -+$(OBJS): xv.h config.h -+ -+ -+################# bitmap dependencies #################### -+ -+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_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_trash bits/fcurs bits/fccurs bits/fdcurs bits/fcursm -+xvbrowse.o: bits/br_xwd bits/br_png -+ -+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/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/uicon bits/oicon1 bits/oicon2 bits/icon -+xvctrl.o: bits/padimg bits/annot -+ -+xvcut.o: bits/cut bits/cutm bits/copy bits/copym -+ -+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 -+ -+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/blur bits/blurm -+ -+xvgam.o: bits/h_rotl bits/h_rotr bits/h_flip bits/h_sinc bits/h_sdec -+xvgam.o: bits/h_sat bits/h_desat -+ -+xvgraf.o: bits/gf1_addh bits/gf1_delh bits/gf1_line bits/gf1_spln -+xvgraf.o: bits/gf1_rst bits/gf1_gamma -+ -+xvinfo.o: bits/penn bits/pennnet -+ -+xvmisc.o: bits/fc_left bits/fc_leftm bits/fc_left1 bits/fc_left1m -+xvmisc.o: bits/fc_mid bits/fc_midm bits/fc_right1 bits/fc_right1m -+xvmisc.o: bits/fc_right bits/fc_rightm -+ -+xvpopup.o: bits/icon -+ -+xvroot.o: bits/root_weave -+ -+xvscrl.o: bits/up bits/down bits/up1 bits/down1 bits/uph bits/downh -+xvscrl.o: bits/uph1 bits/downh1 bits/scrlgray -+ -+################# end bitmap dependencies #################### -+ -+ -+ -diff -urN xv-3.10a/bits/br_png xv-3.10apatched/bits/br_png ---- xv-3.10a/bits/br_png Wed Dec 31 16:00:00 1969 -+++ xv-3.10apatched/bits/br_png Tue Apr 30 00:23:33 2002 -@@ -0,0 +1,28 @@ -+#define br_png_width 48 -+#define br_png_height 48 -+static unsigned char br_png_bits[] = { -+ 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, -+ 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, -+ 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, -+ 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, -+ 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0xf8, 0x19, 0xc3, 0x07, 0x02, 0x20, 0x18, 0x3b, 0x63, 0x0c, 0x02, -+ 0x20, 0x18, 0x3b, 0x33, 0x00, 0x02, 0x20, 0x18, 0x5b, 0x33, 0x00, 0x02, -+ 0x20, 0xf8, 0x59, 0x33, 0x0f, 0x02, 0x20, 0x18, 0x98, 0x33, 0x0c, 0x02, -+ 0x20, 0x18, 0x98, 0x33, 0x0c, 0x02, 0x20, 0x18, 0x18, 0x63, 0x0c, 0x02, -+ 0x20, 0x18, 0x18, 0xc3, 0x0b, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, -+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, -+ }; -diff -urN xv-3.10a/config.h xv-3.10apatched/config.h ---- xv-3.10a/config.h Thu Jan 5 10:49:21 1995 -+++ xv-3.10apatched/config.h Tue Apr 30 00:11:18 2002 -@@ -13,14 +13,14 @@ - * definition appropriately. (use 'which gunzip' to find if you have gunzip, - * and where it lives) - */ --#undef USE_GUNZIP -+#define USE_GUNZIP - - #ifdef USE_GUNZIP --# ifdef VMS --# define GUNZIP "UNCOMPRESS" --# else --# define GUNZIP "/usr/local/bin/gunzip -q" --# endif -+#ifdef VMS -+#define GUNZIP "UNCOMPRESS" -+#else -+#define GUNZIP "/bin/gunzip -q" -+#endif - #endif - - -@@ -88,9 +88,9 @@ - * should not need to be changed - */ - --/* #define GS_PATH "/usr/local/bin/gs" */ --/* #define GS_LIB "." */ --/* #define GS_DEV "ppmraw" */ -+#define GS_PATH "/usr/bin/gs" -+#define GS_LIB "." -+#define GS_DEV "ppmraw" - - - /*************************************************************************** -@@ -103,7 +103,7 @@ - * change 'undef' to 'define' in the following line - */ - --#undef USEOLDPIC -+#define USEOLDPIC - - - /*************************************************************************** -diff -urN xv-3.10a/tiff/Makefile xv-3.10apatched/tiff/Makefile ---- xv-3.10a/tiff/Makefile Thu Dec 22 14:35:12 1994 -+++ xv-3.10apatched/tiff/Makefile Tue Apr 30 00:12:54 2002 -@@ -36,7 +36,7 @@ - IPATH= -I. - - COPTS= -O --CFLAGS= ${COPTS} ${IPATH} -+CFLAGS= ${COPTS} ${IPATH} -D_BSD_SOURCE - - INCS= tiff.h tiffio.h - -diff -urN xv-3.10a/xv.c xv-3.10apatched/xv.c ---- xv-3.10a/xv.c Thu Jan 19 10:08:43 1995 -+++ xv-3.10apatched/xv.c Tue Apr 30 00:20:19 2002 -@@ -277,6 +277,10 @@ - tiffW = (Window) NULL; tiffUp = 0; - #endif - -+#ifdef HAVE_PNG -+ pngW = (Window) NULL; pngUp = 0; -+#endif -+ - imap = ctrlmap = gmap = browmap = cmtmap = 0; - - ch_offx = ch_offy = p_offx = p_offy = 0; -@@ -309,7 +313,11 @@ - - 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); -@@ -782,6 +790,10 @@ - XSetTransientForHint(theDisp, tiffW, dirW); - #endif - -+#ifdef HAVE_PNG -+ CreatePNGW(); -+ XSetTransientForHint(theDisp, pngW, dirW); -+#endif - - LoadFishCursors(); - SetCursors(-1); -@@ -950,7 +962,11 @@ - - 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); - -@@ -1184,6 +1200,14 @@ - } - } - -+ 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; - -@@ -1646,6 +1670,7 @@ - printoption("[-/+vsperfect]"); - printoption("[-wait seconds]"); - printoption("[-white color]"); -+ printoption("[-windowid windowid]"); - printoption("[-/+wloop]"); - printoption("[filename ...]"); - fprintf(stderr,"\n\n"); -@@ -1668,6 +1693,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); - } -@@ -2611,6 +2637,11 @@ - (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 - else if (strncmp((char *) magicno, "NJPL1I00", (size_t) 8)==0 || - strncmp((char *) magicno+2,"NJPL1I", (size_t) 6)==0 || -@@ -2625,6 +2656,10 @@ - strncmp((char *) magicno, "\004%!", (size_t) 3)==0) rv = RFT_PS; - #endif - -+#ifdef GS_PATH -+ else if (strncmp((char *) magicno, "%PDF", (size_t) 4)==0) rv = RFT_PS; -+#endif -+ - return rv; - } - -@@ -2671,6 +2706,10 @@ - case RFT_TIFF: rv = LoadTIFF (fname, pinfo); 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; - #endif -@@ -4043,16 +4082,30 @@ - unsigned long nitems, nleft; - byte *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); -+ 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); -diff -urN xv-3.10a/xv.c~ xv-3.10apatched/xv.c~ ---- xv-3.10a/xv.c~ Wed Dec 31 16:00:00 1969 -+++ xv-3.10apatched/xv.c~ Tue Apr 30 00:19:26 2002 -@@ -0,0 +1,4156 @@ -+/* -+ * xv.c - main section of xv. X setup, window creation, etc. -+ */ -+ -+#include "copyright.h" -+ -+#define MAIN -+#define NEEDSTIME -+#define NEEDSDIR /* for value of MAXPATHLEN */ -+ -+#include "xv.h" -+ -+#include "bits/icon" -+#include "bits/iconmask" -+#include "bits/runicon" -+#include "bits/runiconm" -+#include "bits/cboard50" -+#include "bits/gray25" -+ -+#include <X11/Xatom.h> -+ -+#ifdef VMS -+ extern Window pseudo_root(); -+#endif -+ -+ -+/* program needs one of the following fonts. Trys them in ascending order */ -+#define FONT1 "-*-lucida-medium-r-*-*-12-*-*-*-*-*-*-*" -+#define FONT2 "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*" -+#define FONT3 "-*-helvetica-medium-r-*-*-11-*-*-*-*-*-*-*" -+#define FONT4 "6x13" -+#define FONT5 "fixed" -+ -+/* a mono-spaced font needed for the 'pixel value tracking' feature */ -+#define MFONT1 "-misc-fixed-medium-r-normal-*-13-*" -+#define MFONT2 "6x13" -+#define MFONT3 "-*-courier-medium-r-*-*-12-*" -+#define MFONT4 "fixed" -+ -+ -+/* default positions for various windows */ -+#define DEFINFOGEOM "-10+10" /* default position of info window */ -+#define DEFCTRLGEOM "+170+380" /* default position of ctrl window */ -+#define DEFGAMGEOM "+10-10" /* default position of gamma window */ -+#define DEFBROWGEOM "-10-10" /* default position of browse window */ -+#define DEFTEXTGEOM "-10+320" /* default position of text window */ -+#define DEFCMTGEOM "-10+300" /* default position of comment window */ -+ -+ -+ -+static int revvideo = 0; /* true if we should reverse video */ -+static int dfltkludge = 0; /* true if we want dfltpic dithered */ -+static int clearonload; /* clear window/root (on colormap visuals) */ -+static int randomShow = 0; /* do a 'random' slideshow */ -+static int startIconic = 0; /* '-iconic' option */ -+static int defaultVis = 0; /* true if using DefaultVisual */ -+static double hexpand = 1.0; /* '-expand' argument */ -+static double vexpand = 1.0; /* '-expand' argument */ -+static char *maingeom = NULL; -+static char *icongeom = NULL; -+static Atom __SWM_VROOT = None; -+ -+static char basefname[128]; /* just the current fname, no path */ -+ -+/* things to do upon successfully loading an image */ -+static int autoraw = 0; /* force raw if using stdcmap */ -+static int autodither = 0; /* dither */ -+static int autosmooth = 0; /* smooth */ -+static int auto4x3 = 0; /* do a 4x3 */ -+static int autorotate = 0; /* rotate 0, +-90, +-180, +-270 */ -+static int autohflip = 0; /* Flip Horizontally */ -+static int autovflip = 0; /* Flip Vertically */ -+static int autocrop = 0; /* do an 'AutoCrop' command */ -+static int acrop = 0; /* automatically do a 'Crop' */ -+static int acropX, acropY, acropW, acropH; -+static int autonorm = 0; /* normalize */ -+static int autohisteq = 0; /* Histogram equalization */ -+ -+static int force8 = 0; /* force 8-bit mode */ -+static int force24 = 0; /* force 24-bit mode */ -+ -+/* used in DeleteCmd() and Quit() */ -+static char **mainargv; -+static int mainargc; -+ -+ -+/* local function pre-definitions */ -+ int main PARM((int, char **)); -+static int highbit PARM((unsigned long)); -+static void makeDirectCmap PARM((void)); -+static void useOtherVisual PARM((XVisualInfo *, int)); -+static void parseResources PARM((int, char **)); -+static void parseCmdLine PARM((int, char **)); -+static void verifyArgs PARM((void)); -+static void printoption PARM((char *)); -+static void cmdSyntax PARM((void)); -+static void rmodeSyntax PARM((void)); -+static int openPic PARM((int)); -+static int readpipe PARM((char *, char *)); -+static void openFirstPic PARM((void)); -+static void openNextPic PARM((void)); -+static void openNextQuit PARM((void)); -+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 makeDispNames PARM((void)); -+static void fixDispNames PARM((void)); -+static void deleteFromList PARM((int)); -+static int argcmp PARM((char *, 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; -+ -+ -+ -+ -+/*******************************************/ -+int main(argc, argv) -+ int argc; -+ char **argv; -+/*******************************************/ -+{ -+ int i; -+ XColor ecdef; -+ Window rootReturn, parentReturn, *children; -+ unsigned int numChildren, rootDEEP; -+ -+ -+#ifdef VMS -+ /* convert VMS-style arguments to unix names and glob */ -+ do_vms_wildcard(&argc, &argv); -+ getredirection(&argc, &argv); -+#endif -+ -+ -+ /*****************************************************/ -+ /*** variable Initialization ***/ -+ /*****************************************************/ -+ -+ xv_getwd(initdir, sizeof(initdir)); -+ searchdir[0] = '\0'; -+ fullfname[0] = '\0'; -+ -+ mainargv = argv; -+ mainargc = argc; -+ -+ /* init internal variables */ -+ display = NULL; -+ fgstr = bgstr = rootfgstr = rootbgstr = NULL; -+ histr = lostr = whitestr = blackstr = NULL; -+ visualstr = monofontname = flistName = NULL; -+ winTitle = NULL; -+ -+ pic = egampic = epic = cpic = NULL; -+ theImage = NULL; -+ -+ picComments = (char *) NULL; -+ -+ numPages = 1; curPage = 0; -+ pageBaseName[0] = '\0'; -+ -+ LocalCmap = browCmap = 0; -+ stdinflag = 0; -+ autoclose = autoDelete = 0; -+ cmapInGam = 0; -+ grabDelay = 0; -+ showzoomcursor = 0; -+ perfect = owncmap = stdcmap = rwcolor = 0; -+ -+ ignoreConfigs = 0; -+ browPerfect = 1; -+ gamval = rgamval = ggamval = bgamval = 1.0; -+ -+ picType = -1; /* gets set once file is loaded */ -+ colorMapMode = CM_NORMAL; -+ haveStdCmap = STD_NONE; -+ allocMode = AM_READONLY; -+ novbrowse = 0; -+ -+#ifndef VMS -+ strcpy(printCmd, "lpr"); -+#else -+ strcpy(printCmd, "Print /Queue = XV_Queue"); -+#endif -+ -+ forceClipFile = 0; -+ clearR = clearG = clearB = 0; -+ InitSelection(); -+ -+ -+ /* default Ghostscript parameters */ -+ gsDev = "ppmraw"; -+#ifdef GS_DEV -+ gsDev = GS_DEV; -+#endif -+ -+ gsRes = 72; -+ gsGeomStr = NULL; -+ -+ -+ /* init default colors */ -+ fgstr = "#000000"; bgstr = "#B2C0DC"; -+ histr = "#C6D5E2"; lostr = "#8B99B5"; -+ -+ 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); -+ } -+ -+ /* init command-line options flags */ -+ infogeom = DEFINFOGEOM; ctrlgeom = DEFCTRLGEOM; -+ gamgeom = DEFGAMGEOM; browgeom = DEFBROWGEOM; -+ textgeom = DEFTEXTGEOM; cmtgeom = DEFCMTGEOM; -+ -+ 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; -+ rootMode = 0; hsvmode = 0; -+ rmodeset = gamset = cgamset = 0; -+ nopos = limit2x = 0; -+ resetroot = 1; -+ clearonload = 0; -+ curstype = XC_top_left_arrow; -+ browseMode = savenorm = nostat = 0; -+ preview = 0; -+ pscomp = 0; -+ preset = 0; -+ viewonly = 0; -+ -+ /* init 'xormasks' array */ -+ xorMasks[0] = 0x01010101; -+ xorMasks[1] = 0x02020203; -+ xorMasks[2] = 0x84848485; -+ xorMasks[3] = 0x88888889; -+ xorMasks[4] = 0x10101011; -+ xorMasks[5] = 0x20202023; -+ xorMasks[6] = 0xc4c4c4c5; -+ xorMasks[7] = 0xffffffff; -+ -+ kludge_offx = kludge_offy = winCtrPosKludge = 0; -+ -+ conv24 = CONV24_SLOW; /* use 'slow' algorithm by default */ -+ -+ defaspect = normaspect = 1.0; -+ mainW = dirW = infoW = ctrlW = gamW = psW = (Window) NULL; -+ anyBrowUp = 0; -+ -+#ifdef HAVE_JPEG -+ jpegW = (Window) NULL; jpegUp = 0; -+#endif -+ -+#ifdef HAVE_TIFF -+ tiffW = (Window) NULL; tiffUp = 0; -+#endif -+ -+#ifdef HAVE_PNG -+ pngW = (Window) NULL; pngUp = 0; -+#endif -+ -+ imap = ctrlmap = gmap = browmap = cmtmap = 0; -+ -+ ch_offx = ch_offy = p_offx = p_offy = 0; -+ -+ /* init info box variables */ -+ infoUp = 0; -+ infoMode = INF_STR; -+ for (i=0; i<NISTR; i++) SetISTR(i,""); -+ -+ /* init ctrl box variables */ -+ ctrlUp = 0; -+ curname = -1; -+ formatStr[0] ='\0'; -+ -+ gamUp = 0; -+ psUp = 0; -+ -+ Init24to8(); -+ -+ -+ /* handle user-specified resources and cmd-line arguments */ -+ parseResources(argc,argv); -+ parseCmdLine(argc, argv); -+ verifyArgs(); -+ -+ -+ /*****************************************************/ -+ /*** X Setup ***/ -+ /*****************************************************/ -+ -+ theScreen = DefaultScreen(theDisp); -+ theCmap = DefaultColormap(theDisp, theScreen); -+ rootW = RootWindow(theDisp,theScreen); -+ theGC = DefaultGC(theDisp,theScreen); -+ theVisual = DefaultVisual(theDisp,theScreen); -+ ncells = DisplayCells(theDisp, theScreen); -+ dispDEEP = DisplayPlanes(theDisp,theScreen); -+ maxWIDE = vrWIDE = dispWIDE = DisplayWidth(theDisp,theScreen); -+ maxHIGH = vrHIGH = dispHIGH = DisplayHeight(theDisp,theScreen); -+ -+ -+ rootDEEP = dispDEEP; -+ -+ /* things dependant 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, -+ and if so, use that as the default visual (prefer TrueColor) */ -+ -+ if (!visualstr && !useroot) { -+ XVisualInfo *vinfo, rvinfo; -+ int best, numvis; -+ long flags; -+ -+ best = -1; -+ rvinfo.class = TrueColor; -+ rvinfo.screen = theScreen; -+ flags = VisualClassMask | VisualScreenMask; -+ -+ 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[i].depth == 24) best = i; -+ else if (vinfo[i].depth>24 && best<0) 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++) { -+ if (vinfo[i].depth == 24) best = i; -+ else if (vinfo[i].depth>24 && best<0) 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. "); -+ visualstr = NULL; -+ } -+ -+ if (visualstr && !useroot) { /* handle non-default visual */ -+ int vclass = -1; -+ int vid = -1; -+ -+ lower_str(visualstr); -+ if (!strcmp(visualstr,"staticgray")) vclass = StaticGray; -+ else if (!strcmp(visualstr,"staticcolor")) vclass = StaticColor; -+ else if (!strcmp(visualstr,"truecolor")) vclass = TrueColor; -+ else if (!strcmp(visualstr,"grayscale")) vclass = GrayScale; -+ else if (!strcmp(visualstr,"pseudocolor")) vclass = PseudoColor; -+ else if (!strcmp(visualstr,"directcolor")) vclass = DirectColor; -+ else if (!strcmp(visualstr,"default")) {} /* recognize it as valid */ -+ else if (!strncmp(visualstr,"0x",(size_t) 2)) { /* specified visual id */ -+ if (sscanf(visualstr, "0x%x", &vid) != 1) vid = -1; -+ } -+ else { -+ fprintf(stderr,"%s: Unrecognized visual type '%s'. %s\n", -+ cmd, visualstr, "Using server default."); -+ } -+ -+ -+ /* if 'default', vclass and vid will both be '-1' */ -+ -+ if (vclass >= 0 || vid >= 0) { /* try to find asked-for visual type */ -+ XVisualInfo *vinfo, rvinfo; -+ long vinfomask; -+ int numvis, best; -+ -+ if (vclass >= 0) { -+ rvinfo.class = vclass; vinfomask = VisualClassMask; -+ } -+ else { rvinfo.visualid = vid; vinfomask = VisualIDMask; } -+ -+ rvinfo.screen = theScreen; -+ vinfomask |= VisualScreenMask; -+ -+ vinfo = XGetVisualInfo(theDisp, vinfomask, &rvinfo, &numvis); -+ -+ if (vinfo) { /* choose the 'best' one, if multiple */ -+ for (i=0, best = 0; i<numvis; i++) { -+ if (vinfo[i].depth > vinfo[best].depth) best = i; -+ } -+ -+ useOtherVisual(vinfo, best); -+ XFree((char *) vinfo); -+ } -+ else fprintf(stderr,"%s: Visual type '%s' not available. %s\n", -+ cmd, visualstr, "Using server default."); -+ } -+ } -+ -+ -+ -+ /* make linear colormap for DirectColor visual */ -+ if (theVisual->class == DirectColor) makeDirectCmap(); -+ -+ defaultVis = (XVisualIDFromVisual(theVisual) == -+ XVisualIDFromVisual(DefaultVisual(theDisp, DefaultScreen(theDisp)))); -+ -+ -+ /* turn GraphicsExposures OFF in the default GC */ -+ { -+ XGCValues xgcv; -+ xgcv.graphics_exposures = False; -+ XChangeGC(theDisp, theGC, GCGraphicsExposures, &xgcv); -+ } -+ -+ -+ if (!useroot && limit2x) { maxWIDE *= 2; maxHIGH *= 2; } -+ if (nolimits) { maxWIDE = 65000; maxHIGH = 65000; } -+ -+ XSetErrorHandler(xvErrorHandler); -+ -+ /* always search for virtual root window */ -+ vrootW = rootW; -+#ifndef VMS -+ __SWM_VROOT = XInternAtom(theDisp, "__SWM_VROOT", False); -+ XQueryTree(theDisp, rootW, &rootReturn, &parentReturn, &children, -+ &numChildren); -+ for (i = 0; i < numChildren; i++) { -+ Atom actual_type; -+ int actual_format; -+ unsigned long nitems, bytesafter; -+ Window *newRoot = NULL; -+ 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; -+ XGetWindowAttributes(theDisp, vrootW, &xwa); -+ vrWIDE = xwa.width; vrHIGH = xwa.height; -+ dispDEEP = xwa.depth; -+ break; -+ } -+ } -+#else /* VMS */ -+ vrootW = pseudo_root(theDisp, theScreen); -+#endif -+ -+ -+ -+ -+ if (clrroot || useroot) { -+ /* have enough info to do a '-clear' now */ -+ KillOldRootInfo(); /* if any */ -+ if (resetroot || clrroot) ClearRoot(); /* don't clear on '-noresetroot' */ -+ if (clrroot) Quit(0); -+ } -+ -+ -+ arrow = XCreateFontCursor(theDisp,(u_int) curstype); -+ cross = XCreateFontCursor(theDisp,XC_crosshair); -+ tcross = XCreateFontCursor(theDisp,XC_tcross); -+ 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); -+ } -+ -+ { /* create inviso cursor */ -+ Pixmap pix; -+ static char bits[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -+ XColor cfg; -+ -+ cfg.red = cfg.green = cfg.blue = 0; -+ pix = XCreateBitmapFromData(theDisp, rootW, bits, 8, 8); -+ inviso = XCreatePixmapCursor(theDisp, pix, pix, &cfg, &cfg, 0,0); -+ XFreePixmap(theDisp, pix); -+ } -+ -+ -+ -+ /* set up white,black colors */ -+ whtRGB = 0xffffff; blkRGB = 0x000000; -+ -+ if (defaultVis) { -+ white = WhitePixel(theDisp,theScreen); -+ black = BlackPixel(theDisp,theScreen); -+ } -+ else { -+ ecdef.flags = DoRed | DoGreen | DoBlue; -+ ecdef.red = ecdef.green = ecdef.blue = 0xffff; -+ if (xvAllocColor(theDisp, theCmap, &ecdef)) white = ecdef.pixel; -+ else white = 0xffffffff; /* probably evil... */ -+ -+ ecdef.red = ecdef.green = ecdef.blue = 0x0000; -+ if (xvAllocColor(theDisp, theCmap, &ecdef)) black = ecdef.pixel; -+ else black = 0x00000000; /* probably evil... */ -+ } -+ -+ if (whitestr && XParseColor(theDisp, theCmap, whitestr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) { -+ white = ecdef.pixel; -+ whtRGB = ((ecdef.red>>8)<<16) | (ecdef.green&0xff00) | (ecdef.blue>>8); -+ } -+ -+ if (blackstr && XParseColor(theDisp, theCmap, blackstr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) { -+ black = ecdef.pixel; -+ blkRGB = ((ecdef.red>>8)<<16) | (ecdef.green&0xff00) | (ecdef.blue>>8); -+ } -+ -+ -+ /* set up fg,bg colors */ -+ fg = black; bg = white; -+ if (fgstr && XParseColor(theDisp, theCmap, fgstr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) { -+ fg = ecdef.pixel; -+ } -+ -+ if (bgstr && XParseColor(theDisp, theCmap, bgstr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) { -+ bg = ecdef.pixel; -+ } -+ -+ -+ /* set up root fg,bg colors */ -+ rootfg = white; rootbg = black; -+ if (rootfgstr && XParseColor(theDisp, theCmap, rootfgstr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) rootfg = ecdef.pixel; -+ if (rootbgstr && XParseColor(theDisp, theCmap, rootbgstr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) rootbg = ecdef.pixel; -+ -+ -+ /* set up hi/lo colors */ -+ i=0; -+ if (dispDEEP > 1) { /* only if we're on a reasonable display */ -+ if (histr && XParseColor(theDisp, theCmap, histr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) { hicol = ecdef.pixel; i|=1; } -+ if (lostr && XParseColor(theDisp, theCmap, lostr, &ecdef) && -+ xvAllocColor(theDisp, theCmap, &ecdef)) { locol = ecdef.pixel; i|=2; } -+ } -+ -+ if (i==0) ctrlColor = 0; -+ else if (i==3) ctrlColor = 1; -+ else { /* only got some of them */ -+ if (i&1) xvFreeColors(theDisp, theCmap, &hicol, 1, 0L); -+ if (i&2) xvFreeColors(theDisp, theCmap, &locol, 1, 0L); -+ ctrlColor = 0; -+ } -+ -+ if (!ctrlColor) { hicol = bg; locol = fg; } -+ -+ XSetForeground(theDisp,theGC,fg); -+ XSetBackground(theDisp,theGC,bg); -+ -+ infofg = fg; infobg = bg; -+ -+ /* if '-mono' not forced, determine if we're on a grey or color monitor */ -+ if (!mono) { -+ if (theVisual->class == StaticGray || theVisual->class == GrayScale) -+ mono = 1; -+ } -+ -+ -+ -+ iconPix = MakePix1(rootW, icon_bits, icon_width, icon_height); -+ iconmask = MakePix1(rootW, iconmask_bits, icon_width, icon_height); -+ riconPix = MakePix1(rootW, runicon_bits, runicon_width, runicon_height); -+ riconmask= MakePix1(rootW, runiconm_bits, runiconm_width,runiconm_height); -+ -+ if (!iconPix || !iconmask || !riconPix || !riconmask) -+ FatalError("Unable to create icon pixmaps\n"); -+ -+ gray50Tile = XCreatePixmapFromBitmapData(theDisp, rootW, -+ (char *) cboard50_bits, -+ cboard50_width, cboard50_height, -+ infofg, infobg, dispDEEP); -+ if (!gray50Tile) FatalError("Unable to create gray50Tile bitmap\n"); -+ -+ gray25Tile = XCreatePixmapFromBitmapData(theDisp, rootW, -+ (char *) gray25_bits, -+ 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 && -+ (mfinfo = XLoadQueryFont(theDisp,FONT5))==NULL) { -+ sprintf(str, -+ "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); -+ } -+ mfont=mfinfo->fid; -+ XSetFont(theDisp,theGC,mfont); -+ -+ monofinfo = (XFontStruct *) NULL; -+ -+ if (monofontname) { -+ monofinfo = XLoadQueryFont(theDisp, monofontname); -+ 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 && -+ (monofinfo = XLoadQueryFont(theDisp,MFONT4))==NULL) { -+ sprintf(str,"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); -+ } -+ } -+ -+ monofont=monofinfo->fid; -+ -+ -+ -+ -+ /* 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) { -+ /* 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]"); -+ strcpy(namelist[0], STDINSTR); -+ numnames = 1; -+ } -+ else namelist[0] = NULL; -+ } -+ -+ if (numnames) makeDispNames(); -+ -+ -+ if (viewonly || autoquit) { -+ imap = ctrlmap = gmap = browmap = cmtmap = 0; -+ novbrowse = 1; -+ } -+ -+ -+ /* create the info box window */ -+ CreateInfo(infogeom); -+ XSelectInput(theDisp, infoW, ExposureMask | ButtonPressMask | KeyPressMask -+ | StructureNotifyMask); -+ InfoBox(imap); /* map it (or not) */ -+ if (imap) { -+ 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 */ -+ XWMHints xwmh; -+ xwmh.input = True; -+ xwmh.initial_state = IconicState; -+ xwmh.flags = (InputHint | StateHint); -+ XSetWMHints(theDisp, ctrlW, &xwmh); -+ ctrlmap = 1; -+ } -+ CtrlBox(ctrlmap); /* map it (or not) */ -+ if (ctrlmap) { -+ 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, -+ (cgamset) ? ggamval : -1.0, -+ (cgamset) ? bgamval : -1.0, -+ preset); -+ 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_TIFF -+ CreateTIFFW(); -+ XSetTransientForHint(theDisp, tiffW, dirW); -+#endif -+ -+#ifdef HAVE_PNG -+ CreatePNGW(); -+ XSetTransientForHint(theDisp, pngW, 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; -+ picType = PIC24; -+ } -+ else if (force8) { -+ Set824Menus(PIC8); -+ conv24MB.flags[CONV24_LOCK] = 1; -+ picType = PIC8; -+ } -+ else { -+ Set824Menus(PIC8); /* default mode */ -+ picType = PIC8; -+ } -+ -+ -+ -+ /* make std colormap, maybe */ -+ ChangeCmapMode(colorMapMode, 0, 0); -+ -+ -+ -+ -+ /* Do The Thing... */ -+ mainLoop(); -+ Quit(0); -+ return(0); -+} -+ -+ -+ -+/*****************************************************/ -+static void makeDirectCmap() -+{ -+ int i, j, cmaplen, numgot; -+ byte origgot[256]; -+ XColor c; -+ u_long rmask, gmask, bmask; -+ int rshift, gshift, bshift; -+ -+ -+ rmask = theVisual->red_mask; -+ gmask = theVisual->green_mask; -+ bmask = theVisual->blue_mask; -+ -+ rshift = highbit(rmask) - 15; -+ gshift = highbit(gmask) - 15; -+ bshift = highbit(bmask) - 15; -+ -+ 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++) { -+ c.red = c.green = c.blue = (i * 0xffff) / (cmaplen - 1); -+ c.red = c.red & rmask; -+ c.green = c.green & gmask; -+ c.blue = c.blue & bmask; -+ c.flags = DoRed | DoGreen | DoBlue; -+ -+ if (XAllocColor(theDisp, theCmap, &c)) { -+ /* fprintf(stderr,"%3d: %4x,%4x,%4x\n", i, c.red,c.green,c.blue); */ -+ directConv[i] = i; -+ origgot[i] = 1; -+ numgot++; -+ } -+ } -+ -+ -+ 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]) { -+ int numbak, numfwd; -+ 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!"); -+ } -+ } -+} -+ -+ -+static int highbit(ul) -+ unsigned long ul; -+{ -+ /* returns position of highest set bit in 'ul' as an integer (0-31), -+ or -1 if none */ -+ -+ int i; unsigned long hb; -+ hb = 0x8000; hb = (hb<<16); /* hb = 0x80000000UL */ -+ for (i=31; ((ul & hb) == 0) && i>=0; i--, ul<<=1); -+ return i; -+} -+ -+ -+ -+ -+/*****************************************************/ -+static void useOtherVisual(vinfo, best) -+ XVisualInfo *vinfo; -+ int best; -+{ -+ if (!vinfo || best<0) return; -+ -+ 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, -+ (vinfo[best].class==StaticGray) ? "StaticGray" : -+ (vinfo[best].class==StaticColor) ? "StaticColor" : -+ (vinfo[best].class==TrueColor) ? "TrueColor" : -+ (vinfo[best].class==GrayScale) ? "GrayScale" : -+ (vinfo[best].class==PseudoColor) ? "PseudoColor" : -+ (vinfo[best].class==DirectColor) ? "DirectColor" : "<unknown>", -+ (int) vinfo[best].visualid, -+ vinfo[best].depth, vinfo[best].screen); -+ -+ fprintf(stderr,"\tmasks: (0x%x,0x%x,0x%x), bits_per_rgb=%d\n", -+ (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); -+ 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; -+ 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; -+} -+ -+ -+ -+ -+/*****************************************************/ -+static void parseResources(argc, argv) -+ int argc; -+ char **argv; -+{ -+ int i, pm; -+ -+ /* once through the argument list to find the display name -+ and DEBUG level, if any */ -+ -+ 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++; -+ if (i<argc) display = argv[i]; -+ break; -+ } -+ -+#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]); } -+ } -+#else -+ else if (!argcmp(argv[i],"-DEBUG",2,0,&pm)) { -+ { if (++i<argc) DEBUG = atoi(argv[i]); } -+ } -+#endif -+ } -+ -+ /* open the display */ -+ if ( (theDisp=XOpenDisplay(display)) == NULL) { -+ fprintf(stderr, "%s: Can't open display\n",argv[0]); -+ exit(1); -+ } -+ -+ -+ -+ if (rd_str ("aspect")) { -+ int n,d; -+ if (sscanf(def_str,"%d:%d",&n,&d)!=2 || n<1 || d<1) -+ 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("auto4x3")) auto4x3 = def_int; -+ if (rd_flag("autoClose")) autoclose = def_int; -+ if (rd_flag("autoCrop")) autocrop = def_int; -+ if (rd_flag("autoDither")) autodither = def_int; -+ if (rd_flag("autoHFlip")) autohflip = def_int; -+ if (rd_flag("autoHistEq")) autohisteq = def_int; -+ if (rd_flag("autoNorm")) autonorm = def_int; -+ if (rd_flag("autoRaw")) autoraw = def_int; -+ if (rd_int ("autoRotate")) autorotate = def_int; -+ if (rd_flag("autoSmooth")) autosmooth = def_int; -+ if (rd_flag("autoVFlip")) autovflip = def_int; -+ if (rd_str ("background")) bgstr = def_str; -+ if (rd_flag("best24") && def_int) conv24 = CONV24_BEST; -+ if (rd_str ("black")) blackstr = def_str; -+ if (rd_int ("borderWidth")) bwidth = def_int; -+ if (rd_str ("ceditGeometry")) gamgeom = def_str; -+ if (rd_flag("ceditMap")) gmap = def_int; -+ if (rd_flag("ceditColorMap")) cmapInGam = def_int; -+ if (rd_flag("clearOnLoad")) clearonload = def_int; -+ if (rd_str ("commentGeometry")) cmtgeom = def_str; -+ if (rd_flag("commentMap")) cmtmap = def_int; -+ if (rd_str ("ctrlGeometry")) ctrlgeom = def_str; -+ if (rd_flag("ctrlMap")) ctrlmap = def_int; -+ if (rd_int ("cursor")) curstype = def_int; -+ if (rd_int ("defaultPreset")) preset = def_int; -+ -+ if (rd_str ("driftKludge")) { -+ if (sscanf(def_str,"%d %d", &kludge_offx, &kludge_offy) != 2) { -+ kludge_offx = kludge_offy = 0; -+ } -+ } -+ -+ if (rd_str ("expand")) { -+ if (index(def_str, ':')) { -+ if (sscanf(def_str, "%lf:%lf", &hexpand, &vexpand)!=2) -+ { hexpand = vexpand = 1.0; } -+ } -+ else hexpand = vexpand = atof(def_str); -+ } -+ -+ if (rd_str ("fileList")) flistName = def_str; -+ if (rd_flag("fixed")) fixedaspect = def_int; -+ if (rd_flag("force8")) force8 = def_int; -+ if (rd_flag("force24")) force24 = def_int; -+ if (rd_str ("foreground")) fgstr = def_str; -+ if (rd_str ("geometry")) maingeom = def_str; -+ if (rd_str ("gsDevice")) gsDev = def_str; -+ if (rd_str ("gsGeometry")) gsGeomStr = def_str; -+ if (rd_int ("gsResolution")) gsRes = def_int; -+ if (rd_flag("hsvMode")) hsvmode = def_int; -+ if (rd_str ("highlight")) histr = def_str; -+ if (rd_str ("iconGeometry")) icongeom = def_str; -+ if (rd_flag("iconic")) startIconic = def_int; -+ 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; -+ 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; -+ 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; -+ if (rd_flag("popupKludge")) winCtrPosKludge = def_int; -+ 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; -+ if (rd_flag("quick24") && def_int) conv24 = CONV24_FAST; -+ if (rd_flag("resetroot")) resetroot = def_int; -+ 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_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; -+ 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; -+} -+ -+ -+ -+/*****************************************************/ -+static void parseCmdLine(argc, argv) -+ int argc; char **argv; -+{ -+ int i, oldi, not_in_first_half, pm; -+ -+ orignumnames = 0; -+ -+ for (i=1, numnames=0; i<argc; i++) { -+ oldi = i; -+ -+ not_in_first_half = 0; -+ -+ if (argv[i][0] != '-' && argv[i][0] != '+') { -+ /* a file name. put it in list */ -+ -+ if (!nostat) { -+ struct stat st; int ftype; -+ if (stat(argv[i], &st) == 0) { -+ ftype = st.st_mode; -+ if (!S_ISREG(ftype)) continue; /* stat'd & isn't file. skip it */ -+ } -+ } -+ -+ if (numnames<MAXNAMES) { -+ namelist[numnames++] = argv[i]; -+ if (numnames==MAXNAMES) { -+ fprintf(stderr,"%s: too many filenames. Only using first %d.\n", -+ cmd, MAXNAMES); -+ } -+ } -+ } -+ -+ 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 */ -+ int n,d; -+ if (++i<argc) { -+ if (sscanf(argv[i],"%d:%d",&n,&d)!=2 || n<1 || d<1) -+ fprintf(stderr,"%s: bad aspect ratio '%s'\n",cmd,argv[i]); -+ else defaspect = (float) n / (float) d; -+ } -+ } -+ -+ else if (!argcmp(argv[i],"-best24",3,0,&pm)) /* -best */ -+ conv24 = CONV24_BEST; -+ -+ 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 */ -+ { if (++i<argc) blackstr = argv[i]; } -+ -+ 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 */ -+ { 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 */ -+ if (i+3<argc) { -+ rgamval = atof(argv[++i]); -+ ggamval = atof(argv[++i]); -+ bgamval = atof(argv[++i]); -+ } -+ cgamset++; -+ } -+ -+ 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 */ -+ { 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 */ -+ if (i+4<argc) { -+ 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 */ -+ { if (++i<argc) curstype = atoi(argv[i]); } -+ -+#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]); } -+ } -+#else -+ else if (!argcmp(argv[i],"-DEBUG",2,0,&pm)) { -+ { if (++i<argc) DEBUG = atoi(argv[i]); } -+ } -+#endif -+ -+ 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 */ -+ { if (++i<argc) display = argv[i]; } -+ -+ else if (!argcmp(argv[i],"-dither",4,1,&autodither)); /* autodither */ -+ -+ 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 */ -+ if (++i<argc) { -+ if (index(argv[i], ':')) { -+ 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 */ -+ { 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 */ -+ { if (++i<argc) flistName = argv[i]; } -+ -+ 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 */ -+ { if (++i<argc) maingeom = argv[i]; } -+ -+ 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 */ -+ { if (++i<argc) gsDev = argv[i]; } -+ -+ 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 */ -+ { 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 */ -+ { if (++i<argc) histr = argv[i]; } -+ -+ 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 */ -+ { if (++i<argc) lostr = argv[i]; } -+ -+ else if (!argcmp(argv[i],"-loadclear",4,1,&clearonload)); /* clearonload */ -+ -+ -+ else not_in_first_half = 1; -+ -+ -+ -+ if (i != oldi) continue; /* parsed something... */ -+ -+ -+ -+ /* split huge else-if group into two halves, as it breaks some compilers */ -+ -+ -+ -+ 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; } -+ -+ else if (!argcmp(argv[i],"-mfn",3,0,&pm)) /* mono font name */ -+ { if (++i<argc) monofontname = argv[i]; } -+ -+ 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],"-nodecor", 4,1,&nodecor)); -+ else if (!argcmp(argv[i],"-nofreecols",4,1,&noFreeCols)); -+ else if (!argcmp(argv[i],"-nolimits", 4,1,&nolimits)); /* nolimits */ -+ 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],"-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 */ -+ else if (!argcmp(argv[i],"-perfect", 3,1,&perfect)); /* -perfect */ -+ 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]); -+ 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],"-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]; } -+ -+ 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; -+ } -+ } -+ -+ 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(); -+ } -+ -+ -+ /* build origlist[], a copy of namelist that remains unmodified, for -+ use with the 'autoDelete' option */ -+ orignumnames = numnames; -+ xvbcopy( (char *) namelist, (char *) origlist, sizeof(origlist)); -+} -+ -+ -+/*****************************************************************/ -+static void verifyArgs() -+{ -+ /* check options for validity */ -+ -+ if (strlen(searchdir)) { /* got a search directory */ -+ if (chdir(searchdir)) { -+ fprintf(stderr,"xv: unable to cd to directory '%s'.\n",searchdir); -+ fprintf(stderr, -+ " Ignoring '-dir' option and/or 'xv.searchDirectory' resource\n"); -+ searchdir[0] = '\0'; -+ } -+ } -+ -+ -+ if (flistName) -+ add_filelist_to_namelist(flistName, namelist, &numnames, MAXNAMES); -+ -+ RANGE(curstype,0,254); -+ curstype = curstype & 0xfe; /* clear low bit to make curstype even */ -+ -+ if (hexpand == 0.0 || vexpand == 0.0) cmdSyntax(); -+ if (rootMode < 0 || rootMode > RM_MAX) rmodeSyntax(); -+ -+ if (DEBUG) XSynchronize(theDisp, True); -+ -+ /* 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 (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) { -+ fprintf(stderr, -+ "Invalid '-grabdelay' value ignored. Valid range is 0-15 seconds.\n"); -+ grabDelay = 0; -+ } -+ -+ if (preset<0 || preset>4) { -+ fprintf(stderr,"Invalid default preset value (%d) ignored.\n", preset); -+ fprintf(stderr," (Valid values: 1, 2, 3, 4)\n"); -+ -+ preset = 0; -+ } -+ -+ if (waitsec < 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 */ -+ if (rwcolor) allocMode = AM_READWRITE; -+ -+ if (perfect) colorMapMode = CM_PERFECT; -+ if (owncmap) colorMapMode = CM_OWNCMAP; -+ if (stdcmap) colorMapMode = CM_STDCMAP; -+ -+ defaultCmapMode = colorMapMode; /* default mode for 8-bit images */ -+ -+ if (nopos) { -+ maingeom = infogeom = ctrlgeom = gamgeom = browgeom = textgeom = NULL; -+ cmtgeom = NULL; -+ } -+ -+ /* if -root and -maxp, disallow 'integer' tiling modes */ -+ if (useroot && fixedaspect && automax && !rmodeset && -+ (rootMode == RM_TILE || rootMode == RM_IMIRROR)) -+ rootMode = RM_CSOLID; -+} -+ -+ -+ -+ -+/***********************************/ -+static int cpos = 0; -+static void printoption(st) -+ char *st; -+{ -+ if (strlen(st) + cpos > 78) { -+ fprintf(stderr,"\n "); -+ cpos = 3; -+ } -+ -+ fprintf(stderr,"%s ",st); -+ cpos = cpos + strlen(st) + 1; -+} -+ -+static void cmdSyntax() -+{ -+ fprintf(stderr, "Usage:\n"); -+ printoption(cmd); -+ printoption("[-]"); -+ printoption("[-/+24]"); -+ printoption("[-/+2xlimit]"); -+ printoption("[-/+4x3]"); -+ printoption("[-/+8]"); -+ printoption("[-/+acrop]"); -+ printoption("[-aspect w:h]"); -+ printoption("[-best24]"); -+ printoption("[-bg color]"); -+ printoption("[-black color]"); -+ printoption("[-bw width]"); -+ printoption("[-/+cecmap]"); -+ printoption("[-cegeometry geom]"); -+ printoption("[-/+cemap]"); -+ printoption("[-cgamma rval gval bval]"); -+ printoption("[-cgeometry geom]"); -+ printoption("[-/+clear]"); -+ printoption("[-/+close]"); -+ printoption("[-/+cmap]"); -+ printoption("[-cmtgeometry geom]"); -+ printoption("[-/+cmtmap]"); -+ printoption("[-crop x y w h]"); -+ printoption("[-cursor char#]"); -+ -+#ifndef VMS -+ printoption("[-DEBUG level]"); -+#else -+ printoption("[-debug level]"); -+#endif -+ -+ printoption("[-dir directory]"); -+ printoption("[-display disp]"); -+ printoption("[-/+dither]"); -+ printoption("[-drift dx dy]"); -+ printoption("[-expand exp | hexp:vexp]"); -+ printoption("[-fg color]"); -+ printoption("[-/+fixed]"); -+ printoption("[-flist fname]"); -+ printoption("[-gamma val]"); -+ printoption("[-geometry geom]"); -+ printoption("[-grabdelay seconds]"); -+ printoption("[-gsdev str]"); -+ printoption("[-gsgeom geom]"); -+ printoption("[-gsres int]"); -+ printoption("[-help]"); -+ printoption("[-/+hflip]"); -+ printoption("[-hi color]"); -+ printoption("[-/+hist]"); -+ printoption("[-/+hsv]"); -+ printoption("[-icgeometry geom]"); -+ printoption("[-/+iconic]"); -+ printoption("[-igeometry geom]"); -+ printoption("[-/+imap]"); -+ printoption("[-/+lbrowse]"); -+ printoption("[-lo color]"); -+ printoption("[-/+loadclear]"); -+ printoption("[-/+max]"); -+ printoption("[-/+maxpect]"); -+ printoption("[-mfn font]"); -+ printoption("[-/+mono]"); -+ printoption("[-name str]"); -+ printoption("[-ncols #]"); -+ printoption("[-/+ninstall]"); -+ printoption("[-/+nodecor]"); -+ printoption("[-/+nofreecols]"); -+ printoption("[-/+nolimits]"); -+ printoption("[-/+nopos]"); -+ printoption("[-/+noqcheck]"); -+ printoption("[-/+noresetroot]"); -+ printoption("[-/+norm]"); -+ printoption("[-/+nostat]"); -+ printoption("[-/+owncmap]"); -+ printoption("[-/+perfect]"); -+ printoption("[-/+pkludge]"); -+ printoption("[-/+poll]"); -+ printoption("[-preset #]"); -+ printoption("[-quick24]"); -+ printoption("[-/+quit]"); -+ printoption("[-/+random]"); -+ printoption("[-/+raw]"); -+ printoption("[-rbg color]"); -+ printoption("[-rfg color]"); -+ printoption("[-/+rgb]"); -+ printoption("[-RM]"); -+ printoption("[-rmode #]"); -+ printoption("[-/+root]"); -+ printoption("[-rotate deg]"); -+ printoption("[-/+rv]"); -+ printoption("[-/+rw]"); -+ printoption("[-slow24]"); -+ printoption("[-/+smooth]"); -+ printoption("[-/+stdcmap]"); -+ printoption("[-tgeometry geom]"); -+ printoption("[-/+vflip]"); -+ printoption("[-/+viewonly]"); -+ printoption("[-visual type]"); -+ printoption("[-/+vsdisable]"); -+ printoption("[-vsgeometry geom]"); -+ printoption("[-/+vsmap]"); -+ printoption("[-/+vsperfect]"); -+ printoption("[-wait seconds]"); -+ printoption("[-white color]"); -+ printoption("[-/+wloop]"); -+ printoption("[filename ...]"); -+ fprintf(stderr,"\n\n"); -+ Quit(1); -+} -+ -+ -+/***********************************/ -+static void rmodeSyntax() -+{ -+ fprintf(stderr,"%s: unknown root mode '%d'. Valid modes are:\n", -+ cmd, rootMode); -+ fprintf(stderr,"\t0: tiling\n"); -+ fprintf(stderr,"\t1: integer tiling\n"); -+ fprintf(stderr,"\t2: mirrored tiling\n"); -+ fprintf(stderr,"\t3: integer mirrored tiling\n"); -+ fprintf(stderr,"\t4: centered tiling\n"); -+ fprintf(stderr,"\t5: centered on a solid background\n"); -+ fprintf(stderr,"\t6: centered on a 'warp' background\n"); -+ fprintf(stderr,"\t7: centered on a 'brick' background\n"); -+ fprintf(stderr,"\t8: symmetrical tiling\n"); -+ fprintf(stderr,"\t9: symmetrical mirrored tiling\n"); -+ fprintf(stderr,"\n"); -+ Quit(1); -+} -+ -+ -+/***********************************/ -+static int argcmp(a1, a2, minlen, plusallowed, plusminus) -+ 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 -+ 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; -+ -+ if (strncmp(a1+1, a2+1, strlen(a1)-1)) return 1; -+ -+ if (a1[0]=='-' || (plusallowed && a1[0]=='+')) { -+ /* only set if we match */ -+ *plusminus = (a1[0] == '-'); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+ -+/***********************************/ -+static int openPic(filenum) -+ int filenum; -+{ -+ /* tries to load file #filenum (from 'namelist' list) -+ * returns 0 on failure (cleans up after itself) -+ * returns '-1' if caller should display DFLTPIC (shown as text) -+ * if successful, returns 1, creates mainW -+ * -+ * By the way, I'd just like to point out that this procedure has gotten -+ * *way* out of hand... -+ */ -+ -+ PICINFO pinfo; -+ int i,filetype,freename, frompipe, frompoll, fromint, killpage; -+ int oldeWIDE, oldeHIGH, oldpWIDE, oldpHIGH; -+ 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 */ -+ -+ xvbzero((char *) &pinfo, sizeof(PICINFO)); -+ -+ /* init important fields of pinfo */ -+ pinfo.pic = (byte *) NULL; -+ pinfo.comment = (char *) NULL; -+ pinfo.numpages = 1; -+ pinfo.pagebname[0] = '\0'; -+ -+ -+ normaspect = defaspect; -+ freename = dfltkludge = frompipe = frompoll = fromint = wascropped = 0; -+ oldpWIDE = oldpHIGH = oldCXOFF = oldCYOFF = oldCWIDE = oldCHIGH = 0; -+ oldeWIDE = eWIDE; oldeHIGH = eHIGH; -+ fullname = NULL; -+ killpage = 0; -+ -+ WaitCursor(); -+ -+ SetISTR(ISTR_INFO,""); -+ SetISTR(ISTR_WARNING,""); -+ -+ -+ /* 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) -+ killpage = 1; -+ -+ -+ if (strlen(pageBaseName) && (filenum==OP_PAGEDN || filenum==OP_PAGEUP)) { -+ if (filenum==OP_PAGEUP && curPage>0) curPage--; -+ else if (filenum==OP_PAGEDN && curPage<numPages-1) curPage++; -+ else { -+ XBell(theDisp, 0); /* hit either end */ -+ SetCursors(-1); -+ return 0; -+ } -+ -+ sprintf(filename, "%s%d", pageBaseName, curPage+1); -+ fullname = filename; -+ goto HAVE_FILENAME; -+ } -+ -+ -+ if (filenum == DFLTPIC) { -+ filename[0] = '\0'; basefname[0] = '\0'; fullfname[0] = '\0'; -+ fullname = ""; -+ curname = -1; /* ??? */ -+ LoadDfltPic(&pinfo); -+ -+ if (killpage) { /* kill old page files, if any */ -+ KillPageFiles(pageBaseName, numPages); -+ pageBaseName[0] = '\0'; -+ numPages = 1; -+ curPage = 0; -+ } -+ -+ goto GOTIMAGE; -+ } -+ else if (filenum == GRABBED) { -+ filename[0] = '\0'; basefname[0] = '\0'; fullfname[0] = '\0'; -+ fullname = ""; -+ i = LoadGrab(&pinfo); -+ if (!i) goto FAILED; /* shouldn't happen */ -+ -+ if (killpage) { /* kill old page files, if any */ -+ KillPageFiles(pageBaseName, numPages); -+ pageBaseName[0] = '\0'; -+ numPages = 1; -+ curPage = 0; -+ } -+ -+ goto GOTIMAGE; -+ } -+ -+ else if (filenum == PADDED) { -+ /* 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); -+ -+ if (!i) goto FAILED; /* shouldn't happen */ -+ -+ if (killpage) { /* kill old page files, if any */ -+ KillPageFiles(pageBaseName, numPages); -+ pageBaseName[0] = '\0'; -+ numPages = 1; -+ curPage = 0; -+ } -+ -+ goto GOTIMAGE; -+ } -+ -+ -+ if (filenum == POLLED) { -+ frompoll = 1; -+ oldpWIDE = pWIDE; oldpHIGH = pHIGH; -+ wascropped = (cWIDE!=pWIDE || cHIGH!=pHIGH); -+ oldCXOFF = cXOFF; oldCYOFF = cYOFF; oldCWIDE = cWIDE; oldCHIGH = cHIGH; -+ filenum = curname; -+ } -+ -+ if (filenum == RELOAD) { -+ fromint = 1; -+ filenum = nList.selected; -+ } -+ -+ if (filenum != LOADPIC) { -+ if (filenum >= nList.nstr || filenum < 0) goto FAILED; -+ curname = filenum; -+ nList.selected = curname; -+ ScrollToCurrent(&nList); /* have scrl/list show current */ -+ XFlush(theDisp); /* update NOW */ -+ } -+ -+ -+ -+ /* set up fullname and basefname */ -+ -+ if (filenum == LOADPIC) { -+ fullname = GetDirFullName(); -+ -+ if (ISPIPE(fullname[0])) { /* read from a pipe. */ -+ strcpy(filename, fullname); -+ if (readpipe(fullname, filename)) goto FAILED; -+ frompipe = 1; -+ } -+ } -+ else fullname = namelist[filenum]; -+ -+ -+ strcpy(fullfname, fullname); -+ tmp = BaseName(fullname); -+ strcpy(basefname, tmp); -+ -+ -+ /* 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) -+ basefname[strlen(basefname)-2]='\0'; -+ else { -+#ifdef GUNZIP -+ 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) -+ basefname[strlen(basefname)-3]='\0'; -+#endif /* GUNZIP */ -+ } -+ -+ -+ 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 -+ 'initdir' to relative paths, dealing with reading from stdin, etc. */ -+ -+ /* at this point, fullname = "! do some commands", -+ filename = "/tmp/xv123456", -+ and basefname= "xv123456" */ -+ } -+ -+ 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>') -+ then we need to prepend a directory name to it: -+ -+ 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. -+ if it doesn't, and we have a searchdir, try prepending searchdir -+ and see if file exists. -+ 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; -+ -+ /* stick 'initdir ' onto front of filename */ -+ -+#ifndef VMS -+ tmp1 = (char *) malloc(strlen(fullname) + strlen(initdir) + 2); -+ if (!tmp1) FatalError("malloc 'filename' failed"); -+ sprintf(tmp1,"%s/%s", initdir, fullname); -+#else /* it is VMS */ -+ tmp1 = (char *) malloc(strlen(fullname) + 2); -+ if (!tmp1) FatalError("malloc 'filename' failed"); -+ sprintf(tmp1,"%s", fullname); -+#endif -+ -+ if (!strlen(searchdir)) { /* no searchdir, don't check */ -+ fullname = tmp1; -+ freename = 1; -+ } -+ else { /* see if said file exists */ -+ FILE *fp; -+ fp = fopen(tmp1, "r"); -+ if (fp) { /* initpath/fullname exists */ -+ fclose(fp); -+ fullname = tmp1; -+ freename = 1; -+ } -+ else { /* doesn't: try searchdir */ -+ free(tmp1); -+#ifndef VMS -+ tmp1 = (char *) malloc(strlen(fullname) + strlen(searchdir) + 2); -+ if (!tmp1) FatalError("malloc 'filename' failed"); -+ sprintf(tmp1,"%s/%s", searchdir, fullname); -+#else /* it is VMS */ -+ tmp1 = (char *) malloc(strlen(fullname) + 2); -+ if (!tmp1) FatalError("malloc 'filename' failed"); -+ sprintf(tmp1,"%s", fullname); -+#endif -+ -+ fp = fopen(tmp1, "r"); -+ if (fp) { /* searchpath/fullname exists */ -+ fclose(fp); -+ fullname = tmp1; -+ freename = 1; -+ } -+ else free(tmp1); /* doesn't exist either... */ -+ } -+ } -+ } -+ -+ strcpy(filename, fullname); -+ -+ -+ /* if the file is STDIN, write it out to a temp file */ -+ -+ if (strcmp(filename,STDINSTR)==0) { -+ FILE *fp; -+ -+#ifndef VMS -+ sprintf(filename,"%s/xvXXXXXX",tmpdir); -+#else /* it is VMS */ -+ sprintf(filename, "[]xvXXXXXX"); -+#endif -+ mktemp(filename); -+ -+ clearerr(stdin); -+ fp = fopen(filename,"w"); -+ if (!fp) FatalError("openPic(): can't write temporary file"); -+ -+ while ( (i=getchar()) != EOF) putc(i,fp); -+ fclose(fp); -+ -+ /* and remove it from list, since we can never reload from stdin */ -+ if (strcmp(namelist[0], STDINSTR)==0) deleteFromList(0); -+ } -+ } -+ -+ -+ -+ HAVE_FILENAME: -+ -+ /******* AT THIS POINT 'filename' is the name of an actual data file -+ (no pipes or stdin, though it could be compressed) to be loaded */ -+ filetype = ReadFileType(filename); -+ -+ -+ if (filetype == RFT_COMPRESS) { /* a compressed file. uncompress it */ -+ char tmpname[128]; -+ -+ if ( -+#ifndef VMS -+ UncompressFile(filename, tmpname) -+#else -+ UncompressFile(basefname, tmpname) -+#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); -+ -+ strcpy(filename, tmpname); -+ } -+ else filetype = RFT_ERROR; -+ -+ WaitCursor(); -+ } -+ -+ -+ if (filetype == RFT_ERROR) { -+ char foostr[512]; -+ sprintf(foostr,"Can't open file '%s'\n\n %s.",filename, ERRSTR(errno)); -+ -+ if (!polling) ErrPopUp(foostr, "\nBummer!"); -+ -+ goto FAILED; /* couldn't get magic#, screw it! */ -+ } -+ -+ -+ if (filetype == RFT_UNKNOWN) { -+ /* view as a text/hex file */ -+ TextView(filename); -+ SetISTR(ISTR_INFO,"'%s' not in a recognized format.", basefname); -+ /* Warning(); */ -+ goto SHOWN_AS_TEXT; -+ } -+ -+ if (filetype < RFT_ERROR) { -+ SetISTR(ISTR_INFO,"'%s' not in a readable format.", basefname); -+ Warning(); -+ goto FAILED; -+ } -+ -+ -+ /****** AT THIS POINT: the filetype is a known, readable format */ -+ -+ /* kill old page files, if any */ -+ if (killpage) { -+ KillPageFiles(pageBaseName, numPages); -+ pageBaseName[0] = '\0'; -+ numPages = 1; -+ curPage = 0; -+ } -+ -+ -+ SetISTR(ISTR_INFO,"Loading..."); -+ -+ i = ReadPicFile(filename, filetype, &pinfo, 0); -+ -+ 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; -+ } -+ -+ if (!i) { -+ SetISTR(ISTR_INFO,"Couldn't load file '%s'.",filename); -+ Warning(); -+ goto FAILED; -+ } -+ -+ -+ -+ WaitCursor(); -+ -+ if (pinfo.w==0 || pinfo.h==0) { /* shouldn't happen, but let's be safe */ -+ SetISTR(ISTR_INFO,"Image size '0x0' not allowed."); -+ Warning(); -+ if (pinfo.pic) free(pinfo.pic); pinfo.pic = (byte *) NULL; -+ if (pinfo.comment) free(pinfo.comment); pinfo.comment = (char *) NULL; -+ goto FAILED; -+ } -+ -+ -+ /**************/ -+ /* SUCCESS!!! */ -+ /**************/ -+ -+ -+ GOTIMAGE: -+ /* successfully read this picture. No failures from here on out -+ (well, once the pic has been converted if we're locked in a mode) */ -+ -+ -+ state824 = 0; -+ -+ /* if we're locked into a mode, do appropriate conversion */ -+ 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, -+ pinfo.r, pinfo.g, pinfo.b); -+ free(pinfo.pic); -+ pinfo.pic = pic8; -+ pinfo.type = PIC8; -+ -+ state824 = 1; -+ } -+ -+ else if (pinfo.type!=PIC24 && picType==PIC24) { /* 8 -> 24 bit */ -+ byte *pic24; -+ pic24 = Conv8to24(pinfo.pic, pinfo.w, pinfo.h, -+ pinfo.r, pinfo.g, pinfo.b); -+ free(pinfo.pic); -+ pinfo.pic = pic24; -+ pinfo.type = PIC24; -+ } -+ } -+ else { /* not locked. switch 8/24 mode */ -+ picType = pinfo.type; -+ Set824Menus(picType); -+ } -+ -+ -+ if (!pinfo.pic) { /* must've failed in the 8-24 or 24-8 conversion */ -+ SetISTR(ISTR_INFO,"Couldn't do %s conversion.", -+ (picType==PIC24) ? "8->24" : "24->8"); -+ if (pinfo.comment) free(pinfo.comment); pinfo.comment = (char *) NULL; -+ Warning(); -+ goto FAILED; -+ } -+ -+ -+ -+ /* ABSOLUTELY no failures from here on out... */ -+ -+ -+ if (strlen(pinfo.pagebname)) { -+ strcpy(pageBaseName, pinfo.pagebname); -+ numPages = pinfo.numpages; -+ curPage = 0; -+ } -+ -+ ignoreConfigs = 1; -+ -+ if (mainW && !useroot) { -+ /* avoid generating excess configure events while we resize the window */ -+ XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask -+ | StructureNotifyMask -+ | ButtonPressMask | KeyReleaseMask -+ | EnterWindowMask | LeaveWindowMask); -+ XFlush(theDisp); -+ } -+ -+ /* kill off OLD picture, now that we've succesfully loaded a new one */ -+ KillOldPics(); -+ SetInfoMode(INF_STR); -+ -+ -+ /* get info out of the PICINFO struct */ -+ pic = pinfo.pic; -+ pWIDE = pinfo.w; -+ 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(); -+ -+ for (i=0; i<256; i++) { -+ rMap[i] = pinfo.r[i]; -+ gMap[i] = pinfo.g[i]; -+ bMap[i] = pinfo.b[i]; -+ } -+ -+ -+ -+ AlgInit(); -+ -+ /* stick this file in the 'ctrlW' name list */ -+ if (filenum == LOADPIC && !frompipe) StickInCtrlList(1); -+ -+ if (polling && !frompoll) InitPoll(); -+ -+ /* turn off 'frompoll' if the pic has changed size */ -+ if (frompoll && (pWIDE != oldpWIDE || pHIGH != oldpHIGH)) frompoll = 0; -+ -+ -+ if (!browseCB.val && filenum == LOADPIC) DirBox(0); /* close the DirBox */ -+ -+ -+ /* if we read a /tmp file, delete it. won't be needing it any more */ -+ if (fullname && strcmp(fullname,filename)!=0) unlink(filename); -+ -+ -+ SetISTR(ISTR_INFO,formatStr); -+ -+ SetInfoMode(INF_PART); -+ SetISTR(ISTR_FILENAME, -+ (filenum==DFLTPIC || filenum==GRABBED || frompipe) -+ ? "<none>" : basefname); -+ -+ SetISTR(ISTR_RES,"%d x %d",pWIDE,pHIGH); -+ SetISTR(ISTR_COLOR, ""); -+ SetISTR(ISTR_COLOR2,""); -+ -+ /* adjust button in/activity */ -+ if (HaveSelection()) EnableSelection(0); -+ SetSelectionString(); -+ BTSetActive(&but[BCROP], 0); -+ BTSetActive(&but[BUNCROP], 0); -+ BTSetActive(&but[BCUT], 0); -+ BTSetActive(&but[BCOPY], 0); -+ BTSetActive(&but[BCLEAR], 0); -+ -+ ActivePrevNext(); -+ -+ -+ -+ /* handle various 'auto-whatever' command line options -+ 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 */ -+ -+ -+ if (frompoll) { -+ cpic = pic; cWIDE = pWIDE; cHIGH = pHIGH; cXOFF = cYOFF = 0; -+ FreeEpic(); -+ if (wascropped) DoCrop(oldCXOFF, oldCYOFF, oldCWIDE, oldCHIGH); -+ FreeEpic(); eWIDE = oldeWIDE; eHIGH = oldeHIGH; -+ SetCropString(); -+ } -+ else { -+ int w,h,aspWIDE,aspHIGH,oldemode; -+ -+ oldemode = epicMode; -+ epicMode = EM_RAW; /* be in raw mode for all intermediate conversions */ -+ cpic = pic; cWIDE = pWIDE; cHIGH = pHIGH; cXOFF = cYOFF = 0; -+ epic = cpic; eWIDE = cWIDE; eHIGH = cHIGH; -+ -+ SetCropString(); -+ -+ /*****************************************/ -+ /* handle aspect options: -aspect, -4x3 */ -+ /*****************************************/ -+ -+ if (normaspect != 1.0) { /* -aspect */ -+ FixAspect(1, &w, &h); -+ eWIDE = w; eHIGH = h; -+ } -+ -+ if (auto4x3) { -+ w = eWIDE; h = (w*3) / 4; -+ eWIDE = w; eHIGH = h; -+ } -+ -+ -+ if (eWIDE != cWIDE || eHIGH != cHIGH) epic = (byte *) NULL; -+ -+ /**************************************/ -+ /* handle cropping (-acrop and -crop) */ -+ /**************************************/ -+ -+ if (autocrop) DoAutoCrop(); -+ if (acrop) DoCrop(acropX, acropY, acropW, acropH); -+ -+ if (eWIDE != cWIDE || eHIGH != cHIGH) epic = (byte *) NULL; -+ -+ /********************************/ -+ /* handle rotation and flipping */ -+ /********************************/ -+ -+ if (autorotate) { -+ /* figure out optimal rotation. (ie, instead of +270, do -90) */ -+ if (autorotate == 270) autorotate = -90; -+ else if (autorotate == -270) autorotate = 90; -+ -+ i = autorotate; -+ while (i) { -+ if (i < 0) { /* rotate CW */ -+ DoRotate(0); -+ i += 90; -+ } -+ else { /* rotate CCW */ -+ DoRotate(1); -+ i -= 90; -+ } -+ } -+ } -+ -+ if (autohflip) Flip(0); /* horizontal flip */ -+ if (autovflip) Flip(1); /* vertical flip */ -+ -+ -+ /********************************************/ -+ /* handle expansion options: */ -+ /* -expand, -max, -maxpect, -fixed, -geom */ -+ /********************************************/ -+ -+ /* at this point, treat whatever eWIDE,eHIGH is as 1x1 expansion, -+ (due to earlier aspect-ratio option handling). Note that -+ all that goes on here is that eWIDE/eHIGH are modified. No -+ images are generated. */ -+ -+ aspWIDE = eWIDE; aspHIGH = eHIGH; /* aspect-corrected eWIDE,eHIGH */ -+ -+ if (hexpand < 0.0) eWIDE=(int)(aspWIDE / -hexpand); /* neg: reciprocal */ -+ else eWIDE=(int)(aspWIDE * hexpand); -+ if (vexpand < 0.0) eHIGH=(int)(aspHIGH / -vexpand); /* neg: reciprocal */ -+ 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; -+ i = XParseGeometry(maingeom,&x,&y,&w,&h); -+ -+ 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; } -+ } -+ -+ /* specified a 'maximum size, but please keep your aspect ratio */ -+ if (fixedaspect && i&WidthValue && i&HeightValue) { -+ if (aspWIDE > gewide || aspHIGH > gehigh) { -+ /* shrink aspWIDE,HIGH accordingly... */ -+ double r,wr,hr; -+ -+ wr = ((double) aspWIDE) / gewide; -+ hr = ((double) aspHIGH) / gehigh; -+ -+ r = (wr>hr) ? wr : hr; /* r is the max(wr,hr) */ -+ aspWIDE = (int) ((aspWIDE / r) + 0.5); -+ aspHIGH = (int) ((aspHIGH / r) + 0.5); -+ } -+ -+ /* image is now definitely no larger than gewide,gehigh */ -+ /* should now expand it so that one axis is of specified size */ -+ -+ if (aspWIDE != gewide && aspHIGH != gehigh) { /* is smaller */ -+ /* grow aspWIDE,HIGH accordingly... */ -+ double r,wr,hr; -+ -+ wr = ((double) aspWIDE) / gewide; -+ hr = ((double) aspHIGH) / gehigh; -+ -+ r = (wr>hr) ? wr : hr; /* r is the max(wr,hr) */ -+ aspWIDE = (int) ((aspWIDE / r) + 0.5); -+ aspHIGH = (int) ((aspHIGH / r) + 0.5); -+ -+ } -+ -+ eWIDE = aspWIDE; eHIGH = aspHIGH; -+ } -+ else { eWIDE = gewide; eHIGH = gehigh; } -+ } -+ -+ -+ if (automax) { /* -max and -maxpect */ -+ eWIDE = dispWIDE; eHIGH = dispHIGH; -+ if (fixedaspect) FixAspect(0,&eWIDE,&eHIGH); -+ } -+ -+ -+ /* now, just make sure that eWIDE/eHIGH aren't too big... */ -+ /* shrink eWIDE,eHIGH preserving aspect ratio, if so... */ -+ if (eWIDE>maxWIDE || eHIGH>maxHIGH) { -+ /* the numbers here can get big. use floats */ -+ double r,wr,hr; -+ -+ wr = ((double) eWIDE) / maxWIDE; -+ hr = ((double) eHIGH) / maxHIGH; -+ -+ r = (wr>hr) ? wr : hr; /* r is the max(wr,hr) */ -+ eWIDE = (int) ((eWIDE / r) + 0.5); -+ eHIGH = (int) ((eHIGH / r) + 0.5); -+ } -+ -+ if (eWIDE < 1) eWIDE = 1; /* just to be safe... */ -+ if (eHIGH < 1) eHIGH = 1; -+ -+ /* 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; -+ i = (dispHIGH + eHIGH-1) / eHIGH; eHIGH = (dispHIGH + i-1) / i; -+ } -+ -+ -+ if (eWIDE != cWIDE || eHIGH != cHIGH) epic = (byte *) NULL; -+ -+ /********************************************/ -+ /* handle epic generation options: */ -+ /* -raw, -dith, -smooth */ -+ /********************************************/ -+ -+ 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 -smooth or image has been shrunk to fit screen */ -+ if (autosmooth || (pWIDE >maxWIDE || pHIGH>maxHIGH) -+ || (cWIDE != eWIDE || cHIGH != eHIGH)) epicMode = EM_SMOOTH; -+ -+ if (autoraw) epicMode = EM_RAW; -+ -+ /* 'dithering' makes no sense in 24-bit mode */ -+ if (picType == PIC24 && epicMode == EM_DITH) epicMode = EM_RAW; -+ -+ SetEpicMode(); -+ } /* end of !frompoll */ -+ -+ -+ -+ /* at this point eWIDE,eHIGH are correct, but a proper epic (particularly -+ if in DITH or SMOOTH mode) doesn't exist yet. Will be made once the -+ colors have been picked. */ -+ -+ -+ -+ /* clear old image (window/root) before we start changing colors... */ -+ if (CMAPVIS(theVisual) && clearonload && picType == PIC8 && -+ colorMapMode != CM_STDCMAP) { -+ -+ if (mainW && !useroot) { -+ XClearArea(theDisp, mainW, 0,0, (u_int)oldeWIDE, (u_int)oldeHIGH, True); -+ XFlush(theDisp); -+ } -+ -+ if (useroot) { -+ mainW = vrootW; -+ ClearRoot(); -+ } -+ } -+ -+ -+ if (useroot) mainW = vrootW; -+ if (eWIDE != cWIDE || eHIGH != cHIGH) epic = (byte *) NULL; -+ -+ NewPicGetColors(autonorm, autohisteq); -+ -+ GenerateEpic(eWIDE, eHIGH); /* want to dither *after* color allocs */ -+ CreateXImage(); -+ -+ WaitCursor(); -+ HandleDispMode(); /* create root pic, or mainW, depending... */ -+ -+ -+ if (LocalCmap) { -+ XSetWindowAttributes xswa; -+ xswa.colormap = LocalCmap; -+ -+ if (!ninstall) XInstallColormap(theDisp,LocalCmap); -+ XChangeWindowAttributes(theDisp,mainW,CWColormap,&xswa); -+ if (cmapInGam) XChangeWindowAttributes(theDisp,gamW,CWColormap,&xswa); -+ } -+ -+ -+ -+ tmp = GetISTR(ISTR_COLOR); -+ SetISTR(ISTR_INFO,"%s %s %s", formatStr, -+ (picType==PIC8) ? "8-bit mode." : "24-bit mode.", -+ tmp); -+ -+ SetInfoMode(INF_FULL); -+ if (freename) free(fullname); -+ -+ -+ SetCursors(-1); -+ -+ -+ if (dirUp!=BLOAD) { -+ /* put current filename into the 'save-as' filename */ -+ if (strcmp(filename,STDINSTR)==0) SetDirFName("stdin"); -+ else if (frompipe || filenum == LOADPIC || filenum == GRABBED || -+ filenum == DFLTPIC || filenum == PADDED) {} /* leave it alone */ -+ else SetDirFName(basefname); -+ } -+ -+ -+ /* force a redraw of the whole window, as I can't quite trust Config's -+ to generate the correct exposes (particularly with 'BitGravity' turned -+ on */ -+ -+ if (mainW && !useroot) 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) -+ unlink(filename); /* kill /tmp file */ -+ if (freename) free(fullname); -+ -+ if (!fromint && !polling && filenum>=0 && filenum<nList.nstr) -+ deleteFromList(filenum); -+ -+ if (polling) sleep(1); -+ -+ return 0; -+ -+ -+ SHOWN_AS_TEXT: /* file wasn't in recognized format... */ -+ SetCursors(-1); -+ -+ if (strcmp(fullname,filename)!=0) unlink(filename); /* kill /tmp file */ -+ if (freename) free(fullname); -+ -+ ActivePrevNext(); -+ return 1; /* we've displayed the file 'ok' */ -+} -+ -+ -+ -+/********************************/ -+int ReadFileType(fname) -+ char *fname; -+{ -+ /* opens fname (which *better* be an actual file by this point!) and -+ reads the first couple o' bytes. Figures out what the file's likely -+ to be, and returns the appropriate RFT_*** code */ -+ -+ -+ FILE *fp; -+ byte magicno[30]; /* first 30 bytes of file */ -+ int rv, n; -+ -+ 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); -+ fclose(fp); -+ -+ if (n<30) return RFT_UNKNOWN; /* files less than 30 bytes long... */ -+ -+ rv = RFT_UNKNOWN; -+ -+ 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; -+ -+ else if (magicno[0] == 'P' && magicno[1]>='1' && -+ magicno[1]<='6') 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; -+ -+ else if (magicno[0]==0x59 && (magicno[1]&0x7f)==0x26 && -+ 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]==0x52 && magicno[1]==0xcc) rv = RFT_UTAHRLE; -+ -+ else if ((magicno[0]==0x01 && magicno[1]==0xda) || -+ (magicno[0]==0xda && magicno[1]==0x01)) rv = RFT_IRIS; -+ -+ else if (magicno[0]==0x1f && magicno[1]==0x9d) rv = RFT_COMPRESS; -+ -+#ifdef GUNZIP -+ else if (magicno[0]==0x1f && magicno[1]==0x8b) rv = RFT_COMPRESS; -+#endif -+ -+ 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 (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; -+ -+ else if (magicno[4]==0x00 && magicno[5]==0x00 && -+ 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; -+ -+ -+#ifdef HAVE_JPEG -+ else if (magicno[0]==0xff && magicno[1]==0xd8 && -+ magicno[2]==0xff) rv = RFT_JFIF; -+#endif -+ -+#ifdef HAVE_TIFF -+ else if ((magicno[0]=='M' && magicno[1]=='M') || -+ (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 -+ else if (strncmp((char *) magicno, "NJPL1I00", (size_t) 8)==0 || -+ strncmp((char *) magicno+2,"NJPL1I", (size_t) 6)==0 || -+ strncmp((char *) magicno, "CCSD3ZF", (size_t) 7)==0 || -+ strncmp((char *) magicno+2,"CCSD3Z", (size_t) 6)==0 || -+ strncmp((char *) magicno, "LBLSIZE=", (size_t) 8)==0) -+ rv = RFT_PDSVICAR; -+#endif -+ -+#ifdef GS_PATH -+ else if (strncmp((char *) magicno, "%!", (size_t) 2)==0 || -+ strncmp((char *) magicno, "\004%!", (size_t) 3)==0) rv = RFT_PS; -+#endif -+ -+#ifdef GS_PATH -+ else if (strncmp((char *) magicno, "%PDF", (size_t) 4)==0) rv = RFT_PS; -+#endif -+ -+ return rv; -+} -+ -+ -+ -+/********************************/ -+int ReadPicFile(fname, ftype, pinfo, quick) -+ char *fname; -+ int ftype, quick; -+ 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 */ -+ -+ int rv = 0; -+ -+ /* by default, most formats aren't multi-page */ -+ pinfo->numpages = 1; -+ pinfo->pagebname[0] = '\0'; -+ -+ switch (ftype) { -+ case RFT_GIF: rv = LoadGIF (fname, pinfo); break; -+ case RFT_PM: rv = LoadPM (fname, pinfo); break; -+ case RFT_PBM: rv = LoadPBM (fname, pinfo); break; -+ case RFT_XBM: rv = LoadXBM (fname, pinfo); break; -+ case RFT_SUNRAS: rv = LoadSunRas(fname, pinfo); break; -+ case RFT_BMP: rv = LoadBMP (fname, pinfo); break; -+ case RFT_UTAHRLE: rv = LoadRLE (fname, pinfo); break; -+ case RFT_IRIS: rv = LoadIRIS (fname, pinfo); break; -+ case RFT_PCX: rv = LoadPCX (fname, pinfo); break; -+ case RFT_IFF: rv = LoadIFF (fname, pinfo); break; -+ case RFT_TARGA: rv = LoadTarga (fname, pinfo); break; -+ 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; -+ -+#ifdef HAVE_JPEG -+ case RFT_JFIF: rv = LoadJFIF (fname, pinfo, quick); break; -+#endif -+ -+#ifdef HAVE_TIFF -+ case RFT_TIFF: rv = LoadTIFF (fname, pinfo); 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; -+#endif -+ -+#ifdef GS_PATH -+ case RFT_PS: rv = LoadPS (fname, pinfo, quick); break; -+#endif -+ -+ } -+ return rv; -+} -+ -+ -+/********************************/ -+int UncompressFile(name, uncompname) -+ char *name, *uncompname; -+{ -+ /* returns '1' on success, with name of uncompressed file in uncompname -+ returns '0' on failure */ -+ -+ char namez[128], *fname, buf[512]; -+ -+ fname = name; -+ namez[0] = '\0'; -+ -+ -+#if !defined(VMS) && !defined(GUNZIP) -+ /* see if compressed file name ends with '.Z'. If it *doesn't* we need -+ temporarily rename it so it *does*, uncompress it, and rename *back* -+ to what it was. necessary because uncompress doesn't handle files -+ that don't end with '.Z' */ -+ -+ if (strlen(name) >= (size_t) 2 && -+ strcmp(name + strlen(name)-2,".Z")!=0 && -+ strcmp(name + strlen(name)-2,".z")!=0) { -+ strcpy(namez, name); -+ strcat(namez,".Z"); -+ -+ if (rename(name, namez) < 0) { -+ sprintf(buf, "Error renaming '%s' to '%s': %s", -+ name, namez, ERRSTR(errno)); -+ ErrPopUp(buf, "\nBummer!"); -+ return 0; -+ } -+ -+ fname = namez; -+ } -+#endif /* not 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 */ -+ strcpy(uncompname, "[]xvuXXXXXX"); -+ mktemp(uncompname); -+# 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)) { -+#else -+ 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', -+ rename it back to what it once was... */ -+ -+ if (strlen(namez)) { -+ if (rename(namez, name) < 0) { -+ sprintf(buf, "Error renaming '%s' to '%s': %s", -+ namez, name, ERRSTR(errno)); -+ ErrPopUp(buf, "\nBummer!"); -+ } -+ } -+#else -+ /* -+ sprintf(buf,"Rename %s %s", fname, uncompname); -+ SetISTR(ISTR_INFO,"Renaming '%s'...", fname); -+ if (!system(buf)) { -+ SetISTR(ISTR_INFO,"Unable to rename '%s'.", fname); -+ Warning(); -+ return 0; -+ } -+ */ -+#endif /* not VMS */ -+ -+ return 1; -+} -+ -+ -+/********************************/ -+void KillPageFiles(bname, numpages) -+ char *bname; -+ int numpages; -+{ -+ /* deletes any page files (numbered 1 through numpages) that might exist */ -+ char tmp[128]; -+ int i; -+ -+ if (strlen(bname) == 0) return; /* no page files */ -+ -+ for (i=1; i<=numpages; i++) { -+ sprintf(tmp, "%s%d", bname, i); -+ unlink(tmp); -+ } -+} -+ -+ -+/********************************/ -+void NewPicGetColors(donorm, dohist) -+ int donorm, dohist; -+{ -+ int i; -+ -+ /* 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; -+ -+ if (picType == PIC8) { -+ byte trans[256]; -+ SortColormap(pic,pWIDE,pHIGH,&numcols,rMap,gMap,bMap,colAllocOrder,trans); -+ ColorCompress8(trans); -+ } -+ -+ if (picType == PIC8) { -+ /* 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; -+ bMap[0] = whtRGB&0xff; -+ -+ rMap[1] = (blkRGB>>16)&0xff; -+ gMap[1] = (blkRGB>>8)&0xff; -+ bMap[1] = blkRGB&0xff; -+ } -+ -+ else if ((rMap[0] == gMap[0] && rMap[0] == bMap[0] && rMap[0] == 0) && -+ (rMap[1] == gMap[1] && rMap[1] == bMap[1] && rMap[1] == 255)) { -+ /*0=blk,1=wht*/ -+ rMap[0] = (blkRGB>>16)&0xff; -+ gMap[0] = (blkRGB>>8)&0xff; -+ bMap[0] = blkRGB&0xff; -+ -+ rMap[1] = (whtRGB>>16)&0xff; -+ gMap[1] = (whtRGB>>8)&0xff; -+ bMap[1]=whtRGB&0xff; -+ } -+ } -+ } -+ -+ -+ if (picType == PIC8) { -+ /* reverse image, if desired */ -+ if (revvideo) { -+ for (i=0; i<numcols; i++) { -+ rMap[i] = 255 - rMap[i]; -+ gMap[i] = 255 - gMap[i]; -+ bMap[i] = 255 - bMap[i]; -+ } -+ } -+ -+ /* 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]; -+ } -+ } -+ -+ else if (picType == PIC24 && revvideo) { -+ if (pic) InvertPic24(pic, pWIDE, pHIGH); -+ if (cpic && cpic!=pic) InvertPic24(cpic, cWIDE, cHIGH); -+ if (epic && epic!=cpic) InvertPic24(epic, eWIDE, eHIGH); -+ if (egampic && egampic != epic) InvertPic24(egampic, eWIDE, eHIGH); -+ } -+ -+ -+ NewCMap(); -+ -+ if (donorm) DoNorm(); -+ if (dohist) DoHistEq(); -+ -+ GammifyColors(); -+ -+ if (picType == PIC24) ChangeCmapMode(CM_STDCMAP, 0, 1); -+ else ChangeCmapMode(defaultCmapMode, 0, 1); -+ -+ ChangeEC(0); -+} -+ -+ -+ -+/***********************************/ -+static int readpipe(cmd, fname) -+ char *cmd, *fname; -+{ -+ /* cmd is something like: "! bggen 100 0 0" -+ * -+ * 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; -+ -+ if (!cmd || (strlen(cmd) < (size_t) 2)) return 1; -+ -+ sprintf(tmpname,"%s/xvXXXXXX", tmpdir); -+ mktemp(tmpname); -+ if (tmpname[0] == '\0') { /* mktemp() blew up */ -+ sprintf(str,"Unable to create temporary filename."); -+ ErrPopUp(str, "\nHow unlikely!"); -+ return 1; -+ } -+ -+ /* build command */ -+ strcpy(fullcmd, cmd+1); /* skip the leading '!' character in cmd */ -+ strcat(fullcmd, " > "); -+ strcat(fullcmd, tmpname); -+ -+ /* execute the command */ -+ sprintf(str, "Doing command: '%s'", fullcmd); -+ OpenAlert(str); -+ i = system(fullcmd); -+ if (i) { -+ sprintf(str, "Unable to complete command:\n %s\n\n exit status: %d", -+ fullcmd, i); -+ CloseAlert(); -+ ErrPopUp(str, "\nThat Sucks!"); -+ unlink(tmpname); /* just in case it was created */ -+ return 1; -+ } -+ -+ CloseAlert(); -+ strcpy(fname, tmpname); -+ return 0; -+} -+ -+ -+ -+ -+ -+ -+/****************/ -+static void openFirstPic() -+{ -+ int i; -+ -+ 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; -+ } -+ } -+ } -+ -+ 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); -+} -+ -+ -+/****************/ -+static void openNextPic() -+{ -+ int i; -+ -+ 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 */ -+ -+ openPic(DFLTPIC); -+} -+ -+ -+/****************/ -+static void openNextQuit() -+{ -+ int i; -+ -+ if (!randomShow) { -+ 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; -+ } -+ -+ Quit(0); -+} -+ -+ -+/****************/ -+static void openNextLoop() -+{ -+ int i,j,loop; -+ -+ 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 (loop) { i = 0; loop = 0; } -+ -+ while (i<numnames && !openPic(i)); -+ if (i<numnames) return; -+ } -+ else { -+ for (i=findRandomPic(); i>=0; i=findRandomPic()) -+ if (openPic(i)) return; -+ } -+ -+ loop = 1; /* back to top of list */ -+ if (j) break; /* we're in a 'failure loop' */ -+ j++; -+ } -+ -+ openPic(DFLTPIC); -+} -+ -+ -+/****************/ -+static void openPrevPic() -+{ -+ int i; -+ -+ if (curname>0) i = curname-1; -+ else if (nList.selected>0 && nList.selected < numnames) -+ i = nList.selected - 1; -+ else i = numnames-1; -+ -+ for ( ; i>=0; i--) { -+ if (openPic(i)) return; /* success */ -+ } -+ -+ openPic(DFLTPIC); -+} -+ -+ -+/****************/ -+static void openNamedPic() -+{ -+ /* if (!openPic(LOADPIC)) openPic(DFLTPIC); */ -+ 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 -+ 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 -+ 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 */ -+ -+ if (!pic) { /* must've opened a text file... display dflt pic */ -+ openPic(DFLTPIC); -+ if (mainW && !useroot) RaiseTextWindows(); -+ } -+ -+ if (useroot && autoquit) Quit(0); -+ -+ while ((i=EventLoop()) != QUIT) { -+ if (i==NEXTPIC) { -+ if ((curname<0 && numnames>0) || -+ (curname<numnames-1)) openNextPic(); -+ } -+ -+ else if (i==PREVPIC) { -+ if (curname>0 || (curname<0 && nList.selected>0)) -+ openPrevPic(); -+ } -+ -+ else if (i==NEXTQUIT) openNextQuit(); -+ else if (i==NEXTLOOP) openNextLoop(); -+ else if (i==LOADPIC) openNamedPic(); -+ -+ else if (i==DELETE) { /* deleted currently-viewed image */ -+ curname = -1; -+ ActivePrevNext(); -+ if (but[BNEXT].active) -+ FakeButtonPress(&but[BNEXT]); -+ else openPic(DFLTPIC); -+ } -+ -+ else if (i==THISNEXT) { /* open current sel, 'next' until success */ -+ int j; -+ j = nList.selected; -+ if (j<0) j = 0; -+ while (j<numnames && !openPic(j)); -+ if (!pic) openPic(DFLTPIC); -+ } -+ -+ else if (i>=0 || i==GRABBED || i==POLLED || i==RELOAD || -+ i==OP_PAGEUP || i==OP_PAGEDN || i==DFLTPIC || i==PADDED) { -+ openPic(i); -+ /* if (!openPic(i)) openPic(DFLTPIC); */ -+ } -+ } -+} -+ -+ -+ -+/***********************************/ -+static void createMainWindow(geom, name) -+ char *geom, *name; -+{ -+ XSetWindowAttributes xswa; -+ unsigned long xswamask; -+ XWindowAttributes xwa; -+ XWMHints xwmh; -+ XSizeHints hints; -+ XClassHint classh; -+ int i,x,y; -+ unsigned int w,h; -+ static int firstTime = 1; -+ -+ /* -+ * this function mainly deals with parsing the geometry spec correctly. -+ * More trouble than it should be, and probably more trouble than -+ * it has to be, but who can tell these days, what with all those -+ * Widget-usin' Weenies out there... -+ * -+ * Note: eWIDE,eHIGH have the correct, desired window size. Ignore the -+ * w,h fields in the geometry spec, as they've already been dealt with -+ */ -+ -+ x = y = w = h = 1; -+ i = XParseGeometry(geom,&x,&y,&w,&h); -+ -+ hints.flags = 0; -+ 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); -+ -+ if (x+eWIDE > vrWIDE) x = vrWIDE - eWIDE; /* keep on screen */ -+ if (y+eHIGH > vrHIGH) y = vrHIGH - eHIGH; -+ -+ -+#define VROOT_TRANS -+#ifdef VROOT_TRANS -+ if (vrootW != rootW) { /* 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); -+ x = x1; y = y1; -+ } -+#endif -+ -+ 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; -+ 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 -+ servers (HP 9000/300 series running X11R4) don't properly deal with -+ things when the image window changes size. It isn't a big performance -+ 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 -+ image window will, too */ -+ -+ xswamask = CWBackPixel | CWBorderPixel | CWColormap /* | CWBackingStore */; -+ if (!clearonload) xswamask |= CWBitGravity; -+ -+ if (mainW) { -+ GetWindowPos(&xwa); -+ 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 < 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, -+ theVisual, xswamask, &xswa); -+ if (!mainW) FatalError("can't create window!"); -+ -+ XSetCommand(theDisp, mainW, mainargv, mainargc); -+ -+ if (LocalCmap) { -+ xswa.colormap = LocalCmap; -+ XChangeWindowAttributes(theDisp,mainW,CWColormap,&xswa); -+ } -+ } -+ -+ -+ XSetStandardProperties(theDisp,mainW,"","",None,NULL,0,&hints); -+ setWinIconNames(name); -+ -+ xwmh.input = True; -+ xwmh.flags = InputHint; -+ -+ xwmh.icon_pixmap = iconPix; -+ xwmh.icon_mask = iconmask; -+ xwmh.flags |= (IconPixmapHint | IconMaskHint); -+ -+ -+ if (startIconic && firstTime) { -+ xwmh.initial_state = IconicState; -+ xwmh.flags |= StateHint; -+ -+ if (icongeom) { -+ int i,x,y; unsigned int w,h; -+ i = XParseGeometry(icongeom, &x, &y, &w, &h); /* ignore w,h */ -+ if (i&XValue && i&YValue) { -+ if (i&XValue && i&XNegative) x = vrWIDE - icon_width - abs(x); -+ if (i&YValue && i&YNegative) y = vrHIGH - icon_height - abs(y); -+ -+ xwmh.icon_x = x; xwmh.icon_y = y; -+ xwmh.flags |= (IconPositionHint); -+ } -+ } -+ } -+ XSetWMHints(theDisp, mainW, &xwmh); -+ -+ classh.res_name = "xv"; -+ classh.res_class = "XVroot"; -+ XSetClassHint(theDisp, mainW, &classh); -+ -+ -+ if (nodecor) { /* turn of image window decorations (in MWM) */ -+ Atom mwm_wm_hints; -+ struct s_mwmhints { -+ long flags; -+ long functions; -+ long decorations; -+ 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)); -+ mwmhints.flags = 2; -+ mwmhints.decorations = 4; -+ -+ XChangeProperty(theDisp, mainW, mwm_wm_hints, mwm_wm_hints, 32, -+ PropModeReplace, (byte *) &mwmhints, -+ (int) (sizeof(mwmhints))/4); -+ XSync(theDisp, False); -+ } -+ } -+ -+ -+ firstTime = 0; -+} -+ -+ -+/***********************************/ -+static void setWinIconNames(name) -+ char *name; -+{ -+ char winname[256], iconname[256]; -+ -+ if (winTitle) { -+ strcpy(winname, winTitle); -+ strcpy(iconname, winTitle); -+ } -+ else if (name[0] == '\0') { -+ sprintf(winname, "xv %s",VERSTR); -+ sprintf(iconname,"xv"); -+ } -+ else { -+ sprintf(winname,"xv %s: %s", VERSTR, name); -+ sprintf(iconname,"%s",name); -+ } -+ -+#ifndef REGSTR -+ strcat(winname, " <unregistered>"); -+#endif -+ -+ if (mainW) { -+ XStoreName(theDisp, mainW, winname); -+ XSetIconName(theDisp, mainW, iconname); -+ } -+} -+ -+ -+/***********************************/ -+void FixAspect(grow,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. -+ Returns these values in 'w' and 'h' */ -+ -+ float xr,yr,curaspect,a,exp; -+ -+ *w = eWIDE; *h = eHIGH; -+ -+ /* xr,yr are expansion factors */ -+ xr = ((float) eWIDE) / cWIDE; -+ yr = ((float) eHIGH) / cHIGH; -+ curaspect = xr / yr; -+ -+ /* if too narrow & shrink, shrink height. too wide and grow, grow height */ -+ 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) || -+ (curaspect > normaspect && !grow)) { /* modify width */ -+ exp = normaspect / curaspect; -+ *w = (int) (eWIDE * exp + .5); -+ } -+ -+ -+ /* shrink to fit screen without changing aspect ratio */ -+ if (*w>maxWIDE) { -+ int i; -+ a = (float) *w / maxWIDE; -+ *w = maxWIDE; -+ i = (int) (*h / a + .5); /* avoid freaking some optimizers */ -+ *h = i; -+ } -+ -+ if (*h>maxHIGH) { -+ a = (float) *h / maxHIGH; -+ *h = maxHIGH; -+ *w = (int) (*w / a + .5); -+ } -+ -+ if (*w < 1) *w = 1; -+ if (*h < 1) *h = 1; -+} -+ -+ -+/***********************************/ -+static void makeDispNames() -+{ -+ int prelen, n, i, done; -+ char *suffix; -+ -+ 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++) -+ dispnames[i] = namelist[i] + prelen; -+} -+ -+ -+/***********************************/ -+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; -+ } -+ } -+ dispnames[i] = tmp; -+ } -+ } -+} -+ -+ -+/***********************************/ -+void StickInCtrlList(select) -+ int select; -+{ -+ /* stick current name (from 'load/save' box) and current working directory -+ into 'namelist'. Does redraw list. */ -+ -+ char *name; -+ char cwd[MAXPATHLEN]; -+ -+ name = GetDirFName(); -+ GetDirPath(cwd); -+ -+ AddFNameToCtrlList(cwd, name); -+ -+ if (select) { -+ nList.selected = numnames-1; -+ curname = numnames - 1; -+ } -+ -+ ChangedCtrlList(); -+} -+ -+ -+/***********************************/ -+void AddFNameToCtrlList(fpath,fname) -+ char *fpath, *fname; -+{ -+ /* stick given path/name into 'namelist'. Doesn't redraw list */ -+ -+ char *fullname, *dname; -+ char cwd[MAXPATHLEN], globnm[MAXPATHLEN+100]; -+ int i; -+ -+ if (!fpath) fpath = ""; /* bulletproofing... */ -+ 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 */ -+ fullname = (char *) malloc(strlen(fname) + 1); -+ 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(); -+ fixDispNames(); -+} -+ -+ -+/***********************************/ -+void ChangedCtrlList() -+{ -+ /* called when the namelist/dispnames arrays have changed, and list needs -+ to be re-displayed */ -+ -+ int cname, lsel; -+ -+ if (numnames>0) BTSetActive(&but[BDELETE],1); -+ windowMB.dim[WMB_TEXTVIEW] = (numnames==0); -+ -+ cname = curname; lsel = nList.selected; /* get blown away in LSNewData */ -+ LSChangeData(&nList, dispnames, numnames); -+ curname = cname; nList.selected = lsel; /* restore prev values */ -+ -+ ActivePrevNext(); -+ -+ ScrollToCurrent(&nList); -+ DrawCtrlNumFiles(); -+} -+ -+ -+/***********************************/ -+void ActivePrevNext() -+{ -+ /* 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 -+ selected file (or the 0th file, if no selection either), and 'Prev' means -+ view the one right before the selected file */ -+ -+ if (curname<0) { /* light things based on nList.selected, instead */ -+ BTSetActive(&but[BNEXT], (numnames>0)); -+ BTSetActive(&but[BPREV], (nList.selected>0)); -+ } -+ else { -+ BTSetActive(&but[BNEXT], (curname<numnames-1)); -+ 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 -+ different, and should be auto-loaded, or something */ -+ -+ static char *bnames[] = { "\004Disk File", "\nList Entry", "\033Cancel" }; -+ char str[512]; -+ int del, i, delnum, rv; -+ -+ /* failsafe */ -+ delnum = nList.selected; -+ if (delnum < 0 || delnum >= numnames) return 0; -+ -+ 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' */ -+ name = (char *) malloc(strlen(namelist[delnum]) + strlen(initdir) + 2); -+ if (!name) FatalError("malloc in DeleteCmd failed\n"); -+ sprintf(name,"%s/%s", initdir, namelist[delnum]); -+ } -+ else name = namelist[delnum]; -+ -+ i = unlink(name); -+ if (i) { -+ sprintf(str,"Can't delete file '%s'\n\n %s.", name, ERRSTR(errno)); -+ ErrPopUp(str, "\nPity"); -+ if (name != namelist[delnum]) free(name); -+ return 0; -+ } -+ -+ XVDeletedFile(name); -+ if (name != namelist[delnum]) free(name); -+ } -+ -+ deleteFromList(delnum); -+ -+ rv = 0; -+ if (delnum == curname) { /* deleted the viewed file */ -+ curname = nList.selected; -+ rv = 1; /* auto-load currently 'selected' filename */ -+ } -+ else if (delnum < curname) curname = (curname > 0) ? curname-1 : 0; -+ -+ return rv; -+} -+ -+ -+/********************************************/ -+static void deleteFromList(delnum) -+ int delnum; -+{ -+ int i; -+ -+ /* remove from list on either 'List Entry' or (successful) 'Disk File' */ -+ -+ /* determine if namelist[delnum] needs to be freed or not */ -+ for (i=0; i<mainargc && mainargv[i] != namelist[delnum]; i++) ; -+ if (i == mainargc) { /* not found. free it */ -+ free(namelist[delnum]); -+ } -+ -+ if (delnum != numnames-1) { -+ /* snip out of namelist and dispnames lists */ -+ xvbcopy((char *) &namelist[delnum+1], (char *) &namelist[delnum], -+ (numnames - delnum - 1) * sizeof(namelist[0])); -+ -+ 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); -+ -+ nList.nstr = numnames; -+ nList.selected = delnum; -+ -+ if (nList.selected >= numnames) nList.selected = numnames-1; -+ if (nList.selected < 0) nList.selected = 0; -+ -+ SCSetRange(&nList.scrl, 0, numnames - nList.nlines, -+ nList.scrl.val, nList.nlines-1); -+ ScrollToCurrent(&nList); -+ DrawCtrlNumFiles(); -+ -+ ActivePrevNext(); -+} -+ -+ -+/***********************************/ -+void HandleDispMode() -+{ -+ /* handles a change in the display mode (windowed/root). -+ Also, called to do the 'right' thing when opening a picture -+ displays epic, in current size, UNLESS we've selected an 'integer' -+ root tiling thingy, in which case we resize epic appropriately */ -+ -+ static int haveoldinfo = 0; -+ static Window oldMainW; -+ static int oldCmapMode; -+ static XSizeHints oldHints; -+ static XWindowAttributes oldXwa; -+ int i; -+ -+ -+ WaitCursor(); -+ -+ /****************************************************************/ -+ /*** RMB_WINDOW windowed mode */ -+ /****************************************************************/ -+ -+ -+ if (dispMode == RMB_WINDOW) { /* windowed */ -+ char fnam[256]; -+ -+ BTSetActive(&but[BANNOT], 1); -+ -+ if (fullfname[0] == '\0') fnam[0] = '\0'; -+ else { -+ char *tmp; -+ int i, state; -+ -+ /* find beginning of next-to-last pathname component, ie, -+ if fullfname is "/foo/bar/snausage", we'd like "bar/snausage" */ -+ -+ state = 0; -+ for (i=strlen(fullfname); i>0 && state!=2; i--) { -+ if (fullfname[i] == '/') state++; -+ } -+ -+ if (state==2) tmp = fullfname + i + 2; -+ else tmp = fullfname; -+ -+ strcpy(fnam, tmp); -+ -+ /* if we're viewing a multi-page doc, add page # to title */ -+ if (strlen(pageBaseName) && numPages>1) { -+ char foo[64]; -+ sprintf(foo, " Page %d of %d", curPage+1, numPages); -+ strcat(fnam, foo); -+ } -+ -+ } -+ -+ if (useroot && resetroot) ClearRoot(); -+ -+ if (mainW == (Window) NULL || useroot) { /* window not visible */ -+ useroot = 0; -+ -+ if (haveoldinfo) { /* just remap mainW and resize it */ -+ XWMHints xwmh; -+ -+ mainW = oldMainW; -+ -+ /* enable 'perfect' and 'owncmap' options */ -+ dispMB.dim[DMB_COLPERF] = (picType == PIC8) ? 0 : 1; -+ dispMB.dim[DMB_COLOWNC] = (picType == PIC8) ? 0 : 1; -+ -+ XSetStandardProperties(theDisp,mainW,"","",None,NULL,0,&oldHints); -+ setWinIconNames(fnam); -+ -+ xwmh.initial_state = NormalState; -+ xwmh.input = True; -+ xwmh.flags = InputHint; -+ -+ xwmh.icon_pixmap = iconPix; -+ xwmh.icon_mask = iconmask; -+ xwmh.flags |= ( IconPixmapHint | IconMaskHint) ; -+ -+ xwmh.flags |= StateHint; -+ XSetWMHints(theDisp, mainW, &xwmh); -+ -+ oldXwa.width = eWIDE; oldXwa.height = eHIGH; -+ SetWindowPos(&oldXwa); -+ XResizeWindow(theDisp, mainW, (u_int) eWIDE, (u_int) eHIGH); -+ XMapWindow(theDisp, mainW); -+ } -+ -+ else { /* first time. need to create mainW */ -+ mainW = (Window) NULL; -+ createMainWindow(maingeom, fnam); -+ XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask -+ | StructureNotifyMask | ButtonPressMask -+ | KeyReleaseMask | ColormapChangeMask -+ | EnterWindowMask | LeaveWindowMask ); -+ -+ StoreDeleteWindowProp(mainW); -+ XFlush(theDisp); -+ XMapWindow(theDisp,mainW); -+ XFlush(theDisp); -+ if (startIconic) sleep(2); /* give it time to get the window up...*/ -+ } -+ } -+ -+ else { /* mainW already visible */ -+ createMainWindow(maingeom, fnam); -+ XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask -+ | StructureNotifyMask | ButtonPressMask -+ | KeyReleaseMask | ColormapChangeMask -+ | EnterWindowMask | LeaveWindowMask ); -+ -+ if (LocalCmap) { /* AllocColors created local colormap */ -+ XSetWindowColormap(theDisp, mainW, LocalCmap); -+ } -+ } -+ -+ -+ -+ useroot = 0; -+ } -+ -+ -+ /****************************************************************/ -+ /*** ROOT mode */ -+ /****************************************************************/ -+ -+ -+ else if (dispMode > RMB_WINDOW && dispMode < RMB_MAX) { -+ int ew, eh, regen; -+ -+ BTSetActive(&but[BANNOT], 0); -+ -+ regen = 0; -+ if (!useroot) { /* have to hide mainW, etc. */ -+ dispMB.dim[DMB_COLPERF] = 1; /* no perfect or owncmap in root mode */ -+ dispMB.dim[DMB_COLOWNC] = 1; -+ -+ /* save current window stuff */ -+ haveoldinfo = 1; -+ oldMainW = mainW; -+ oldCmapMode = colorMapMode; -+ -+ GetWindowPos(&oldXwa); -+ if (!XGetNormalHints(theDisp, mainW, &oldHints)) oldHints.flags = 0; -+ oldHints.x=oldXwa.x; oldHints.y=oldXwa.y; oldHints.flags|=USPosition; -+ -+ if (LocalCmap) regen=1; -+ -+ /* this reallocs the colors */ -+ 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; -+ xwmh.initial_state = IconicState; -+ xwmh.flags = (InputHint | StateHint); -+ XSetWMHints(theDisp, ctrlW, &xwmh); -+ CtrlBox(1); -+ } -+ } -+ -+ useroot = 1; -+ rootMode = dispMode - RMB_ROOT; -+ ew = eWIDE; eh = eHIGH; -+ -+ RANGE(ew,1,maxWIDE); RANGE(eh,1,maxHIGH); -+ -+ if (rootMode == RM_TILE || rootMode == RM_IMIRROR) { -+ i = (dispWIDE + ew-1) / ew; ew = (dispWIDE + i-1) / i; -+ i = (dispHIGH + eh-1) / eh; eh = (dispHIGH + i-1) / i; -+ } -+ -+ if (ew != eWIDE || eh != eHIGH) { /* changed size... */ -+ GenerateEpic(ew, eh); -+ CreateXImage(); -+ } -+ else if (regen) CreateXImage(); -+ -+ KillOldRootInfo(); -+ MakeRootPic(); -+ SetCursors(-1); -+ } -+ -+ else { -+ fprintf(stderr,"unknown dispMB value '%d' in HandleDispMode()\n", -+ dispMode); -+ } -+ -+ SetCursors(-1); -+} -+ -+ -+/*******************************************************/ -+static void add_filelist_to_namelist(flist, nlist, numn, maxn) -+ char *flist; -+ char **nlist; -+ int *numn, maxn; -+{ -+ /* written by Brian Gregory (bgregory@megatest.com) */ -+ -+ FILE *fp; -+ -+ fp = fopen(flist,"r"); -+ if (!fp) { -+ fprintf(stderr,"Can't open filelist '%s': %s\n", flist, ERRSTR(errno)); -+ return; -+ } -+ -+ while (*numn < maxn) { -+ char *s, *nlp, fbuf[MAXPATHLEN]; -+ if (!fgets(fbuf, MAXPATHLEN, fp) || -+ !(s = (char *) malloc(strlen(fbuf)))) break; -+ -+ nlp = (char *) rindex(fbuf, '\n'); -+ if (nlp) *nlp = '\0'; -+ strcpy(s, fbuf); -+ -+ namelist[*numn] = s; (*numn)++; -+ } -+ -+ -+ if (*numn == maxn) { -+ fprintf(stderr, "%s: too many filenames. Only using first %d.\n", -+ flist, maxn); -+ } -+ -+ fclose(fp); -+} -+ -+ -+ -+ -+/************************************************************************/ -+ -+/***********************************/ -+char *lower_str(str) -+ char *str; -+{ -+ char *p; -+ for (p=str; *p; p++) if (isupper(*p)) *p = tolower(*p); -+ return str; -+} -+ -+ -+/***********************************/ -+int rd_int(name) -+ 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", -+ cmd, name); -+ return 0; -+ } -+ } -+ else return 0; -+} -+ -+ -+/***********************************/ -+int rd_str(name) -+ char *name; -+{ -+ return rd_str_cl(name, "", 0); -+} -+ -+ -+/***********************************/ -+int rd_flag(name) -+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) || -+ (strcmp(buf, "1")==0) || -+ (strcmp(buf, "true")==0) || -+ (strcmp(buf, "yes")==0); -+ return 1; -+ } -+ -+ else return 0; -+} -+ -+ -+ -+ -+static int xrm_initted = 0; -+ -+/***********************************/ -+int rd_str_cl (name_str, class_str, reinit) -+ char *name_str; -+ char *class_str; -+ int reinit; -+{ -+ /* note: *all* X resource reading goes through this routine... */ -+ -+ /* returns '1' if successful, result in def_str */ -+ -+ char q_name[BUFSIZ], q_class[BUFSIZ]; -+ char *type; -+ XrmValue result; -+ int gotit; -+ static XrmDatabase def_resource; -+ -+ -+ if (reinit) { -+#ifndef vax11c -+ if (xrm_initted && def_resource) XrmDestroyDatabase(def_resource); -+#endif -+ xrm_initted = 0; -+ } -+ -+ if (!xrm_initted) { -+ Atom resAtom; -+ char *xrm_str; -+ -+ XrmInitialize(); -+ xrm_initted = 1; -+ def_resource = (XrmDatabase) 0; -+ -+ gotit = 0; -+ -+ -+ /* don't use XResourceManagerString, as it is a snapshot of the -+ string when theDisp was opened, and doesn't change */ -+ -+ resAtom = XInternAtom(theDisp, "RESOURCE_MANAGER", True); -+ if (resAtom != None) { -+ Atom actType; -+ int i, actFormat; -+ 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 (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 (i==Success && actType==XA_STRING && actFormat==8 && data) { -+ def_resource = XrmGetStringDatabase((char *) data); -+ XFree(data); -+ gotit = 1; -+ } -+ } -+ } -+ -+ -+ -+ if (!gotit) { -+ 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; -+ XrmDatabase res1; -+ -+#ifdef VMS -+ strcpy(foo, "SYS$LOGIN:DECW$XDEFAULTS.DAT"); -+#else -+ homedir = (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"); -+ } -+ } -+ } -+ -+ -+ if (!def_resource) return 0; /* no resource database to search! */ -+ -+ -+ 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); -+} -+ -+ -diff -urN xv-3.10a/xv.h xv-3.10apatched/xv.h ---- xv-3.10a/xv.h Mon Jan 23 12:22:23 1995 -+++ xv-3.10apatched/xv.h Tue Apr 30 00:20:19 2002 -@@ -8,8 +8,8 @@ - #include "config.h" - - --#define REVDATE "Version 3.10a Rev: 12/29/94" --#define VERSTR "3.10a" -+#define REVDATE "Version 3.10a Rev: 12/29/94 (PNG patch 1.2)" -+#define VERSTR "3.10a(PNG)" - - /* - * uncomment the following, and modify for your site, but only if you've -@@ -114,8 +114,8 @@ - - #ifndef VMS - # include <errno.h> -- extern int errno; /* SHOULD be in errno.h, but often isn't */ --# ifndef __NetBSD__ -+# if !defined(__NetBSD__) && !defined(__GNU_LIBRARY__) -+ extern int errno; /* SHOULD be in errno.h, but often isn't */ - extern char *sys_errlist[]; /* this too... */ - # endif - #endif -@@ -327,6 +327,10 @@ - #define HAVE_TIFF - #endif - -+#ifdef DOPNG -+#define HAVE_PNG -+#endif -+ - #ifdef DOPDS - #define HAVE_PDS - #endif -@@ -458,24 +462,31 @@ - #define F_TIFINC 0 - #endif - -+#ifdef HAVE_PNG -+#define F_PNGINC 1 -+#else -+#define F_PNGINC 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 */ -+#define F_PNG ( 0 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_PS ( 1 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_PBMRAW ( 2 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_PBMASCII ( 3 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_XBM ( 4 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_XPM ( 5 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_BMP ( 6 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_SUNRAS ( 7 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_IRIS ( 8 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_TARGA ( 9 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_FITS (10 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_PM (11 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_DELIM1 (12 + F_JPGINC + F_TIFINC + F_PNGINC) /* ----- */ -+#define F_FILELIST (13 + F_JPGINC + F_TIFINC + F_PNGINC) -+#define F_MAXFMTS (14 + F_JPGINC + F_TIFINC + F_PNGINC) /* 17, normally */ - - - -@@ -505,6 +516,7 @@ - #define RFT_XPM 17 - #define RFT_XWD 18 - #define RFT_FITS 19 -+#define RFT_PNG 20 - - /* definitions for page up/down, arrow up/down list control */ - #define LS_PAGEUP 0 -@@ -563,7 +575,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,7 +626,8 @@ - #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 */ -@@ -765,9 +779,10 @@ - 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 */ -+ 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 */ - char *title; /* title for this guage */ - char *units; /* string appended to value */ - u_long fg,bg,hi,lo; /* colors */ -@@ -935,7 +950,7 @@ - WHERE unsigned int ncells, dispWIDE, dispHIGH, dispDEEP; - WHERE unsigned int vrWIDE, vrHIGH, maxWIDE, maxHIGH; - 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; -@@ -1154,6 +1169,13 @@ - #endif - - -+#ifdef HAVE_PNG -+/* stuff used for 'png' box */ -+WHERE Window pngW; -+WHERE int pngUp; /* is pngW mapped, or what? */ -+#endif -+ -+ - #undef WHERE - - -@@ -1465,12 +1487,12 @@ - - - /*************************** 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 DCreate PARM((DIAL *, Window, int, int, int, int, double, -+ double, double, double, double, u_long, -+ u_long, u_long, u_long, char *, char *)); - --void DSetRange PARM((DIAL *, int, int, int, int)); --void DSetVal PARM((DIAL *, int)); -+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)); -@@ -1613,6 +1635,13 @@ - int TIFFCheckEvent PARM((XEvent *)); - void TIFFSaveParams PARM((char *, int)); - -+/**************************** XVPNG.C ***************************/ -+int LoadPNG PARM((char *, PICINFO *)); -+void CreatePNGW PARM((void)); -+void PNGDialog PARM((int)); -+int PNGCheckEvent PARM((XEvent *)); -+void PNGSaveParams PARM((char *, int)); -+ - /**************************** XVPDS.C ***************************/ - int LoadPDS PARM((char *, PICINFO *)); - -diff -urN xv-3.10a/xvbmp.c xv-3.10apatched/xvbmp.c ---- xv-3.10a/xvbmp.c Thu Dec 22 14:34:42 1994 -+++ xv-3.10apatched/xvbmp.c Tue Apr 30 00:20:27 2002 -@@ -32,7 +32,7 @@ - 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 loadBMP24 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)); -@@ -127,7 +127,8 @@ - - - /* error checking */ -- if ((biBitCount!=1 && biBitCount!=4 && biBitCount!=8 && biBitCount!=24) || -+ if ((biBitCount!=1 && biBitCount!=4 && biBitCount!=8 && -+ biBitCount!=24 && biBitCount!=32) || - biPlanes!=1 || biCompression>BI_RLE4) { - - sprintf(buf,"Bogus BMP File! (bitCount=%d, Planes=%d, Compression=%d)", -@@ -137,7 +138,8 @@ - goto ERROR; - } - -- if (((biBitCount==1 || biBitCount==24) && biCompression != BI_RGB) || -+ if (((biBitCount==1 || biBitCount==24 || biBitCount==32) -+ && biCompression != BI_RGB) || - (biBitCount==4 && biCompression==BI_RLE8) || - (biBitCount==8 && biCompression==BI_RLE4)) { - -@@ -159,7 +161,7 @@ - } - - /* load up colormap, if any */ -- if (biBitCount!=24) { -+ if (biBitCount!=24 && biBitCount!=32) { - int i, cmaplen; - - cmaplen = (biClrUsed) ? biClrUsed : 1 << biBitCount; -@@ -197,7 +199,7 @@ - - /* create pic8 or pic24 */ - -- if (biBitCount==24) { -+ if (biBitCount==24 || biBitCount==32) { - pic24 = (byte *) calloc((size_t) biWidth * biHeight * 3, (size_t) 1); - if (!pic24) return (bmpError(bname, "couldn't malloc 'pic24'")); - } -@@ -212,16 +214,18 @@ - 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, -+ else if (biBitCount == 8) rv = loadBMP8(fp,pic8,biWidth,biHeight, - biCompression); -- else rv = loadBMP24(fp,pic24,biWidth,biHeight); -+ else rv = loadBMP24(fp,pic24,biWidth,biHeight, -+ biBitCount); -+ - - if (rv) bmpError(bname, "File appears truncated. Winging it.\n"); - - fclose(fp); - - -- if (biBitCount == 24) { -+ if (biBitCount == 24 || biBitCount == 32) { - pinfo->pic = pic24; - pinfo->type = PIC24; - } -@@ -384,10 +388,12 @@ - u_int w,h,comp; - { - int i,j,c,c1,padw,x,y,rv; -- byte *pp; -+ byte *pp, *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) */ - -@@ -407,12 +413,12 @@ - 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 */ -@@ -431,7 +437,7 @@ - } - - 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; - } -@@ -454,10 +460,10 @@ - - - /*******************************************/ --static int loadBMP24(fp, pic24, w, h) -+static int loadBMP24(fp, pic24, w, h, bits) - FILE *fp; - byte *pic24; -- u_int w,h; -+ u_int w,h, bits; - { - int i,j,padb,rv; - byte *pp; -@@ -465,6 +471,7 @@ - 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); -@@ -474,6 +481,7 @@ - pp[2] = getc(fp); /* blue */ - pp[1] = getc(fp); /* green */ - pp[0] = getc(fp); /* red */ -+ if (bits==32) getc(fp); - pp += 3; - } - -diff -urN xv-3.10a/xvbrowse.c xv-3.10apatched/xvbrowse.c ---- xv-3.10a/xvbrowse.c Thu Jan 19 09:49:17 1995 -+++ xv-3.10apatched/xvbrowse.c Tue Apr 30 00:19:13 2002 -@@ -55,6 +55,7 @@ - #include "bits/br_xpm" - #include "bits/br_xwd" - #include "bits/br_fits" -+#include "bits/br_png" - - #include "bits/br_trash" - #include "bits/fcurs" -@@ -94,7 +95,8 @@ - #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_MAX 29 /* # of built-in icons */ - - #define ISLOADABLE(ftyp) (ftyp!=BF_DIR && ftyp!=BF_CHR && ftyp!=BF_BLK && \ - ftyp!=BF_SOCK && ftyp!=BF_FIFO) -@@ -524,6 +526,7 @@ - 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_PNG]=MakePix1(br->win,br_png_bits,br_png_width,br_png_height); - - - /* check that they all got built */ -@@ -956,6 +959,7 @@ - char *str; - { - strncpy(br->dispstr, str, (size_t) 256); -+ br->dispstr[255] = '\0'; - drawBrowStr(br); - XFlush(theDisp); - } -@@ -1490,6 +1494,7 @@ - if (StringWidth(str) > ISPACE_WIDE-6) { - int dotpos; - strncpy(tmpstr, str, (size_t) 56); -+ tmpstr[56] = '\0'; /* MR: otherwise it dies on long file names */ - dotpos = strlen(tmpstr); - strcat(tmpstr,"..."); - -@@ -1505,7 +1510,7 @@ - nstr = tmpstr; - } - else nstr = str; -- -+ - - /* draw the title */ - sw = StringWidth(nstr); -@@ -3020,6 +3025,7 @@ - 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; - } - } - } -@@ -3567,6 +3573,7 @@ - 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; - default: strcat(str,"file of unknown type"); break; - } - -diff -urN xv-3.10a/xvbrowse.c~ xv-3.10apatched/xvbrowse.c~ ---- xv-3.10a/xvbrowse.c~ Wed Dec 31 16:00:00 1969 -+++ xv-3.10apatched/xvbrowse.c~ Tue Apr 30 00:10:16 2002 -@@ -0,0 +1,5427 @@ -+/* -+ * xvbrowse.c - visual schnauzer routines -+ * -+ * includes: -+ * void CreateBrowse(char *, char *, char *, char *, char *); -+ * void OpenBrowse(); -+ * void HideBrowseWindows(); -+ * void UnHideBrowseWindows(); -+ * void SetBrowseCursor(Cursor); -+ * void KillBrowseWindows(); -+ * int BrowseCheckEvent(evt, int *retval, int *done); -+ * int BrowseDelWin(Window); -+ * void SetBrowStr(char *); -+ * void RegenBrowseIcons(); -+ * -+ */ -+ -+#include "copyright.h" -+ -+#define NEEDSDIR -+#include "xv.h" -+ -+#if defined(VMS) || defined(isc) -+typedef unsigned int mode_t; /* file mode bits */ -+#endif -+ -+ -+/* load up built-in icons */ -+#include "bits/br_file" -+#include "bits/br_dir" -+#include "bits/br_exe" -+#include "bits/br_chr" -+#include "bits/br_blk" -+#include "bits/br_sock" -+#include "bits/br_fifo" -+#include "bits/br_error" -+#include "bits/br_unknown" -+#include "bits/br_cmpres" -+ -+#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_iris" -+#include "bits/br_pcx" -+#include "bits/br_jfif" -+#include "bits/br_tiff" -+#include "bits/br_pds" -+#include "bits/br_ps" -+#include "bits/br_iff" -+#include "bits/br_targa" -+#include "bits/br_xpm" -+#include "bits/br_xwd" -+#include "bits/br_fits" -+#include "bits/br_png" -+ -+#include "bits/br_trash" -+#include "bits/fcurs" -+#include "bits/fccurs" -+#include "bits/fdcurs" -+#include "bits/fcursm" -+ -+ -+ -+/* FileTypes */ -+#define BF_HAVEIMG -1 /* should use 'pimage' and 'ximage' fields */ -+#define BF_FILE 0 -+#define BF_DIR 1 -+#define BF_EXE 2 -+#define BF_CHR 3 -+#define BF_BLK 4 -+#define BF_SOCK 5 -+#define BF_FIFO 6 -+#define BF_ERROR 7 -+#define BF_UNKNOWN 8 -+#define BF_GIF 9 -+#define BF_PM 10 -+#define BF_PBM 11 -+#define BF_XBM 12 -+#define BF_SUNRAS 13 -+#define BF_BMP 14 -+#define BF_UTAHRLE 15 -+#define BF_IRIS 16 -+#define BF_PCX 17 -+#define BF_JFIF 18 -+#define BF_TIFF 19 -+#define BF_PDS 20 -+#define BF_COMPRESS 21 -+#define BF_PS 22 -+#define BF_IFF 23 -+#define BF_TARGA 24 -+#define BF_XPM 25 -+#define BF_XWD 26 -+#define BF_FITS 27 -+#define BF_PNG 28 -+#define BF_MAX 29 /* # 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 -+ -+#define SCROLLVERT 8 /* height of scroll region at top/bottom of iconw */ -+#define PAGEVERT 40 /* during rect drag, if further than this, page */ -+ -+#define ICON_ONLY 2 /* if 'lit' field ==, invert icon only, not title */ -+#define TEMP_LIT 3 /* temporarily selected, normally off */ -+#define TEMP_LIT1 4 /* temporarily selected, normally on */ -+ -+#define TOPMARGIN 30 /* from top of window to top of iconwindow */ -+#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 -+ -+#define ISPACE_WIDE (ISIZE_WIDE+16) /* 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 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" -+ }; -+ -+ -+#define MAXDEEP 30 /* maximum directory depth */ -+ -+#define BOGUSPATH "NO SUCH PATH" -+ -+ -+typedef struct { char *name; /* name of file */ -+ char *imginfo; /* info on the real image */ -+ int ftype; /* BF_EXE, BF_DIR, BF_FILE, etc... */ -+ byte *pimage; /* normal, 8-bit-per image */ -+ XImage *ximage; /* X version of pimage */ -+ int w,h; /* size of icon */ -+ int lit; /* true if 'selected' */ -+ } BFIL; -+ -+/* data needed per schnauzer window */ -+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; -+ unsigned long lastClickTime; -+ -+ int ndirs; -+ char *mblist[MAXDEEP]; -+ char path[MAXPATHLEN+2]; /* '/' terminated */ -+ } BROWINFO; -+ -+ -+static Cursor movecurs, copycurs, delcurs; -+static BROWINFO binfo[MAXBRWIN]; -+static Pixmap bfIcons[BF_MAX], trashPix; -+static int hasBeenSized = 0; -+static int haveWindows = 0; -+ -+static unsigned long browfg, browbg, browhi, browlo; -+ -+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 doCmd PARM((BROWINFO *, int)); -+static void drawBrow PARM((BROWINFO *)); -+static void drawNumfiles PARM((BROWINFO *)); -+static void eraseNumfiles PARM((BROWINFO *, int)); -+static void drawTrash PARM((BROWINFO *)); -+static int inTrash PARM((BROWINFO *, int, int)); -+static void drawBrowStr PARM((BROWINFO *)); -+static void changedNumLit PARM((BROWINFO *, int, int)); -+static void setSelInfoStr PARM((BROWINFO *, int)); -+static void exposeIconWin PARM((BROWINFO *, int, int, int, int)); -+static void drawIconWin PARM((int, SCRL *)); -+static void eraseIcon PARM((BROWINFO *, int)); -+static void eraseIconTitle PARM((BROWINFO *, int)); -+static void drawIcon PARM((BROWINFO *, int)); -+static void makeIconVisible PARM((BROWINFO *, int)); -+static void clickBrow PARM((BROWINFO *, int, int)); -+static int clickIconWin PARM((BROWINFO *, int, int, unsigned long, int)); -+static void doubleClick PARM((BROWINFO *, int)); -+static int mouseInWhichIcon PARM((BROWINFO *, int, int)); -+static void invertSelRect PARM((BROWINFO *, int, int, int, int)); -+static void keyIconWin PARM((BROWINFO *, XKeyEvent *)); -+static void browKey PARM((BROWINFO *, int)); -+static void browAlpha PARM((BROWINFO *, int)); -+static void changedBrDirMB PARM((BROWINFO *, int)); -+static int cdBrow PARM((BROWINFO *)); -+static void scanDir PARM((BROWINFO *)); -+static void copyDirInfo PARM((BROWINFO *, BROWINFO *)); -+static void endScan PARM((BROWINFO *, int)); -+static void scanFile PARM((BROWINFO *, BFIL *, char *)); -+static void sortBFList PARM((BROWINFO *)); -+static int bfnamCmp PARM((const void *, const void *)); -+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 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, -+ int, char *)); -+ -+static void makeThumbDir PARM((BROWINFO *)); -+static void updateIcons PARM((BROWINFO *)); -+ -+static void drawTemp PARM((BROWINFO *, int, int)); -+static void clearTemp PARM((BROWINFO *)); -+ -+static void doTextCmd PARM((BROWINFO *)); -+static void doRenameCmd PARM((BROWINFO *)); -+static void doMkdirCmd PARM((BROWINFO *)); -+ -+static void doChdirCmd PARM((BROWINFO *)); -+static void doDeleteCmd PARM((BROWINFO *)); -+static void doSelFilesCmd PARM((BROWINFO *)); -+ -+static void doRecurseCmd PARM((BROWINFO *)); -+static void recurseUpdate PARM((BROWINFO *, 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 int moveFile PARM((char *, char *)); -+static int copyFile PARM((char *, char *)); -+static void cp PARM((void)); -+static void cp_dir PARM((void)); -+static void cp_file PARM((struct stat *, int)); -+static void cp_special PARM((struct stat *, int)); -+static void cp_fifo PARM((struct stat *, int)); -+ -+static int stat2bf PARM((u_int)); -+ -+static int selmatch PARM((char *, char *)); -+static int selmatch1 PARM((char *, char *)); -+ -+ -+ -+/***************************************************************/ -+void CreateBrowse(geom, fgstr, bgstr, histr, lostr) -+ char *geom, *fgstr, *bgstr, *histr, *lostr; -+{ -+ int i; -+ XSizeHints hints; -+ XSetWindowAttributes xswa; -+ BROWINFO *br; -+ XColor ecdef, cursfg, cursbg; -+ Pixmap mcpix, ccpix, dcpix, fcmpix; -+ int gx, gy, gw, gh, gset, gx1, gy1; -+ unsigned int uw, uh; -+ char wgeom[64]; -+ -+ if (!geom) geom = ""; -+ -+ /* map color spec strings into browCmap, if we're in browPerfect mode */ -+ if (browPerfect && browCmap) { -+ browfg = 0; browbg = 255; /* black text on white bg, by default */ -+ if (fgstr && XParseColor(theDisp, browCmap, fgstr, &ecdef)) { -+ browfg = browcols[((ecdef.red >> 8) & 0xe0) | -+ ((ecdef.green >> 11) & 0x1c) | -+ ((ecdef.blue >> 14) & 0x03)]; -+ } -+ -+ if (bgstr && XParseColor(theDisp, browCmap, bgstr, &ecdef)) { -+ browbg = browcols[((ecdef.red >> 8) & 0xe0) | -+ ((ecdef.green >> 11) & 0x1c) | -+ ((ecdef.blue >> 14) & 0x03)]; -+ } -+ -+ browhi = browbg; browlo = browfg; -+ if (histr && XParseColor(theDisp, browCmap, histr, &ecdef)) { -+ browhi = browcols[((ecdef.red >> 8) & 0xe0) | -+ ((ecdef.green >> 11) & 0x1c) | -+ ((ecdef.blue >> 14) & 0x03)]; -+ } -+ -+ if (lostr && XParseColor(theDisp, browCmap, lostr, &ecdef)) { -+ browlo = browcols[((ecdef.red >> 8) & 0xe0) | -+ ((ecdef.green >> 11) & 0x1c) | -+ ((ecdef.blue >> 14) & 0x03)]; -+ } -+ } -+ else { -+ browfg = infofg; browbg = infobg; browhi = hicol; browlo = locol; -+ } -+ -+ -+ -+ gset = XParseGeometry(geom, &gx, &gy, &uw, &uh); -+ gw = (int) uw; gh = (int) uh; -+ -+ /* creates *all* schnauzer windows at once */ -+ -+ for (i=0; i<MAXBRWIN; i++) binfo[i].win = (Window) NULL; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ char wname[64]; -+ -+ /* create a slightly offset geometry, so the windows stack nicely */ -+ if ((gset & XValue) && (gset & YValue)) { -+ if (gset & XNegative) gx1 = gx - i * 20; -+ else gx1 = gx + i * 20; -+ -+ 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, -+ (gset & XNegative) ? "-" : "+", abs(gx1), -+ (gset & YNegative) ? "-" : "+", abs(gy1)); -+ else -+ sprintf(wgeom, "%s%d%s%d", -+ (gset & XNegative) ? "-" : "+", abs(gx1), -+ (gset & YNegative) ? "-" : "+", abs(gy1)); -+ } -+ else strcpy(wgeom, geom); -+ -+ br = &binfo[i]; -+ -+ if (i) sprintf(wname, "xv visual schnauzer (%d)", i); -+ else sprintf(wname, "xv visual schnauzer"); -+ -+ br->win = CreateWindow(wname, "XVschnauze", wgeom, -+ DEF_BROWWIDE, DEF_BROWHIGH, browfg, browbg, 1); -+ if (!br->win) FatalError("can't create schnauzer window!"); -+ -+ haveWindows = 1; -+ br->vis = br->wasvis = 0; -+ -+ if (browPerfect && browCmap) { -+ xswa.colormap = browCmap; -+ XChangeWindowAttributes(theDisp, br->win, CWColormap, &xswa); -+ } -+ -+ if (ctrlColor) XSetWindowBackground(theDisp, br->win, browlo); -+ else XSetWindowBackgroundPixmap(theDisp, br->win, grayTile); -+ -+ /* note: everything is sized and positioned in ResizeBrowse() */ -+ -+ 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, -+ browfg, browbg, browhi, browlo, drawIconWin); -+ -+ -+ if (XGetNormalHints(theDisp, br->win, &hints)) { -+ hints.min_width = 325 + 96; -+ hints.min_height = 180; -+ hints.flags |= PMinSize; -+ XSetNormalHints(theDisp, br->win, &hints); -+ } -+ -+#ifdef BACKING_STORE -+ xswa.backing_store = WhenMapped; -+ XChangeWindowAttributes(theDisp, br->iconW, CWBackingStore, &xswa); -+#endif -+ -+ XSelectInput(theDisp, br->iconW, ExposureMask | ButtonPressMask); -+ -+ -+ -+ BTCreate(&(br->but[BR_CHDIR]), br->win, 0,0,BUTTW,BUTTH, -+ "Change Dir",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_DELETE]), br->win, 0,0,BUTTW,BUTTH, -+ "Delete",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_MKDIR]), br->win, 0,0,BUTTW,BUTTH, -+ "New Dir",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_RENAME]), br->win, 0,0,BUTTW,BUTTH, -+ "Rename",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_RESCAN]), br->win, 0,0,BUTTW,BUTTH, -+ "ReScan",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_UPDATE]), br->win, 0,0,BUTTW,BUTTH, -+ "Update",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_NEWWIN]), br->win, 0,0,BUTTW,BUTTH, -+ "Open Win",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_GENICON]),br->win, 0,0,BUTTW,BUTTH, -+ "GenIcon",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_SELALL]), br->win, 0,0,BUTTW,BUTTH, -+ "Select All",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_TEXTVIEW]), br->win, 0,0,BUTTW,BUTTH, -+ "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, -+ "Quit xv",browfg,browbg,browhi,browlo); -+ BTCreate(&(br->but[BR_CLOSE]), br->win, 0,0,BUTTW,BUTTH, -+ "Close",browfg,browbg,browhi,browlo); -+ -+ XMapSubwindows(theDisp, br->win); -+ -+ MBCreate(&(br->dirMB), br->win, 0,0,100,19, NULL,NULL,0, -+ browfg,browbg,browhi,browlo); -+ -+ MBCreate(&(br->cmdMB), br->win, 0,0,160,19, "Misc. Commands", -+ cmdMList, BR_NCMDS, browfg,browbg,browhi,browlo); -+ -+ br->showhidden = 0; -+ br->cmdMB.list[BR_HIDDEN] = showHstr; -+ -+ br->numbutshown = 0; -+ br->numlit = 0; -+ br->bfList = NULL; -+ br->bfLen = 0; -+ br->dispstr[0] = '\0'; -+ br->ndirs = 0; -+ sprintf(br->path, BOGUSPATH); -+ -+ br->lastIconClicked = -1; -+ br->lastClickTime = 0; -+ } -+ -+ -+ /* create built-in icon pixmaps */ -+ bfIcons[BF_FILE]=MakePix1(br->win,br_file_bits,br_file_width,br_file_height); -+ bfIcons[BF_DIR] =MakePix1(br->win,br_dir_bits, br_dir_width, br_dir_height); -+ bfIcons[BF_EXE] =MakePix1(br->win,br_exe_bits, br_exe_width, br_exe_height); -+ bfIcons[BF_CHR] =MakePix1(br->win,br_chr_bits, br_chr_width, br_chr_height); -+ bfIcons[BF_BLK] =MakePix1(br->win,br_blk_bits, br_blk_width, br_blk_height); -+ 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, -+ 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_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_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_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_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_PNG]=MakePix1(br->win,br_png_bits,br_png_width,br_png_height); -+ -+ -+ /* check that they all got built */ -+ for (i=0; i<BF_MAX && bfIcons[i]; i++); -+ 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 | -+ KeyPressMask | StructureNotifyMask); -+ } -+ -+ -+ trashPix = MakePix1(br->win, br_trash_bits, br_trash_width, br_trash_height); -+ if (!trashPix) -+ FatalError("unable to create all built-in icons for schnauzer"); -+ -+ -+ /* create movecurs and copycurs cursors */ -+ mcpix = MakePix1(rootW, filecurs_bits, filecurs_width, filecurs_height); -+ ccpix = MakePix1(rootW, fileccurs_bits, fileccurs_width, fileccurs_height); -+ dcpix = MakePix1(rootW, fdcurs_bits, fdcurs_width, fdcurs_height); -+ fcmpix= MakePix1(rootW, filecursm_bits, filecursm_width, filecursm_height); -+ -+ if (mcpix && ccpix && fcmpix && dcpix) { -+ cursfg.red = cursfg.green = cursfg.blue = 0; -+ cursbg.red = cursbg.green = cursbg.blue = 0xffff; -+ -+ 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) -+ FatalError("unable to create schnauzer cursors..."); -+ } -+ else FatalError("unable to create schnauzer cursors..."); -+ -+ XFreePixmap(theDisp, mcpix); -+ XFreePixmap(theDisp, ccpix); -+ XFreePixmap(theDisp, dcpix); -+ XFreePixmap(theDisp, fcmpix); -+ -+ -+ hasBeenSized = 1; /* we can now start looking at browse events */ -+} -+ -+ -+/***************************************************************/ -+void OpenBrowse() -+{ -+ /* opens up a single browser window */ -+ int i; -+ BROWINFO *br; -+ char path[MAXPATHLEN+1]; -+ -+ /* find next browser to be opened */ -+ for (i=0; i<MAXBRWIN; i++) { -+ br = &binfo[i]; -+ 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, -+ copy the info, rather than reading the directory */ -+ xv_getwd(path, sizeof(path)); -+ if (path[strlen(path)-1] != '/') strcat(path,"/"); /* add trailing '/' */ -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (strcmp(binfo[i].path,path)==0) break; -+ } -+ -+ if (i<MAXBRWIN && &binfo[i] != br) copyDirInfo(&binfo[i], br); -+ else scanDir(br); -+ -+ SCSetVal(&(br->scrl), 0); -+ -+ -+ /* see if that was the last one */ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (!binfo[i].vis) break; -+ } -+ if (i==MAXBRWIN) { /* can't open any more */ -+ windowMB.dim[WMB_BROWSE] = 1; -+ for (i=0; i<MAXBRWIN; i++) { -+ BTSetActive(&(binfo[i].but[BR_NEWWIN]), 0); -+ binfo[i].cmdMB.dim[BR_NEWWIN] = 1; -+ } -+ } -+ -+ -+ changedNumLit(br, -1, 0); -+} -+ -+ -+/***************************************************************/ -+static void closeBrowse(br) -+ BROWINFO *br; -+{ -+ int i; -+ -+ WaitCursor(); -+ -+ /* closes a specified browse window */ -+ XUnmapWindow(theDisp, br->win); -+ br->vis = 0; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (binfo[i].vis) break; -+ } -+ if (i==MAXBRWIN) anyBrowUp = 0; -+ -+ /* 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++) { -+ BTSetActive(&(binfo[i].but[BR_NEWWIN]), 1); -+ binfo[i].cmdMB.dim[BR_NEWWIN] = 0; -+ } -+ -+ SetCursors(-1); -+} -+ -+ -+/***************************************************************/ -+void HideBrowseWindows() -+{ -+ int i; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (binfo[i].vis) { -+ XUnmapWindow(theDisp, binfo[i].win); -+ binfo[i].wasvis = 1; -+ binfo[i].vis = 0; -+ } -+ } -+} -+ -+ -+/***************************************************************/ -+void UnHideBrowseWindows() -+{ -+ int i; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (binfo[i].wasvis) { -+ XMapRaised(theDisp, binfo[i].win); -+ binfo[i].wasvis = 0; -+ binfo[i].vis = 1; -+ } -+ } -+} -+ -+ -+/***************************************************************/ -+void SetBrowseCursor(c) -+ Cursor c; -+{ -+ int i; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (haveWindows && binfo[i].win) XDefineCursor(theDisp, binfo[i].win, c); -+ } -+} -+ -+ -+/***************************************************************/ -+void KillBrowseWindows() -+{ -+ int i; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (haveWindows && binfo[i].win) XDestroyWindow(theDisp, binfo[i].win); -+ } -+} -+ -+ -+static int *event_retP, *event_doneP; -+ -+/***************************************************************/ -+int BrowseCheckEvent(xev, retP, doneP) -+ XEvent *xev; -+ int *retP, *doneP; -+{ -+ int i; -+ -+ event_retP = retP; /* so don't have to pass these all over the place */ -+ event_doneP = doneP; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (brChkEvent(&binfo[i], xev)) break; -+ } -+ -+ if (i<MAXBRWIN) return 1; -+ return 0; -+} -+ -+ -+/***************************************************************/ -+static int brChkEvent(br, xev) -+ BROWINFO *br; -+ XEvent *xev; -+{ -+ /* 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; -+ -+ if (!hasBeenSized) return 0; /* ignore evrythng until we get 1st Resize */ -+ -+ 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)) {} -+ -+ 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 */ -+ int count; -+ Region reg; -+ XRectangle rect; -+ XEvent evt; -+ -+ XSync(theDisp, False); -+ -+ xvbcopy((char *) e, (char *) &evt, sizeof(XEvent)); -+ reg = XCreateRegion(); -+ count = 0; -+ do { -+ rect.x = evt.xexpose.x; -+ rect.y = evt.xexpose.y; -+ rect.width = evt.xexpose.width; -+ rect.height = evt.xexpose.height; -+ -+ XUnionRectWithRegion(&rect, reg, reg); -+ count++; -+ } while (XCheckWindowEvent(theDisp, evt.xexpose.window, -+ ExposureMask, &evt)); -+ -+ XClipBox(reg, &rect); /* bounding box of region */ -+ XSetRegion(theDisp, theGC, reg); -+ -+ if (DEBUG) { -+ fprintf(stderr,"win = %lx, br->win = %lx, iconW = %lx\n", -+ e->window, br->win, br->iconW); -+ 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) -+ exposeIconWin(br, rect.x, rect.y, rect.width, rect.height); -+ -+ XSetClipMask(theDisp, theGC, None); -+ XDestroyRegion(reg); -+ } -+ -+ else rv = 0; -+ } -+ -+ -+ else if (xev->type == ButtonPress) { -+ XButtonEvent *e = (XButtonEvent *) xev; -+ int i,x,y; -+ x = e->x; y = e->y; -+ -+ 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, -+ (e->state&ControlMask) || (e->state&ShiftMask)); -+ -+ } -+ else rv = 0; -+ } -+ else rv = 0; -+ } -+ -+ -+ else if (xev->type == KeyPress) { -+ XKeyEvent *e = (XKeyEvent *) xev; -+ if (e->window == br->win) keyIconWin(br, e); -+ else rv = 0; -+ } -+ -+ -+ else if (xev->type == ConfigureNotify) { -+ XConfigureEvent *e = (XConfigureEvent *) xev; -+ -+ if (e->window == br->win) { -+ if (DEBUG) fprintf(stderr,"browW got a configure event (%dx%d)\n", -+ e->width, e->height); -+ -+ 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, -+ (u_int) e->width, (u_int) e->height, True); -+ resizeBrowse(br, e->width, e->height); -+ } -+ } -+ else rv = 0; -+ } -+ -+ else rv = 0; -+ -+ return rv; -+} -+ -+ -+/***************************************************************/ -+int BrowseDelWin(win) -+ Window win; -+{ -+ /* got a delete window request. see if the window is a browser window, -+ and close accordingly. Return 1 if event was eaten */ -+ -+ int i; -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (binfo[i].win == win) { -+ closeBrowse(&binfo[i]); -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+ -+/***************************************************************/ -+static void resizeBrowse(br,w,h) -+ BROWINFO *br; -+ int w,h; -+{ -+ XSizeHints hints; -+ int i, minv, maxv, curv, page, maxh; -+ -+ if (br->wide == w && br->high == h) return; /* no change in size */ -+ -+ if (XGetNormalHints(theDisp, br->win, &hints)) { -+ hints.width = w; -+ hints.height = h; -+ hints.flags |= USSize; -+ XSetNormalHints(theDisp, br->win, &hints); -+ } -+ -+ br->wide = w; br->high = h; -+ br->iwWide = br->wide - (2*LRMARGINS) - (br->scrl.tsize+1) - 2; -+ maxh = br->high - (TOPMARGIN + BOTMARGIN); -+ -+ br->iwHigh = (maxh / ISPACE_HIGH) * ISPACE_HIGH; -+ if (br->iwHigh < ISPACE_HIGH) br->iwHigh = ISPACE_HIGH; -+ -+ XMoveResizeWindow(theDisp, br->iconW, LRMARGINS, TOPMARGIN, -+ (u_int) br->iwWide, (u_int) br->iwHigh); -+ -+ -+ /* move the buttons around */ -+ br->numbutshown = (br->wide / (BUTTW + 5)); -+ RANGE(br->numbutshown, 1, BR_NBUTTS); -+ br->numbutshown--; -+ -+ for (i=0; i<BR_NBUTTS; i++) { -+ /* 'close' always goes on right-most edge */ -+ -+ 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 -+ br->but[i].x = br->wide + 10; /* offscreen */ -+ -+ br->but[i].y = br->high - BUTTH - 5; -+ } -+ -+ br->dirMB.x = br->wide/2 - br->dirMB.w/2; -+ br->dirMB.x = br->dirMB.x - br->cmdMB.w/2 + (StringWidth("123 files") + 6)/2; -+ -+ br->dirMB.y = 5; -+ -+ br->cmdMB.x = br->wide - LRMARGINS - br->cmdMB.w - 2; -+ br->cmdMB.y = 5; -+ -+ br->numWide = br->iwWide / ISPACE_WIDE; -+ br->visHigh = br->iwHigh / ISPACE_HIGH; -+ -+ /* compute minv,maxv,curv,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, -+ 1, br->iwHigh, 0, maxv, br->scrl.val, page); -+} -+ -+ -+ -+/***************************************************************/ -+void SetBrowStr(str) -+ char *str; -+{ -+ /* put string in *all* browse windows */ -+ int i; -+ -+ for (i=0; i<MAXBRWIN; i++) -+ setBrowStr(&binfo[i], str); -+} -+ -+ -+/***************************************************************/ -+static void setBrowStr(br, str) -+ BROWINFO *br; -+ char *str; -+{ -+ strncpy(br->dispstr, str, (size_t) 256); -+ drawBrowStr(br); -+ XFlush(theDisp); -+} -+ -+ -+/***************************************************************/ -+void RegenBrowseIcons() -+{ -+ /* called whenever colormaps have changed, and icons need to be rebuilt */ -+ -+ int i, j, iconcount; -+ BFIL *bf; -+ BROWINFO *br; -+ -+ for (j=0; j<MAXBRWIN; j++) { -+ br = &binfo[j]; -+ -+ iconcount = 0; -+ -+ for (i=0; i<br->bfLen; i++) { -+ bf = &(br->bfList[i]); -+ -+ drawTemp(br, i, br->bfLen); -+ -+ if (bf->pimage && bf->ftype == BF_HAVEIMG) { -+ xvDestroyImage(bf->ximage); -+ bf->ximage = Pic8ToXImage(bf->pimage, (u_int) bf->w, (u_int) bf->h, -+ browcols, browR, browG, browB); -+ iconcount++; -+ } -+ -+ if ((i && (i %100)==0) || -+ (iconcount && (iconcount% 20)==0)) { /* mention progress */ -+ -+ char tmp[64]; -+ -+ sprintf(tmp, "Re-coloring icons: processed %d out of %d...", -+ i+1, br->bfLen); -+ setBrowStr(br, tmp); -+ } -+ } -+ -+ clearTemp(br); -+ setBrowStr(br, ""); -+ drawIconWin(0, &(br->scrl)); /* redraw new icons */ -+ } -+} -+ -+ -+/***************************************************************/ -+void BRDeletedFile(name) -+ char *name; -+{ -+ /* 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 = '\0'; /* truncate after last '/' */ -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (strcmp(binfo[i].path, buf)==0) rescanDir(&binfo[i]); -+ } -+} -+ -+ -+/***************************************************************/ -+void BRCreatedFile(name) -+ char *name; -+{ -+ BRDeletedFile(name); -+} -+ -+ -+/**************************************************************/ -+/*** INTERNAL FUNCTIONS ***/ -+/**************************************************************/ -+ -+ -+/***************************************************************/ -+static void doCmd(br, cmd) -+ BROWINFO *br; -+ int cmd; -+{ -+ switch (cmd) { -+ case BR_CHDIR: doChdirCmd(br); -+ break; -+ -+ case BR_DELETE: doDeleteCmd(br); -+ break; -+ -+ case BR_MKDIR: doMkdirCmd(br); -+ break; -+ -+ case BR_RENAME: doRenameCmd(br); -+ break; -+ -+ case BR_RESCAN: rescanDir(br); -+ break; -+ -+ case BR_UPDATE: rescanDir(br); -+ updateIcons(br); -+ break; -+ -+ case BR_NEWWIN: cdBrow(br); /* try to open current dir */ -+ OpenBrowse(); -+ break; -+ -+ case BR_GENICON: genSelectedIcons(br); break; -+ -+ case BR_SELALL: { -+ int i; char buf[128]; -+ -+ for (i=0; i<br->bfLen; i++) -+ br->bfList[i].lit = 1; -+ br->numlit = br->bfLen; -+ -+ /* EXCEPT for parent directory */ -+ if (br->bfLen>0 && strcmp(br->bfList[0].name,"..")==0) { -+ br->numlit--; br->bfList[0].lit = 0; -+ } -+ -+ changedNumLit(br, -1, 0); -+ drawIconWin(0, &(br->scrl)); -+ } -+ 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; -+ rescanDir(br); -+ break; -+ -+ case BR_SELFILES: doSelFilesCmd(br); break; -+ -+ case BR_RECURSUP: doRecurseCmd(br); break; -+ } -+} -+ -+ -+ -+/***************************************************************/ -+static void drawBrow(br) -+ BROWINFO *br; -+{ -+ int i; -+ -+ drawNumfiles(br); -+ drawTrash(br); -+ drawBrowStr(br); -+ -+ for (i=0; i<BR_NBUTTS; i++) { -+ if (i<br->numbutshown || i == BR_CLOSE) BTRedraw(&(br->but[i])); -+ } -+ -+ MBRedraw(&(br->dirMB)); -+ MBRedraw(&(br->cmdMB)); -+} -+ -+ -+/***************************************************************/ -+static void drawNumfiles(br) -+ BROWINFO *br; -+{ -+ char foo[40]; -+ int x, y; -+ -+ x = 30; -+ y = br->dirMB.y; -+ -+ 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, -+ (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, -+ (u_int) br->dirMB.h-2, R3D_IN, 2, browhi, browlo, browbg); -+ -+ XSetForeground(theDisp,theGC,browfg); -+ DrawString(br->win, x+3, (int) CENTERY(mfinfo, y + br->dirMB.h/2), foo); -+} -+ -+ -+/***************************************************************/ -+static void eraseNumfiles(br,nf) -+ BROWINFO *br; -+ int nf; -+{ -+ char foo[40]; -+ -+ 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); -+} -+ -+ -+/***************************************************************/ -+static void drawTrash(br) -+ BROWINFO *br; -+{ -+ int x, y, w, h; -+ -+ x = 5; -+ y = br->dirMB.y; -+ w = 20; -+ h = br->dirMB.h; -+ -+ XSetForeground(theDisp, theGC, browbg); -+ XFillRectangle(theDisp,br->win, theGC, x+1,y+1, (u_int) w-1, (u_int) h-1); -+ -+ 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, -+ 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, -+ x+(w-br_trash_width)/2, y+(h-br_trash_height)/2, -+ 1L); -+} -+ -+ -+/***************************************************************/ -+static int inTrash(br, mx,my) -+ BROWINFO *br; -+ int mx,my; -+{ -+ int x, y, w, h; -+ -+ x = 5; -+ y = br->dirMB.y; -+ w = 20; -+ h = br->dirMB.h; -+ -+ return PTINRECT(mx, my, x,y,w,h); -+} -+ -+ -+/***************************************************************/ -+static void drawBrowStr(br) -+ BROWINFO *br; -+{ -+ int y; -+ -+ y = br->high - (BUTTH+10) - (CHIGH + 6); -+ -+ XSetForeground(theDisp, theGC, browbg); -+ XFillRectangle(theDisp, br->win, theGC, 0, y+3, -+ (u_int) br->wide, (u_int) CHIGH+1); -+ -+ XSetForeground(theDisp, theGC, browfg); -+ XDrawLine(theDisp, br->win, theGC, 0, y, br->wide, y); -+ XDrawLine(theDisp, br->win, theGC, 0, y+CHIGH+4, br->wide, y+CHIGH+4); -+ -+ XSetForeground(theDisp, theGC, (ctrlColor) ? browlo : browbg); -+ XDrawLine(theDisp, br->win, theGC, 0, y+1, br->wide, y+1); -+ XDrawLine(theDisp, br->win, theGC, 0, y+CHIGH+5, br->wide, y+CHIGH+5); -+ -+ XSetForeground(theDisp, theGC, (ctrlColor) ? browhi : browfg); -+ XDrawLine(theDisp, br->win, theGC, 0, y+2, br->wide, y+2); -+ XDrawLine(theDisp, br->win, theGC, 0, y+CHIGH+6, br->wide, y+CHIGH+6); -+ -+ XSetForeground(theDisp, theGC, browfg); -+ DrawString(br->win, 5, y+ASCENT+3, br->dispstr); -+} -+ -+ -+/***************************************************************/ -+static void changedNumLit(br, sel, nostr) -+ BROWINFO *br; -+ int sel, nostr; -+{ -+ int i, allowtext; -+ -+ if (!nostr) setSelInfoStr(br, sel); -+ BTSetActive(&br->but[BR_DELETE], br->numlit>0); -+ br->cmdMB.dim[BR_DELETE] = !(br->numlit>0); -+ -+ BTSetActive(&br->but[BR_RENAME], br->numlit==1); -+ br->cmdMB.dim[BR_RENAME] = !(br->numlit==1); -+ -+ BTSetActive(&br->but[BR_GENICON], br->numlit>0); -+ br->cmdMB.dim[BR_GENICON] = !(br->numlit>0); -+ -+ /* turn on 'text view' cmd if exactly one non-dir is lit */ -+ allowtext = 0; -+ if (br->numlit == 1) { -+ for (i=0; i<br->bfLen && !br->bfList[i].lit; i++); -+ if (i<br->bfLen && br->bfList[i].ftype != BF_DIR) allowtext = 1; -+ } -+ BTSetActive(&br->but[BR_TEXTVIEW], allowtext); -+ br->cmdMB.dim[BR_TEXTVIEW] = !allowtext; -+} -+ -+ -+/***************************************************************/ -+static void setSelInfoStr(br, sel) -+ BROWINFO *br; -+ int sel; -+{ -+ /* sets the '# files selected' string in the brow window appropriately */ -+ -+ /* 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 -+ * if >1 files are lit, and clicked on nothing, disp '# files selected' -+ * otherwise, display info on selected file -+ */ -+ -+ int i; -+ char buf[256], buf1[256]; -+ BFIL *bf; -+ -+ -+ /* default case if no special info */ -+ if (br->numlit>0) sprintf(buf, "%d file%s selected", br->numlit, -+ (br->numlit>1) ? "s" : ""); -+ else buf[0] = '\0'; -+ -+ -+ if (br->numlit > 0) { /* one or more files lit */ -+ if (br->numlit == 1) { /* pretend it was selected */ -+ for (i=0; i<br->bfLen && !br->bfList[i].lit; i++); -+ sel = i; -+ } -+ -+ if (sel >= 0 && sel < br->bfLen) { /* display info on selected file */ -+ bf = &(br->bfList[sel]); -+ -+ if (bf->lit) { -+ if (br->numlit>1) sprintf(buf1," (%d files selected)", br->numlit); -+ else buf1[0] = '\0'; -+ -+ if (bf->ftype==BF_HAVEIMG && bf->imginfo) { -+ sprintf(buf,"%s: %s", bf->name, bf->imginfo); -+ strcat(buf, buf1); -+ } -+ -+ else if (bf->ftype != BF_DIR) { /* no info. display file size */ -+ struct stat st; -+ -+ sprintf(buf, "%s%s", br->path, bf->name); /* build filename */ -+ if (stat(buf, &st) == 0) { -+ sprintf(buf, "%s: %ld bytes", bf->name, st.st_size); -+ strcat(buf, buf1); -+ } -+ } -+ } -+ } -+ } -+ -+ setBrowStr(br, buf); -+} -+ -+ -+/***************************************************************/ -+static void exposeIconWin(br, x,y,w,h) -+ BROWINFO *br; -+ int x,y,w,h; -+{ -+ int i, j, cnt; -+ -+ if (!hasBeenSized || !br->bfList || !br->bfLen) return; -+ -+ /* figure out what icons intersect the clip rect, and only redraw those, -+ as drawing entirely clipped-out images *still* requires transmitting -+ the image */ -+ -+ cnt = (1 + br->visHigh) * br->numWide; /* # of icons to check */ -+ -+ for (i=0, j=br->scrl.val * br->numWide; i<cnt; i++,j++) { -+ int ix,iy,iw,ih; -+ -+ /* figure out if this icon region is in the clip region */ -+ -+ ix = (i%br->numWide) * ISPACE_WIDE; /* x,y = top-left of icon region */ -+ iy = (i/br->numWide) * ISPACE_HIGH; -+ iw = ISPACE_WIDE; -+ ih = ISPACE_HIGH; -+ -+ if ((ix+iw >= x) && (ix < x+w) && (iy+ih >= y) && (iy < y+h)) { -+ if (j>=0 && j < br->bfLen) drawIcon(br,j); -+ } -+ } -+ -+ Draw3dRect(br->iconW, 0, 0, (u_int) br->iwWide-1, (u_int) br->iwHigh-1, -+ R3D_IN, 2, browhi, browlo, browbg); -+} -+ -+ -+/***************************************************************/ -+static void drawIconWin(delta, sptr) -+ int delta; -+ SCRL *sptr; -+{ -+ int i,indx, x,y, ix,iy, num; -+ BFIL *bf; -+ BROWINFO *br; -+ char tmpstr[64], *nstr; -+ -+ /* figure out BROWINFO pointer from SCRL pointer */ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (&(binfo[i].scrl) == sptr) break; -+ } -+ if (i==MAXBRWIN) return; /* didn't find one */ -+ -+ br = &binfo[i]; -+ -+ /* make sure we've been sized. Necessary, as creating/modifying the -+ scrollbar calls this routine directly, rather than through -+ BrowseCheckEvent() */ -+ -+ if (!hasBeenSized) return; -+ -+ XSetForeground(theDisp, theGC, browfg); -+ XSetBackground(theDisp, theGC, browbg); -+ -+ if (br->bfList && br->bfLen) { -+ num = br->visHigh * br->numWide; -+ -+ for (i=0, indx=br->scrl.val * br->numWide; i<num; i++,indx++) { -+ int x,y,w,h; -+ -+ /* erase old icon + string */ -+ x = (i%br->numWide) * ISPACE_WIDE; /* x,y = top-left of icon region */ -+ y = (i/br->numWide) * ISPACE_HIGH; -+ w = ISPACE_WIDE; -+ h = ISPACE_HIGH; -+ -+ XSetForeground(theDisp, theGC, browbg); -+ if (ctrlColor) { /* keep from erasing borders */ -+ if (x<2) x = 2; -+ if (y<2) y = 2; -+ if (x+w > br->iwWide-4) w = (br->iwWide-4)-x + 2; -+ 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, -+ R3D_IN, 2, browhi, browlo, browbg); -+} -+ -+ -+ -+/***************************************/ -+static void drawIcon(br, num) -+ BROWINFO *br; -+ int num; -+{ -+ int i,x,y,ix,iy,sw,sh,sx,sy; -+ BFIL *bf; -+ char tmpstr[64], fixedname[64], *nstr, *str; -+ -+ -+ if (num<0 || num >= br->bfLen) return; -+ bf = &(br->bfList[num]); -+ -+ i = num - (br->scrl.val * br->numWide); -+ if (i<0 || i>(br->visHigh+1)*br->numWide) return; /* not visible */ -+ -+ if (bf->lit) { -+ XSetForeground(theDisp, theGC, browbg); -+ XSetBackground(theDisp, theGC, browfg); -+ } -+ else { -+ XSetForeground(theDisp, theGC, browfg); -+ XSetBackground(theDisp, theGC, browbg); -+ } -+ -+ x = (i%br->numWide) * ISPACE_WIDE; /* x,y = top-left of icon region */ -+ y = (i/br->numWide) * ISPACE_HIGH; -+ -+ /* draw the icon */ -+ ix = x + ISPACE_WIDE/2 - bf->w/2; /* center align */ -+ iy = y + ISPACE_TOP + ISIZE_HIGH - bf->h; /* bottom align */ -+ -+ -+ if (bf->ftype >= 0 && bf->ftype <BF_MAX) { /* built-in icon */ -+ XCopyPlane(theDisp, bfIcons[bf->ftype], br->iconW, theGC, -+ 0, 0, (u_int) bf->w, (u_int) bf->h, ix, iy, 1L); -+ } -+ -+ else if (bf->ftype == BF_HAVEIMG && bf->ximage) { -+ 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, -+ (u_int) bf->w, (u_int) bf->h); -+ } -+ -+ -+ str = bf->name; -+#ifdef VMS -+ if (bf->ftype == BF_DIR) { -+ strcpy(fixedname, bf->name); -+ str = rindex(fixedname, '.'); /* lop off '.DIR' suffix, if any */ -+ if (str) *str = '\0'; -+ str = fixedname; -+ } -+#endif /* VMS */ -+ -+ if (!strcmp(bf->name,"..")) str = "<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); -+ 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; -+ -+ -+ /* draw the title */ -+ sw = StringWidth(nstr); -+ sh = CHIGH; -+ -+ sx = x + ISPACE_WIDE/2 - sw/2 - 2; -+ sy = y + ISPACE_TOP + ISIZE_HIGH + ISPACE_TTOP - 1; -+ -+ XSetForeground(theDisp, theGC, -+ (bf->lit && bf->lit!=ICON_ONLY) ? browfg : browbg); -+ 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, -+ y + ISPACE_TOP + ISIZE_HIGH + ISPACE_TTOP + CHIGH/2, nstr); -+} -+ -+ -+/***************************************/ -+static void eraseIcon(br, num) -+ BROWINFO *br; -+ int num; -+{ -+ /* note: doesn't erase the icon's title, just the icon itself */ -+ -+ 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]); -+ -+ i = num - (br->scrl.val * br->numWide); -+ -+ XSetForeground(theDisp, theGC, browbg); -+ -+ x = (i % br->numWide) * ISPACE_WIDE; /* x,y = top-left of icon region */ -+ y = (i / br->numWide) * ISPACE_HIGH; -+ w = bf->w; -+ h = bf->h; -+ -+ ix = x + ISPACE_WIDE/2 - w/2; /* center align */ -+ iy = y + ISPACE_TOP + ISIZE_HIGH - h; /* bottom align */ -+ -+ if (ctrlColor) { /* keep from erasing borders */ -+ if (ix<2) ix = 2; -+ if (iy<2) iy = 2; -+ if (ix+w > br->iwWide-2) w = (br->iwWide-2) - ix; -+ if (iy+h > br->iwHigh-2) h = (br->iwHigh-2) - iy; -+ } -+ -+ XFillRectangle(theDisp, br->iconW, theGC, ix, iy, (u_int) w+1, (u_int) h+1); -+} -+ -+ -+/***************************************/ -+static void eraseIconTitle(br, num) -+ BROWINFO *br; -+ int num; -+{ -+ /* note: doesn't erase the icon, just the icon's title */ -+ -+ int i,x,y; -+ -+ if (num<0 || num >= br->bfLen) return; -+ i = num - (br->scrl.val * br->numWide); -+ -+ x = (i % br->numWide) * ISPACE_WIDE; /* x,y = top-left of icon region */ -+ y = (i / br->numWide) * ISPACE_HIGH; -+ -+ XSetForeground(theDisp, theGC, browbg); -+ 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, -+ R3D_IN, 2, browhi, browlo, browbg); -+} -+ -+ -+ -+/***************************************/ -+static void makeIconVisible(br, num) -+ BROWINFO *br; -+ int num; -+{ -+ int sval, first, numvis; -+ -+ /* if icon #i isn't visible, adjust scrollbar so it *is* */ -+ -+ sval = br->scrl.val; -+ first = sval * br->numWide; -+ numvis = br->visHigh * br->numWide; -+ -+ while (num<first) { sval--; first = sval * br->numWide; } -+ if (num>= (first+numvis)) { -+ /* get #num into top row, to reduce future scrolling */ -+ while (num>=(first+br->numWide) && sval<br->scrl.max) { -+ sval++; first = sval * br->numWide; -+ } -+ } -+ SCSetVal(&br->scrl, sval); -+} -+ -+ -+ -+/***************************************************************/ -+static void clickBrow(br, x,y) -+ BROWINFO *br; -+ int x,y; -+{ -+ int i; -+ BUTT *bp; -+ -+ for (i=0; i<BR_NBUTTS; i++) { -+ bp = &(br->but[i]); -+ if (PTINRECT(x,y,bp->x,bp->y,bp->w,bp->h)) break; -+ } -+ -+ if (i<BR_NBUTTS) { -+ if (BTTrack(bp)) doCmd(br, i); -+ return; -+ } -+ -+ if (MBClick(&(br->dirMB), x,y)) { -+ i = MBTrack(&(br->dirMB)); -+ if (i >= 0) changedBrDirMB(br, i); -+ return; -+ } -+ -+ if (MBClick(&(br->cmdMB), x,y)) { -+ i = MBTrack(&(br->cmdMB)); -+ if (i >= 0) doCmd(br, i); -+ return; -+ } -+ -+ return; -+} -+ -+ -+/***************************************************************/ -+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, 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; -+ -+ if (sel == -1) { /* clicked on nothing */ -+ if (!multi) { /* deselect all */ -+ for (i=0; i<br->bfLen; i++) { -+ if (br->bfList[i].lit) { br->bfList[i].lit = 0; drawIcon(br,i); } -+ br->numlit = 0; -+ } -+ } -+ -+ changedNumLit(br, sel, 0); -+ br->lastIconClicked = -1; -+ } -+ -+ -+ else if (multi) { /* clicked on something, while 'multi' key down */ -+ bf = &(br->bfList[sel]); -+ -+ bf->lit = !bf->lit; -+ br->lastIconClicked = -1; -+ -+ if (!bf->lit) br->numlit--; -+ else br->numlit++; -+ -+ drawIcon(br, sel); -+ -+ changedNumLit(br, sel, 0); -+ } -+ -+ -+ else { /* clicked on something, and not in 'multi' mode */ -+ /* if there are some lit, and we *didn't* click one of them, turn -+ all others off */ -+ if (br->numlit && !br->bfList[sel].lit) { -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if (bf->lit && i!=sel) { -+ bf->lit = 0; -+ drawIcon(br, i); -+ br->numlit--; -+ } -+ } -+ } -+ -+ -+ bf = &br->bfList[sel]; -+ -+ if (!bf->lit) { -+ bf->lit = 1; -+ drawIcon(br, sel); -+ br->numlit = 1; -+ } -+ -+ -+ changedNumLit(br, sel, 0); -+ -+ -+ /* see if we've double-clicked something */ -+ if (sel==br->lastIconClicked && mtime-br->lastClickTime < DBLCLICKTIME) { -+ int k; -+ br->lastIconClicked = -1; /* YES */ -+ -+ doubleClick(br, sel); -+ return rv; -+ } -+ -+ else { -+ br->lastIconClicked = sel; -+ br->lastClickTime = mtime; -+ } -+ } -+ -+ -+ changedNumLit(br, -1, 0); -+ -+ -+ -+ { /* track mouse until button1 is released */ -+ -+ Window rW, win, cW; -+ int x, y, rootx, rooty, iwx, iwy, bwx, bwy; -+ unsigned int mask; -+ Cursor curs; -+ int samepos, oldx, oldy, oldbrnum, destic, origsval, first; -+ int hasrect, rx, ry, rw, rh; -+ -+ rx = ry = rw = rh = 0; -+ first = 1; hasrect = 0; cpymode = 0; -+ origsval = br->scrl.val; -+ -+ if ( (sel>=0 && !multi) || sel==-1) { -+ /* clicked on an icon, or clicked on nothing... */ -+ -+ while (!XQueryPointer(theDisp, rootW, &rW, &cW, &rootx, &rooty, -+ &x,&y,&mask)); -+ if (mask & Button1Mask) { /* still held down */ -+ -+ if (sel == -1) curs = tcross; -+ else if ((mask & ControlMask) || (mask & ShiftMask)) { -+ curs = copycurs; cpymode = 1; -+ } -+ else curs = movecurs; -+ -+ /* change cursors */ -+ for (i=0; i<MAXBRWIN; i++) -+ XDefineCursor(theDisp,binfo[i].iconW, curs); -+ -+ samepos = oldx = oldy = oldbrnum = 0; -+ -+ while (1) { /* wait for button 1 to be released */ -+ while (!XQueryPointer(theDisp,rootW,&rW,&win,&rootx,&rooty, -+ &x,&y,&mask)); -+ if (!(mask & Button1Mask)) break; -+ -+ 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++) -+ 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, -+ &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++) -+ XDefineCursor(theDisp,binfo[i].iconW, curs); -+ } -+ -+ else if (!dodel && i<MAXBRWIN) { /* moved in */ -+ dodel = 1; -+ for (i=0; i<MAXBRWIN; i++) -+ XDefineCursor(theDisp,binfo[i].iconW, delcurs); -+ } -+ } -+ -+ -+ -+ XTranslateCoordinates(theDisp, rW, br->iconW, rootx,rooty, -+ &iwx,&iwy, &cW); -+ -+ /* find deepest child that the mouse is in */ -+ while (win!=None) { -+ XTranslateCoordinates(theDisp, rW, win, rootx, rooty, &x, &y, &cW); -+ if (cW == None) break; -+ else win = cW; -+ } -+ -+ for (i=0; i<MAXBRWIN && win!=binfo[i].iconW; i++); -+ if (i==MAXBRWIN) { destBr=(BROWINFO *) NULL; destFolderName = ""; } -+ -+ /* 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) 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 -+ a rect drag */ -+ -+ if (sel>=0 && (oldx!=x || oldy!=y || oldbrnum!=i)) { /* moved */ -+ samepos = 0; oldx = x; oldy = y; oldbrnum = i; -+ } -+ else { -+ int scamt = 0; -+ if (sel == -1) { /* rectangle dragging */ -+ if (iwy < SCROLLVERT) scamt = -1; -+ if (iwy < -PAGEVERT) scamt = -destBr->visHigh; -+ if (iwy > destBr->iwHigh-SCROLLVERT) scamt = 1; -+ if (iwy > destBr->iwHigh+PAGEVERT) scamt = destBr->visHigh; -+ } -+ else { /* file dragging */ -+ if (y >= 0 && y < SCROLLVERT) scamt = -1; -+ if (y <= destBr->iwHigh && y > destBr->iwHigh-SCROLLVERT) -+ scamt = 1; -+ } -+ -+ if ((scamt < 0 && destBr->scrl.val > 0) || -+ (scamt > 0 && destBr->scrl.val < destBr->scrl.max)) { -+ -+ if (hasrect) invertSelRect(br,rx,ry,rw,rh); -+ hasrect = 0; -+ -+ SCSetVal(&(destBr->scrl), destBr->scrl.val + scamt); -+ Timer(150); -+ } -+ } -+ -+ -+ /* 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 -+ only* of the selected folder, by setting it's 'lit' field to -+ ICON_ONLY, and clearing any other folders that might have -+ that set (only one dest folder can be lit at a time) */ -+ -+ if (sel>=0) { -+ destic = mouseInWhichIcon(destBr, x, y); -+ -+ bf = (destic>=0) ? &(destBr->bfList[destic]) : (BFIL *) NULL; -+ if (!bf || (bf && bf->ftype == BF_DIR && bf->lit!=ICON_ONLY)) { -+ for (i=0; i<destBr->bfLen; i++) { /* clear prev dest */ -+ if (destBr->bfList[i].lit == ICON_ONLY) { -+ destBr->bfList[i].lit = 0; -+ drawIcon(destBr, i); -+ } -+ } -+ destFolderName = "."; -+ } -+ -+ if (bf && bf->ftype == BF_DIR && !bf->lit) { -+ bf->lit = ICON_ONLY; -+ drawIcon(destBr, destic); -+ destFolderName = bf->name; -+ } -+ } -+ -+ /* Dragging a selection rectangle. */ -+ -+ else { -+ static int prevx, prevy, prevcnt; -+ int origy, top, left, wide, high, cnt; -+ -+ if (first) { prevx = mx; prevy = my; first=0; prevcnt = -1; } -+ -+ /* set x,y to iconW coordinate system, clipped... */ -+ x = iwx; y = iwy; -+ RANGE(x, 0, br->iwWide-1); -+ RANGE(y, 0, br->iwHigh-1); -+ -+ if (x != prevx || y != prevy || !hasrect) { /* cursor moved */ -+ origy = my - (br->scrl.val - origsval) * ISPACE_HIGH; -+ -+ if (hasrect) invertSelRect(br, rx, ry, rw, rh); /* turn off */ -+ -+ rx = (mx < x) ? mx : x; -+ ry = (origy < y) ? origy : y; -+ 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; -+ -+ ix = ((i%br->numWide) * ISPACE_WIDE) -+ + ISPACE_WIDE/2 - bf->w/2; -+ iy = ((i/br->numWide) * ISPACE_HIGH) -+ + ISPACE_TOP + ISIZE_HIGH - bf->h; -+ -+ iy = iy - br->scrl.val * ISPACE_HIGH; -+ -+ /* is the icon rectangle of this beastie inside the -+ dragging rectangle ? */ -+ -+ isin = (ix+bf->w >= rx && ix < rx+rw && -+ iy+bf->h >= ry && iy < ry+rh); -+ -+ if (isin) { -+ if (bf->lit==0) { -+ bf->lit = TEMP_LIT; drawIcon(br, i); -+ } -+ else if (bf->lit==1) { -+ bf->lit = TEMP_LIT1; drawIcon(br, i); -+ } -+ } -+ else { -+ if (bf->lit == TEMP_LIT) { -+ bf->lit = 0; drawIcon(br, i); -+ } -+ else if (bf->lit == TEMP_LIT1) { -+ bf->lit = 1; drawIcon(br, i); -+ } -+ } -+ -+ if (bf->lit) cnt++; -+ } -+ -+ invertSelRect(br, rx, ry, rw, rh); /* turn on */ -+ hasrect = 1; -+ -+ if (cnt != prevcnt) { -+ if (cnt) sprintf(buf, "%d file%s selected", cnt, -+ (cnt>1) ? "s" : ""); -+ else buf[0]='\0'; -+ setBrowStr(br, buf); -+ prevcnt = cnt; -+ } -+ -+ prevx = x; prevy = y; -+ } -+ } -+ } -+ -+ else { /* NOT in an icon window... */ -+ /* turn off ALL ICON_ONLY icons in ALL icon windows... */ -+ for (i=0; i<MAXBRWIN; i++) { -+ for (j=0, bf=binfo[i].bfList; j<binfo[i].bfLen; j++,bf++) { -+ if (bf->lit == ICON_ONLY) { -+ bf->lit = 0; -+ drawIcon(&binfo[i], j); -+ } -+ } -+ } -+ } -+ } -+ -+ /* RELEASED BUTTON: back to normal arrow cursor */ -+ for (i=0; i<MAXBRWIN; i++) -+ XDefineCursor(theDisp, binfo[i].iconW, None); -+ -+ if (sel == -1) { /* was dragging rectangle */ -+ if (hasrect) invertSelRect(br, rx, ry, rw, rh); -+ -+ br->numlit = 0; -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if (!multi && bf->lit == 1) { bf->lit = 0; drawIcon(br, i); } -+ -+ if (bf->lit == TEMP_LIT || bf->lit == TEMP_LIT1) { -+ bf->lit = 1; drawIcon(br, i); -+ } -+ -+ if (bf->lit) br->numlit++; -+ } -+ -+ changedNumLit(br, -1, 0); -+ } -+ } -+ } -+ } -+ -+ -+ /* if doing a copy or a move, do the thing to the files */ -+ if (sel >= 0) { -+ char *destFolder; -+ -+ if (DEBUG) { -+ fprintf(stderr,"---------------\n"); -+ fprintf(stderr,"Source Dir: '%s'\n", br->path); -+ fprintf(stderr,"Dest Dir: '%s'\n", destBr ? destBr->path : "<null>"); -+ fprintf(stderr,"Dest Folder: '%s'\n", destFolderName); -+ } -+ -+ -+ if (!br->numlit) { -+ if (DEBUG) fprintf(stderr, "no selected files. Nothing to do!\n"); -+ } -+ -+ else if (dodel) { -+ doDeleteCmd(br); -+ } -+ -+ else if (!destBr || strlen(destFolderName) == 0) { -+ if (DEBUG) fprintf(stderr, "no destination. Nothing to do!\n"); -+ } -+ -+ else if (strcmp(destFolderName,".") == 0 && -+ strcmp(br->path, destBr->path) == 0) { -+ if (DEBUG) fprintf(stderr,"source == destination. Nothing to do!\n"); -+ } -+ -+ else { /* have to do some copying/moving */ -+ char **nlist; int ncnt; -+ -+ if (DEBUG) fprintf(stderr,"Files to %s: ", cpymode ? "copy" : "move"); -+ -+ nlist = (char **) malloc(br->numlit * sizeof(char *)); -+ if (!nlist) FatalError("clickIconWin: couldn't malloc nlist"); -+ -+ /* copy names to nlist */ -+ for (i=ncnt=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if (bf->lit == 1 && ncnt < br->numlit) { -+ nlist[ncnt] = (char *) malloc(strlen(bf->name)+1); -+ if (!nlist[ncnt]) FatalError("out of memory building namelist"); -+ -+ strcpy(nlist[ncnt], bf->name); -+ ncnt++; -+ if (DEBUG) fprintf(stderr, "%s ", bf->name); -+ } -+ } -+ 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 -+ * in a copy command... :( RLD 26-FEB-1993 -+ */ -+ -+ *rindex ( destFolderName, '.' ) = '\0'; -+#endif -+ -+ -+ dragFiles(br, destBr, br->path, destBr->path, destFolderName, nlist, -+ ncnt, cpymode); -+ -+ /* free namelist */ -+ for (i=0; i<ncnt; i++) if (nlist[i]) free(nlist[i]); -+ free(nlist); -+ } -+ -+ -+ if (destBr) { /* turn off any ICON_ONLY folders */ -+ for (i=0, bf=destBr->bfList; i<destBr->bfLen; i++,bf++) { -+ if (bf->lit == ICON_ONLY) { -+ bf->lit = 0; -+ drawIcon(destBr, i); -+ } -+ } -+ } -+ } /* end of 'tracking' sub-function */ -+ -+ return rv; -+} -+ -+/*******************************************/ -+static void doubleClick(br, sel) -+ BROWINFO *br; -+ int sel; -+{ -+ int i, j, k; -+ char buf[512]; -+ BFIL *bf; -+ -+ /* called to 'open' icon #sel, which could be a file or a dir */ -+ -+ /* if sel == -1, then called via RETURN key. just use first lit item -+ as thing that was double clicked on */ -+ -+ if (sel < 0) { -+ for (sel=0; sel<br->bfLen && br->bfList[sel].lit==0; sel++); -+ } -+ -+ j = 0; -+ k = numnames; -+ if (sel < 0 || sel >= br->bfLen) return; /* no selection */ -+ -+ /* if this isn't a dir, copy it, and all other selected non-dir -+ filenames into the ctrl list */ -+ if (ISLOADABLE(br->bfList[sel].ftype)) { -+ AddFNameToCtrlList(br->path, br->bfList[sel].name); -+ j++; -+ } -+ -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if (bf->lit && ISLOADABLE(bf->ftype) && i!=sel) { -+ AddFNameToCtrlList(br->path, bf->name); -+ j++; -+ } -+ } -+ -+ /* clear all 'other' selections */ -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if (bf->lit && i!=sel) { -+ bf->lit = 0; -+ drawIcon(br, i); -+ } -+ } -+ br->numlit = 1; -+ changedNumLit(br, sel, 0); -+ -+ -+ if (j && k<numnames) { /* stuff was *actually* added to the list */ -+ curname = nList.selected = k; -+ ChangedCtrlList(); /* added something to list */ -+ } -+ -+ -+ -+ /* double-clicked something. We should do something about it */ -+ if (br->bfList[sel].ftype == BF_DIR) { /* try to cd */ -+#ifndef VMS -+ sprintf(buf, "%s%s", br->path, br->bfList[sel].name); -+#else -+ if (strcmp(br->bfList[sel].name,"..")==0) sprintf(buf,"[-]"); -+ else sprintf(buf, "%s%s", br->path, br->bfList[sel].name); -+#endif -+ -+ if (chdir(buf)) { -+ char str[512]; -+ sprintf(str,"Unable to cd to '%s'\n", br->bfList[sel].name); -+ setBrowStr(br, str); -+ XBell(theDisp, 50); -+ } -+ else { -+ scanDir(br); -+ SCSetVal(&(br->scrl), 0); /* reset to top on a chdir */ -+ } -+ } -+ -+ else { /* not a directory. Try to open it as a file */ -+ int j; -+ -+ sprintf(buf, "%s%s", br->path, br->bfList[sel].name); -+ -+ /* if name is already in namelist, make it the current selection */ -+ for (j=0; j<numnames && strcmp(namelist[j],buf); j++); -+ -+ if (j<numnames) { -+ if (nList.selected != j) { -+ curname = nList.selected = j; -+ ChangedCtrlList(); -+ } -+ *event_retP = THISNEXT; -+ } -+ else { *event_retP = LOADPIC; SetDirFName(buf); } -+ -+ *event_doneP = 1; /* make MainLoop load image */ -+ } -+} -+ -+/*******************************************/ -+static int mouseInWhichIcon(br, mx, my) -+ BROWINFO *br; -+ int mx, my; -+{ -+ /* mx,my are mouse position in iconW coordinates. Returns '-1' if the -+ mouse is not in any icon */ -+ -+ int i, x, y, ix, iy, sel, base, num; -+ BFIL *bf; -+ -+ /* figure out what was clicked... */ -+ base = br->scrl.val * br->numWide; -+ num = (1+br->visHigh) * br->numWide; -+ -+ for (i=0, sel=base; i<num; i++,sel++) { -+ if (sel>=0 && sel<br->bfLen) { -+ bf = &(br->bfList[sel]); -+ -+ x = (i%br->numWide) * ISPACE_WIDE; /* x,y=top-left of icon region */ -+ y = (i/br->numWide) * ISPACE_HIGH; -+ -+ ix = x + ISPACE_WIDE/2 - bf->w/2; /* center align */ -+ iy = y + ISPACE_TOP + ISIZE_HIGH - bf->h; /* bottom align */ -+ -+ if (PTINRECT(mx,my, ix, iy, bf->w, bf->h)) break; -+ } -+ } -+ -+ if (i==num) return -1; -+ return sel; -+} -+ -+ -+/*******************************************/ -+static void invertSelRect(br, x, y, w, h) -+ BROWINFO *br; -+ int x,y,w,h; -+{ -+ if (w>1 && h>1) { -+ XSetState(theDisp,theGC, browfg, browbg, GXinvert, browfg^browbg); -+ XDrawRectangle(theDisp, br->iconW, theGC, x,y, (u_int) w, (u_int) h); -+ XSetState(theDisp,theGC, browfg, browbg, GXcopy, AllPlanes); -+ } -+} -+ -+ -+ -+ -+/***************************************************************/ -+static void keyIconWin(br, kevt) -+ BROWINFO *br; -+ XKeyEvent *kevt; -+{ -+ char buf[128]; -+ KeySym ks; -+ int stlen, shift, dealt, ck; -+ -+ stlen = XLookupString(kevt, buf, 128, &ks, (XComposeStatus *) NULL); -+ shift = kevt->state & ShiftMask; -+ ck = CursorKey(ks, shift, 1); -+ dealt = 1; -+ -+ RemapKeyCheck(ks, buf, &stlen); -+ -+ /* check for arrow keys, Home, End, PgUp, PgDown, etc. */ -+ if (ck!=CK_NONE) browKey(br,ck); -+ else dealt = 0; -+ -+ /* fake tab and backtab to be same as 'space' and 'backspace' */ -+ if (ks==XK_Tab && shift) { buf[0] = '\010'; stlen = 1; } -+ if (ks==XK_Tab && !shift) { buf[0] = ' '; stlen = 1; } -+ -+ if (dealt || !stlen) return; -+ -+ /* keyboard equivalents */ -+ switch (buf[0]) { -+ case '\003': doCmd(br, BR_CHDIR); break; /* ^C = Chdir */ -+ case '\004': doCmd(br, BR_DELETE); break; /* ^D = Delete Files */ -+ case '\016': doCmd(br, BR_MKDIR); break; /* ^N = New Directory */ -+ case '\022': doCmd(br, BR_RENAME); break; /* ^R = Rename */ -+ case '\023': doCmd(br, BR_RESCAN); break; /* ^S = reScan */ -+ case '\025': doCmd(br, BR_UPDATE); break; /* ^U = Update icons */ -+ case '\027': doCmd(br, BR_NEWWIN); break; /* ^W = open new Window */ -+ case '\007': doCmd(br, BR_GENICON); break; /* ^G = Generate icons */ -+ case '\001': doCmd(br, BR_SELALL); break; /* ^A = select All */ -+ case '\024': doCmd(br, BR_TEXTVIEW); break; /* ^T = Textview */ -+ case '\005': doCmd(br, BR_RECURSUP); break; /* ^E = rEcursive update */ -+ case '\021': doCmd(br, BR_QUIT); break; /* ^Q = Quit xv */ -+ -+ case '\006': doCmd(br, BR_SELFILES); break; /* ^F = Select Files */ -+ -+ -+ /* case '\003': FakeButtonPress(&but[BCMTVIEW]); break; */ /* ^C */ -+ -+ case '\033': doCmd(br, BR_CLOSE); break; /* ESC = Close window */ -+ -+ case '\r': -+ case '\n': doubleClick(br, -1); break; /* RETURN = load selected */ -+ -+ case ' ': -+ case '\010': -+ case '\177': /* SPACE = load next, BS/DEL = load prev */ -+ if (br->bfLen && br->numlit >= 1) { -+ int i, j, viewsel; -+ 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 -+ are the only cases where br->numlit >1 allowed */ -+ -+ if (br->numlit>1 && buf[0] != ' ') return; -+ -+ 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++) { -+ if (br->bfList[j].lit && j!=i) { -+ br->bfList[j].lit = 0; -+ drawIcon(br, j); -+ } -+ } -+ } -+ -+ br->bfList[i].lit = 1; -+ -+ for (j=0, br->numlit=0; j<br->bfLen; j++) -+ if (br->bfList[j].lit) br->numlit++; -+ -+ makeIconVisible(br, i); -+ drawIcon(br, i); -+ setSelInfoStr(br, i); -+ -+ /* load this file, stick it in ctrlList, etc. */ -+ -+ if (ISLOADABLE(br->bfList[i].ftype)) { -+ char foo[256]; -+ -+ j = numnames; -+ AddFNameToCtrlList(br->path, br->bfList[i].name); -+ if (j<numnames) { /* actually added it */ -+ curname = nList.selected = j; -+ ChangedCtrlList(); -+ } -+ -+ /* try to open this file */ -+ sprintf(foo, "%s%s", br->path, br->bfList[i].name); -+ for (j=0; j<numnames && strcmp(namelist[j],foo); j++); -+ if (j<numnames) { -+ curname = nList.selected = j; -+ ChangedCtrlList(); -+ *event_retP = THISNEXT; -+ } -+ else { *event_retP = LOADPIC; SetDirFName(foo); } -+ -+ *event_doneP = 1; -+ } -+ } -+ -+ 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); -+ viewsel = !(strcmp(fname, fullfname)); -+ -+ if (viewsel) { -+ if (buf[0]==' ') browKey(br, CK_RIGHT); -+ else browKey(br, CK_LEFT); -+ } -+ -+ 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) -+ doubleClick(br, -1); -+ } -+ } -+ } -+ break; -+ -+ -+ default: /* unknown character. Take it as an alpha accelerator */ -+ if (buf[0] > 32) browAlpha(br, buf[0]); -+ else XBell(theDisp, 0); -+ break; -+ } -+ -+} -+ -+ -+/***************************************************/ -+static void browKey(br, key) -+ BROWINFO *br; -+ int key; -+{ -+ int i,j; -+ -+ if (!br->bfLen) return; -+ -+ /* an arrow key (or something like that) was pressed in icon window. -+ change selection/scrollbar accordingly */ -+ -+ /* 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); -+ if (key == CK_HOME) SCSetVal(&br->scrl, br->scrl.min); -+ if (key == CK_END) SCSetVal(&br->scrl, br->scrl.max); -+ -+ /* handle up/down/left/right keys -+ * -+ * if precisely *one* item is lit, than the up/down/left/right keys move -+ * 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 -+ * anything -+ * -+ * if more than one item is lit, up/down/left/right keys BEEP -+ */ -+ -+ if (key==CK_UP || key==CK_DOWN || key==CK_LEFT || key==CK_RIGHT) { -+ -+ if (br->numlit > 1) XBell(theDisp, 50); -+ else if (br->numlit == 1) { -+ /* find it */ -+ for (i=0; i<br->bfLen && !br->bfList[i].lit; i++); -+ -+ /* if it's not visible, lose it */ -+ if ((i < br->scrl.val * br->numWide) || -+ (i >= (br->scrl.val + br->visHigh) * br->numWide)) { -+ br->numlit = 0; -+ br->bfList[i].lit = 0; -+ drawIcon(br, i); -+ } -+ else { -+ /* make it visible */ -+ makeIconVisible(br, i); -+ -+ j = i; -+ -+ if (key == CK_UP) j = i - br->numWide; -+ 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) { -+ br->bfList[i].lit = 0; -+ br->bfList[j].lit = 1; -+ makeIconVisible(br,j); -+ drawIcon(br,i); -+ drawIcon(br,j); -+ setSelInfoStr(br, j); -+ } -+ } -+ } -+ -+ -+ 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); -+ if (key == CK_LEFT || key == CK_RIGHT) { -+ if (key == CK_LEFT) i = (br->scrl.val+br->visHigh) * br->numWide - 1; -+ else i = (br->scrl.val * br->numWide); -+ RANGE(i, 0, br->bfLen-1); -+ br->bfList[i].lit = 1; -+ br->numlit = 1; -+ changedNumLit(br, i, 0); -+ drawIcon(br, i); -+ } -+ } -+ } -+} -+ -+ -+ -+/***************************************************/ -+static void browAlpha(br, ch) -+ BROWINFO *br; -+ int ch; -+{ -+ /* find first 'plain' file that is lexically >= than the given ch */ -+ -+ int i,j; -+ -+ if (!br->bfLen) return; -+ 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 */ -+ -+ for ( ; i<br->bfLen; i++) { -+ if (br->bfList[i].name[0] >= ch) break; -+ } -+ -+ if (i==br->bfLen) i--; -+ -+ for (j=0; j<br->bfLen; j++) { -+ if (br->bfList[j].lit) { -+ br->bfList[j].lit = 0; -+ drawIcon(br, j); -+ } -+ } -+ -+ br->bfList[i].lit = 1; -+ drawIcon(br, i); -+ br->numlit = 1; -+ -+ makeIconVisible(br, i); -+ changedNumLit(br, i, 0); -+} -+ -+ -+ -+/***************************************************/ -+static void changedBrDirMB(br, sel) -+ BROWINFO *br; -+ int sel; -+{ -+ -+ if (sel != 0) { /* changed directories */ -+ char tmppath[MAXPATHLEN+1]; -+ int i; -+ -+ /* build 'tmppath' */ -+ tmppath[0] = '\0'; -+ for (i = br->ndirs-1; i>=sel; i--) -+ strcat(tmppath, br->mblist[i]); -+ -+ if (tmppath[0] == '\0') { -+ /* special case: if cd to '/', fix path (it's currently "") */ -+#ifdef apollo /*** Apollo DomainOS uses // as the network root ***/ -+ strcpy(tmppath,"//"); -+#else -+ strcpy(tmppath,"/"); -+#endif -+ } -+#ifdef VMS -+ else { -+ /* -+ * 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 -+ * disks). -+ * -+ * End 'tmppath' by changing trailing '/' (of dir name) to a '\0' -+ */ -+ *rindex ( tmppath, '/') = '\0'; -+ 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 -+ -+ if (chdir(tmppath)) { -+ char str[512]; -+ sprintf(str,"Unable to cd to '%s'\n", tmppath); -+ MBRedraw(&(br->dirMB)); -+ setBrowStr(br,str); -+ XBell(theDisp, 50); -+ } -+ else { -+ scanDir(br); -+ SCSetVal(&br->scrl, 0); /* reset to top of window on a chdir */ -+ } -+ } -+} -+ -+ -+ -+/***************************************************************/ -+static int cdBrow(br) -+ BROWINFO *br; -+{ -+ /* returns non-zero on failure */ -+ -+ int rv; -+ -+ /* temporarily excise trailing '/' char from br->path */ -+ if ((strlen(br->path) > (size_t) 2) && br->path[strlen(br->path)-1] == '/') -+ br->path[strlen(br->path)-1] = '\0'; -+ -+ rv = chdir(br->path); -+ if (rv) { -+ char str[512]; -+ sprintf(str, "Unable to cd to '%s'\n", br->path); -+ setBrowStr(br, str); -+ XBell(theDisp, 50); -+ } -+ -+ strcat(br->path, "/"); /* put trailing '/' back on */ -+ return rv; -+} -+ -+ -+/***************************************************************/ -+static void copyDirInfo(srcbr, dstbr) -+ BROWINFO *srcbr, *dstbr; -+{ -+ /* copies br info from an already existing browser window -+ (ie, one that is already showing the same directory) */ -+ -+ int i, oldnum, maxv, page; -+ -+ oldnum = dstbr->bfLen; -+ dstbr->lastIconClicked = -1; -+ setBrowStr(dstbr,""); -+ -+ /* copy mblist */ -+ dstbr->ndirs = srcbr->ndirs; -+ for (i=0; i<dstbr->ndirs; i++) { -+ dstbr->mblist[i] = (char *) malloc(strlen(srcbr->mblist[i]) + 1); -+ if (!dstbr->mblist[i]) FatalError("unable to malloc brMBlist[]"); -+ strcpy(dstbr->mblist[i], srcbr->mblist[i]); -+ } -+ -+ dstbr->dirMB.list = srcbr->mblist; -+ dstbr->dirMB.nlist = srcbr->ndirs; -+ -+ 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; -+ dstbr->dirMB.x = dstbr->dirMB.x + dstbr->dirMB.w/2 - i/2; -+ dstbr->dirMB.w = i; -+ MBRedraw(&dstbr->dirMB); -+ -+ strcpy(dstbr->path, srcbr->path); -+ -+ WaitCursor(); -+ freeBfList(dstbr); /* just to be safe */ -+ -+ /* copy the bfList info */ -+ dstbr->numlit = 0; -+ dstbr->bfLen = srcbr->bfLen; -+ -+ dstbr->bfList = (BFIL *) calloc((size_t) dstbr->bfLen, sizeof(BFIL)); -+ if (!dstbr->bfList) FatalError("can't create bfList!"); -+ -+ for (i=0; i<dstbr->bfLen; i++) { -+ BFIL *sbf, *dbf; -+ -+ if ((i&0x03) == 0) drawTemp(dstbr, i, dstbr->bfLen); -+ if ((i & 0x3f) == 0) WaitCursor(); -+ -+ sbf = &(srcbr->bfList[i]); -+ dbf = &(dstbr->bfList[i]); -+ -+ if (sbf->name) { -+ dbf->name = (char *) malloc(strlen(sbf->name) + 1); -+ if (!dbf->name) FatalError("ran out of memory for dbf->name"); -+ strcpy(dbf->name, sbf->name); -+ } -+ else dbf->name = (char *) NULL; -+ -+ if (sbf->imginfo) { -+ dbf->imginfo = (char *) malloc(strlen(sbf->imginfo) + 1); -+ if (!dbf->imginfo) FatalError("ran out of memory for dbf->imginfo"); -+ strcpy(dbf->imginfo, sbf->imginfo); -+ } -+ else dbf->imginfo = (char *) NULL; -+ -+ dbf->ftype = sbf->ftype; -+ dbf->lit = 0; -+ dbf->w = sbf->w; -+ dbf->h = sbf->h; -+ -+ 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, -+ (size_t) (dbf->w * dbf->h)); -+ } -+ else dbf->pimage = (byte *) NULL; -+ -+ if (sbf->ximage) { -+ dbf->ximage = (XImage *) malloc(sizeof(XImage)); -+ if (!dbf->ximage) FatalError("ran out of memory for dbf->ximage"); -+ 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->bytes_per_line); -+ if (!dbf->ximage->data) FatalError("ran out of memory for ximg data"); -+ xvbcopy((char *) sbf->ximage->data, (char *) dbf->ximage->data, -+ (size_t) dbf->ximage->height * dbf->ximage->bytes_per_line); -+ } -+ } -+ else dbf->ximage = (XImage *) NULL; -+ -+ } -+ -+ clearTemp(dstbr); -+ -+ /* misc setup (similar to endScan(), but without unnecessary stuff) */ -+ eraseNumfiles(dstbr, oldnum); -+ drawNumfiles(dstbr); -+ drawTrash(dstbr); -+ computeScrlVals(dstbr, &maxv, &page); -+ if (dstbr->scrl.val > maxv) dstbr->scrl.val = maxv; -+ -+ 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) -+ BROWINFO *br; -+{ -+ /* loads contents of current working directory into BFIL structures... -+ * and also loads up the MB list -+ * -+ * note: when actually doing the code, in addition to stat'ing files, we -+ * might want to try reading the first couple of bytes out of them, to see -+ * what magicno they have, and putting up an appropriate icon for different -+ * types of standard files. Make this mechanism fairly clean and easily -+ * extensible, as different machines will have different types of files, -+ * and it's reasonable to expect folks to want to add their own bitmaps -+ */ -+ -+ int i,j,k,oldbflen,vmsparent; -+ BFIL *bf; -+ -+ DIR *dirp; -+ char *dbeg, *dend; -+ char *dirnames[MAXDEEP]; -+ static char path[MAXPATHLEN + 2] = { '\0' }; -+ -+#ifdef NODIRENT -+ struct direct *dp; -+#else -+ struct dirent *dp; -+#endif -+ -+ -+ br->lastIconClicked = -1; /* turn off possibility of seeing a dblclick */ -+ setBrowStr(br,""); -+ -+ -+ /********************************************************************/ -+ /*** LOAD UP the brdirMB information to reflect the new directory ***/ -+ /********************************************************************/ -+ -+ -+ 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 */ -+ -+ /* path will be something like: "/u3/bradley/src/weiner/whatever/" */ -+ -+ dbeg = dend = path; -+ for (i=0; i<MAXDEEP && dend; i++) { -+ dend = (char *) index(dbeg,'/'); /* find next '/' char */ -+ -+#ifdef apollo -+ /** On Apollos the path will be something like //machine/users/foo/ **/ -+ /** handle the initial // **/ -+ if ((dend == dbeg ) && (dbeg[0] == '/') && (dbeg[1] == '/')) dend += 1; -+#endif -+ -+ dirnames[i] = dbeg; -+ dbeg = dend+1; -+ } -+ br->ndirs = i-1; -+ -+ -+ /* 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] -+ : strlen(dirnames[i]); -+ -+ br->mblist[j] = (char *) malloc(stlen+1); -+ if (!br->mblist[j]) FatalError("unable to malloc brMBlist[]"); -+ -+ strncpy(br->mblist[j], dirnames[i], stlen); -+ br->mblist[j][stlen] = '\0'; -+ } -+ -+ -+ /* 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, -+ br->dirMB.w+3, br->dirMB.h+3, False); -+ -+ i = StringWidth(br->mblist[0]) + 10; -+ br->dirMB.x = br->dirMB.x + br->dirMB.w/2 - i/2; -+ br->dirMB.w = i; -+ MBRedraw(&br->dirMB); -+ -+ strcpy(br->path, path); /* will have a trailing '/' character */ -+ -+ -+ /********************************************************************/ -+ /*** read the directory (load up bfList) ***/ -+ /********************************************************************/ -+ -+ -+ WaitCursor(); -+ -+ oldbflen = br->bfLen; -+ -+ freeBfList(br); /* free all memory currently used by bfList structure */ -+ -+ /* count how many files are in the list */ -+ -+ dirp = opendir("."); -+ if (!dirp) { -+ endScan(br, oldbflen); -+ setBrowStr(br, "Couldn't read current directory."); -+ SetCursors(-1); -+ return; -+ } -+ -+#ifdef VMS -+ br->bfLen = 1; /* always have a parent directory */ -+#endif -+ -+ while ( (dp = readdir(dirp)) != NULL) { -+ if (strcmp(dp->d_name, ".") && -+ strcmp(dp->d_name, THUMBDIR)) { -+ if (!br->showhidden && dp->d_name[0] == '.' && -+ strcmp(dp->d_name,"..")!=0) continue; -+ else -+ br->bfLen++; -+ } -+ if ((br->bfLen & 0x3f) == 0) WaitCursor(); -+ } -+ -+ -+ if (br->bfLen) { -+ int readcount, iconcount, statcount; -+ -+ br->bfList = (BFIL *) calloc((size_t) br->bfLen, sizeof(BFIL)); -+ -+ if (!br->bfList) FatalError("can't create bfList! (malloc failed)\n"); -+ -+ rewinddir(dirp); /* back to beginning of directory */ -+ -+ vmsparent = 0; -+#ifdef VMS -+ vmsparent = 1; -+#endif -+ -+ /* get info for each file in directory */ -+ -+ readcount = 0; iconcount = 0; statcount = 0; -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ -+ drawTemp(br, i, br->bfLen); -+ -+ if ((i & 0x1f) == 0) WaitCursor(); -+ -+ /* get next directory entry that isn't '.' or THUMBDIR or -+ '..' in root directory, or a hidden file if !showhidden */ -+ -+ if (vmsparent) { /* first time: make bogus parent for VMS */ -+ bf->name = (char *) malloc(strlen("..") + 1); -+ if (!bf->name) FatalError("out of memory in scanDir()"); -+ strcpy(bf->name, ".."); -+ bf->ftype = BF_DIR; -+ bf->w = br_dir_width; -+ bf->h = br_chr_width; -+ bf->pimage = (byte *) NULL; -+ bf->ximage = (XImage *) NULL; -+ bf->lit = 0; -+ } -+ else { -+ do { dp = readdir(dirp); } -+ 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] == '.' && -+ strcmp(dp->d_name,"..")!=0))); -+ -+ if (!dp) { br->bfLen = i; break; } /* dir got shorter... */ -+ } -+ -+ if (!vmsparent) scanFile(br, bf, dp->d_name); -+ vmsparent = 0; -+ -+ statcount++; -+ if (bf->ftype == BF_HAVEIMG) iconcount++; -+ if (bf->ftype == BF_FILE) readcount++; -+ -+ if ((statcount && (statcount%100)==0) || -+ (iconcount && (iconcount% 20)==0) || -+ (readcount && (readcount% 20)==0)) { /* mention progress */ -+ -+ char tmp[64]; -+ -+ sprintf(tmp, "Processed %d out of %d...", i+1, br->bfLen); -+ setBrowStr(br, tmp); -+ } -+ } -+ -+ clearTemp(br); -+ } -+ -+ closedir(dirp); -+ -+ endScan(br, oldbflen); -+} -+ -+ -+/***************************************************************/ -+static void endScan(br, oldnum) -+ BROWINFO *br; -+ int oldnum; -+{ -+ /* called at end of scanDir() and rescanDir() */ -+ -+ int maxv, page; -+ int w,h; -+ -+ setBrowStr(br,""); -+ sortBFList(br); -+ -+ eraseNumfiles(br, oldnum); -+ drawNumfiles(br); -+ drawTrash(br); -+ -+ computeScrlVals(br, &maxv, &page); -+ if (br->scrl.val>maxv) br->scrl.val = maxv; -+ -+ /* have to clear window as # of icons may have changed */ -+ w = br->iwWide; h = br->iwHigh; -+ if (ctrlColor) { w -= 4; h -= 4; } -+ if (w<1) w = 1; -+ if (h<1) h = 1; -+ -+ 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); -+} -+ -+ -+/***************************************************************/ -+static void scanFile(br, bf, name) -+ BROWINFO *br; -+ BFIL *bf; -+ char *name; -+{ -+ /* given a pointer to an empty BFIL structure, and a filename, -+ loads up the BFIL structure appropriately */ -+ -+ struct stat st; -+ -+ /* copy name */ -+ bf->name = (char *) malloc(strlen(name) + 1); -+ -+ if (!bf->name) FatalError("ran out of memory for bf->name"); -+ strcpy(bf->name, name); -+ -+ /* default icon values. (in case 'stat' doesn't work) */ -+ bf->ftype = BF_FILE; -+ bf->w = br_file_width; bf->h = br_file_height; -+ bf->pimage = (byte *) NULL; -+ bf->ximage = (XImage *) NULL; -+ bf->lit = 0; -+ -+ -+ if (stat(bf->name, &st)==0) { -+ bf->ftype = stat2bf((u_int) st.st_mode); -+ if (bf->ftype == BF_FILE && (st.st_mode & 0111)) bf->ftype = BF_EXE; -+ -+ switch (bf->ftype) { -+ case BF_DIR: bf->w = br_dir_width; bf->h = br_dir_height; break; -+ case BF_CHR: bf->w = br_chr_width; bf->h = br_chr_height; break; -+ case BF_BLK: bf->w = br_blk_width; bf->h = br_blk_height; break; -+ case BF_SOCK: bf->w = br_sock_width; bf->h = br_sock_height; break; -+ case BF_FIFO: bf->w = br_fifo_width; bf->h = br_fifo_height; break; -+ case BF_EXE: bf->w = br_exe_width; bf->h = br_exe_height; break; -+ } -+ } -+ -+ -+ loadThumbFile(br, bf); -+ -+ -+ if (bf->ftype == BF_FILE || bf->ftype == BF_EXE) { -+ /* if it's a regular file, with no thumbnail, try to determine what -+ type of file it is */ -+ -+ int filetype; -+ -+ filetype = ReadFileType(bf->name); -+ -+ switch (filetype) { -+ case RFT_GIF: bf->ftype = BF_GIF; break; -+ case RFT_PM: bf->ftype = BF_PM; break; -+ case RFT_PBM: bf->ftype = BF_PBM; break; -+ 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_UTAHRLE: bf->ftype = BF_UTAHRLE; break; -+ case RFT_IRIS: bf->ftype = BF_IRIS; break; -+ case RFT_PCX: bf->ftype = BF_PCX; break; -+ case RFT_JFIF: bf->ftype = BF_JFIF; break; -+ 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_PS: bf->ftype = BF_PS; break; -+ case RFT_IFF: bf->ftype = BF_IFF; break; -+ case RFT_TARGA: bf->ftype = BF_TARGA; 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; -+ } -+ } -+} -+ -+ -+ -+/***************************************************************/ -+static unsigned long bfcompares; -+ -+static void sortBFList(br) -+ BROWINFO *br; -+{ -+ bfcompares = 0; -+ qsort((char *) br->bfList, (size_t) br->bfLen, sizeof(BFIL), bfnamCmp); -+} -+ -+ -+static int bfnamCmp(p1, p2) -+ const void *p1, *p2; -+{ -+ BFIL *b1, *b2; -+ -+ b1 = (BFIL *) p1; -+ b2 = (BFIL *) p2; -+ -+ bfcompares++; -+ if ((bfcompares & 0x7f)==0) WaitCursor(); -+ -+ /* 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)) -+ return strcmp(b1->name, b2->name); -+ -+ else if (b1->ftype == BF_DIR && b2->ftype != BF_DIR) return -1; -+ else return 1; -+} -+ -+ -+/***************************************************************/ -+static void rescanDir(br) -+ BROWINFO *br; -+{ -+ /* chdir to br->path -+ * build two name-lists, one holding the names of all files in the bfList, -+ * and the second holding the names of all files in this directory -+ * (ignore . and .. and THUMBDIR in both) -+ * -+ * include directories in both lists, but filter files (in the second list) -+ * by br->showhidden -+ * -+ * sort the two namelists in pure-alpha order. -+ * for each item in the first list, see if it has an entry in the second -+ * list. If it does, remove the entry from *both* lists -+ * -+ * once that's done, we'll have a list of files that have been deleted -+ * (are in bfList, but not in directory) -+ * and a list of files that have been created -+ * (aren't in bfList, are in directory) -+ * -+ * malloc a new temp bfList that has room for (bfLen - #del'd + #created) -+ * entries, copy all entries from the old bfList (that aren't on the -+ * deleted list) into the new list. for each entry on the created list, -+ * copy it to the new bfList and load its icon (not that it's likely to -+ * have one, in which case fall back to the generic file-type icon). -+ * -+ * free data used by any remaining (deleted) entries in the old bfList -+ * -+ * call sortBfList to put the new bflist into the right order -+ */ -+ -+ int i, j, bflen, dirlen, dnum, cmpval, newlen, n, oldlen; -+ char **bfnames, **dirnames; -+ BFIL *newbflist, *bf; -+ -+ if (cdBrow(br)) return; -+ -+ WaitCursor(); -+ -+ /* build 'bfnames' array */ -+ bflen = oldlen = br->bfLen; bfnames = (char **) NULL; -+ if (bflen) { -+ bfnames = (char **) malloc(bflen * sizeof(char *)); -+ if (!bfnames) FatalError("couldn't alloc bfnames in rescanDir()"); -+ 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); -+ } -+ } -+ -+ WaitCursor(); -+ -+ dirnames = getDirEntries(".", &dirlen, br->showhidden); -+ -+ WaitCursor(); -+ -+ /* 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); -+ -+ /* run through the bflist, and delete entries common to both lists */ -+ for (i=0, dnum=0; i<bflen && dnum<dirlen; i++) { -+ cmpval = strcmp(bfnames[i], dirnames[dnum]); -+ if (cmpval < 0) continue; -+ else if (cmpval > 0) { /* advance dnum, and try again */ -+ dnum++; -+ i--; -+ } -+ else /* cmpval == 0 */ { /* remove from both lists */ -+ free(bfnames[i]); free(dirnames[dnum]); -+ bfnames[i] = dirnames[dnum] = (char *) NULL; -+ dnum++; -+ } -+ } -+ -+ -+ WaitCursor(); -+ -+ /* compress the lists, removing NULL entries, . .. and THUMBDIR */ -+ -+ for (i=j=0; i<bflen; i++) { -+ if (bfnames[i] && strcmp(bfnames[i],".") && strcmp(bfnames[i],"..") && -+ strcmp(bfnames[i],THUMBDIR) && strcmp(bfnames[i],THUMBDIRNAME)) { -+ bfnames[j++] = bfnames[i]; -+ } -+ } -+ bflen = j; -+ -+ -+ for (i=j=0; i<dirlen; i++) { -+ if (dirnames[i] && strcmp(dirnames[i],".") && strcmp(dirnames[i],"..") && -+ strcmp(dirnames[i],THUMBDIR) && strcmp(dirnames[i],THUMBDIRNAME)) { -+ dirnames[j++] = dirnames[i]; -+ } -+ } -+ dirlen = j; -+ -+ -+ if (DEBUG) { -+ fprintf(stderr,"%d files seem to have gone away: ", bflen); -+ 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++) -+ 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) { -+ newbflist = (BFIL *) calloc((size_t) newlen, sizeof(BFIL)); -+ if (!newbflist) FatalError("couldn't malloc newbflist in rescanDir()"); -+ -+ /* copy all entries from old bflist that aren't on deleted list into new */ -+ for (i=n=0, bf=br->bfList; i<br->bfLen && n<newlen; i++, bf++) { -+ for (j=0; j<bflen; j++) { -+ if (strcmp(bf->name, bfnames[j])==0) break; -+ } -+ if (j == bflen) { /* not in del list. copy to new list */ -+ xvbcopy((char *) bf, (char *) &(newbflist[n++]), sizeof(BFIL)); -+ } -+ else { /* in deleted list. free all data for this entry */ -+ if (bf->name) free(bf->name); -+ if (bf->imginfo) free(bf->imginfo); -+ if (bf->pimage) free(bf->pimage); -+ if (bf->ximage) xvDestroyImage(bf->ximage); -+ } -+ } -+ -+ -+ /* add all entries in the 'created' list */ -+ for (i=0; i<dirlen && n<newlen; i++) { -+ scanFile(br, &newbflist[n++], dirnames[i]); -+ } -+ -+ -+ if (br->bfList) free(br->bfList); -+ -+ br->bfList = newbflist; -+ br->bfLen = (n < newlen) ? n : newlen; -+ } -+ else freeBfList(br); /* dir is now empty */ -+ -+ WaitCursor(); -+ -+ -+ /* free memory still in use by bfnames and dirnames arrays */ -+ for (i=0; i<bflen; i++) { if (bfnames[i]) free(bfnames[i]); } -+ for (i=0; i<dirlen; i++) { if (dirnames[i]) free(dirnames[i]); } -+ if (bfnames) free(bfnames); -+ if (dirnames) free(dirnames); -+ -+ endScan(br, oldlen); -+} -+ -+/***************************************************************/ -+static void freeBfList(br) -+ BROWINFO *br; -+{ -+ int i; -+ BFIL *bf; -+ -+ if (br->bfList) { -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if ((i & 0x3f) == 0) WaitCursor(); -+ -+ if (bf->name) free(bf->name); -+ if (bf->imginfo) free(bf->imginfo); -+ if (bf->pimage) free(bf->pimage); -+ if (bf->ximage) xvDestroyImage(bf->ximage); -+ } -+ -+ free(br->bfList); -+ } -+ -+ br->bfList = (BFIL *) NULL; -+ br->bfLen = 0; -+ br->numlit = 0; -+} -+ -+ -+static int namcmp(p1, p2) -+ const void *p1, *p2; -+{ -+ char **s1, **s2; -+ s1 = (char **) p1; -+ s2 = (char **) p2; -+ -+ return strcmp(*s1,*s2); -+} -+ -+/***************************************************************/ -+static char **getDirEntries(dir, lenP, dohidden) -+ 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 -+ 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; -+ DIR *dirp; -+ char **names; -+#ifdef NODIRENT -+ struct direct *dp; -+#else -+ struct dirent *dp; -+#endif -+ -+ -+ dirp = opendir(dir); -+ if (!dirp) { -+ SetISTR(ISTR_WARNING, "%s: %s", dir, ERRSTR(errno)); -+ *lenP = 0; -+ return (char **) NULL; -+ } -+ -+ -+ /* count # of entries in dir (worst case) */ -+ for (dirlen=0; (dp = readdir(dirp)) != NULL; dirlen++); -+ if (!dirlen) { -+ closedir(dirp); -+ *lenP = dirlen; -+ return (char **) NULL; -+ } -+ -+ -+ /* load up the entries, now that we know how many to make */ -+ names = (char **) malloc(dirlen * sizeof(char *)); -+ if (!names) FatalError("malloc failure in getDirEntries()"); -+ -+ -+ rewinddir(dirp); -+ for (i=0; i<dirlen; ) { -+ dp = readdir(dirp); -+ if (!dp) break; -+ -+ if (!dohidden) { -+#ifndef VMS -+ if (dp->d_name[0] == '.' && -+ strcmp(dp->d_name,"." )!=0 && -+ strcmp(dp->d_name,"..")!=0) continue; -+#endif -+ } -+ -+ names[i] = (char *) malloc(strlen(dp->d_name) + 1); -+ if (!names[i]) FatalError("malloc failure in getDirEntries()"); -+ -+ strcpy(names[i], dp->d_name); -+ i++; -+ } -+ -+ if (i<dirlen) dirlen = i; /* dir got shorter... */ -+ -+ closedir(dirp); -+ -+ *lenP = dirlen; -+ return names; -+} -+ -+ -+ -+/***************************************************************/ -+static void computeScrlVals(br, max, page) -+ BROWINFO *br; -+ int *max, *page; -+{ -+ /* called whenever bfList or size of icon window has changed */ -+ -+ if (br->numWide<1) br->numWide = 1; /* safety */ -+ -+ br->numHigh = (br->bfLen + br->numWide-1) / br->numWide; /* # icons high */ -+ -+ *page = br->visHigh; -+ *max = br->numHigh - *page; -+} -+ -+ -+ -+ -+ -+ -+/***************************************************************/ -+static void genSelectedIcons(br) -+ BROWINFO *br; -+{ -+ int i, sval, first, numvis, cnt; -+ -+ setBrowStr(br, ""); -+ -+ if (!br->bfList || !br->bfLen) return; -+ -+ if (cdBrow(br)) return; -+ -+ WaitCursor(); -+ -+ for (i=cnt=0; i<br->bfLen; i++) { -+ if (br->bfList[i].lit) { -+ if (br->numlit) drawTemp(br, cnt, br->numlit); -+ cnt++; -+ makeIconVisible(br, i); -+ eraseIcon(br, i); -+ genIcon(br, &(br->bfList[i])); -+ br->bfList[i].lit = 0; -+ drawIcon(br, i); -+ } -+ } -+ -+ if (br->numlit) clearTemp(br); -+ br->numlit = 0; -+ changedNumLit(br, -1, 1); -+ -+ SetCursors(-1); -+} -+ -+ -+/***************************************************************/ -+static void genIcon(br, bf) -+ BROWINFO *br; -+ BFIL *bf; -+{ -+ /* given a BFIL entry, load 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 -+ */ -+ -+ PICINFO pinfo; -+ int i, filetype; -+ double wexpand,hexpand; -+ int iwide, ihigh; -+ byte *icon24, *icon8; -+ char str[256], str1[256], *readname, 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; -+ -+ /* 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; -+ -+ -+ /* skip all 'special' files */ -+ if (!ISLOADABLE(bf->ftype)) return; -+ -+ filetype = ReadFileType(bf->name); -+ -+ if (filetype == RFT_COMPRESS) { -+#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 */ -+ strcpy (basefname, bf->name); -+ *rindex (basefname, '.') = '\0'; -+ uncName = basefname; -+#else -+ uncName = bf->name; -+#endif -+ -+ if (UncompressFile(uncName, uncompname)) { -+ filetype = ReadFileType(uncompname); -+ readname = uncompname; -+ } -+ else { -+ sprintf(str, "Couldn't uncompress file '%s'", bf->name); -+ setBrowStr(br, str); -+ bf->ftype = BF_ERROR; -+ } -+ } -+ -+ /* get rid of comments. don't need 'em */ -+ if (pinfo.comment) free(pinfo.comment); pinfo.comment = (char *) NULL; -+ -+ 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... */ -+ -+ 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) { -+ free(pinfo.comment); pinfo.comment = (char *) NULL; -+ } -+ -+ /* if we made an uncompressed file, we can rm it now */ -+ if (readname != bf->name) 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) */ -+ -+ wexpand = (double) pinfo.w / (double) ISIZE_WIDE; -+ hexpand = (double) pinfo.h / (double) ISIZE_HIGH; -+ -+ if (wexpand >= 1.0 || hexpand >= 1.0) { /* don't expand small icons */ -+ if (wexpand>hexpand) { -+ iwide = (int) (pinfo.w / wexpand + 0.5); -+ ihigh = (int) (pinfo.h / wexpand + 0.5); -+ } -+ else { -+ iwide = (int) (pinfo.w / hexpand + 0.5); -+ ihigh = (int) (pinfo.h / hexpand + 0.5); -+ } -+ } -+ else { /* smaller than ISIZE. Leave it that way. */ -+ iwide = pinfo.w; ihigh = pinfo.h; -+ } -+ -+ -+ /* generate icon */ -+ 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")) -+ strcat(str,"GIF89 file"); -+ else -+ strcat(str,"GIF87 file"); -+ break; -+ -+ case RFT_PM: strcat(str,"PM file"); break; -+ -+ 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; -+ -+ case RFT_XBM: strcat(str,"X11 bitmap file"); break; -+ case RFT_SUNRAS: strcat(str,"Sun rasterfile"); break; -+ case RFT_BMP: strcat(str,"BMP file"); break; -+ case RFT_UTAHRLE: strcat(str,"Utah RLE file"); break; -+ case RFT_IRIS: strcat(str,"Iris RGB file"); break; -+ case RFT_PCX: strcat(str,"PCX file"); break; -+ case RFT_JFIF: strcat(str,"JPEG file"); break; -+ case RFT_TIFF: strcat(str,"TIFF file"); break; -+ case RFT_PDSVICAR: strcat(str,"PDS/VICAR file"); break; -+ case RFT_PS: strcat(str,"PostScript file"); break; -+ case RFT_IFF: strcat(str,"ILBM file"); break; -+ case RFT_TARGA: strcat(str,"Targa file"); break; -+ 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; -+ 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); -+ } -+ } -+ -+ -+ sprintf(str1, "%s: %s", bf->name, str); -+ setBrowStr(br, str1); -+ -+ /* dither 24-bit icon into 8-bit icon (using 3/3/2 cmap) */ -+ icon8 = DoColorDither(icon24, NULL, iwide, ihigh, NULL, NULL, NULL, -+ browR, browG, browB, 256); -+ if (!icon8) { bf->ftype = BF_FILE; free(icon24); free(pinfo.pic); return; } -+ -+ writeThumbFile(br, bf, icon8, iwide, ihigh, str); -+ -+ /* have to make a *copy* of str */ -+ if (strlen(str)) { -+ bf->imginfo = (char *) malloc(strlen(str)+1); -+ if (bf->imginfo) strcpy(bf->imginfo, str); -+ } -+ else bf->imginfo = (char *) NULL; -+ -+ bf->pimage = icon8; -+ 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); -+} -+ -+ -+ -+ -+ -+ -+/* -+ * THUMBNAIL FILE FORMAT: -+ * -+ * <magic number 'P7 332' > -+ * <comment identifying version of XV that wrote this file> -+ * <comment identifying type & size of the full-size image> -+ * <OPTIONAL comment identifying this as a BUILT-IN icon, in which case -+ * there is no width,height,maxval info, nor any 8-bit data> -+ * <comment signifying end of comments> -+ * <width, height, and maxval of this file > -+ * <raw binary 8-bit data, in 3/3/2 Truecolor format> -+ * -+ * Example: -+ * P7 332 -+ * #XVVERSION:Version 2.28 Rev: 9/26/92 -+ * #IMGINFO:512x440 Color JPEG -+ * #END_OF_COMMENTS -+ * 48 40 255 -+ * <binary data> -+ * -+ * alternately: -+ * P7 332 -+ * #XVVERSION:Version 2.28 Rev: 9/26/92 -+ * #BUILTIN:UNKNOWN -+ * #IMGINFO: -+ * #END_OF_COMMENTS -+ */ -+ -+ -+ -+/***************************************************************/ -+static void loadThumbFile(br, bf) -+ BROWINFO *br; -+ BFIL *bf; -+{ -+ /* determine if bf has an associated thumbnail file. If so, load it up, -+ and create the ximage, and such */ -+ -+ FILE *fp; -+ char thFname[512]; -+ char buf[256], *st, *info; -+ int w,h,mv,i,builtin; -+ byte *icon8; -+ -+ info = NULL; icon8 = NULL; builtin = 0; -+ -+ sprintf(thFname, "%s%s/%s", br->path, THUMBDIR, bf->name); -+ -+ fp = fopen(thFname, "r"); -+ if (!fp) return; /* nope, it doesn't have one */ -+ -+ /* read in the file */ -+ if (!fgets(buf, 256, fp)) goto errexit; -+ -+ if (strncmp(buf, "P7 332", (size_t) 6)) goto errexit; -+ -+ -+ /* 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; -+ -+ else if (!strncmp(buf, "#XVVERSION:", strlen("#XVVERSION:"))) { -+ /* probably should check for compatibility, or something... */ -+ } -+ -+ else if (!strncmp(buf, "#BUILTIN:", strlen("#BUILTIN:"))) { -+ builtin = 1; -+ st = (char *) index(buf, ':') + 1; -+ if (strcmp(st, "ERROR")==0) bf->ftype = BF_ERROR; -+ else bf->ftype = BF_UNKNOWN; -+ } -+ -+ else if (!strncmp(buf, "#IMGINFO:", strlen("#IMGINFO:"))) { -+ st = (char *) index(buf, ':') + 1; -+ info = (char *) malloc(strlen(st) + 1); -+ if (info) strcpy(info, st); -+ } -+ } -+ -+ -+ if (builtin) { -+ bf->imginfo = info; -+ fclose(fp); -+ return; -+ } -+ -+ -+ -+ /* read width, height, maxval */ -+ if (!fgets(buf, 256, fp) || sscanf(buf, "%d %d %d", &w, &h, &mv) != 3) -+ goto errexit; -+ -+ -+ if (w>ISIZE_WIDE || h>ISIZE_HIGH || w<1 || h<1 || mv != 255) { -+ sprintf(buf,"Bogus thumbnail file for '%s'. Skipping.", bf->name); -+ setBrowStr(br, buf); -+ goto errexit; -+ } -+ -+ -+ /* read binary data */ -+ icon8 = (byte *) malloc((size_t) w * h); -+ if (!icon8) goto errexit; -+ -+ i = fread(icon8, (size_t) 1, (size_t) w*h, fp); -+ if (i != w*h) goto errexit; -+ -+ if (icon8) { -+ bf->pimage = icon8; -+ bf->w = w; -+ bf->h = h; -+ bf->ftype = BF_HAVEIMG; -+ bf->imginfo = info; -+ -+ bf->ximage = Pic8ToXImage(icon8, (u_int) w, (u_int) h, browcols, -+ browR, browG, browB); -+ } -+ else { -+ if (info) free(info); -+ } -+ -+ fclose(fp); -+ return; -+ -+ -+ errexit: -+ fclose(fp); -+ if (info) free(info); -+ if (icon8) free(icon8); -+} -+ -+ -+ -+/***************************************************************/ -+static void writeThumbFile(br, bf, icon8, w, h, info) -+ BROWINFO *br; -+ BFIL *bf; -+ byte *icon8; -+ int w,h; -+ char *info; -+{ -+ FILE *fp; -+ char thFname[512], buf[256]; -+ int i, perm; -+ struct stat st; -+ -+ -+ makeThumbDir(br); -+ -+ -+ /* stat the original file, get permissions for thumbfile */ -+ sprintf(thFname, "%s%s", br->path, bf->name); -+ i = stat(thFname, &st); -+ if (!i) perm = st.st_mode & 07777; -+ else perm = 0755; -+ -+ -+ -+ sprintf(thFname, "%s%s/%s", br->path, THUMBDIR, bf->name); -+ -+ fp = fopen(thFname, "w"); -+ if (!fp) { -+ sprintf(buf, "Can't create thumbnail file '%s': %s", thFname, -+ ERRSTR(errno)); -+ setBrowStr(br, buf); -+ return; /* can't write... */ -+ } -+ -+ -+ /* write the file */ -+ fprintf(fp, "P7 332\n"); -+ fprintf(fp, "#XVVERSION:%s\n", REVDATE); -+ -+ if (icon8) { -+ fprintf(fp, "#IMGINFO:%s\n", (info) ? info : ""); -+ } -+ else { -+ fprintf(fp, "#BUILTIN:"); -+ switch (bf->ftype) { -+ case BF_ERROR: fprintf(fp,"ERROR\n"); break; -+ case BF_UNKNOWN: fprintf(fp,"UNKNOWN\n"); break; -+ default: fprintf(fp,"UNKNOWN\n"); break; -+ } -+ -+ fprintf(fp, "#IMGINFO:%s\n", (info) ? info : ""); -+ } -+ -+ fprintf(fp, "#END_OF_COMMENTS\n"); -+ -+ if (icon8) { -+ fprintf(fp, "%d %d %d\n", w, h, 255); -+ -+ /* write the raw data */ -+ fwrite(icon8, (size_t) 1, (size_t) w*h, fp); -+ } -+ -+ if (ferror(fp)) { /* error occurred */ -+ fclose(fp); -+ unlink(thFname); /* delete it */ -+ sprintf(buf, "Can't write thumbnail file '%s': %s", thFname, -+ ERRSTR(errno)); -+ setBrowStr(br, buf); -+ return; /* can't write... */ -+ } -+ -+ fclose(fp); -+ -+ chmod(thFname, (mode_t) perm); -+} -+ -+ -+/***************************************************************/ -+static void makeThumbDir(br) -+ BROWINFO *br; -+{ -+ char thFname[512]; -+ int i, perm; -+ struct stat st; -+ -+ /* stat the THUMBDIR directory: if it doesn't exist, and we are not -+ already in a THUMBDIR, create it */ -+ -+ sprintf(thFname, "%s%s", br->path, THUMBDIRNAME); -+ -+ i = stat(thFname, &st); -+ if (i) { /* failed, let's create it */ -+ sprintf(thFname, "%s.", br->path); -+ 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); -+ } -+} -+ -+ -+ -+/***************************************************************/ -+static void updateIcons(br) -+ BROWINFO *br; -+{ -+ /* for each file in the bfList, see if it has an icon file. -+ * if it doesn't, generate one -+ * if it does, check the dates. If the pic file is newer, regen icon -+ * -+ * for each file in the current directory's thumbnail directory, -+ * see if there's a corresponding pic file. If not, delete the -+ * icon file -+ */ -+ -+ int i, iconsBuilt, iconsKilled, statcount; -+ char tmpstr[128]; -+ BFIL *bf; -+ DIR *dirp; -+#ifdef NODIRENT -+ struct direct *dp; -+#else -+ struct dirent *dp; -+#endif -+ -+ -+ iconsBuilt = iconsKilled = statcount = 0; -+ -+ makeThumbDir(br); -+ -+ /* okay, we're in the right directory. run through the bfList, and look -+ for corresponding thumbnail files */ -+ -+ WaitCursor(); -+ -+ 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 */ -+ -+ int s1, s2; -+ char thfname[256]; -+ struct stat filest, thumbst; -+ -+ drawTemp(br, i, br->bfLen); -+ -+ s1 = stat(bf->name, &filest); -+ -+ /* see if this file has an associated thumbnail file */ -+ 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 -+ time than the thumbnail file */ -+ -+ makeIconVisible(br, i); -+ eraseIcon(br, i); -+ genIcon(br, bf); -+ drawIcon(br, i); -+ -+ 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); -+ } -+ } -+ } -+ statcount++; -+ -+ if ((statcount % 30)==0) WaitCursor(); -+ -+ if ((statcount && (statcount % 100)==0) || -+ (iconsBuilt && (iconsBuilt % 20)==0)) { -+ -+ sprintf(tmpstr, "Processed %d out of %d...", i+1, br->bfLen); -+ setBrowStr(br, tmpstr); -+ } -+ } -+ -+ clearTemp(br); -+ -+ -+ -+ /* search the THUMBDIR directory, looking for thumbfiles that don't have -+ corresponding pic files. Delete those. */ -+ -+ setBrowStr(br, "Scanning for excess icon files..."); -+ -+ statcount = 0; -+ dirp = opendir(THUMBDIR); -+ if (dirp) { -+ while ( (dp = readdir(dirp)) != NULL) { -+ char thfname[256]; -+ struct stat filest, thumbst; -+ -+ /* stat this directory entry to make sure it's a plain file */ -+ sprintf(thfname, "%s/%s", THUMBDIR, dp->d_name); -+ if (stat(thfname, &thumbst)==0) { /* success */ -+ int tmp; -+ tmp = stat2bf((u_int) thumbst.st_mode); -+ -+ if (tmp == BF_FILE) { /* a plain file */ -+ /* see if this thumbfile has an associated pic file */ -+ if (stat(dp->d_name, &filest)) { /* failed!: guess it doesn't */ -+ if (unlink(thfname)==0) iconsKilled++; -+ } -+ } -+ } -+ statcount++; -+ -+ if ((statcount % 30)==0) WaitCursor(); -+ } -+ closedir(dirp); -+ } -+ -+ SetCursors(-1); -+ -+ sprintf(tmpstr, "Update finished: %d icon%s created, %d icon%s deleted.", -+ iconsBuilt, (iconsBuilt ==1) ? "" : "s", -+ iconsKilled, (iconsKilled==1) ? "" : "s"); -+ setBrowStr(br, tmpstr); -+ -+ drawIconWin(0, &(br->scrl)); /* redraw icon window */ -+} -+ -+ -+/*******************************************/ -+static void drawTemp(br, cnt, maxcnt) -+ BROWINFO *br; -+ int cnt, maxcnt; -+{ -+ if (maxcnt<1) return; /* none of that naughty ol' divide by zero stuff */ -+ -+ 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, -+ (u_int) br->dirMB.x-10+1, (u_int) br->dirMB.h + 1, True); -+} -+ -+ -+ -+ -+/*******************************************/ -+static void doTextCmd(br) -+ BROWINFO *br; -+{ -+ int i; -+ -+ if (!br->bfLen || !br->bfList || !br->numlit) return; -+ -+ for (i=0; i<br->bfLen && !br->bfList[i].lit; i++); -+ if (i==br->bfLen) return; /* shouldn't happen */ -+ -+ if (cdBrow(br)) return; -+ TextView(br->bfList[i].name); -+} -+ -+ -+/*******************************************/ -+static void doRenameCmd(br) -+ BROWINFO *br; -+{ -+ /* called when one (and *only* one!) item is lit in the current br. -+ 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; -+ -+ 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) { -+ sprintf(buf,"Sorry, you can't rename the parent directory, %s", -+ "for semi-obvious reasons."); -+ ErrPopUp(buf, "\nRight."); -+ return; -+ } -+ -+ sprintf(txt, "Enter a new name for the %s '%s':", -+ (br->bfList[i].ftype==BF_DIR) ? "directory" : "file", -+ origname); -+ -+ strcpy(buf, origname); -+ i = GetStrPopUp(txt, labels, 2, buf, 128, "/ |\'\"<>,", 0); -+ if (i) return; /* cancelled */ -+ -+ -+ if (strcmp(origname, buf)==0) return; -+ -+ -+ /* see if the desired file exists, and attempt to do the rename if -+ it doesn't. On success, free bfList[].name, realloc with the new name, -+ and redraw that icon. If any other br's are pointed to same dir, -+ do rescan's in them */ -+ -+ /* this will also pick up mucking around with '.' and '..' */ -+ if (stat(buf, &st) == 0) { /* successful stat: new name already exists */ -+ sprintf(txt,"Sorry, a file or directory named '%s' already exists.",buf); -+ ErrPopUp(txt, "\nOh!"); -+ return; -+ } -+ -+ /* try to rename the file */ -+ if (rename(origname, buf) < 0) { -+ sprintf(txt, "Error renaming '%s' to '%s': %s", -+ origname, buf, ERRSTR(errno)); -+ ErrPopUp(txt, "\nSo what!"); -+ return; -+ } -+ -+ -+ /* try to rename it's thumbnail file, if any. Ignore errors */ -+ sprintf(txt, "%s/%s", THUMBDIR, origname); -+ sprintf(txt1, "%s/%s", THUMBDIR, buf); -+ rename(txt, txt1); -+ -+ -+ -+ free(br->bfList[num].name); -+ br->bfList[num].name = (char *) malloc(strlen(buf) + 1); -+ if (br->bfList[num].name) strcpy(br->bfList[num].name, buf); -+ else FatalError("out of memory in doRenameCmd"); -+ -+ eraseIconTitle(br, num); -+ drawIcon(br, num); -+ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (&binfo[i] != br && strcmp(binfo[i].path, br->path)==0) -+ rescanDir(&binfo[i]); -+ } -+ -+ DIRCreatedFile(br->path); -+} -+ -+ -+ -+ -+/*******************************************/ -+static void doMkdirCmd(br) -+ BROWINFO *br; -+{ -+ /* called at any time (doesn't have anything to do with current selection) -+ 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; -+ -+ if (cdBrow(br)) return; -+ -+ buf[0] = '\0'; -+ i = GetStrPopUp("Enter name for new directory:", labels, 2, -+ buf, 128, "/ |\'\"<>,", 0); -+ if (i) return; /* cancelled */ -+ -+ if (strlen(buf)==0) return; /* no name entered */ -+ -+ /* make sure they haven't tried to create '.' or '..' (can't be filtered) */ -+ /* see if the file exists already, complain and abort if it does */ -+ -+ if (strcmp(buf,".")==0 || strcmp(buf,"..")==0 || -+ stat(buf, &st)==0) { -+ sprintf(txt,"Sorry, a file or directory named '%s' already exists.",buf); -+ ErrPopUp(txt, "\nZoinks!"); -+ return; -+ } -+ -+ -+ /* if it doesn't, do the mkdir(). On success, need to do a rescan of -+ cwd, and any other br's pointing at same directory */ -+ if (mkdir(buf, 0755) < 0) { -+ sprintf(txt, "Error creating directory '%s': %s", buf, ERRSTR(errno)); -+ ErrPopUp(txt, "\nEat me!"); -+ return; -+ } -+ -+ -+ /* 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) -+ rescanDir(&binfo[i]); -+ } -+ -+ DIRCreatedFile(br->path); -+} -+ -+ -+ -+ -+ -+/*******************************************/ -+static void doChdirCmd(br) -+ BROWINFO *br; -+{ -+ int i; -+ static char buf[MAXPATHLEN+100]; -+ static char *labels[] = { "\nOk", "\033Cancel" }; -+ char str[512]; -+ -+ buf[0] = '\0'; -+ i = GetStrPopUp("Change to directory:", labels, 2, buf, MAXPATHLEN, " ", 0); -+ if (i) return; /* cancelled */ -+ -+#ifndef VMS -+ if (Globify(buf)) { /* do ~ expansion if necessary */ -+ sprintf(str,"Unable to expand '%s' (unknown uid)\n", buf); -+ setBrowStr(br, str); -+ XBell(theDisp, 50); -+ return; -+ } -+#endif -+ -+ if (buf[0] == '.') { /* chdir to relative dir */ -+ if (cdBrow(br)) return; /* prints its own error message */ -+ } -+ -+ if (chdir(buf)) { -+ sprintf(str,"Unable to cd to '%s'\n", buf); -+ setBrowStr(br, str); -+ XBell(theDisp, 50); -+ } -+ else { -+ scanDir(br); -+ SCSetVal(&(br->scrl), 0); /* reset to top on a chdir */ -+ } -+} -+ -+ -+ -+/*******************************************/ -+static void doDeleteCmd(br) -+ BROWINFO *br; -+{ -+ /* if '..' is lit, turn it off and mention that you can't delete it. -+ * -+ * count # of lit files and lit directories. Prompt with an -+ * appropriate 'Are you sure?' box -+ * -+ * if we're proceeding, delete the non-dir files, and their thumbnail -+ * buddies, if any (by calling rm_file() ) -+ * 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" }; -+ -+ if (!br->bfLen || !br->bfList || !br->numlit) return; -+ -+ if (cdBrow(br)) return; /* can't cd to this directory. screw it! */ -+ -+ if (br->bfList[0].lit && strcmp(br->bfList[0].name,"..")==0) { -+ br->numlit--; -+ br->bfList[0].lit = 0; -+ changedNumLit(br, -1, 0); -+ -+ sprintf(buf,"Sorry, but you can't delete the parent directory, %s", -+ "for semi-obvious reasons."); -+ ErrPopUp(buf, "\nRight."); -+ if (!br->numlit) { /* turned off only lit file. return */ -+ drawIcon(br, 0); -+ return; -+ } -+ } -+ -+ numdirs = numfiles = 0; firstdel = -1; -+ 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++; -+ else numfiles++; -+ } -+ } -+ -+ -+ /* if any plain files are being toasted, bring up the low-key -+ confirmation box */ -+ -+ if (numfiles) { -+ sprintf(buf,"Delete file%s: ", numfiles>1 ? "s" : ""); -+ slen = strlen(buf); -+ -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if (bf->lit && bf->ftype != BF_DIR) { -+ if ( (slen + strlen(bf->name) + 1) > 256) { -+ strcat(buf,"..."); -+ break; -+ } -+ else { -+ strcat(buf, bf->name); slen += strlen(bf->name); -+ strcat(buf, " "); slen++; -+ } -+ } -+ } -+ -+ i = PopUp(buf, yesno, 2); -+ if (i) return; /* cancelled */ -+ } -+ -+ -+ /* if any directories are being toasted, bring up the are you REALLY sure -+ confirmation box */ -+ -+ if (numdirs) { -+ sprintf(buf,"Recursively delete director%s: ", numdirs>1 ? "ies" : "y"); -+ slen = strlen(buf); -+ -+ for (i=0, bf=br->bfList; i<br->bfLen; i++,bf++) { -+ if (bf->lit && bf->ftype == BF_DIR) { -+ if ( (slen + strlen(bf->name) + 1) > 256) { -+ strcat(buf,"..."); -+ break; -+ } -+ else { -+ strcat(buf, bf->name); slen += strlen(bf->name); -+ strcat(buf, " "); slen++; -+ } -+ } -+ } -+ -+ i = PopUp(buf, yesno, 2); -+ 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); -+ else rm_file(br, bf->name); -+ } -+ } -+ -+ /* rescan br, as it's probably changed */ -+ rescanDir(br); -+ -+ /* recompute br->numlit */ -+ for (i=br->numlit=0; i<br->bfLen; i++) { -+ if (br->bfList[i].lit) br->numlit++; -+ } -+ changedNumLit(br, -1, 0); -+ -+ -+ /* if deleted a single file, select the icon that's in the same position */ -+ if (numfiles + numdirs >= 1) { -+ if (!br->bfList[firstdel].lit) { -+ br->bfList[firstdel].lit = 1; -+ br->numlit++; -+ drawIcon(br, firstdel); -+ makeIconVisible(br, firstdel); -+ changedNumLit(br, firstdel, 0); -+ } -+ } -+ -+ /* 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) -+ rescanDir(&binfo[i]); -+ } -+ -+ DIRDeletedFile(br->path); -+} -+ -+ -+ -+/*******************************************/ -+static void doSelFilesCmd(br) -+ BROWINFO *br; -+{ -+ int i; -+ static char buf[MAXPATHLEN+100]; -+ static char *labels[] = { "\nOk", "\033Cancel" }; -+ char str[512]; -+ -+ buf[0] = '\0'; -+ strcpy(str,"Select file name(s). Wildcard '*' is allowed. "); -+ strcat(str,"Previously selected files will remain selected."); -+ -+ i = GetStrPopUp(str, labels, 2, buf, MAXPATHLEN, "", 0); -+ if (i) return; /* cancelled */ -+ -+ for (i=0; i<br->bfLen; i++) { -+ if (strcmp(br->bfList[i].name, "..")==0) continue; /* skip '..' */ -+ -+ if (selmatch(br->bfList[i].name, buf)) { -+ br->bfList[i].lit = 1; -+ drawIcon(br,i); -+ } -+ } -+ -+ /* recount numlit */ -+ br->numlit = 0; -+ for (i=0; i<br->bfLen; i++) { -+ if (br->bfList[i].lit) br->numlit++; -+ } -+ changedNumLit(br, -1, 0); -+} -+ -+ -+ -+/*******************************************/ -+ -+static char *dirStack[128]; -+static int dirStackLen; -+ -+ -+/*******************************************/ -+static void doRecurseCmd(br) -+ BROWINFO *br; -+{ -+ int i; -+ static char *labels[] = { "\nOk", "\033Cancel" }; -+ char str[512]; -+ -+ strcpy(str,"Recursive Update: This could take *quite* a while.\n"); -+ strcat(str,"Are you sure?"); -+ -+ i = PopUp(str, labels, 2); -+ if (i) return; /* cancelled */ -+ -+ -+ /* initialize dirname list */ -+ dirStackLen = 0; -+ -+ cdBrow(br); -+ SCSetVal(&(br->scrl),0); -+ recurseUpdate(br, "."); -+} -+ -+ -+/*******************************************/ -+static void recurseUpdate(br, subdir) -+ BROWINFO *br; -+ char *subdir; -+{ -+ /* note: 'br->path + subdir' is the full path to recurse down from */ -+ -+ /* save current directory, so we can restore upon exit -+ * -+ * build new dest directory, cd there, get working directory (which -+ * shouldn't have symlink names in it). If this dir is in dirstack, -+ * we've looped: cd to orig dir and return -+ * otherwise: load 'br' to reflect new dir, do an Update(), -+ * 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]; -+ char curDir[MAXPATHLEN + 2]; -+ char *sp; -+ BFIL *bf; -+ -+ xv_getwd(orgDir, sizeof(orgDir)); -+ -+ sprintf(curDir, "%s%s", br->path, subdir); -+ if (chdir(curDir)) { -+ char str[512]; -+ sprintf(str, "Unable to cd to '%s'\n", curDir); -+ setBrowStr(br, str); -+ return; -+ } -+ -+ xv_getwd(curDir, sizeof(curDir)); -+ -+ /* have we looped? */ -+ for (i=0; i<dirStackLen && strcmp(curDir, dirStack[i]); i++); -+ if (i<dirStackLen) { /* YES */ -+ chdir(orgDir); -+ return; -+ } -+ -+ sp = (char *) malloc((size_t) strlen(curDir) + 1); -+ if (!sp) { -+ setBrowStr(br, "malloc() error in recurseUpdate()\n"); -+ chdir(orgDir); -+ return; -+ } -+ -+ strcpy(sp, curDir); -+ dirStack[dirStackLen++] = sp; -+ -+ if (DEBUG) { -+ fprintf(stderr,"------\n"); -+ for (i=dirStackLen-1; i>=0; i--) fprintf(stderr," %s\n", dirStack[i]); -+ fprintf(stderr,"------\n"); -+ } -+ -+ -+ /* do this directory */ -+ scanDir(br); -+ updateIcons(br); -+ -+ /* 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 && -+ strcmp(bf->name, ".") && -+ strcmp(bf->name, "..") && -+ strcmp(bf->name, THUMBDIRNAME) ) { -+ recurseUpdate(br, bf->name); -+ } -+ } -+ -+ /* remove this directory from the stack */ -+ free(dirStack[--dirStackLen]); -+ -+ xv_getwd(curDir, sizeof(curDir)); -+ if (strcmp(orgDir, curDir)) { /* change back to orgdir */ -+ chdir(orgDir); -+ scanDir(br); -+ } -+} -+ -+ -+/*******************************************/ -+static void rm_file(br, name) -+ BROWINFO *br; -+ char *name; -+{ -+ /* unlinks specified file. br only needed to display potential err msg */ -+ -+ int i; -+ char buf[512], buf1[512], *tmp; -+ -+ if (DEBUG) fprintf(stderr,"rm %s", name); -+ -+ i = unlink(name); -+ if (i) { -+ sprintf(buf, "rm %s: %s", name, ERRSTR(errno)); -+ setBrowStr(br, buf); -+ } -+ -+ /* 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); -+ -+ unlink(buf); -+} -+ -+static char rmdirPath[MAXPATHLEN+1]; -+ -+/*******************************************/ -+static void rm_dir(br, dname) -+ BROWINFO *br; -+ char *dname; -+{ -+ /* called to remove top-level dir. All subdirs are handled by rm_dir1() */ -+ -+ strcpy(rmdirPath, dname); -+ rm_dir1(br); -+} -+ -+static void rm_dir1(br) -+ BROWINFO *br; -+{ -+ /* recursively delete this directory, and all things under it */ -+ -+ int i, dirlen, longpath, oldpathlen; -+ char **names, *name, buf[512]; -+ struct stat st; -+ -+ if (DEBUG) fprintf(stderr,"rm %s\n", rmdirPath); -+ -+ longpath = 0; -+ oldpathlen = strlen(rmdirPath); -+ -+ /* delete all plain files under this directory */ -+ names = getDirEntries(rmdirPath, &dirlen, 1); -+ -+ if (names && dirlen) { -+ /* we've got the names of all files & dirs in this directory. rm the -+ non-subdirectories first */ -+ -+ for (i=0; i<dirlen; i++) { -+ name = names[i]; -+ -+ /* skip . and .. (not that we should ever see them... */ -+ if (name[0] == '.' && (name[1]=='\0' || -+ (name[1]=='.' && name[2]=='\0'))) goto done; -+ -+ if (strlen(name) + oldpathlen >= (MAXPATHLEN-3)) { -+ longpath = 1; -+ goto done; -+ } -+ -+ strcat(rmdirPath, "/"); -+ strcat(rmdirPath, name); -+ -+ if (stat(rmdirPath, &st) < 0) { -+ sprintf(buf, "%s: %s", name, ERRSTR(errno)); -+ setBrowStr(br, buf); -+ rmdirPath[oldpathlen] = '\0'; -+ goto done; -+ } -+ -+ if (stat2bf((u_int) st.st_mode) == BF_DIR) { /* skip, for now */ -+ 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; -+ } -+ -+ -+ /* rm subdirectories, the only things left in the list */ -+ for (i=0; i<dirlen; i++) { -+ if (!names[i]) continue; /* loop until next name found */ -+ name = names[i]; -+ -+ if (strlen(name) + oldpathlen >= (MAXPATHLEN-3)) { -+ longpath = 1; -+ continue; -+ } -+ -+ strcat(rmdirPath, "/"); -+ strcat(rmdirPath, name); -+ -+ rm_dir1(br); /* RECURSE! */ -+ -+ rmdirPath[oldpathlen] = '\0'; -+ } -+ -+ /* empty rest of namelist */ -+ for (i=0; i<dirlen; i++) { -+ if (names[i]) free(names[i]); -+ } -+ free(names); -+ } -+ -+ if (longpath) setBrowStr(br, "Path too long error!"); -+ -+ i = rmdir(rmdirPath); -+ if (i < 0) { -+ sprintf(buf, "rm %s: %s", rmdirPath, ERRSTR(errno)); -+ setBrowStr(br, buf); -+ } -+} -+ -+ -+ -+ -+static int overwrite; -+#define OWRT_ASK 0 -+#define OWRT_NOASK 1 -+#define OWRT_CANCEL 2 -+ -+ -+/*******************************************/ -+static void dragFiles(srcBr, dstBr, srcpath, dstpath, dstdir, -+ names, nlen, cpymode) -+ BROWINFO *srcBr, *dstBr; -+ char *srcpath, *dstpath, *dstdir, **names; -+ int nlen, cpymode; -+{ -+ /* 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; -+ char dstp[MAXPATHLEN + 1]; -+ char src[MAXPATHLEN+1], dst[MAXPATHLEN+1]; -+ char buf[128]; -+ struct stat st; -+ -+ -+ /* build real destination dir */ -+ strcpy(dstp, dstpath); -+ -+ /* note dstpath of "/" and dstdir of ".." will never happen, as there's -+ no parent folder shown when in the root directory */ -+ -+ if (strcmp(dstdir,"..")==0) { /* lop off last pathname component */ -+ for (i=strlen(dstp)-2; i>0 && dstp[i]!='/'; i--); -+ i++; -+ dstp[i] = '\0'; -+ } -+ else if (strcmp(dstdir,".")!=0) sprintf(dstp, "%s%s/", dstpath, dstdir); -+ -+ -+ -+ /* if there is a thumbnail directory in 'srcpath', make one for dstpath */ -+ sprintf(src,"%s%s", srcpath, THUMBDIR); -+ dothumbs = 0; -+ if (stat(src, &st)==0) { -+ sprintf(dst,"%s%s", dstp, THUMBDIR); -+ mkdir(dst, st.st_mode & 07777); -+ dothumbs = 1; -+ } -+ -+ -+ overwrite = OWRT_ASK; -+ -+ if (nlen>1) { -+ if (cpymode) setBrowStr(srcBr, "Copying files..."); -+ else setBrowStr(srcBr, "Moving files..."); -+ } -+ -+ for (i=fail=0; i<nlen; i++) { -+ WaitCursor(); -+ /* progress report */ -+ if (nlen>1) drawTemp(srcBr, i, nlen); -+ -+ if (strcmp(names[i], "..")==0) continue; /* don't move parent */ -+ -+ sprintf(src,"%s%s", srcpath, names[i]); -+ sprintf(dst,"%s%s", dstp, names[i]); -+ -+ if (cpymode) j = copyFile(src,dst); -+ else j = moveFile(src,dst); -+ -+ if (overwrite == OWRT_CANCEL) break; /* abort move */ -+ if (j==1) fail++; -+ -+ if (dothumbs && j==0) { -+ sprintf(src,"%s%s/%s", srcpath, THUMBDIR, names[i]); -+ sprintf(dst,"%s%s/%s", dstp, THUMBDIR, names[i]); -+ -+ /* delete destination thumbfile to avoid 'overwrite' warnings */ -+ unlink(dst); -+ -+ if (cpymode) j = copyFile(src,dst); -+ else j = moveFile(src,dst); -+ } -+ } -+ -+ if (nlen>1) clearTemp(srcBr); -+ -+ -+ /* update icon windows appropriately */ -+ for (i=0; i<MAXBRWIN; i++) { -+ if (strcmp(binfo[i].path, srcpath)==0 || -+ strcmp(binfo[i].path, dstp)==0) { -+ rescanDir(&binfo[i]); -+ } -+ } -+ -+ /* update directory window (load/save) */ -+ sprintf(src, "%sbozo", srcpath); -+ DIRDeletedFile(src); -+ sprintf(src, "%sbozo", dstp); -+ DIRCreatedFile(src); -+ -+ if (dothumbs) { -+ sprintf(src, "%s%s/bozo", srcpath, THUMBDIR); -+ DIRDeletedFile(src); -+ sprintf(src, "%s%s/bozo", dstp, THUMBDIR); -+ DIRCreatedFile(src); -+ } -+ -+ -+ /* clear all files in the destination folder */ -+ for (i=0; i<dstBr->bfLen; i++) { -+ dstBr->bfList[i].lit = 0; -+ } -+ dstBr->numlit = 0; -+ -+ -+ /* light all named files in the destination folder */ -+ for (i=0; i<nlen; i++) { -+ char *name; BFIL *bf; -+ name = names[i]; -+ 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++; -+ } -+ } -+ -+ -+ /* scroll so first lit file is visible */ -+ for (i=0; i<dstBr->bfLen && !dstBr->bfList[i].lit; i++); -+ if (i<dstBr->bfLen) makeIconVisible(dstBr, i); -+ -+ drawIconWin(0, &(dstBr->scrl)); /* redraw dst window */ -+ changedNumLit(dstBr, -1, 0); -+ -+ -+ /* adjust srcBr */ -+ for (i=srcBr->numlit=0; i<srcBr->bfLen; i++) { -+ if (srcBr->bfList[i].lit) srcBr->numlit++; -+ } -+ changedNumLit(srcBr, -1, 0); -+ -+ -+ 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, -+ (cpymode) ? "copied" : "moved"); -+ else buf[0] = '\0'; -+ setBrowStr(srcBr, buf); -+ -+ SetCursors(-1); -+} -+ -+ -+ -+/*************************************************/ -+static int moveFile(src,dst) -+ char *src, *dst; -+{ -+ /* essentially the same as the 'mv' command. src and dst are full -+ pathnames. It's semi-quiet about errors. a non-existant src file is -+ *not* considered an error (as we don't check for thumbfiles to exist -+ before calling this function). Returns '1' on error, '0' if ok. -+ Returns '-1' on 'skip this' -+ -+ 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" }; -+ -+ if (DEBUG) fprintf(stderr,"moveFile %s %s\n", src, dst); -+ -+ if (stat(src, &st)) return 0; /* src doesn't exist, it would seem */ -+ srcdir = (stat2bf((u_int) st.st_mode) == BF_DIR); -+ -+ /* see if destination exists */ -+ if (stat(dst, &st)==0) { -+ dstdir = (stat2bf((u_int) st.st_mode) == BF_DIR); -+ -+ if (overwrite==OWRT_ASK) { -+ sprintf(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; } -+ } -+ -+ 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... */ -+ SetISTR(ISTR_WARNING, "Unable to remove directory %s", dst); -+ return 1; -+ } -+#endif /* VMS */ -+ } -+ else if (unlink(dst)) { -+ SetISTR(ISTR_WARNING, "unlink %s: %s", dst, ERRSTR(errno)); -+ return 1; -+ } -+ } -+ -+ -+ if (!rename(src, dst)) return 0; /* Ok */ -+ if (errno != EXDEV) return 1; /* failure, of some sort */ -+ -+ /* We're crossing filesystem boundaries. Copy the file and rm the -+ original */ -+ -+ i = copyFile(src, dst); -+ 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); -+ return 1; -+ } -+#endif /* VMS */ -+ } -+ else if (unlink(src)) { -+ SetISTR(ISTR_WARNING, "unlink %s: %s", src, ERRSTR(errno)); -+ return 1; -+ } -+ } -+ -+ return i; -+} -+ -+ -+/* needed to recursively copy directories */ -+static int userMask, copyerr; -+static char cpSrcPath[MAXPATHLEN], cpDstPath[MAXPATHLEN]; -+ -+ -+/*************************************************/ -+static int copyFile(src,dst) -+ char *src, *dst; -+{ -+ /* src and dst are full -+ pathnames. It's semi-quiet about errors. a non-existant src file is -+ *not* considered an error (as we don't check for thumbfiles to exist -+ before calling this function). Returns '1' on error, '0' if ok. -+ -+ Will be called with full filenames of source and destination, as in: -+ src="/usr/bozo/foobie" and dst="/somewhere/else/foobie" */ -+ -+ /* 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 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 -+ fall through: if dest doesn't exist, copy the file -+ if source is a dir: -+ 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 -+ 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" }; -+ -+ if (DEBUG) fprintf(stderr,"copyFile %s %s\n", src, dst); -+ -+ 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); -+ -+ 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_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; } -+ } -+ } -+ 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; } -+ } -+ -+ -+ /* it's okay... rm the destination */ -+ if (dstdir) { -+ if (rmdir(dst)) return 1; /* failed to remove */ -+ } -+ else { -+ if (unlink(dst)) return 1; /* failed to remove */ -+ } -+ -+ dstExists = 0; -+ } -+ -+ -+ /* 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); -+ -+ copyerr = 0; -+ cp(); -+ -+ return (copyerr>0) ? 1 : 0; -+} -+ -+ -+/* The following cp() and cp_* functions are derived from the source -+ to 'cp' from the BSD sources */ -+ -+/* -+ * Copyright (c) 1988 The Regents of the University of California. -+ * All rights reserved. -+ * -+ * This code is derived from software contributed to Berkeley by -+ * David Hitz of Auspex Systems Inc. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+ -+/************************/ -+static void cp() -+/************************/ -+{ -+ /* copies 'thing' at cpSrcPath to cpDstPath. Since this function is -+ called recursively by cp_dir, there are *no* guarantees that either file -+ exists or not */ -+ -+ int i, havedst; -+ struct stat srcSt, dstSt; -+ -+ if (stat(cpSrcPath, &srcSt)) { /* src doesn't exist, usefully... */ -+ SetISTR(ISTR_WARNING, "%s: %s", cpSrcPath, ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+ -+ if (stat(cpDstPath, &dstSt)) { /* dst doesn't exist. not really a prob */ -+ havedst = 0; -+ } -+ else { -+ if (srcSt.st_dev == dstSt.st_dev && srcSt.st_ino == dstSt.st_ino) { -+ return; /* identical files: nothing to do */ -+ } -+ havedst = 1; -+ } -+ -+ -+ switch(stat2bf((u_int) srcSt.st_mode)) { -+ /* determine how to copy, by filetype */ -+ -+ /* NOTE: There is no S_IFLNK case here, since we're using 'stat()' and -+ * not lstat(). As such we'll never see symbolic links, only that which -+ * they point to -+ */ -+ -+ case BF_DIR: if (!havedst) { /* create destination directory */ -+ if (mkdir(cpDstPath, srcSt.st_mode | 0700) < 0) { -+ SetISTR(ISTR_WARNING,"%s: %s",cpDstPath,ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+ } -+ else { -+ if (stat2bf((u_int) dstSt.st_mode) != BF_DIR) { -+ 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; -+ -+ case BF_FIFO: cp_fifo(&srcSt, havedst); break; -+ -+ case BF_SOCK: SetISTR(ISTR_WARNING,"Socket file '%s' not copied.", -+ cpSrcPath); -+ copyerr++; -+ break; -+ -+ default: cp_file(&srcSt, havedst); -+ } -+ -+ return; -+} -+ -+ -+/********************/ -+static void cp_dir() -+/********************/ -+{ -+ int i, dirlen, oldsrclen, olddstlen, longpath; -+ char **names, *name; -+ struct stat srcSt, dstSt; -+ -+ -+ /* src and dst directories both exists now. copy entries */ -+ -+ if (DEBUG) fprintf(stderr,"cp_dir: src='%s', dst='%s'\n", -+ cpSrcPath, cpDstPath); -+ -+ longpath = 0; -+ oldsrclen = strlen(cpSrcPath); -+ olddstlen = strlen(cpDstPath); -+ -+ names = getDirEntries(cpSrcPath, &dirlen, 1); -+ if (!names || !dirlen) return; /* nothing to copy */ -+ -+ -+ /* now, we've got a list of entry names. Copy the non-subdirs first, for -+ performance reasons... */ -+ -+ for (i=0; i<dirlen && overwrite!=OWRT_CANCEL; i++) { -+ name = names[i]; -+ 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))) { -+ copyerr++; /* path too long */ -+ longpath = 1; -+ goto done; -+ } -+ -+ strcat(cpSrcPath, "/"); -+ strcat(cpSrcPath, name); -+ -+ if (stat(cpSrcPath, &srcSt) < 0) { -+ SetISTR(ISTR_WARNING,"%s: %s",cpSrcPath,ERRSTR(errno)); -+ copyerr++; -+ cpSrcPath[oldsrclen] = '\0'; -+ goto done; -+ } -+ -+ if (stat2bf((u_int) srcSt.st_mode) == BF_DIR) { -+ cpSrcPath[oldsrclen] = '\0'; -+ continue; /* don't remove from list, just skip */ -+ } -+ -+ strcat(cpDstPath, "/"); -+ strcat(cpDstPath, name); -+ cp(); /* RECURSE */ -+ -+ cpSrcPath[oldsrclen] = '\0'; -+ cpDstPath[olddstlen] = '\0'; -+ -+ done: /* remove name from list */ -+ free(name); -+ names[i] = (char *) NULL; -+ } -+ -+ -+ /* copy subdirectories, which are the only things left in the list */ -+ for (i=0; i<dirlen && overwrite!=OWRT_CANCEL; i++) { -+ if (!names[i]) continue; /* loop until next name found */ -+ name = names[i]; -+ -+ /* add name to src and dst paths */ -+ if ((strlen(name) + oldsrclen >= (MAXPATHLEN-3)) || -+ (strlen(name) + olddstlen >= (MAXPATHLEN-3))) { -+ copyerr++; -+ longpath = 1; -+ continue; -+ } -+ -+ strcat(cpSrcPath, "/"); -+ strcat(cpSrcPath, name); -+ -+ strcat(cpDstPath, "/"); -+ strcat(cpDstPath, name); -+ -+ cp(); /* RECURSE */ -+ -+ cpSrcPath[oldsrclen] = '\0'; -+ cpDstPath[olddstlen] = '\0'; -+ } -+ -+ /* free all memory still in use */ -+ for (i=0; i<dirlen; i++) { -+ if (names[i]) free(names[i]); -+ } -+ free(names); -+ -+ if (longpath) SetISTR(ISTR_WARNING, "Path too long error!"); -+} -+ -+ -+/*****************************/ -+static void cp_file(st, exists) -+ struct stat *st; -+ int exists; -+/*****************************/ -+{ -+ register int srcFd, dstFd, rcount, wcount, i; -+ char str[512], buf[8192]; -+ static char *owbuts[4] = { "\nOk", "dDon't Ask", "nNo", "\033Cancel" }; -+ -+ if (DEBUG) fprintf(stderr,"cp_file: src='%s', dst='%s'\n", -+ cpSrcPath, cpDstPath); -+ -+ if ((srcFd = open(cpSrcPath, O_RDONLY, 0)) == -1) { -+ SetISTR(ISTR_WARNING, "%s: %s", cpSrcPath, ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+ -+ if (exists) { -+ 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; } -+ } -+ dstFd = open(cpDstPath, O_WRONLY|O_TRUNC, 0); -+ } -+ else -+ dstFd = open(cpDstPath, O_WRONLY|O_CREAT|O_TRUNC, -+ (st->st_mode & 0777) & (~userMask)); -+ -+ if (dstFd == -1) { -+ SetISTR(ISTR_WARNING, "%s: %s", cpDstPath, ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+ -+ WaitCursor(); -+ -+ /* copy the file contents */ -+ while ((rcount = read(srcFd, buf, (size_t) 8192)) > 0) { -+ wcount = write(dstFd, buf, (size_t) rcount); -+ if (rcount != wcount || wcount == -1) { -+ SetISTR(ISTR_WARNING, "%s: %s", cpDstPath, ERRSTR(errno)); -+ copyerr++; -+ break; -+ } -+ } -+ if (rcount < 0) { -+ SetISTR(ISTR_WARNING, "%s: %s", cpSrcPath, ERRSTR(errno)); -+ copyerr++; -+ } -+ -+ close(srcFd); -+ if (close(dstFd)) { -+ SetISTR(ISTR_WARNING, "%s: %s", cpDstPath, ERRSTR(errno)); -+ copyerr++; -+ } -+} -+ -+ -+ -+/*********************************/ -+static void cp_special(st, exists) -+ struct stat *st; -+ int exists; -+/*********************************/ -+{ -+ if (DEBUG) fprintf(stderr,"cp_spec: src='%s', dst='%s'\n", -+ cpSrcPath, cpDstPath); -+ -+ if (exists && unlink(cpDstPath)) { -+ SetISTR(ISTR_WARNING, "unlink %s: %s", cpDstPath, ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+ -+#ifndef VMS /* VMS doesn't have a mknod command */ -+ if (mknod(cpDstPath, st->st_mode, st->st_rdev)) { -+ SetISTR(ISTR_WARNING, "mknod %s: %s", cpDstPath, ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+#endif -+ -+} -+ -+ -+/*********************************/ -+static void cp_fifo(st, exists) -+ struct stat *st; -+ int exists; -+/*********************************/ -+{ -+ if (DEBUG) fprintf(stderr,"cp_fifo: src='%s', dst='%s'\n", -+ cpSrcPath, cpDstPath); -+ -+#ifdef S_IFIFO -+ if (exists && unlink(cpDstPath)) { -+ SetISTR(ISTR_WARNING, "unlink %s: %s", cpDstPath, ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+ -+ if (mknod(cpDstPath, (st->st_mode & 07777) | S_IFIFO, 0)) { -+ /* was: mkfifo(cpDstPath, st->st_mode) */ -+ SetISTR(ISTR_WARNING, "mkfifo %s: %s", cpDstPath, ERRSTR(errno)); -+ copyerr++; -+ return; -+ } -+#endif -+} -+ -+ -+ -+ -+/*********************************/ -+static int stat2bf(uistmode) -+ u_int uistmode; -+{ -+ /* 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 */ -+ -+ int rv; -+ mode_t stmode = (mode_t) uistmode; -+ -+ if (S_ISDIR(stmode)) rv = BF_DIR; -+ else if (S_ISCHR(stmode)) rv = BF_CHR; -+ else if (S_ISBLK(stmode)) rv = BF_BLK; -+ else if (S_ISFIFO(stmode)) rv = BF_FIFO; -+ else if (S_ISSOCK(stmode)) rv = BF_SOCK; -+ else rv = BF_FILE; -+ -+ return rv; -+} -+ -+ -+ -+/*********************************/ -+static int selmatch(name, line) -+ char *name, *line; -+{ -+ /* returns non-zero if 'name' is found in 'line'. Line can be sequence of -+ words separated by whitespace, in which case 'name' is compared to each -+ word in the line */ -+ -+ char *arg; -+ int ch, rv; -+ -+ rv = 0; -+ -+ while (*line && !rv) { -+ while (*line && isspace(*line)) line++; /* to begin of next word */ -+ arg = line; -+ while (*line && !isspace(*line)) line++; /* end of this word */ -+ -+ ch = *line; *line = '\0'; /* null-terminate 'arg' */ -+ rv = selmatch1(name, arg); -+ *line = ch; -+ } -+ -+ return rv; -+} -+ -+ -+/*********************************/ -+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, -+ including zero. */ -+ -+ char *sp, *oldnp; -+ -+ while (*arg && *name) { -+ if (*arg != '*') { -+ if (*arg != *name) return 0; -+ arg++; name++; -+ } -+ -+ else { /* hit a '*' ... */ -+ for (sp=arg+1; *sp && *sp!='*'; sp++); /* any other '*'s in arg? */ -+ if (!*sp) { -+ /* this is the last '*'. Advance name, arg to end of their strings, -+ and match backwards until we hit the '*' character */ -+ -+ oldnp = name; -+ while (*name) name++; -+ while (*arg ) arg++; -+ name--; arg--; -+ -+ while (*arg != '*') { -+ if (*arg != *name || name<oldnp) return 0; -+ arg--; name--; -+ } -+ return 1; /* success! */ -+ } -+ -+ else { /* there are more '*'s in arg... */ -+ /* 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 '*' */ -+ sp--; /* points to char before second '*' */ -+ -+ if (arg<=sp) { /* find string arg..sp in name */ -+ int i; -+ int sslen = (sp-arg) + 1; -+ -+ while (*name) { -+ for (i=0; i<sslen && name[i] && name[i]==arg[i]; i++); -+ if (i==sslen) break; -+ else name++; -+ } -+ if (!*name) return 0; -+ -+ /* found substring in name */ -+ name += sslen; -+ arg = sp+1; -+ } -+ } -+ } -+ } -+ -+ if (!*arg && !*name) return 1; -+ -+ return 0; -+} -+ -+ -+ -diff -urN xv-3.10a/xvctrl.c xv-3.10apatched/xvctrl.c ---- xv-3.10a/xvctrl.c Thu Dec 22 14:34:41 1994 -+++ xv-3.10apatched/xvctrl.c Tue Apr 30 00:20:19 2002 -@@ -101,7 +101,8 @@ - "Root: centered, warp", - "Root: centered, brick", - "Root: symmetrical tiled", -- "Root: symmetrical mirrored" }; -+ "Root: symmetrical mirrored", -+ "Root: upper left corner" }; - - static char *conv24MList[] = { "8-bit mode\t\2448", - "24-bit mode\t\2448", -diff -urN xv-3.10a/xvdial.c xv-3.10apatched/xvdial.c ---- xv-3.10a/xvdial.c Tue Jan 3 13:20:31 1995 -+++ xv-3.10apatched/xvdial.c Tue Apr 30 00:10:16 2002 -@@ -41,20 +41,21 @@ - - - /* 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; -+int x,y,w,h; -+double minv,maxv,curv,inc,page; - unsigned long fg,bg,hi,lo; - char *title, *units; - { -@@ -98,18 +99,18 @@ - 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,8 +119,8 @@ - - /***************************************************/ - void DSetVal(dp, curv) --DIAL *dp; --int curv; -+DIAL *dp; -+double curv; - { - RANGE(curv, dp->min, dp->max); /* make sure curv is in-range */ - -@@ -129,7 +130,7 @@ - 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); -@@ -202,7 +203,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,9 +226,9 @@ - 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)(); -@@ -235,8 +237,9 @@ - } - - else { -- i = computeDialVal(dp, mx, my); -- DSetVal(dp, i); -+ double v; -+ v = computeDialVal(dp, mx, my); -+ DSetVal(dp, v); - if (dp->drawobj != NULL) (dp->drawobj)(); - } - -@@ -246,11 +249,11 @@ - 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)(); - } -@@ -266,11 +269,11 @@ - - 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; -@@ -320,19 +323,20 @@ - 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,23 +347,37 @@ - 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); - -@@ -411,12 +429,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; -@@ -436,8 +455,10 @@ - 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 -urN xv-3.10a/xvdir.c xv-3.10apatched/xvdir.c ---- xv-3.10a/xvdir.c Tue Jan 3 13:21:39 1995 -+++ xv-3.10apatched/xvdir.c Tue Apr 30 00:19:13 2002 -@@ -62,6 +62,9 @@ - #ifdef HAVE_TIFF - "TIFF", - #endif -+#ifdef HAVE_PNG -+ "PNG", -+#endif - "PostScript", - "PBM/PGM/PPM (raw)", - "PBM/PGM/PPM (ascii)", -@@ -1115,6 +1118,15 @@ - } - #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 -+ - - - -@@ -1168,7 +1180,8 @@ - - case F_XPM: - rv = WriteXPM (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, -- fullname, picComments); -+ fullname, picComments); -+ break; - case F_FITS: - rv = WriteFITS (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, - picComments); -@@ -1200,6 +1213,7 @@ - char *st; - { - strncpy(deffname, st, (size_t) MAXFNLEN-1); -+ deffname[MAXFNLEN-1] = '\0'; - setFName(st); - } - -@@ -1380,14 +1394,21 @@ - (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_TIFF - (strcmp(lowsuf,"tif" )==0) || -- (strcmp(lowsuf,"tiff")==0)) { -+ (strcmp(lowsuf,"tiff")==0) || -+#endif -+#ifdef HAVE_PNG -+ (strcmp(lowsuf,"png" )==0) || -+#endif -+ (strcmp(lowsuf,"xpm" )==0)) { - - /* found one. set lowsuf = to the new suffix, and tack on to filename */ - -@@ -1423,6 +1444,10 @@ - #ifdef HAVE_TIFF - case F_TIFF: strcpy(lowsuf,"tif"); break; - #endif -+ -+#ifdef HAVE_PNG -+ case F_PNG: strcpy(lowsuf,"png"); break; -+#endif - } - - if (allcaps) { /* upper-caseify lowsuf */ -diff -urN xv-3.10a/xvdir.c~ xv-3.10apatched/xvdir.c~ ---- xv-3.10a/xvdir.c~ Wed Dec 31 16:00:00 1969 -+++ xv-3.10apatched/xvdir.c~ Tue Apr 30 00:10:16 2002 -@@ -0,0 +1,2088 @@ -+/* -+ * xvdir.c - Directory changin', file i/o dialog box -+ * -+ * callable functions: -+ * -+ * CreateDirW(geom,bwidth)- creates the dirW window. Doesn't map it. -+ * DirBox(vis) - random processing based on value of 'vis' -+ * maps/unmaps window, etc. -+ * ClickDirW() - handles mouse clicks in DirW -+ * LoadCurrentDirectory() - loads up current dir information for dirW -+ * GetDirPath() - returns path that 'dirW' is looking at -+ * DoSave() - calls appropriate save routines -+ * SetDirFName() - sets the 'load/save-as' filename and default -+ * GetDirFName() - gets the 'load/save-as' filename (no path) -+ * SetDirSaveMode() - sets default format/color settings -+ * -+ * InitPoll() - called whenever a file is first loaded -+ * CheckPoll(int) - checks to see whether we should reload -+ */ -+ -+#include "copyright.h" -+ -+#define NEEDSTIME /* for CheckPoll */ -+#define NEEDSDIR -+#include "xv.h" -+ -+#include "bits/d_load" -+#include "bits/d_save" -+ -+#ifndef VMS -+#include <pwd.h> /* for getpwnam() prototype and passwd struct */ -+#endif -+ -+ -+#define DIRWIDE 350 /* (fixed) size of directory window */ -+#define DIRHIGH 400 -+ -+#define NLINES 15 /* # of lines in list control (keep odd) */ -+#define LISTWIDE 237 /* width of list window */ -+#define BUTTW 60 /* width of buttons */ -+#define BUTTH 24 /* height of buttons */ -+#define DDWIDE (LISTWIDE-80+15) /* max width of dirMB */ -+#define DNAMWIDE 252 /* width of 'file name' entry window */ -+#define MAXDEEP 30 /* max num of directories in cwd path */ -+#define MAXFNLEN 256 /* max len of filename being entered */ -+ -+#define FMTLABEL "Format:" /* label shown next to fmtMB */ -+#define COLLABEL "Colors:" /* label shown next to colMB */ -+#define FMTWIDE 150 /* width of fmtMB */ -+#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", -+#ifdef HAVE_JPEG -+ "JPEG", -+#endif -+#ifdef HAVE_TIFF -+ "TIFF", -+#endif -+#ifdef HAVE_PNG -+ "PNG", -+#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"}; -+ -+ -+static void arrangeButts PARM((int)); -+static void RedrawDList PARM((int, SCRL *)); -+static void changedDirMB PARM((int)); -+static int dnamcmp PARM((const void *, const void *)); -+static int FNameCdable PARM((void)); -+static void loadCWD PARM((void)); -+static int cd_able PARM((char *)); -+static void scrollToFileName PARM((void)); -+static void setFName PARM((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 *, -+ 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 Pixmap d_loadPix, d_savePix; -+ -+static int haveoldinfo = 0; -+static int oldformat, oldcolors; -+static char oldfname[MAXFNLEN+100]; -+ -+/* the name of the file actually opened. (the temp file if we are piping) */ -+static char outFName[256]; -+static int dopipe; -+ -+ -+/***************************************************/ -+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, -+ hicol, locol, RedrawDList, 1, 0); -+ -+ 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, -+ "Browse", infofg, infobg, hicol,locol); -+ -+ 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, -+ "Selected Area", infofg, infobg,hicol,locol); -+ -+ -+ /* y-coordinates get filled in when window is opened */ -+ BTCreate(&dbut[S_BOK], dirW, 259, 0, 80, BUTTH, -+ "Ok", infofg, infobg,hicol,locol); -+ BTCreate(&dbut[S_BCANC], dirW, 259, 0, 80, BUTTH, -+ "Cancel", infofg,infobg,hicol,locol); -+ BTCreate(&dbut[S_BRESCAN], dirW, 259, 0, 80, BUTTH, -+ "Rescan", infofg,infobg,hicol,locol); -+ BTCreate(&dbut[S_BOLDSET], dirW, 259, 0, 80, BUTTH, -+ "Prev Set", infofg,infobg,hicol,locol); -+ BTCreate(&dbut[S_BOLDNAM], dirW, 259, 0, 80, BUTTH, -+ "Prev Name", infofg,infobg,hicol,locol); -+ -+ SetDirFName(""); -+ XMapSubwindows(theDisp, dirW); -+ numfnames = 0; -+ -+ -+ /* -+ * create MBUTTs *after* calling XMapSubWindows() to keep popup unmapped -+ */ -+ -+ 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, -+ 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, -+ 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, -+ infofg, infobg, dispDEEP); -+ -+ d_savePix = XCreatePixmapFromBitmapData(theDisp, dirW, -+ (char *) d_save_bits, d_save_width, d_save_height, -+ infofg, infobg, dispDEEP); -+ -+} -+ -+ -+/***************************************************/ -+void DirBox(mode) -+ int mode; -+{ -+ static int firstclose = 1; -+ -+ if (!mode) { -+ if (savemode) strcpy(savepath, path); -+ else strcpy(loadpath, path); -+ -+ if (firstclose) { -+ strcpy(loadpath, path); -+ strcpy(savepath, path); -+ firstclose = 0; -+ } -+ -+ XUnmapWindow(theDisp, dirW); /* close */ -+ } -+ -+ else if (mode == BLOAD) { -+ strcpy(path, loadpath); -+ WaitCursor(); LoadCurrentDirectory(); SetCursors(-1); -+ -+ XStoreName(theDisp, dirW, "xv load"); -+ XSetIconName(theDisp, dirW, "xv load"); -+ -+ dbut[S_BLOADALL].str = "Load All"; -+ BTSetActive(&dbut[S_BLOADALL], 1); -+ -+ arrangeButts(mode); -+ -+ MBSetActive(&fmtMB, 0); -+ MBSetActive(&colMB, 0); -+ -+ CenterMapWindow(dirW, dbut[S_BOK].x+30, dbut[S_BOK].y + BUTTH/2, -+ DIRWIDE, DIRHIGH); -+ -+ savemode = 0; -+ } -+ -+ else if (mode == BSAVE) { -+ strcpy(path, savepath); -+ WaitCursor(); LoadCurrentDirectory(); SetCursors(-1); -+ -+ XStoreName(theDisp, dirW, "xv save"); -+ XSetIconName(theDisp, dirW, "xv save"); -+ -+ dbut[S_BOLDSET].str = "Prev Set"; -+ -+ arrangeButts(mode); -+ -+ BTSetActive(&dbut[S_BOLDSET], haveoldinfo); -+ BTSetActive(&dbut[S_BOLDNAM], haveoldinfo); -+ -+ CBSetActive(&saveselCB, HaveSelection()); -+ -+ MBSetActive(&fmtMB, 1); -+ if (MBWhich(&fmtMB) == F_FILELIST) { -+ MBSetActive(&colMB, 0); -+ CBSetActive(&savenormCB, 0); -+ } -+ else { -+ MBSetActive(&colMB, 1); -+ CBSetActive(&savenormCB, 1); -+ } -+ -+ CenterMapWindow(dirW, dbut[S_BOK].x+30, dbut[S_BOK].y + BUTTH/2, -+ DIRWIDE, DIRHIGH); -+ -+ savemode = 1; -+ } -+ -+ scrollToFileName(); -+ -+ dirUp = mode; -+ BTSetActive(&but[BLOAD], !dirUp); -+ BTSetActive(&but[BSAVE], !dirUp); -+} -+ -+ -+/***************************************************/ -+static void arrangeButts(mode) -+ int mode; -+{ -+ int i, nbts, ngaps, szdiff, top, gap; -+ -+ nbts = (mode==BLOAD) ? S_LOAD_NBUTTS : S_NBUTTS; -+ ngaps = nbts-1; -+ -+ szdiff = dList.h - (nbts * BUTTH); -+ gap = szdiff / ngaps; -+ -+ 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++) -+ dbut[i].y = dList.y + ((dList.h-BUTTH)*i) / ngaps; -+ } -+} -+ -+ -+ -+/***************************************************/ -+void RedrawDirW(x,y,w,h) -+ int x,y,w,h; -+{ -+ int i, ypos, txtw; -+ char foo[30], *str; -+ XRectangle xr; -+ -+ 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, -+ (u_int) DIRWIDE, (u_int) CHIGH); -+ XSetForeground(theDisp, theGC, infofg); -+ DrawString(dirW, 10, ypos, foo); -+ -+ -+ 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); -+ if (ctrlColor) { -+ XSetForeground(theDisp, theGC, locol); -+ XDrawLine(theDisp, dirW, theGC, 0, dirMB.y-5, DIRWIDE, dirMB.y-5); -+ 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); -+ -+ XSetForeground(theDisp, theGC, infofg); -+ XSetBackground(theDisp, theGC, infobg); -+ -+ txtw = StringWidth(FMTLABEL); -+ if (StringWidth(COLLABEL) > txtw) txtw = StringWidth(COLLABEL); -+ -+ if (!savemode) { -+ 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); -+ XSetStipple(theDisp, theGC, dimStip); -+ DrawString(dirW, fmtMB.x-6-txtw, 5+3+ASCENT, FMTLABEL); -+ DrawString(dirW, fmtMB.x-6-txtw, 5+3+ASCENT + (LINEHIGH+6), COLLABEL); -+ XSetFillStyle(theDisp,theGC,FillSolid); -+ -+ CBRedraw(&browseCB); -+ } -+ else { -+ XCopyArea(theDisp, d_savePix, dirW, theGC, 0,0,d_save_width,d_save_height, -+ 10, (dirMB.y-6)/2 - d_save_height/2); -+ -+ XSetForeground(theDisp, theGC, infofg); -+ DrawString(dirW, fmtMB.x-6-txtw, 5+3+ASCENT, FMTLABEL); -+ DrawString(dirW, fmtMB.x-6-txtw, 5+3+ASCENT + (LINEHIGH+6), COLLABEL); -+ -+ CBRedraw(&savenormCB); -+ CBRedraw(&saveselCB); -+ } -+} -+ -+ -+/***************************************************/ -+int ClickDirW(x,y) -+int x,y; -+{ -+ BUTT *bp; -+ int bnum,i,maxbut,v; -+ char buf[1024]; -+ -+ if (savemode) { /* check format/colors MBUTTS */ -+ 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); -+ } -+ -+ -+ maxbut = (savemode) ? S_NBUTTS : S_LOAD_NBUTTS; -+ -+ for (bnum=0; bnum<maxbut; bnum++) { -+ bp = &dbut[bnum]; -+ if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break; -+ } -+ -+ if (bnum<maxbut && BTTrack(bp)) { /* found one */ -+ if (bnum<S_BOLDSET) return bnum; /* do Ok,Cancel,Rescan in xvevent.c */ -+ -+ if (bnum == S_BOLDSET && savemode && haveoldinfo) { -+ MBSelect(&fmtMB, oldformat); -+ MBSelect(&colMB, oldcolors); -+ changeSuffix(); -+ } -+ -+ else if (bnum == S_BOLDNAM && savemode && haveoldinfo) { -+ setFName(oldfname); -+ } -+ -+ else if (bnum == S_BLOADALL && !savemode) { -+ int j, oldnumnames; -+ char *dname; -+ -+ oldnumnames = numnames; -+ -+ for (i=0; i<numfnames && numnames<MAXNAMES; i++) { -+ if (fnames[i][0] == C_REG || fnames[i][0] == C_EXE) { -+ sprintf(buf,"%s%s", path, fnames[i]+1); -+ -+ /* check for dups. Don't add it if it is. */ -+ for (j=0; j<numnames && strcmp(buf,namelist[j]); j++); -+ -+ if (j==numnames) { /* add to list */ -+ namelist[numnames] = (char *) malloc(strlen(buf)+1); -+ if (!namelist[numnames]) FatalError("out of memory!\n"); -+ strcpy(namelist[numnames],buf); -+ -+ dname = namelist[numnames]; -+ -+ /* figure out how much of name can be shown */ -+ if (StringWidth(dname) > (nList.w-10-16)) { /* truncate */ -+ char *tmp; -+ int prelen = 0; -+ -+ tmp = dname; -+ while (1) { -+ tmp = (char *) index(tmp,'/'); /* find next '/' in buf */ -+ if (!tmp) break; -+ -+ tmp++; /* move to char following the '/' */ -+ prelen = tmp - dname; -+ if (StringWidth(tmp) <= (nList.w-10-16)) break; /* cool now */ -+ } -+ -+ dispnames[numnames] = dname + prelen; -+ } -+ else dispnames[numnames] = dname; -+ -+ numnames++; -+ } -+ } -+ } -+ -+ if (oldnumnames != numnames) { /* added some */ -+ if (numnames>0) BTSetActive(&but[BDELETE],1); -+ windowMB.dim[WMB_TEXTVIEW] = (numnames==0); -+ -+ LSNewData(&nList, dispnames, numnames); -+ nList.selected = oldnumnames; -+ curname = oldnumnames - 1; -+ -+ ActivePrevNext(); -+ -+ ScrollToCurrent(&nList); -+ DrawCtrlNumFiles(); -+ -+ if (!browseCB.val) DirBox(0); -+ } -+ -+ } -+ } -+ -+ -+ -+ if (MBClick(&dirMB, x, y)) { -+ i = MBTrack(&dirMB); -+ if (i >= 0) changedDirMB(i); -+ } -+ -+ return -1; -+} -+ -+ -+/***************************************************/ -+void SelectDir(n) -+int n; -+{ -+ /* called when entry #n in the dir list was selected/double-clicked */ -+ -+ /* if n<0, nothing was double-clicked, but perhaps the selection -+ has changed. Copy the selection to the filename if a) we're in -+ the 'load' box, and b) it's not a directory name */ -+ -+ if (n<0) { -+ if (dList.selected>=0) -+ setFName(dList.str[dList.selected]+1); -+ return; -+ } -+ -+ /* can just pretend 'enter' was hit on a double click, as the original -+ click would've copied the string to filename */ -+ -+ if (!DirCheckCD()) FakeButtonPress(&dbut[S_BOK]); -+} -+ -+ -+ -+/***************************************************/ -+static void changedDirMB(sel) -+ int sel; -+{ -+ if (sel != 0) { /* changed directories */ -+ char tmppath[MAXPATHLEN+1], *trunc_point; -+ -+ /* end 'path' by changing trailing '/' (of dir name) to a '\0' */ -+ trunc_point = (dirs[(ndirs-1)-sel + 1] - 1); -+ *trunc_point = '\0'; -+ -+ if (path[0] == '\0') { -+ /* special case: if cd to '/', fix path (it's currently "") */ -+#ifdef apollo /*** Apollo DomainOS uses // as the network root ***/ -+ strcpy(tmppath,"//"); -+#else -+ strcpy(tmppath,"/"); -+#endif -+ } -+ else strcpy(tmppath, path); -+ -+#ifdef VMS -+ /* -+ * The VMS chdir always needs 2 components (device and directory), -+ * so convert "/device" to "/device/000000" and convert -+ * "/" to "/XV_Root_Device/000000" (XV_Root_Device will need to be -+ * a special concealed device setup to provide a list of available -+ * disks). -+ */ -+ 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 -+ -+ if (chdir(tmppath)) { -+ char str[512]; -+ sprintf(str,"Unable to cd to '%s'\n", tmppath); -+ *trunc_point = '/'; /* restore the path */ -+ MBRedraw(&dirMB); -+ ErrPopUp(str, "\nWhatever"); -+ } -+ else { -+ loadCWD(); -+ } -+ } -+} -+ -+ -+/***************************************************/ -+static void RedrawDList(delta, sptr) -+ int delta; -+ SCRL *sptr; -+{ -+ LSRedraw(&dList,delta); -+} -+ -+ -+/***************************************************/ -+static void loadCWD() -+{ -+ /* loads up current-working-directory into load/save list */ -+ -+ xv_getwd(path, sizeof(path)); -+ LoadCurrentDirectory(); -+} -+ -+ -+ -+/***************************************************/ -+void LoadCurrentDirectory() -+{ -+ /* rescans current load/save directory */ -+ -+ DIR *dirp; -+ int i, j, ftype, mode, changedDir; -+ struct stat st; -+ char *dbeg, *dend; -+ static char oldpath[MAXPATHLEN + 2] = { '\0' }; -+ -+#ifdef NODIRENT -+ struct direct *dp; -+#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]); -+ -+#ifndef VMS -+ if (strlen(path) == 0) xv_getwd(path, sizeof(path)); /* no dir, use cwd */ -+#else -+ xv_getwd(path, sizeof(path)); -+#endif -+ -+ if (chdir(path)) { -+ ErrPopUp("Current load/save directory seems to have gone away!", -+ "\nYikes!"); -+#ifdef apollo -+ strcpy(path,"//"); -+#else -+ strcpy(path,"/"); -+#endif -+ chdir(path); -+ } -+ -+ changedDir = strcmp(path, oldpath); -+ strcpy(oldpath, path); -+ -+ if ((strlen(path) > (size_t) 1) && path[strlen(path)-1] != '/') -+ strcat(path,"/"); /* tack on a trailing '/' to make path consistent */ -+ -+ /* path will be something like: "/u3/bradley/src/weiner/whatever/" */ -+ /* parse path into individual directory names */ -+ dbeg = dend = path; -+ for (i=0; i<MAXDEEP && dend; i++) { -+ dend = (char *) index(dbeg,'/'); /* find next '/' char */ -+ -+#ifdef apollo -+ /** On apollos the path will be something like //machine/users/foo/ **/ -+ /** handle the initial // **/ -+ if ((dend == dbeg ) && (dbeg[0] == '/') && (dbeg[1] == '/')) dend += 1; -+#endif -+ -+ dirs[i] = dbeg; -+ dbeg = dend+1; -+ } -+ ndirs = i-1; -+ -+ -+ /* 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[]"); -+ -+ strncpy(dirMBlist[j], dirs[i], stlen); -+ dirMBlist[j][stlen] = '\0'; -+ } -+ -+ -+ lastdir = dirs[ndirs-1]; -+ dirMB.list = dirMBlist; -+ dirMB.nlist = ndirs; -+ 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; -+ dirMB.w = i; -+ MBRedraw(&dirMB); -+ -+ -+ dirp = opendir("."); -+ if (!dirp) { -+ LSNewData(&dList, fnames, 0); -+ RedrawDirW(0,0,DIRWIDE,DIRHIGH); -+ return; -+ } -+ -+ WaitCursor(); -+ -+ i=0; -+ while ( (dp = readdir(dirp)) != NULL) { -+ 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 */ -+ } -+ else { -+ -+ if (i == MAXNAMES) { -+ fprintf(stderr, -+ "%s: too many directory entries. Only using first %d.\n", -+ cmd, MAXNAMES); -+ break; -+ } -+ -+ if ((i&31)==0) WaitCursor(); -+ -+ fnames[i] = (char *) malloc(strlen(dp->d_name)+2); /* +2=ftype + '\0' */ -+ -+ if (!fnames[i]) FatalError("malloc error while reading directory"); -+ strcpy(fnames[i]+1, dp->d_name); -+ -+ /* figure out what type of file the beastie is */ -+ fnames[i][0] = C_REG; /* default to normal file, if stat fails */ -+ -+#ifdef VMS -+ /* 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; -+#else -+ if (!nostat && (stat(fnames[i]+1, &st)==0)) { -+ mode = st.st_mode & 0777; /* rwx modes */ -+ -+ ftype = st.st_mode; -+ if (S_ISDIR(ftype)) fnames[i][0] = C_DIR; -+ else if (S_ISCHR(ftype)) fnames[i][0] = C_CHR; -+ else if (S_ISBLK(ftype)) fnames[i][0] = C_BLK; -+ else if (S_ISLINK(ftype)) fnames[i][0] = C_LNK; -+ 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; -+ } -+ else { -+ /* fprintf(stderr,"problems 'stat-ing' files\n");*/ -+ fnames[i][0] = C_REG; -+ } -+#endif /* VMS */ -+ -+ i++; -+ } -+ } -+ -+ closedir(dirp); -+ -+ numfnames = i; -+ -+ qsort((char *) fnames, (size_t) numfnames, sizeof(char *), dnamcmp); -+ -+ if (changedDir) LSNewData(&dList, fnames, numfnames); -+ else LSChangeData(&dList, fnames, numfnames); -+ RedrawDirW(0,0,DIRWIDE,DIRHIGH); -+ SetCursors(-1); -+} -+ -+ -+/***************************************************/ -+void GetDirPath(buf) -+ char *buf; -+{ -+ /* returns current 'dirW' path. buf should be MAXPATHLEN long */ -+ -+ strcpy(buf, path); -+} -+ -+ -+/***************************************************/ -+static int cd_able(str) -+char *str; -+{ -+ return ((str[0] == C_DIR || str[0] == C_LNK)); -+} -+ -+ -+/***************************************************/ -+static int dnamcmp(p1,p2) -+ const void *p1, *p2; -+{ -+ char **s1, **s2; -+ -+ s1 = (char **) p1; -+ s2 = (char **) p2; -+ -+#ifdef FOO -+ /* sort so that directories are at beginning of list */ -+ -+ /* if both dir/lnk or both NOT dir/lnk, sort on name */ -+ -+ if ( ( cd_able(*s1) && cd_able(*s2)) || -+ (!cd_able(*s1) && !cd_able(*s2))) -+ return (strcmp((*s1)+1, (*s2)+1)); -+ -+ else if (cd_able(*s1)) return -1; /* s1 is first */ -+ else return 1; /* s2 is first */ -+#else -+ /* sort in pure alpha order */ -+ return(strcmp((*s1)+1, (*s2)+1)); -+#endif -+} -+ -+ -+ -+ -+ -+/***************************************************/ -+int DirKey(c) -+ int c; -+{ -+ /* got keypress in dirW. stick on end of filename */ -+ int len; -+ -+ len = strlen(filename); -+ -+ if (c>=' ' && c<'\177') { /* printable characters */ -+ /* note: only allow 'piped commands' in savemode... */ -+ -+ /* only allow spaces in 'piped commands', not filenames */ -+ if (c==' ' && (!ISPIPE(filename[0]) || curPos==0)) return (-1); -+ -+ /* 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 */ -+ if (curPos==0) return(-1); /* at beginning of str */ -+ xvbcopy(&filename[curPos], &filename[curPos-1], (size_t) (len-curPos+1)); -+ curPos--; -+ -+ if (strlen(filename) > (size_t) 0) scrollToFileName(); -+ } -+ -+ else if (c=='\025') { /* ^U: clear entire line */ -+ filename[0] = '\0'; -+ curPos = 0; -+ } -+ -+ else if (c=='\013') { /* ^K: clear to end of line */ -+ filename[curPos] = '\0'; -+ } -+ -+ else if (c=='\001') { /* ^A: move to beginning */ -+ curPos = 0; -+ } -+ -+ else if (c=='\005') { /* ^E: move to end */ -+ curPos = len; -+ } -+ -+ else if (c=='\004') { /* ^D: delete character at curPos */ -+ if (curPos==len) return(-1); -+ xvbcopy(&filename[curPos+1], &filename[curPos], (size_t) (len-curPos)); -+ } -+ -+ else if (c=='\002') { /* ^B: move backwards char */ -+ if (curPos==0) return(-1); -+ curPos--; -+ } -+ -+ else if (c=='\006') { /* ^F: move forwards char */ -+ if (curPos==len) return(-1); -+ curPos++; -+ } -+ -+ else if (c=='\012' || c=='\015') { /* CR or LF */ -+ if (!DirCheckCD()) FakeButtonPress(&dbut[S_BOK]); -+ } -+ -+ else if (c=='\033') { /* ESC = Cancel */ -+ FakeButtonPress(&dbut[S_BCANC]); -+ } -+ -+ else if (c=='\011') { /* tab = filename expansion */ -+ if (!autoComplete()) XBell(theDisp, 0); -+ else { -+ curPos = strlen(filename); -+ scrollToFileName(); -+ } -+ } -+ -+ else return(-1); /* unhandled character */ -+ -+ showFName(); -+ -+ /* if we cleared out filename, clear out deffname as well */ -+ if (!filename[0]) deffname[0] = '\0'; -+ -+ return(0); -+} -+ -+ -+/***************************************************/ -+static int autoComplete() -+{ -+ /* 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, -+ 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). -+ 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 || -+ ISPIPE(filename[0]) || -+ index(filename, '/') || -+ filename[0]=='~' ) return 0; -+ -+ slen = strlen(filename); -+ for (i=0; i<dList.nstr; i++) { -+ if (strncmp(filename, dList.str[i]+1, (size_t) slen) <= 0) break; -+ } -+ if (i==dList.nstr) return 0; -+ if (strncmp(filename, dList.str[i]+1, (size_t) slen) < 0) return 0; -+ -+ /* there's a match of some sort... */ -+ firstmatch = i; -+ -+ /* count # of matches */ -+ for (i=firstmatch, nummatch=0; -+ i<dList.nstr && strncmp(filename, dList.str[i]+1, (size_t) slen)==0; -+ i++, nummatch++); -+ -+ if (nummatch == 1) { /* only one match */ -+ strcpy(filename, dList.str[firstmatch]+1); -+ return 1; -+ } -+ -+ -+ /* compute longest common prefix among the matches */ -+ 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; -+} -+ -+/***************************************************/ -+static void scrollToFileName() -+{ -+ int i, hi, lo, pos, cmp; -+ -+ /* called when 'fname' changes. Tries to scroll the directory list -+ so that fname would be centered in it */ -+ -+ /* nothing to do if scrlbar not enabled ( <= NLINES names in list) */ -+ if (dList.scrl.max <= 0) return; -+ -+ /* find the position in the namelist that the current name should be at -+ (binary search) */ -+ -+ pos = 0; lo = 0; hi = dList.nstr-1; -+ i = strlen(filename); -+ if (!i) { SCSetVal(&dList.scrl, 0); return; } -+ -+ while ((hi-lo)>=0) { -+ pos = lo + (hi-lo)/2; -+ cmp = strcmp(filename, dList.str[pos]+1); -+ if (cmp<0) hi = pos-1; -+ else if (cmp>0) lo = pos+1; -+ else break; /* found it! */ -+ } -+ -+ /* set scroll position so that 'pos' will be centered in the list */ -+ i = pos - (NLINES/2); -+ SCSetVal(&dList.scrl, i); -+} -+ -+ -+/***************************************************/ -+void RedrawDNamW() -+{ -+ int cpos; -+ -+ /* draw substring filename[stPos:enPos] and cursor */ -+ -+ Draw3dRect(dnamW, 0, 0, (u_int) DNAMWIDE+5, (u_int) LINEHIGH+4, R3D_IN, 2, -+ hicol, locol, infobg); -+ -+ XSetForeground(theDisp, theGC, infofg); -+ -+ if (stPos>0) { /* draw a "there's more over here" doowah */ -+ XDrawLine(theDisp, dnamW, theGC, 0,0,0,LINEHIGH+5); -+ XDrawLine(theDisp, dnamW, theGC, 1,0,1,LINEHIGH+5); -+ XDrawLine(theDisp, dnamW, theGC, 2,0,2,LINEHIGH+5); -+ } -+ -+ 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); -+ XDrawLine(theDisp, dnamW, theGC, DNAMWIDE+3,0,DNAMWIDE+3,LINEHIGH+5); -+ } -+ -+ XDrawString(theDisp, dnamW, theGC,3,ASCENT+3,filename+stPos, enPos-stPos); -+ -+ 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); -+ XDrawLine(theDisp, dnamW, theGC, 3+cpos, 2+CHIGH+1, 1+cpos, 2+CHIGH+3); -+} -+ -+ -+/***************************************************/ -+int DoSave() -+{ -+ FILE *fp; -+ byte *thepic, *rp, *gp, *bp; -+ int i, w, h, rv, fmt, col, nc, ptype, pfree; -+ char *fullname; -+ -+ /* opens file, does appropriate color pre-processing, calls save routine -+ based on chosen format. Returns '0' if successful */ -+ -+ dbut[S_BOK].lit = 1; BTRedraw(&dbut[S_BOK]); -+ -+ fullname = GetDirFullName(); -+ -+ fmt = MBWhich(&fmtMB); -+ col = MBWhich(&colMB); -+ -+ if (fmt<0 || col<0) -+ FatalError("xv: no 'checked' format or color. shouldn't happen!\n"); -+ -+ -+ if (fmt == F_FILELIST) { /* write filename list */ -+ fp = OpenOutFile(fullname); -+ if (!fp) { -+ SetCursors(-1); -+ 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; -+ } /* FILELIST */ -+ -+ -+ /* handle formats that pop up 'how do you want to save this' boxes */ -+ -+ -+ if (fmt == F_PS) { /* PostScript */ -+ PSSaveParams(fullname, col); -+ PSDialog(1); /* open PSDialog box */ -+ dbut[S_BOK].lit = 0; BTRedraw(&dbut[S_BOK]); -+ return 0; /* always 'succeeds' */ -+ } -+ -+#ifdef HAVE_JPEG -+ else if (fmt == F_JPEG) { /* JPEG */ -+ JPEGSaveParams(fullname, col); -+ JPEGDialog(1); /* open JPEGDialog box */ -+ dbut[S_BOK].lit = 0; BTRedraw(&dbut[S_BOK]); -+ return 0; /* always 'succeeds' */ -+ } -+#endif -+ -+#ifdef HAVE_TIFF -+ else if (fmt == F_TIFF) { /* TIFF */ -+ TIFFSaveParams(fullname, col); -+ 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 -+ -+ -+ -+ -+ WaitCursor(); -+ -+ thepic = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rp, &gp, &bp); -+ -+ fp = OpenOutFile(fullname); -+ if (!fp) { -+ if (pfree) free(thepic); -+ SetCursors(-1); -+ dbut[S_BOK].lit = 0; BTRedraw(&dbut[S_BOK]); -+ return -1; -+ } -+ -+ -+ if (col == F_REDUCED) col = F_FULLCOLOR; -+ rv = 0; -+ -+ switch (fmt) { -+ case F_GIF: -+ rv = WriteGIF (fp, thepic, ptype, w, h, rp,gp,bp, nc,col,picComments); -+ break; -+ -+ case F_PM: -+ rv = WritePM (fp, thepic, ptype, w, h, rp,gp,bp, nc,col,picComments); -+ break; -+ -+ case F_PBMRAW: -+ rv = WritePBM (fp, thepic, ptype, w, h, rp,gp,bp, nc,col,1,picComments); -+ break; -+ -+ 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; -+ -+ case F_SUNRAS: -+ 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; -+ -+ case F_IRIS: -+ 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; -+ -+ case F_XPM: -+ 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); -+ break; -+ } -+ -+ -+ if (CloseOutFile(fp, fullname, rv) == 0) { -+ DirBox(0); -+ if (!dopipe) { -+ XVCreatedFile(fullname); -+ StickInCtrlList(0); -+ } -+ } -+ -+ -+ if (pfree) free(thepic); -+ -+ SetCursors(-1); -+ dbut[S_BOK].lit = 0; BTRedraw(&dbut[S_BOK]); -+ -+ return rv; -+} -+ -+ -+ -+/***************************************************/ -+void SetDirFName(st) -+ char *st; -+{ -+ strncpy(deffname, st, (size_t) MAXFNLEN-1); -+ setFName(st); -+} -+ -+ -+/***************************************************/ -+static void setFName(st) -+ 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(); -+} -+ -+ -+/***************************************************/ -+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++; } -+ -+ /* while substring is longer than window, dec enpos, unless enpos==curpos, -+ in which case, inc stpos */ -+ -+ while (XTextWidth(mfinfo, &filename[stPos], enPos-stPos) > DNAMWIDE) { -+ if (enPos != curPos) enPos--; -+ else stPos++; -+ } -+ -+ -+ if (ctrlColor) XClearArea(theDisp, dnamW, 2,2, (u_int) DNAMWIDE+5-3, -+ (u_int) LINEHIGH+4-3, False); -+ else XClearWindow(theDisp, dnamW); -+ -+ RedrawDNamW(); -+ BTSetActive(&dbut[S_BOK], strlen(filename)!=0); -+} -+ -+ -+/***************************************************/ -+char *GetDirFName() -+{ -+ return (filename); -+} -+ -+ -+/***************************************************/ -+char *GetDirFullName() -+{ -+ static char globname[MAXFNLEN+100]; /* the +100 is for ~ expansion */ -+ static char fullname[MAXPATHLEN+2]; -+ -+ if (ISPIPE(filename[0])) strcpy(fullname, filename); -+ else { -+ strcpy(globname, filename); -+ if (globname[0] == '~') Globify(globname); -+ -+ if (globname[0] != '/') sprintf(fullname, "%s%s", path, globname); -+ else strcpy(fullname, globname); -+ } -+ -+ return (fullname); -+} -+ -+ -+/***************************************************/ -+void SetDirSaveMode(group, bnum) -+ int group, bnum; -+{ -+ if (group == F_COLORS) { -+ if (picType == PIC24) { /* disable REDUCED COLOR */ -+ colMB.dim[F_REDUCED] = 1; -+ if (MBWhich(&colMB) == F_REDUCED) MBSelect(&colMB, F_FULLCOLOR); -+ } -+ else { /* PIC8 - turn on REDUCED COLOR, if not XBM */ -+ if (MBWhich(&fmtMB) != F_XBM) { -+ colMB.dim[F_REDUCED] = 0; -+ 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 */ -+ colMB.dim[F_FULLCOLOR] = 1; -+ colMB.dim[F_GREYSCALE] = 1; -+ colMB.dim[F_BWDITHER] = 0; -+ colMB.dim[F_REDUCED] = 1; -+ MBSelect(&colMB, F_BWDITHER); -+ } -+ -+ else if (MBWhich(&fmtMB) == F_FITS) { /* turn off 'color' modes */ -+ colMB.dim[F_FULLCOLOR] = 1; -+ colMB.dim[F_GREYSCALE] = 0; -+ colMB.dim[F_BWDITHER] = 0; -+ colMB.dim[F_REDUCED] = 1; -+ MBSelect(&colMB, F_GREYSCALE); -+ } -+ -+ else { /* turn on all */ -+ colMB.dim[F_FULLCOLOR] = 0; -+ 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) -+ MBSelect(&colMB, F_FULLCOLOR); -+ } -+ -+ if (MBWhich(&fmtMB) == F_FILELIST) { -+ MBSetActive(&colMB, 0); -+ CBSetActive(&savenormCB, 0); -+ } -+ else { -+ MBSetActive(&colMB, 1); -+ CBSetActive(&savenormCB, 1); -+ } -+ } -+} -+ -+ -+ -+/***************************************/ -+static void changeSuffix() -+{ -+ /* 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 */ -+ -+ int allcaps; -+ char *suffix, *sp, *dp, lowsuf[512]; -+ -+ /* find the last '.' in the filename */ -+ suffix = (char *) rindex(filename, '.'); -+ if (!suffix) return; -+ suffix++; /* point to first letter of the suffix */ -+ -+ /* check for all-caposity */ -+ for (sp = suffix, allcaps=1; *sp; sp++) -+ if (islower(*sp)) allcaps = 0; -+ -+ /* copy the suffix into an all-lower-case buffer */ -+ for (sp=suffix, dp=lowsuf; *sp; sp++, dp++) { -+ *dp = (isupper(*sp)) ? tolower(*sp) : *sp; -+ } -+ *dp = '\0'; -+ -+ /* compare for common suffixes */ -+ if ((strcmp(lowsuf,"gif" )==0) || -+ (strcmp(lowsuf,"pm" )==0) || -+ (strcmp(lowsuf,"pbm" )==0) || -+ (strcmp(lowsuf,"pgm" )==0) || -+ (strcmp(lowsuf,"ppm" )==0) || -+ (strcmp(lowsuf,"pnm" )==0) || -+ (strcmp(lowsuf,"bm" )==0) || -+ (strcmp(lowsuf,"xbm" )==0) || -+ (strcmp(lowsuf,"ras" )==0) || -+ (strcmp(lowsuf,"bmp" )==0) || -+ (strcmp(lowsuf,"ps" )==0) || -+ (strcmp(lowsuf,"eps" )==0) || -+ (strcmp(lowsuf,"rgb" )==0) || -+ (strcmp(lowsuf,"tga" )==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_TIFF -+ (strcmp(lowsuf,"tif" )==0) || -+ (strcmp(lowsuf,"tiff")==0) || -+#endif -+#ifdef HAVE_PNG -+ (strcmp(lowsuf,"png" )==0) || -+#endif -+ (strcmp(lowsuf,"xpm" )==0)) { -+ -+ /* found one. set lowsuf = to the new suffix, and tack on to filename */ -+ -+ int fmt, col; -+ fmt = MBWhich(&fmtMB); -+ col = MBWhich(&colMB); -+ -+ if (fmt<0 || col<0) return; /* shouldn't happen */ -+ -+ switch (fmt) { -+ 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) -+ strcpy(lowsuf,"ppm"); -+ else if (col == F_GREYSCALE) strcpy(lowsuf,"pgm"); -+ else if (col == F_BWDITHER) strcpy(lowsuf,"pbm"); -+ break; -+ -+ case F_XBM: strcpy(lowsuf,"xbm"); break; -+ case F_SUNRAS: strcpy(lowsuf,"ras"); break; -+ case F_BMP: strcpy(lowsuf,"bmp"); break; -+ case F_PS: strcpy(lowsuf,"ps"); break; -+ case F_IRIS: strcpy(lowsuf,"rgb"); break; -+ case F_TARGA: strcpy(lowsuf,"tga"); break; -+ case F_XPM: strcpy(lowsuf,"xpm"); break; -+ case F_FITS: strcpy(lowsuf,"fts"); break; -+ -+#ifdef HAVE_JPEG -+ case F_JPEG: strcpy(lowsuf,"jpg"); break; -+#endif -+ -+#ifdef HAVE_TIFF -+ case F_TIFF: strcpy(lowsuf,"tif"); break; -+#endif -+ -+#ifdef HAVE_PNG -+ case F_PNG: strcpy(lowsuf,"png"); break; -+#endif -+ } -+ -+ if (allcaps) { /* upper-caseify lowsuf */ -+ for (sp=lowsuf; *sp; sp++) -+ *sp = (islower(*sp)) ? toupper(*sp) : *sp; -+ } -+ -+ /* one other case: if the original suffix started with a single -+ capital letter, make the new suffix start with a single cap */ -+ if (isupper(suffix[0])) lowsuf[0] = toupper(lowsuf[0]); -+ -+ strcpy(suffix, lowsuf); /* tack onto filename */ -+ SetDirFName(filename); -+ } -+ -+} -+ -+ -+/***************************************************/ -+int DirCheckCD() -+{ -+ /* checks if the current filename is a directory. If so, -+ cd's there, resets the filename to 'deffname', and returns '1' -+ -+ otherwise, does nothing and returns '0' */ -+ -+ if (FNameCdable()) { -+ setFName(deffname); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+ -+/***************************************************/ -+static int FNameCdable() -+{ -+ /* returns '1' if filename is a directory, and goes there */ -+ -+ char newpath[1024]; -+ struct stat st; -+ int retval = 0; -+ -+ newpath[0] = '\0'; /* start out empty */ -+ -+ if (ISPIPE(filename[0]) || strlen(filename)==0) return 0; -+ -+ if (filename[0] == '/' || filename[0] == '~') { /* absolute path */ -+ strcpy(newpath, filename); -+ } -+ else { /* not an absolute pathname */ -+ strcpy(newpath,path); -+ strcat(newpath,filename); -+ } -+ -+ if (newpath[0]=='~') { /* handle globbing */ -+ Globify(newpath); -+ } -+ -+#ifdef VMS -+ /* Convert names of form "/device.dir" to "/device/000000.DIR" */ -+ if ( rindex ( newpath, '/' ) == newpath ) { -+ strcpy ( rindex ( newpath, '.' ), "/000000.DIR" ); -+ } -+#endif -+ -+ if (stat(newpath, &st)==0) { -+ int isdir; -+ -+ isdir = S_ISDIR(st.st_mode); -+ -+ if (isdir) { -+#ifdef VMS -+ /* remove .DIR from the path so that false 000000 directories work */ -+ char *dirext; -+ dirext = rindex ( newpath, '/' ); -+ if ( dirext == NULL ) dirext = newpath; else dirext++; -+ dirext = xv_strstr ( dirext, "." ); -+ *dirext = '\0'; -+#endif -+ -+ if (chdir(newpath)==0) { -+ loadCWD(); /* success! */ -+ } -+ -+ else { -+ char str[512]; -+ -+ sprintf(str,"Can't chdir to '%s'.\n\n %s.",filename, ERRSTR(errno)); -+ ErrPopUp(str, "\nPity"); -+ } -+ retval = 1; -+ } -+ } -+ -+ return retval; -+} -+ -+ -+/**************************************************************************/ -+int Globify(fname) -+ char *fname; -+{ -+ /* expands ~s in file names. Returns the name inplace 'name'. -+ returns 0 if okay, 1 if error occurred (user name not found) */ -+ -+ struct passwd *entry; -+ char *cp, *sp, *up, uname[64], tmp[MAXFNLEN+100]; -+ -+#ifdef VMS -+ return 1; -+#else -+ if (*fname != '~') return 0; /* doesn't start with a tilde, don't expand */ -+ -+ /* look for the first '/' after the tilde */ -+ sp = (char *) index(fname,'/'); -+ if (sp == 0) { /* no '/' after the tilde */ -+ sp = fname+strlen(fname); /* sp = end of string */ -+ } -+ -+ /* uname equals the string between the ~ and the / */ -+ for (cp=fname+1,up=uname; cp<sp; *up++ = *cp++); -+ *up='\0'; -+ -+ if (*uname=='\0') { /* no name. substitute ~ with $HOME */ -+ char *homedir; -+ homedir = (char *) getenv("HOME"); -+ if (homedir == NULL) homedir = "."; -+ strcpy(tmp,homedir); -+ strcat(tmp,sp); -+ } -+ -+ else { /* get password entry for uname */ -+ entry = getpwnam(uname); -+ if (entry==0) return 1; /* name not found */ -+ strcpy(tmp,entry->pw_dir); -+ strcat(tmp,sp); -+ endpwent(); -+ } -+ -+ strcpy(fname,tmp); /* return expanded file name */ -+ return 0; -+#endif /* !VMS */ -+} -+ -+ -+ -+ -+/***************************************/ -+FILE *OpenOutFile(filename) -+ char *filename; -+{ -+ /* opens file for output. does various error handling bits. Returns -+ an open file pointer if success, NULL if failure */ -+ -+ FILE *fp; -+ struct stat st; -+ -+ if (!filename || filename[0] == '\0') return NULL; -+ strcpy(outFName, filename); -+ dopipe = 0; -+ -+ /* make sure we're in the correct directory */ -+ if (strlen(path)) chdir(path); -+ -+ 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 -+ mktemp(outFName); -+ 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]; -+ -+ sprintf(str,"Overwrite existing file '%s'?", outFName); -+ if (PopUp(str, foo, 2)) return NULL; -+ } -+ -+ -+ /* Open file */ -+ fp = 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; -+} -+ -+ -+/***************************************/ -+int CloseOutFile(fp, filename, failed) -+ FILE *fp; -+ char *filename; -+ int failed; -+{ -+ char buf[64]; -+ -+ /* close output file, and if piping, deal... Returns '0' if everything OK */ -+ -+ if (failed) { /* failure during format-specific output routine */ -+ char str[512]; -+ sprintf(str,"Couldn't write file '%s'.", outFName); -+ ErrPopUp(str, "\nBummer!"); -+ unlink(outFName); /* couldn't properly write file: delete it */ -+ 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!"); -+ return 1; -+ } -+ -+ buf[0]= '\0'; /* empty buffer */ -+ { /* compute size of written file */ -+ FILE *fp; -+ long filesize; -+ fp = fopen(outFName,"r"); -+ if (fp) { -+ fseek(fp, 0L, 2); -+ filesize = ftell(fp); -+ fclose(fp); -+ -+ sprintf(buf," (%ld bytes)", filesize); -+ } -+ } -+ -+ SetISTR(ISTR_INFO,"Successfully wrote '%s'%s", outFName, buf); -+ -+ if (dopipe) { -+ char cmd[512], str[1024]; -+ int i; -+ -+#ifndef VMS -+ sprintf(cmd, "cat %s |%s", outFName, filename+1); /* lose pipe char */ -+#else -+ sprintf(cmd, "Print /Queue = XV_Queue /Delete %s", outFName); -+#endif -+ sprintf(str,"Doing command: '%s'", cmd); -+ OpenAlert(str); -+ i = system(cmd); -+ -+#ifdef VMS -+ i = !i; -+#endif -+ -+ if (i) { -+ sprintf(str, "Unable to complete command:\n %s", cmd); -+ CloseAlert(); -+ ErrPopUp(str, "\nThat Sucks!"); -+ unlink(outFName); -+ return 1; -+ } -+ else { -+ CloseAlert(); -+ SetISTR(ISTR_INFO,"Successfully completed command."); -+#ifndef VMS -+ unlink(outFName); -+#endif -+ } -+ } -+ -+ /* save old info */ -+ haveoldinfo = 1; -+ oldformat = MBWhich(&fmtMB); -+ oldcolors = MBWhich(&colMB); -+ strcpy(oldfname, filename); -+ -+ return 0; -+} -+ -+ -+ -+ -+static byte rBW[2], gBW[2], bBW[2]; -+static byte gray[256]; -+ -+/***************************************/ -+static byte *handleBWandReduced(pic, ptype, pw, ph, color, nc, rpp, gpp, bpp) -+ byte *pic; -+ int ptype, pw, ph, color, *nc; -+ byte **rpp, **gpp, **bpp; -+{ -+ /* given 'color mode' (F_FULLCOLOR, etc.), we may have to dither -+ and/or use different colormaps. Returns 'nc', rpp, gpp, bpp (the -+ colormap to use). Also, if the function returns non-NULL, it generated -+ a new (dithered) image to use. */ -+ -+ int i; -+ byte *bwpic; -+ -+ 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 -+ 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 -+ size, no problem. Otherwise, if we're saving at original size, -+ smoothing should have no effect, so there's no reason to smooth -+ the original pic... -+ -+ In any event: in 24-bit mode, all we have to do here is determine -+ if we're saving B/W DITHERED, and deal accordingly */ -+ -+ -+ 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 ... */ -+ -+ *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, -+ make color=REDUCED, so it will be written with the correct colortable */ -+ -+ if ((epicMode == EM_DITH || epicMode == EM_SMOOTH) && color != F_REDUCED) { -+ if (color == F_FULLCOLOR) { -+ *rpp = rdisp; *gpp = gdisp; *bpp = bdisp; -+ } -+ else if (color == F_GREYSCALE) { -+ for (i=0; i<256; i++) gray[i] = MONO(rdisp[i], gdisp[i], bdisp[i]); -+ *rpp = gray; *gpp = gray; *bpp = gray; -+ } -+ } -+ -+ -+ -+ -+ if (color==F_BWDITHER || (ncols==0 && color==F_REDUCED) ) { -+ /* if we're saving as 'dithered', or we're viewing as dithered -+ and we're saving 'reduced' then generate a dithered image */ -+ -+ if (numcols==2) return NULL; /* already dithered */ -+ -+ /* generate a dithered 1-byte per pixel image */ -+ bwpic = FSDither(pic, PIC8, pw, ph, rMap,gMap,bMap, 0, 1); -+ if (!bwpic) FatalError("unable to malloc dithered picture (DoSave)"); -+ -+ /* put a BW colormap */ -+ rBW[0] = (blkRGB>>16)&0xff; rBW[1] = (whtRGB>>16)&0xff; -+ gBW[0] = (blkRGB>>8)&0xff; gBW[1] = (whtRGB>>8)&0xff; -+ bBW[0] = blkRGB&0xff; bBW[1] = whtRGB&0xff; -+ *rpp = rBW; *gpp = gBW; *bpp = bBW; -+ *nc = 2; -+ } -+ -+ return bwpic; -+} -+ -+ -+/***************************************/ -+static byte *handleNormSel(pptype, pwide, phigh, pfree) -+ int *pptype, *pwide, *phigh, *pfree; -+{ -+ /* called to return a pointer to a 'pic', its type, its width & height, -+ * 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. -+ * -+ * if selection does not intersect cpic/epic, returns cpic/epic -+ * NEVER RETURNS NULL -+ */ -+ -+ byte *thepic; -+ int pw, ph, slx, sly, slw, slh; -+ -+ *pfree = 0; *pptype = picType; -+ -+ if (savenormCB.val) { thepic = cpic; pw = cWIDE; ph = cHIGH; } -+ else { thepic = epic; pw = eWIDE; ph = eHIGH; } -+ -+ *pwide = pw; *phigh = ph; -+ -+ -+ if (saveselCB.active && saveselCB.val && HaveSelection()) { -+ GetSelRCoords(&slx, &sly, &slw, &slh); /* in 'pic' coords */ -+ -+ if (savenormCB.val) { -+ CropRect2Rect(&slx, &sly, &slw, &slh, 0,0,pWIDE,pHIGH); -+ -+ if (slw<1 || slh<1) { slx = sly = 0; slw=pWIDE; slh=pHIGH; } -+ -+ if (slx==0 && sly==0 && slw==pWIDE && slh==pHIGH) thepic = pic; -+ else { -+ thepic = XVGetSubImage(pic, *pptype, pWIDE,pHIGH, slx, sly, slw, slh); -+ *pfree = 1; -+ } -+ } -+ else { /* convert sel -> epic coords */ -+ int x1,x2,y1,y2; -+ x1 = slx; y1 = sly; -+ x2 = slx + slw; y2 = sly + slh; -+ CoordP2E(x1,y1, &x1, &y1); -+ 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) { -+ thepic = XVGetSubImage(thepic, *pptype, pw, ph, slx, sly, slw, slh); -+ *pfree = 1; -+ } -+ } -+ -+ *pwide = slw; *phigh = slh; -+ } -+ -+ return thepic; -+} -+ -+ -+/***************************************/ -+byte *GenSavePic(ptypeP, wP, hP, freeP, ncP, rmapP, gmapP, bmapP) -+ int *ptypeP, *wP, *hP, *freeP, *ncP; -+ byte **rmapP, **gmapP, **bmapP; -+{ -+ /* handles the whole ugly mess of the various save options. -+ * 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 -+ */ -+ -+ byte *pic1, *pic2; -+ int ptype, w, h, pfree; -+ -+ pic1 = handleNormSel(&ptype, &w, &h, &pfree); -+ -+ pic2 = handleBWandReduced(pic1, ptype, w,h, MBWhich(&colMB), -+ ncP, rmapP, gmapP, bmapP); -+ if (pic2) { -+ if (pfree) free(pic1); -+ pic1 = pic2; -+ pfree = 1; -+ ptype = PIC8; -+ } -+ -+ -+ if (ptype == PIC24) { -+ pic2 = GammifyPic24(pic1, w, h); -+ if (pic2) { -+ if (pfree) free(pic1); -+ pic1 = pic2; -+ pfree = 1; -+ } -+ } -+ -+ *ptypeP = ptype; *wP = w; *hP = h; *freeP = pfree; -+ -+ return pic1; -+} -+ -+ -+/***************************************/ -+void GetSaveSize(wP, hP) -+ int *wP, *hP; -+{ -+ /* returns the size (in pixels) of the save image. Takes 'normal size' -+ and 'save selection' checkboxes into account */ -+ -+ int slx,sly,slw,slh; -+ -+ if (savenormCB.val) { slw = cWIDE; slh = cHIGH; } -+ else { slw = eWIDE; slh = eHIGH; } -+ -+ if (saveselCB.active && saveselCB.val && HaveSelection()) { -+ GetSelRCoords(&slx, &sly, &slw, &slh); /* pic coord */ -+ if (savenormCB.val) { -+ CropRect2Rect(&slx, &sly, &slw, &slh, 0,0,pWIDE,pHIGH); -+ if (slw<1 || slh<1) { slx = sly = 0; slw=pWIDE; slh=pHIGH; } -+ } -+ else { /* -> epic coord */ -+ int x1,x2,y1,y2; -+ x1 = slx; y1 = sly; -+ x2 = slx + slw; y2 = sly + slh; -+ CoordP2E(x1,y1, &x1, &y1); -+ 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; } -+ } -+ } -+ -+ *wP = slw; *hP = slh; -+} -+ -+ -+ -+ -+/*************************************************************/ -+/* POLLING ROUTINES */ -+/*************************************************************/ -+ -+ -+static struct stat origStat, lastStat; -+static int haveStat = 0, haveLastStat = 0; -+static time_t lastchgtime; -+ -+/****************************/ -+void InitPoll() -+{ -+ /* called whenever a file is initially loaded. stat's the file and puts -+ the results in origStat */ -+ -+ haveStat = haveLastStat = 0; -+ lastchgtime = (time_t) 0; -+ -+ /* only do stat() if curname is a valid index, and it's not '<stdin>' */ -+ if (curname>=0 && curname<numnames && -+ (strcmp(namelist[curname], STDINSTR)!=0)) { -+ -+ 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); -+ } -+ } -+} -+ -+ -+/****************************/ -+int CheckPoll(del) -+ int del; -+{ -+ /* 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 -+ */ -+ -+ struct stat st; -+ time_t nowT; -+ -+ time(&nowT); -+ -+ if (haveStat && curname>=0 && curname<numnames && -+ (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 ((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 || -+ st.st_size != lastStat.st_size || -+ st.st_mtime != lastStat.st_mtime) { -+ xvbcopy((char *) &st, (char *) &lastStat, sizeof(struct stat)); -+ haveLastStat = 1; -+ lastchgtime = nowT; -+ return 0; -+ } -+ -+ /* if it hasn't changed in a while... */ -+ if (haveLastStat && st.st_size > 0 && (nowT - lastchgtime) > del) { -+ xvbcopy((char *) &st, (char *) &origStat, sizeof(struct stat)); -+ haveLastStat = 0; lastchgtime = 0; -+ return 1; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+ -+/***************************************************************/ -+void DIRDeletedFile(name) -+ char *name; -+{ -+ /* 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 = '\0'; /* truncate after last '/' */ -+ -+ if (strcmp(path, buf)==0) LoadCurrentDirectory(); -+} -+ -+ -+/***************************************************************/ -+void DIRCreatedFile(name) -+ char *name; -+{ -+ DIRDeletedFile(name); -+} -+ -+ -diff -urN xv-3.10a/xvevent.c xv-3.10apatched/xvevent.c ---- xv-3.10a/xvevent.c Mon Jan 23 15:20:24 1995 -+++ xv-3.10apatched/xvevent.c Tue Apr 30 00:10:16 2002 -@@ -154,7 +154,7 @@ - int *donep; - { - static int wasInfoUp=0, wasCtrlUp=0, wasDirUp=0, wasGamUp=0, wasPsUp=0; -- static int wasJpegUp=0, wasTiffUp=0; -+ static int wasJpegUp=0, wasTiffUp=0, wasPngUp=0; - - static int mainWKludge=0; /* force first mainW expose after a mainW config - to redraw all of mainW */ -@@ -233,6 +233,10 @@ - if (TIFFCheckEvent(event)) break; /* event has been processed */ - #endif - -+#ifdef HAVE_PNG -+ if (PNGCheckEvent (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 */ -@@ -359,6 +363,10 @@ - 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 == mainW) Quit(0); - } - } -@@ -538,6 +546,10 @@ - #ifdef HAVE_TIFF - if (wasTiffUp) { TIFFDialog(wasTiffUp); wasTiffUp=0; } - #endif -+ -+#ifdef HAVE_PNG -+ if (wasPngUp) { PNGDialog(wasJpegUp); wasPngUp=0; } -+#endif - } - } - } -@@ -576,6 +588,10 @@ - #ifdef HAVE_TIFF - if (tiffUp) { wasTiffUp = tiffUp; TIFFDialog(0); } - #endif -+ -+#ifdef HAVE_PNG -+ if (pngUp) { wasPngUp = pngUp; PNGDialog(0); } -+#endif - } - } - } -@@ -1147,6 +1163,10 @@ - if (TIFFCheckEvent(event)) break; - #endif - -+#ifdef HAVE_PNG -+ if (PNGCheckEvent (event)) break; -+#endif -+ - if (GamCheckEvent (event)) break; - if (BrowseCheckEvent (event, &retval, &done)) break; - if (TextCheckEvent (event, &retval, &done)) break; -@@ -1366,6 +1386,10 @@ - if (TIFFCheckEvent(event)) break; - #endif - -+#ifdef HAVE_PNG -+ if (PNGCheckEvent (event)) break; -+#endif -+ - if (GamCheckEvent (event)) break; - if (BrowseCheckEvent (event, &retval, &done)) break; - if (TextCheckEvent (event, &retval, &done)) break; -@@ -2372,6 +2396,10 @@ - if (tiffUp) TIFFDialog(0); /* close tiff window */ - #endif - -+#ifdef HAVE_PNG -+ if (pngUp) PNGDialog(0); /* close png window */ -+#endif -+ - ClosePopUp(); - - /* make the interrupt signal look like a '\n' keypress in ctrlW */ -diff -urN xv-3.10a/xvgam.c xv-3.10apatched/xvgam.c ---- xv-3.10a/xvgam.c Fri Jan 13 11:51:14 1995 -+++ xv-3.10apatched/xvgam.c Tue Apr 30 00:10:16 2002 -@@ -265,11 +265,11 @@ - 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; -@@ -359,7 +359,7 @@ - - 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", -@@ -722,7 +722,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++); -@@ -1291,14 +1291,14 @@ - 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]); - } - } - -@@ -1310,16 +1310,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; - } - } - -@@ -1561,9 +1560,9 @@ - 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 +1580,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); -@@ -1891,7 +1890,7 @@ - } - - /* 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; - -@@ -2007,7 +2006,7 @@ - - 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); -@@ -2064,8 +2063,8 @@ - changed++; - } - -- if (gs->satval != satDial.val) { -- DSetVal(&satDial,gs->satval); -+ if (gs->satval != (int)satDial.val) { -+ DSetVal(&satDial,(double)gs->satval); - changed++; - } - -@@ -3200,7 +3199,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++) { -@@ -3284,7 +3283,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; - -diff -urN xv-3.10a/xvgif.c xv-3.10apatched/xvgif.c ---- xv-3.10a/xvgif.c Tue Jan 10 11:54:41 1995 -+++ xv-3.10apatched/xvgif.c Tue Apr 30 00:19:00 2002 -@@ -113,7 +113,8 @@ - int aspect, gotimage; - - /* initialize variables */ -- BitOffset = XC = YC = Pass = OutCount = gotimage = 0; -+ BitOffset = XC = YC = OutCount = gotimage = 0; -+ Pass = -1; - RawGIF = Raster = pic8 = NULL; - gif89 = 0; - -@@ -692,7 +693,12 @@ - { - 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) -diff -urN xv-3.10a/xvgrab.c xv-3.10apatched/xvgrab.c ---- xv-3.10a/xvgrab.c Thu Dec 22 14:34:47 1994 -+++ xv-3.10apatched/xvgrab.c Tue Apr 30 00:13:18 2002 -@@ -341,16 +341,16 @@ - 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"); -diff -urN xv-3.10a/xvimage.c xv-3.10apatched/xvimage.c ---- xv-3.10a/xvimage.c Fri Jan 13 16:11:36 1995 -+++ xv-3.10apatched/xvimage.c Tue Apr 30 00:18:50 2002 -@@ -1736,10 +1736,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; -+ -+ *((unsigned char *)ip)++ = (xcol>>8) & 0xff; -+ *((unsigned char *)ip)++ = (xcol) & 0xff; - } - } - else { /* LSBFirst */ -@@ -1749,8 +1751,8 @@ - if (dithpic) xcol = ((*pp) ? white : black) & 0xffff; - else xcol = xcolors[*pp]; - -- /* WAS *ip++ = ((xcol>>8) & 0xff) | ((xcol&0xff) << 8); */ -- *ip++ = (unsigned short) (xcol); -+ *((unsigned char *)ip)++ = (xcol) & 0xff; -+ *((unsigned char *)ip)++ = (xcol>>8) & 0xff; - } - } - } -diff -urN xv-3.10a/xvjpeg.c xv-3.10apatched/xvjpeg.c ---- xv-3.10a/xvjpeg.c Thu Jan 5 00:17:13 1995 -+++ xv-3.10apatched/xvjpeg.c Tue Apr 30 00:12:38 2002 -@@ -51,11 +51,11 @@ - static void clickJD PARM((int, int)); - static void doCmd PARM((int)); - static void writeJPEG PARM((void)); --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)); -+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)); - static unsigned int j_getc PARM((j_decompress_ptr)); --METHODDEF boolean xv_process_comment PARM((j_decompress_ptr)); -+METHODDEF(boolean) xv_process_comment PARM((j_decompress_ptr)); - static int writeJFIF PARM((FILE *, byte *, int,int,int)); - - -@@ -87,10 +87,10 @@ - - 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, -@@ -400,7 +400,7 @@ - - - /**************************************************/ --METHODDEF void xv_error_exit(cinfo) -+METHODDEF(void) xv_error_exit(cinfo) - j_common_ptr cinfo; - { - my_error_ptr myerr; -@@ -412,7 +412,7 @@ - - - /**************************************************/ --METHODDEF void xv_error_output(cinfo) -+METHODDEF(void) xv_error_output(cinfo) - j_common_ptr cinfo; - { - my_error_ptr myerr; -@@ -426,7 +426,7 @@ - - - /**************************************************/ --METHODDEF void xv_prog_meter(cinfo) -+METHODDEF(void) xv_prog_meter(cinfo) - j_common_ptr cinfo; - { - struct jpeg_progress_mgr *prog; -@@ -671,7 +671,7 @@ - - - /**************************************************/ --METHODDEF boolean xv_process_comment(cinfo) -+METHODDEF(boolean) xv_process_comment(cinfo) - j_decompress_ptr cinfo; - { - int length, hasnull; -@@ -759,8 +759,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,7 +769,7 @@ - /*** 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; -diff -urN xv-3.10a/xvmisc.c xv-3.10apatched/xvmisc.c ---- xv-3.10a/xvmisc.c Fri Jan 13 15:41:34 1995 -+++ xv-3.10apatched/xvmisc.c Tue Apr 30 00:10:16 2002 -@@ -520,6 +520,10 @@ - if (tiffW) XDestroyWindow(theDisp, tiffW); - #endif - -+#ifdef HAVE_PNG -+ if (pngW) XDestroyWindow(theDisp, pngW); -+#endif -+ - /* if NOT using stdcmap for images, free stdcmap */ - if (colorMapMode != CM_STDCMAP) { - int j; -@@ -716,6 +720,10 @@ - #ifdef HAVE_TIFF - if (tiffW) XDefineCursor(theDisp, tiffW, otherc); - #endif -+ -+#ifdef HAVE_PNG -+ if (pngW) XDefineCursor(theDisp, pngW, otherc); -+#endif - } - - -diff -urN xv-3.10a/xvpng.c xv-3.10apatched/xvpng.c ---- xv-3.10a/xvpng.c Wed Dec 31 16:00:00 1969 -+++ xv-3.10apatched/xvpng.c Tue Apr 30 00:24:17 2002 -@@ -0,0 +1,965 @@ -+/* -+ * xvpng.c - load and write routines for 'PNG' format pictures -+ * -+ * callable functions -+ * -+ * CreatePNGW() -+ * PNGDialog(vis) -+ * PNGCheckEvent(xev) -+ * PNGSaveParams(fname, col) -+ * LoadPNG(fname, pinfo) -+ */ -+ -+/*#include "copyright.h"*/ -+/* (c) 1995 by Alexander Lehmann <lehmann@mathematik.th-darmstadt.de> -+ * this file is a suplement to xv and is supplied under the same copying -+ * conditions (except the shareware part) -+ * Modified by Andreas Dilger <adilger@enel.ucalgary.ca> to fix -+ * error handling for bad PNGs, add dialogs for interlacing and -+ * compression selection, and upgrade to libpng-0.89 -+ * The copyright will be passed on to JB at some future point if he -+ * so desires. -+ */ -+ -+#include "xv.h" -+ -+#ifdef HAVE_PNG -+ -+#include "png.h" -+ -+/*** Stuff for PNG Dialog box ***/ -+#define PWIDE 318 -+#define PHIGH 215 -+ -+#define DISPLAY_GAMMA 2.20 /* Default display gamma */ -+/* Default zlib compression level -+#define COMPRESSION Z_BEST_COMPRESSION -+*/ -+#define COMPRESSION 6 -+ -+#define DWIDE 86 -+#define DHIGH 104 -+#define PFX PWIDE-93 -+#define PFY 44 -+#define PFH 20 -+ -+#define P_BOK 0 -+#define P_BCANC 1 -+#define P_NBUTTS 2 -+ -+#define BUTTH 24 -+ -+/*** local functions ***/ -+static void drawPD PARM((int, int, int, int)); -+static void clickPD PARM((int, int)); -+static void doCmd PARM((int)); -+static void writePNG PARM((void)); -+static int WritePNG PARM((FILE *, byte *, int, int, int, -+ byte *, byte *, byte *, int)); -+ -+static void png_xv_error PARM((png_struct *png_ptr, char *message)); -+static void png_xv_warning PARM((png_struct *png_ptr, char *message)); -+ -+/*** local variables ***/ -+static char *filename; -+static char *fbasename; -+static int colorType; -+static int read_anything; -+static double Display_Gamma = DISPLAY_GAMMA; -+ -+static DIAL cDial, gDial; -+static BUTT pbut[P_NBUTTS]; -+static CBUTT interCB; -+static CBUTT FdefCB, FnoneCB, FsubCB, FupCB, FavgCB, FPaethCB; -+ -+/**************************************************************************/ -+/* PNG SAVE DIALOG ROUTINES ***********************************************/ -+/**************************************************************************/ -+ -+ -+/*******************************************/ -+void CreatePNGW() -+{ -+ pngW = CreateWindow("xv png", "XVPNG", NULL, -+ PWIDE, PHIGH, infofg, infobg, 0); -+ if (!pngW) FatalError("can't create PNG window!"); -+ -+ XSelectInput(theDisp, pngW, ExposureMask | ButtonPressMask | KeyPressMask); -+ -+ DCreate(&cDial, pngW, 12, 25, DWIDE, DHIGH, (double)Z_NO_COMPRESSION, -+ (double)Z_BEST_COMPRESSION, COMPRESSION, 1.0, 2.0, -+ infofg, infobg, hicol, locol, "Compression", NULL); -+ -+ DCreate(&gDial, pngW, DWIDE+27, 25, DWIDE, DHIGH, 1.0, 3.5,DISPLAY_GAMMA,0.01,0.2, -+ infofg, infobg, hicol, locol, "Disp. Gamma", NULL); -+ -+ CBCreate(&interCB, pngW, DWIDE+30, DHIGH+3*LINEHIGH+2, "interlace", -+ infofg, infobg, hicol, locol); -+ -+ CBCreate(&FdefCB, pngW, PFX, PFY, "Default", -+ infofg, infobg, hicol, locol); -+ FdefCB.val = 1; -+ -+ CBCreate(&FnoneCB, pngW, PFX, FdefCB.y + PFH + 4, "none", -+ infofg, infobg, hicol, locol); -+ CBCreate(&FsubCB, pngW, PFX, FnoneCB.y + PFH, "sub", -+ infofg, infobg, hicol, locol); -+ CBCreate(&FupCB, pngW, PFX, FsubCB.y + PFH, "up", -+ infofg, infobg, hicol, locol); -+ CBCreate(&FavgCB, pngW, PFX, FupCB.y + PFH, "average", -+ infofg, infobg, hicol, locol); -+ CBCreate(&FPaethCB, pngW, PFX, FavgCB.y + PFH, "Paeth", -+ infofg, infobg, hicol, locol); -+ -+ FnoneCB.val = FsubCB.val = FupCB.val = FavgCB.val = FPaethCB.val = 1; -+ CBSetActive(&FnoneCB, !FdefCB.val); -+ CBSetActive(&FsubCB, !FdefCB.val); -+ CBSetActive(&FupCB, !FdefCB.val); -+ CBSetActive(&FavgCB, !FdefCB.val); -+ CBSetActive(&FPaethCB, !FdefCB.val); -+ -+ BTCreate(&pbut[P_BOK], pngW, PWIDE-180-1, PHIGH-10-BUTTH-1, 80, BUTTH, -+ "Ok", infofg, infobg, hicol, locol); -+ BTCreate(&pbut[P_BCANC], pngW, PWIDE-90-1, PHIGH-10-BUTTH-1, 80, BUTTH, -+ "Cancel", infofg, infobg, hicol, locol); -+ -+ XMapSubwindows(theDisp, pngW); -+} -+ -+ -+/*******************************************/ -+void PNGDialog(vis) -+ int vis; -+{ -+ if (vis) { -+ CenterMapWindow(pngW, pbut[P_BOK].x + (int) pbut[P_BOK].w/2, -+ pbut[P_BOK].y + (int) pbut[P_BOK].h/2, -+ PWIDE, PHIGH); -+ } -+ else XUnmapWindow(theDisp, pngW); -+ pngUp = vis; -+} -+ -+ -+/*******************************************/ -+int PNGCheckEvent(xev) -+ XEvent *xev; -+{ -+ /* check event to see if it's for one of our subwindows. If it is, -+ deal accordingly, and return '1'. Otherwise, return '0' */ -+ -+ int rv; -+ rv = 1; -+ -+ if (!pngUp) return 0; -+ -+ if (xev->type == Expose) { -+ int x,y,w,h; -+ XExposeEvent *e = (XExposeEvent *) xev; -+ x = e->x; y = e->y; w = e->width; h = e->height; -+ -+ /* throw away excess expose events for 'dumb' windows */ -+ if (e->count > 0 && (e->window == cDial.win)) {} -+ -+ else if (e->window == pngW) drawPD(x, y, w, h); -+ else if (e->window == cDial.win) DRedraw(&cDial); -+ else if (e->window == gDial.win) DRedraw(&gDial); -+ else rv = 0; -+ } -+ -+ else if (xev->type == ButtonPress) { -+ XButtonEvent *e = (XButtonEvent *) xev; -+ int x,y; -+ x = e->x; y = e->y; -+ -+ if (e->button == Button1) { -+ if (e->window == pngW) clickPD(x,y); -+ else if (e->window == cDial.win) DTrack(&cDial,x,y); -+ else if (e->window == gDial.win) DTrack(&gDial,x,y); -+ else rv = 0; -+ } /* button1 */ -+ else rv = 0; -+ } /* button press */ -+ -+ else if (xev->type == KeyPress) { -+ XKeyEvent *e = (XKeyEvent *) xev; -+ char buf[128]; KeySym ks; -+ int stlen; -+ -+ stlen = XLookupString(e,buf,128,&ks,(XComposeStatus *) NULL); -+ buf[stlen] = '\0'; -+ -+ RemapKeyCheck(ks, buf, &stlen); -+ -+ if (e->window == pngW) { -+ if (stlen) { -+ if (buf[0] == '\r' || buf[0] == '\n') { /* enter */ -+ FakeButtonPress(&pbut[P_BOK]); -+ } -+ else if (buf[0] == '\033') { /* ESC */ -+ FakeButtonPress(&pbut[P_BCANC]); -+ } -+ } -+ } -+ else rv = 0; -+ } -+ else rv = 0; -+ -+ if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) { -+ XBell(theDisp, 50); -+ rv = 1; /* eat it */ -+ } -+ -+ return rv; -+} -+ -+ -+/*******************************************/ -+void PNGSaveParams(fname, col) -+ char *fname; -+ int col; -+{ -+ filename = fname; -+ colorType = col; -+} -+ -+ -+/*******************************************/ -+static void drawPD(x, y, w, h) -+ int x, y, w, h; -+{ -+ char *title = "Save PNG file..."; -+ -+ char ctitle1[20]; -+ char *ctitle2 = "Useful range"; -+ char *ctitle3 = "is 2 - 7."; -+ char *ctitle4 = "Uncompressed = 0"; -+ -+ char *ftitle = "Row Filters:"; -+ -+ char gtitle[20]; -+ -+ int i; -+ XRectangle xr; -+ -+ xr.x = x; xr.y = y; xr.width = w; xr.height = h; -+ XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted); -+ -+ XSetForeground(theDisp, theGC, infofg); -+ XSetBackground(theDisp, theGC, infobg); -+ -+ for (i=0; i<P_NBUTTS; i++) BTRedraw(&pbut[i]); -+ -+ DrawString(pngW, 15, 6+ASCENT, title); -+ -+ sprintf(ctitle1, "Default = %d", COMPRESSION); -+ DrawString(pngW, 18, 6+DHIGH+cDial.y+ASCENT, ctitle1); -+ DrawString(pngW, 17, 6+DHIGH+cDial.y+ASCENT+LINEHIGH, ctitle2); -+ DrawString(pngW, 17, 6+DHIGH+cDial.y+ASCENT+2*LINEHIGH, ctitle3); -+ DrawString(pngW, 17, 6+DHIGH+cDial.y+ASCENT+3*LINEHIGH, ctitle4); -+ -+ sprintf(gtitle, "Default = %g", DISPLAY_GAMMA); -+ DrawString(pngW, DWIDE+30, 6+DHIGH+gDial.y+ASCENT, gtitle); -+ -+ ULineString(pngW, FdefCB.x, FdefCB.y-3-DESCENT, ftitle); -+ XDrawRectangle(theDisp, pngW, theGC, FdefCB.x-11, FdefCB.y-LINEHIGH-3, -+ 93, 8*LINEHIGH+15); -+ CBRedraw(&FdefCB); -+ XDrawLine(theDisp, pngW, theGC, FdefCB.x-11, FdefCB.y+LINEHIGH+4, -+ FdefCB.x+82, FdefCB.y+LINEHIGH+4); -+ -+ CBRedraw(&FnoneCB); -+ CBRedraw(&FupCB); -+ CBRedraw(&FsubCB); -+ CBRedraw(&FavgCB); -+ CBRedraw(&FPaethCB); -+ -+ CBRedraw(&interCB); -+ -+ XSetClipMask(theDisp, theGC, None); -+} -+ -+ -+/*******************************************/ -+static void clickPD(x,y) -+ int x,y; -+{ -+ int i; -+ BUTT *bp; -+ -+ /* check BUTTs */ -+ -+ for (i=0; i<P_NBUTTS; i++) { -+ bp = &pbut[i]; -+ if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break; -+ } -+ -+ if (i<P_NBUTTS) { /* found one */ -+ if (BTTrack(bp)) doCmd(i); -+ } -+ -+ /* check CBUTTs */ -+ -+ else if (CBClick(&FdefCB,x,y)) { -+ int oldval = FdefCB.val; -+ -+ CBTrack(&FdefCB); -+ -+ if (oldval != FdefCB.val) -+ { -+ CBSetActive(&FnoneCB, !FdefCB.val); -+ CBSetActive(&FsubCB, !FdefCB.val); -+ CBSetActive(&FupCB, !FdefCB.val); -+ CBSetActive(&FavgCB, !FdefCB.val); -+ CBSetActive(&FPaethCB, !FdefCB.val); -+ -+ CBRedraw(&FnoneCB); -+ CBRedraw(&FupCB); -+ CBRedraw(&FsubCB); -+ CBRedraw(&FavgCB); -+ CBRedraw(&FPaethCB); -+ } -+ } -+ else if (CBClick(&FnoneCB,x,y)) CBTrack(&FnoneCB); -+ else if (CBClick(&FsubCB,x,y)) CBTrack(&FsubCB); -+ else if (CBClick(&FupCB,x,y)) CBTrack(&FupCB); -+ else if (CBClick(&FavgCB,x,y)) CBTrack(&FavgCB); -+ else if (CBClick(&FPaethCB,x,y)) CBTrack(&FPaethCB); -+ else if (CBClick(&interCB,x,y)) CBTrack(&interCB); -+} -+ -+ -+/*******************************************/ -+static void doCmd(cmd) -+ int cmd; -+{ -+ switch (cmd) { -+ case P_BOK: { -+ char *fullname; -+ -+ writePNG(); -+ PNGDialog(0); -+ -+ fullname = GetDirFullName(); -+ if (!ISPIPE(fullname[0])) { -+ XVCreatedFile(fullname); -+ StickInCtrlList(0); -+ } -+ } -+ break; -+ -+ case P_BCANC: PNGDialog(0); break; -+ -+ default: break; -+ } -+} -+ -+ -+/*******************************************/ -+static void writePNG() -+{ -+ FILE *fp; -+ int w, h, nc, rv, ptype, pfree; -+ byte *inpix, *rmap, *gmap, *bmap; -+ -+ fp = OpenOutFile(filename); -+ if (!fp) return; -+ -+ fbasename = BaseName(filename); -+ -+ WaitCursor(); -+ inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap); -+ -+ rv = WritePNG(fp, inpix, ptype, w, h, rmap, gmap, bmap, nc); -+ -+ SetCursors(-1); -+ -+ if (CloseOutFile(fp, filename, rv) == 0) DirBox(0); -+ -+ if (pfree) free(inpix); -+} -+ -+ -+/*******************************************/ -+int WritePNG(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols) -+ FILE *fp; -+ byte *pic; -+ int ptype, w, h; -+ byte *rmap, *gmap, *bmap; -+ int numcols; -+{ -+ png_struct *png_ptr; -+ png_info *info_ptr; -+ png_color palette[256]; -+ png_textp text; -+ byte remap[256]; -+ int i, filter, linesize = 0, pass; -+ byte *p, *png_line; -+ char software[256]; -+ char *savecmnt = NULL; -+ -+ if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, -+ png_xv_error, png_xv_warning)) == NULL) { -+ FatalError("malloc failure in WritePNG"); -+ } -+ -+ if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) -+ { -+ png_destroy_write_struct(&png_ptr, &info_ptr); -+ FatalError("malloc failure in WritePNG"); -+ } -+ -+ if (setjmp(png_ptr->jmpbuf)) { -+ png_destroy_write_struct(&png_ptr, &info_ptr); -+ return -1; -+ } -+ -+ png_init_io(png_ptr, fp); -+ -+ png_set_compression_level(png_ptr, (int)cDial.val); -+ -+ /* Don't bother filtering if we aren't compressing the image */ -+ if (FdefCB.val) -+ { -+ if ((int)cDial.val == 0) -+ png_set_filter(png_ptr, 0, PNG_FILTER_NONE); -+ } -+ else -+ { -+ filter = FnoneCB.val ? PNG_FILTER_NONE : 0; -+ filter |= FsubCB.val ? PNG_FILTER_SUB : 0; -+ filter |= FupCB.val ? PNG_FILTER_UP : 0; -+ filter |= FavgCB.val ? PNG_FILTER_AVG : 0; -+ filter |= FPaethCB.val ? PNG_FILTER_PAETH : 0; -+ -+ png_set_filter(png_ptr, 0, filter); -+ } -+ -+ info_ptr->width = w; -+ info_ptr->height = h; -+ -+ info_ptr->interlace_type = interCB.val ? 1 : 0; -+ -+ if (colorType == F_FULLCOLOR || colorType == F_REDUCED) { -+ if(ptype == PIC24) { -+ linesize = 3*w; -+ info_ptr->color_type = PNG_COLOR_TYPE_RGB; -+ info_ptr->bit_depth = 8; -+ } else { -+ linesize = w; -+ info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; -+ if(numcols <= 2) -+ info_ptr->bit_depth = 1; -+ else -+ if(numcols <= 4) -+ info_ptr->bit_depth = 2; -+ else -+ if(numcols <= 16) -+ info_ptr->bit_depth = 4; -+ else -+ info_ptr->bit_depth = 8; -+ -+ for(i = 0; i < numcols; i++) { -+ palette[i].red = rmap[i]; -+ palette[i].green = gmap[i]; -+ palette[i].blue = bmap[i]; -+ } -+ info_ptr->num_palette = numcols; -+ info_ptr->palette = palette; -+ info_ptr->valid |= PNG_INFO_PLTE; -+ } -+ } -+ -+ else if(colorType == F_GREYSCALE || colorType == F_BWDITHER) { -+ info_ptr->color_type = PNG_COLOR_TYPE_GRAY; -+ if(colorType == F_BWDITHER) { -+ /* shouldn't happen */ -+ if (ptype == PIC24) FatalError("PIC24 and B/W Stipple in WritePNG()"); -+ -+ info_ptr->bit_depth = 1; -+ if(MONO(rmap[0], gmap[0], bmap[0]) > MONO(rmap[1], gmap[1], bmap[1])) { -+ remap[0] = 1; -+ remap[1] = 0; -+ } -+ else { -+ remap[0] = 0; -+ remap[1] = 1; -+ } -+ linesize = w; -+ } -+ else { -+ if(ptype == PIC24) { -+ linesize = w*3; -+ info_ptr->bit_depth = 8; -+ } -+ else { -+ int low_presc; -+ -+ linesize = w; -+ -+ for(i = 0; i < numcols; i++) -+ remap[i] = MONO(rmap[i], gmap[i], bmap[i]); -+ -+ for(; i < 256; i++) -+ remap[i]=0; -+ -+ info_ptr->bit_depth = 8; -+ -+ /* Note that this fails most of the time because of gamma */ -+ /* try to adjust to 4 bit prescision grayscale */ -+ -+ low_presc=1; -+ -+ for(i = 0; i < numcols; i++) { -+ if((remap[i] & 0x0f) * 0x11 != remap[i]) { -+ low_presc = 0; -+ break; -+ } -+ } -+ -+ if(low_presc) { -+ for(i = 0; i < numcols; i++) { -+ remap[i] &= 0xf; -+ } -+ info_ptr->bit_depth = 4; -+ -+ /* try to adjust to 2 bit prescision grayscale */ -+ -+ for(i = 0; i < numcols; i++) { -+ if((remap[i] & 0x03) * 0x05 != remap[i]) { -+ low_presc = 0; -+ break; -+ } -+ } -+ } -+ -+ if(low_presc) { -+ for(i = 0; i < numcols; i++) { -+ remap[i] &= 3; -+ } -+ info_ptr->bit_depth = 2; -+ -+ /* try to adjust to 1 bit prescision grayscale */ -+ -+ for(i = 0; i < numcols; i++) { -+ if((remap[i] & 0x01) * 0x03 != remap[i]) { -+ low_presc = 0; -+ break; -+ } -+ } -+ } -+ -+ if(low_presc) { -+ for(i = 0; i < numcols; i++) { -+ remap[i] &= 1; -+ } -+ info_ptr->bit_depth = 1; -+ } -+ } -+ } -+ } -+ -+ else -+ png_error(png_ptr, "Unknown colorstyle in WritePNG"); -+ -+ if ((text = (png_textp)malloc(sizeof(png_text)))) { -+ sprintf(software, "XV %s", REVDATE); -+ -+ text->compression = -1; -+ text->key = "Software"; -+ text->text = software; -+ text->text_length = strlen(text->text); -+ -+ info_ptr->max_text = 1; -+ info_ptr->num_text = 1; -+ info_ptr->text = text; -+ } -+ -+ Display_Gamma = gDial.val; /* Save the current gamma for loading */ -+ -+ info_ptr->gamma = 1.0/gDial.val; -+ info_ptr->valid |= PNG_INFO_gAMA; -+ -+ png_write_info(png_ptr, info_ptr); -+ -+ if(info_ptr->bit_depth < 8) -+ png_set_packing(png_ptr); -+ -+ pass=png_set_interlace_handling(png_ptr); -+ -+ if((png_line = malloc(linesize)) == NULL) -+ png_error(png_ptr, "cannot allocate temp image line"); -+ -+ for(i = 0; i < pass; i++) { -+ int j; -+ p = pic; -+ for(j = 0; j < h; j++) { -+ fflush(stdout); -+ if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { -+ int k; -+ for(k = 0; k < w; k++) -+ png_line[k] = ptype==PIC24 ? MONO(p[k*3], p[k*3+1], p[k*3+2]) : -+ remap[p[k]]; -+ png_write_row(png_ptr, png_line); -+ } else /* rbg or palette */ -+ png_write_row(png_ptr, p); -+ if((j & 0x1f) == 0) WaitCursor(); -+ p += linesize; -+ } -+ } -+ -+ free(png_line); -+ -+ if (text) -+ { -+ if (picComments && strlen(picComments) && -+ (savecmnt = (char *)malloc((strlen(picComments) + 1)*sizeof(char)))) { -+ png_textp tp; -+ char *comment, *key; -+ -+ strcpy(savecmnt, picComments); -+ key = savecmnt; -+ tp = text; -+ info_ptr->num_text = 0; -+ -+ comment = strchr(key, ':'); -+ -+ do { -+ /* Allocate a larger structure for comments if necessary */ -+ if (info_ptr->num_text >= info_ptr->max_text) -+ { -+ if ((tp = -+ realloc(text, (info_ptr->num_text + 2)*sizeof(png_text))) == NULL) -+ { -+ break; -+ } -+ else -+ { -+ text = tp; -+ tp = &text[info_ptr->num_text]; -+ info_ptr->max_text += 2; -+ } -+ } -+ -+ /* See if it looks like a PNG keyword from LoadPNG */ -+ if(comment && comment[1] == ':' && comment - key <= 80) { -+ *(comment++) = '\0'; -+ *(comment++) = '\0'; -+ -+ /* If the comment is the 'Software' chunk XV writes, we remove it, -+ since we have already stored one */ -+ if (strcmp(key, "Software") == 0 && strncmp(comment, "XV", 2) == 0) { -+ key = strchr(comment, '\n'); -+ if(key) -+ key++; /* skip \n */ -+ comment = strchr(key, ':'); -+ } -+ /* We have another keyword and/or comment to write out */ -+ else { -+ tp->key = key; -+ tp->text = comment; -+ -+ /* We have to find the end of this comment, and the next keyword -+ if there is one */ -+ do { -+ key = comment = strchr(comment, ':'); -+ } while (key && key[1] != ':'); -+ -+ /* It looks like another keyword, go backward to the beginning */ -+ if (key) { -+ while(key > tp->text && *key != '\n') -+ key--; -+ -+ if (key > tp->text && comment - key <= 80) { -+ *key = '\0'; -+ key++; -+ } -+ } -+ -+ tp->text_length = strlen(tp->text); -+ -+ /* We don't have another keyword, so remove the last newline */ -+ if (!key && tp->text[tp->text_length - 1] == '\n') -+ { -+ tp->text[tp->text_length] = '\0'; -+ tp->text_length--; -+ } -+ -+ tp->compression = tp->text_length > 640 ? 0 : -1; -+ info_ptr->num_text++; -+ tp++; -+ } -+ } -+ /* It is just a generic comment */ -+ else { -+ tp->key = "Comment"; -+ tp->text = key; -+ tp->text_length = strlen(tp->text); -+ tp->compression = tp->text_length > 750 ? 0 : -1; -+ info_ptr->num_text++; -+ key = NULL; -+ } -+ } while (key && *key); -+ } -+ else -+ { -+ info_ptr->num_text = 0; -+ } -+ } -+ info_ptr->text = text; -+ -+ png_convert_from_time_t(&(info_ptr->mod_time), time(NULL)); -+ info_ptr->valid |= PNG_INFO_tIME; -+ -+ png_write_end(png_ptr, info_ptr); -+ png_destroy_write_struct(&png_ptr, &info_ptr); -+ -+ if (text) -+ { -+ free(text); -+ if (savecmnt) -+ free(savecmnt); -+ } -+ -+ return 0; -+} -+ -+ -+/*******************************************/ -+int LoadPNG(fname, pinfo) -+ char *fname; -+ PICINFO *pinfo; -+/*******************************************/ -+{ -+ /* returns '1' on success */ -+ -+ FILE *fp; -+ png_struct *png_ptr; -+ png_info *info_ptr; -+ png_color_16 my_background; -+ int i,j; -+ int linesize; -+ int filesize; -+ int pass; -+ size_t commentsize; -+ -+ fbasename = BaseName(fname); -+ -+ pinfo->pic = (byte *) NULL; -+ pinfo->comment = (char *) NULL; -+ -+ read_anything=0; -+ -+ /* open the file */ -+ fp = xv_fopen(fname,"r"); -+ if (!fp) -+ { -+ SetISTR(ISTR_WARNING,"%s: can't open file", fname); -+ return 0; -+ } -+ -+ /* find the size of the file */ -+ fseek(fp, 0L, 2); -+ filesize = ftell(fp); -+ fseek(fp, 0L, 0); -+ -+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, -+ png_xv_error, png_xv_warning); -+ if(!png_ptr) { -+ fclose(fp); -+ FatalError("malloc failure in LoadPNG"); -+ } -+ -+ info_ptr = png_create_info_struct(png_ptr); -+ -+ if(!info_ptr) { -+ fclose(fp); -+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); -+ FatalError("malloc failure in LoadPNG"); -+ } -+ -+ if(setjmp(png_ptr->jmpbuf)) { -+ fclose(fp); -+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); -+ if(!read_anything) { -+ if(pinfo->pic) { -+ free(pinfo->pic); -+ pinfo->pic = NULL; -+ } -+ if(pinfo->comment) { -+ free(pinfo->comment); -+ pinfo->comment = NULL; -+ } -+ } -+ return read_anything; -+ } -+ -+ png_init_io(png_ptr, fp); -+ png_read_info(png_ptr, info_ptr); -+ -+ pinfo->w = pinfo->normw = info_ptr->width; -+ pinfo->h = pinfo->normh = info_ptr->height; -+ -+ pinfo->frmType = F_PNG; -+ -+ sprintf(pinfo->fullInfo, "PNG, %d bit ", -+ info_ptr->bit_depth * info_ptr->channels); -+ -+ switch(info_ptr->color_type) { -+ case PNG_COLOR_TYPE_PALETTE: -+ strcat(pinfo->fullInfo, "palette color"); -+ break; -+ -+ case PNG_COLOR_TYPE_GRAY: -+ strcat(pinfo->fullInfo, "grayscale"); -+ break; -+ -+ case PNG_COLOR_TYPE_GRAY_ALPHA: -+ strcat(pinfo->fullInfo, "grayscale+alpha"); -+ break; -+ -+ case PNG_COLOR_TYPE_RGB: -+ strcat(pinfo->fullInfo, "truecolor"); -+ break; -+ -+ case PNG_COLOR_TYPE_RGB_ALPHA: -+ strcat(pinfo->fullInfo, "truecolor+alpha"); -+ break; -+ } -+ -+ sprintf(pinfo->fullInfo + strlen(pinfo->fullInfo), -+ ", %sinterlaced. (%d bytes)", -+ info_ptr->interlace_type ? "" : "non-", filesize); -+ -+ sprintf(pinfo->shrtInfo, "%dx%d PNG", info_ptr->width, info_ptr->height); -+ -+ if (info_ptr->bit_depth < 8) -+ png_set_packing(png_ptr); -+ -+ if (info_ptr->valid & PNG_INFO_gAMA) -+ png_set_gamma(png_ptr, Display_Gamma, info_ptr->gamma); -+ else -+ png_set_gamma(png_ptr, Display_Gamma, 0.45); -+ -+ if (info_ptr->valid & PNG_INFO_bKGD) -+ png_set_background(png_ptr, &info_ptr->background, -+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); -+ else { -+ my_background.red = my_background.green = my_background.blue = -+ my_background.gray = 0; -+ png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, -+ 0, Display_Gamma); -+ } -+ -+ if (info_ptr->bit_depth == 16) -+ png_set_strip_16(png_ptr); -+ -+ if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || -+ info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) -+ { -+ if (info_ptr->bit_depth == 1) -+ pinfo->colType = F_BWDITHER; -+ else -+ pinfo->colType = F_GREYSCALE; -+ png_set_expand(png_ptr); -+ } -+ -+ pass=png_set_interlace_handling(png_ptr); -+ -+ png_read_update_info(png_ptr, info_ptr); -+ -+ if(info_ptr->color_type == PNG_COLOR_TYPE_RGB || -+ info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { -+ linesize = pinfo->w * 3; -+ pinfo->colType = F_FULLCOLOR; -+ pinfo->type = PIC24; -+ } else { -+ linesize = pinfo->w; -+ pinfo->type = PIC8; -+ if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || -+ info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { -+ for(i = 0; i < 256; i++) -+ pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i; -+ } else { -+ pinfo->colType = F_FULLCOLOR; -+ for(i = 0; i < info_ptr->num_palette; i++) { -+ pinfo->r[i] = info_ptr->palette[i].red; -+ pinfo->g[i] = info_ptr->palette[i].green; -+ pinfo->b[i] = info_ptr->palette[i].blue; -+ } -+ } -+ } -+ pinfo->pic = calloc((size_t)(linesize*pinfo->h), (size_t)1); -+ -+ if(!pinfo->pic) { -+ png_error(png_ptr, "can't allocate space for PNG image"); -+ } -+ -+ png_start_read_image(png_ptr); -+ -+ for(i = 0; i < pass; i++) { -+ byte *p = pinfo->pic; -+ for(j = 0; j < pinfo->h; j++) { -+ png_read_row(png_ptr, p, NULL); -+ read_anything = 1; -+ if((j & 0x1f) == 0) WaitCursor(); -+ p += linesize; -+ } -+ } -+ -+ png_read_end(png_ptr, info_ptr); -+ -+ if(info_ptr->num_text > 0) { -+ commentsize = 1; -+ -+ for(i = 0; i < info_ptr->num_text; i++) -+ commentsize += strlen(info_ptr->text[i].key) + 1 + -+ info_ptr->text[i].text_length + 2; -+ -+ if((pinfo->comment = malloc(commentsize)) == NULL) { -+ png_warning(png_ptr,"can't allocate comment string"); -+ } -+ else { -+ pinfo->comment[0] = '\0'; -+ for(i = 0; i < info_ptr->num_text; i++) { -+ strcat(pinfo->comment, info_ptr->text[i].key); -+ strcat(pinfo->comment, "::"); -+ strcat(pinfo->comment, info_ptr->text[i].text); -+ strcat(pinfo->comment, "\n"); -+ } -+ } -+ } -+ -+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); -+ -+ fclose(fp); -+ -+ return 1; -+} -+ -+ -+/*******************************************/ -+static void -+png_xv_error(png_ptr, message) -+ png_struct *png_ptr; -+ char *message; -+{ -+ SetISTR(ISTR_WARNING,"%s: libpng error: %s", fbasename, message); -+ -+ longjmp(png_ptr->jmpbuf, 1); -+} -+ -+ -+/*******************************************/ -+static void -+png_xv_warning(png_ptr, message) -+ png_struct *png_ptr; -+ char *message; -+{ -+ if (!png_ptr) -+ return; -+ -+ SetISTR(ISTR_WARNING,"%s: libpng warning: %s", fbasename, message); -+} -+ -+#endif -diff -urN xv-3.10a/xvpopup.c xv-3.10apatched/xvpopup.c ---- xv-3.10a/xvpopup.c Thu Jan 19 10:09:31 1995 -+++ xv-3.10apatched/xvpopup.c Tue Apr 30 00:19:13 2002 -@@ -200,14 +200,14 @@ - - 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, -@@ -258,9 +258,9 @@ - else if (poptyp == ISPAD) { - BTSetActive(&bts[0], (int) strlen(gsBuf)); - i = pWIDE * 3; RANGE(i,2048,9999); -- DSetRange(&padWDial, 1, i, padWDial.val, 10); -+ DSetRange(&padWDial, 1.0, (double)i, padWDial.val, 1.0, 10.0); - i = pHIGH * 3; RANGE(i,2048,9999); -- DSetRange(&padHDial, 1, i, padHDial.val, 10); -+ 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)); -@@ -465,9 +465,9 @@ - changedGSBuf(); /* careful! popW doesn't exist yet! */ - - if (padHaveDooDads) { -- oldW = padWDial.val; -- oldH = padHDial.val; -- oldO = padODial.val; -+ oldW = (int)padWDial.val; -+ oldH = (int)padHDial.val; -+ oldO = (int)padODial.val; - } - else { oldW = pWIDE; oldH = pHIGH; oldO = 100; } - -@@ -486,9 +486,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); -@@ -498,9 +498,9 @@ - /* load up return values */ - *pMode = padMode; - *pStr = padBuf; -- *pWide = padWDial.val; -- *pHigh = padHDial.val; -- *pOpaque = padODial.val; -+ *pWide = (int)padWDial.val; -+ *pHigh = (int)padHDial.val; -+ *pOpaque = (int)padODial.val; - *pOmode = padOMode; - - return rv; -@@ -560,6 +560,7 @@ - nams[*lenp] = (char *) malloc((size_t) 32); - if (!nams[*lenp]) { free(vals[*lenp]); continue; } - strncpy(nams[*lenp], vals[*lenp], (size_t) 31); -+ nams[*lenp][31] = '\0'; - } - - if (strlen(nams[*lenp]) > (size_t) 20) { /* fix long names */ -@@ -972,8 +973,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); - } - } - -diff -urN xv-3.10a/xvps.c xv-3.10apatched/xvps.c ---- xv-3.10a/xvps.c Thu Dec 22 14:34:42 1994 -+++ xv-3.10apatched/xvps.c Tue Apr 30 00:20:13 2002 -@@ -139,9 +139,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; -@@ -236,10 +236,10 @@ - - 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); - } - } - -@@ -836,7 +836,7 @@ - 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); -@@ -1564,7 +1564,7 @@ - /* build command string */ - - #ifndef VMS /* VMS needs quotes around mixed case command lines */ -- sprintf(tmp, "%s -sDEVICE=%s -r%d -q -dNOPAUSE -sOutputFile=%s%%d ", -+ sprintf(tmp, "%s -sDEVICE=%s -r%d -q -dSAFER -dNOPAUSE -sOutputFile=%s%%d ", - GS_PATH, gsDev, gsRes, tmpname); - #else - sprintf(tmp, -@@ -1577,11 +1577,20 @@ - # ifndef VMS - sprintf(tmp1, "-I%s ", GS_LIB); - # else -- sprintf(tmp1, "\"-I%s\"", GS_LIB); -+ sprintf(tmp1, "\"-I%s\" ", GS_LIB); - # endif - strcat(tmp, tmp1); - #endif - -+ -+ /* prevent some potential naughtiness... */ -+#ifndef VMS -+ strcat(tmp, "-dSAFER "); -+#else -+ strcat(tmp, "\"-dSAFER\" "); -+#endif -+ -+ - if (gsGeomStr) { - sprintf(tmp1, "-g%s ", gsGeomStr); - strcat(tmp, tmp1); -diff -urN xv-3.10a/xvroot.c xv-3.10apatched/xvroot.c ---- xv-3.10a/xvroot.c Thu Dec 22 14:34:42 1994 -+++ xv-3.10apatched/xvroot.c Tue Apr 30 00:20:19 2002 -@@ -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; - -@@ -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) { -@@ -138,6 +139,12 @@ - - 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) -@@ -157,7 +164,7 @@ - - - /* draw the image centered on top of the background */ -- if (rmode != RM_CENTILE) -+ 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); -diff -urN xv-3.10a/xvtext.c xv-3.10apatched/xvtext.c ---- xv-3.10a/xvtext.c Fri Jan 13 15:46:28 1995 -+++ xv-3.10apatched/xvtext.c Tue Apr 30 00:19:13 2002 -@@ -293,6 +293,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 */ - -diff -urN xv-3.10a/xvtiff.c xv-3.10apatched/xvtiff.c ---- xv-3.10a/xvtiff.c Fri Jan 13 11:53:34 1995 -+++ xv-3.10apatched/xvtiff.c Tue Apr 30 00:20:00 2002 -@@ -301,6 +301,10 @@ - static byte **BWmap; - static byte **PALmap; - -+/* XXXX 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)); - -@@ -340,7 +344,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 *, -@@ -1218,7 +1222,7 @@ - */ - 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; -@@ -1227,8 +1231,7 @@ - - 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; -@@ -1514,7 +1517,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; |