diff -urN xv-3.10a/Imakefile xv-3.10a-jp-extension-current/Imakefile --- xv-3.10a/Imakefile Sat Jan 14 05:24:01 1995 +++ xv-3.10a-jp-extension-current/Imakefile Wed Oct 9 20:36:29 1996 @@ -104,11 +104,16 @@ SGI = -Dsgi #endif +/* install directory of xv_mgcsfx.sample. */ +MGCSFXDIR = $(LIBDIR) +/* Directory of default configuration file. */ +MGCSFX = -DMGCSFXDIR=\"$(MGCSFXDIR)\" + /* This marks the end of the configuration parameters */ @@ -137,6 +142,8 @@ #if defined(SCOArchitecture) SCO= -Dsco -DPOSIX -DNO_RANDOM SYS_LIBRARIES= -lm -lc -lx +#elif defined(HPArchitecture) +SYS_LIBRARIES= -lm -lV3 #else SYS_LIBRARIES= -lm #endif @@ -147,7 +154,7 @@ DEFINES= $(SCO) $(UNIX) $(NODIRENT) $(VPRINTF) $(TIMERS) \ $(HPUX7) $(JPEG) $(TIFF) $(PDS) $(DXWM) $(RAND) \ - $(BACKING_STORE) $(BSDTYPES) $(SGI) + $(BACKING_STORE) $(BSDTYPES) $(SGI) $(MGCSFX) INCLUDES = $(JPEGINCLUDE) $(TIFFINCLUDE) @@ -157,7 +164,9 @@ xvdial.c xvgraf.c xvsunras.c xvjpeg.c xvps.c xvpopup.c xvdflt.c \ xvtiff.c xvtiffwr.c xvpds.c xvrle.c xviris.c xvgrab.c vprintf.c \ xvbrowse.c xvtext.c xvpcx.c xviff.c xvtarga.c xvxpm.c xvcut.c \ - xvxwd.c xvfits.c + xvxwd.c xvfits.c \ + xvmag.c xvpic.c xvmaki.c xvpi.c xvpic2.c xvpcd.c xvvd.c xvmgcsfx.c \ + xvml.c OBJS1 = xv.o xvevent.o xvroot.o xvmisc.o xvimage.o xvcolor.o xvsmooth.o \ xv24to8.o xvgif.o xvpm.o xvinfo.o xvctrl.o xvscrl.o xvalg.o \ @@ -165,7 +174,9 @@ xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \ xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \ xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \ - xvxwd.o xvfits.o + xvxwd.o xvfits.o \ + xvmag.o xvpic.o xvmaki.o xvpi.o xvpic2.o xvpcd.o xvvd.o xvmgcsfx.o \ + xvml.o SRCS2= bggen.c OBJS2= bggen.o @@ -266,6 +277,8 @@ InstallManPageLong(docs/xvp2p,$(MANDIR),xvpictoppm) InstallManPageLong(docs/vdcomp,$(MANDIR),vdcomp) +InstallNonExecFile(xv_mgcsfx.sample,$(MGCSFXDIR)) + tar: tar cf xv.tar Makefile* Imakefile *.c *.h bits docs \ docs unsupt vms $(JPEGDIR) $(TIFFDIR) $(MISC) diff -urN xv-3.10a/Makefile xv-3.10a-jp-extension-current/Makefile --- xv-3.10a/Makefile Tue Jan 24 05:20:54 1995 +++ xv-3.10a-jp-extension-current/Makefile Wed Oct 9 20:36:23 1996 @@ -78,10 +78,12 @@ #----------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 +# Sikarusm etc, uncomment one of the following lines to get you *most* of +# the way there. SYSV means System V R3. +# UNIX = -DSVR4 +# UNIX = -DSYSV + - #----------Machine Specific Configurations---------- ### If you are using an SGI system, uncomment the following line @@ -99,6 +101,9 @@ # note: You may need to add '-I/usr/include/X11R5' (or R6, or whatever) # to whichever of those lines you used, as HP tends to store their X11 # include files in a non-standard place... +# +# And, you probably have to add '-lV3' to the end of the LIBS def, +# when use AUTO_EXPAND feauture. ### for LINUX, uncomment the following line @@ -177,6 +182,16 @@ #VPRINTF = -DNEED_VPRINTF -DLONGINT -DNOSTDHDRS +# if your X Window System compiled with -DX_LOCALE, +# uncomment the following line: +# TVL10N = -DX_LOCALE + +# Install directory of xv_mgcsfx.sample. +MGCSFXDIR = $(LIBDIR) +# Directory of default configuration file. +MGCSFX = -DMGCSFXDIR=\"$(MGCSFXDIR)\" + + ################ END OF CONFIGURATION OPTIONS ################# @@ -186,7 +201,7 @@ CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \ $(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \ - $(DXWM) $(MCHN) + $(DXWM) $(MCHN) $(TVL10N) $(MGCSFX) LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) -lm @@ -196,7 +211,9 @@ xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \ xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \ xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \ - xvxwd.o xvfits.o + xvxwd.o xvfits.o \ + xvmag.o xvpic.o xvmaki.o xvpi.o xvpic2.o xvpcd.o xvvd.o xvmgcsfx.o \ + xvml.o MISC = README INSTALL CHANGELOG IDEAS @@ -244,6 +261,7 @@ cp docs/xvp2p.man $(MANDIR)/xvpictoppm.$(MANSUF) cp docs/vdcomp.man $(MANDIR)/vdcomp.$(MANSUF) cp docs/xvdocs.ps* $(LIBDIR) + cp xv_mgcsfx.sample $(MGCSFXDIR) tar: tar cvf xv.tar Makefile* Imakefile *.c *.h bits \ diff -urN xv-3.10a/Makefile.std xv-3.10a-jp-extension-current/Makefile.std --- xv-3.10a/Makefile.std Tue Jan 24 10:06:26 1995 +++ xv-3.10a-jp-extension-current/Makefile.std Wed Oct 9 20:36:30 1996 @@ -78,10 +78,12 @@ #----------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 +# Sikarusm etc, uncomment one of the following lines to get you *most* of +# the way there. SYSV means System V R3. +# UNIX = -DSVR4 +# UNIX = -DSYSV + - #----------Machine Specific Configurations---------- ### If you are using an SGI system, uncomment the following line @@ -99,6 +101,9 @@ # note: You may need to add '-I/usr/include/X11R5' (or R6, or whatever) # to whichever of those lines you used, as HP tends to store their X11 # include files in a non-standard place... +# +# And, you probably have to add '-lV3' to the end of the LIBS def, +# when use AUTO_EXPAND feauture. ### for LINUX, uncomment the following line @@ -177,6 +182,16 @@ #VPRINTF = -DNEED_VPRINTF -DLONGINT -DNOSTDHDRS +# if your X Window System compiled with -DX_LOCALE, +# uncomment the following line: +# TVL10N = -DX_LOCALE + +# Install directory of xv_mgcsfx.sample. +MGCSFXDIR = $(LIBDIR) +# Directory of default configuration file. +MGCSFX = -DMGCSFXDIR=\"$(MGCSFXDIR)\" + + ################ END OF CONFIGURATION OPTIONS ################# @@ -186,7 +201,7 @@ CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \ $(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \ - $(DXWM) $(MCHN) + $(DXWM) $(MCHN) $(TVL10N) $(MGCSFX) LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) -lm @@ -196,7 +211,9 @@ xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \ xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \ xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \ - xvxwd.o xvfits.o + xvxwd.o xvfits.o \ + xvmag.o xvpic.o xvmaki.o xvpi.o xvpic2.o xvpcd.o xvvd.o xvmgcsfx.o \ + xvml.o MISC = README INSTALL CHANGELOG IDEAS @@ -244,6 +261,7 @@ cp docs/xvp2p.man $(MANDIR)/xvpictoppm.$(MANSUF) cp docs/vdcomp.man $(MANDIR)/vdcomp.$(MANSUF) cp docs/xvdocs.ps* $(LIBDIR) + cp xv_mgcsfx.sample $(MGCSFXDIR) tar: tar cvf xv.tar Makefile* Imakefile *.c *.h bits \ diff -urN xv-3.10a/bggen.c xv-3.10a-jp-extension-current/bggen.c --- xv-3.10a/bggen.c Fri Dec 23 07:34:41 1994 +++ xv-3.10a-jp-extension-current/bggen.c Wed Oct 9 20:36:22 1996 @@ -29,7 +29,7 @@ #define MAXCOLS 128 /* some VMS thing... */ -#ifdef vax11c +#if defined(vax11c) || (defined(__sony_news) && (defined(bsd43) || defined(__bsd43) || defined(SYSTYPE_BSD) || defined(__SYSTYPE_BSD))) #include #endif diff -urN xv-3.10a/bits/br_mag xv-3.10a-jp-extension-current/bits/br_mag --- xv-3.10a/bits/br_mag +++ xv-3.10a-jp-extension-current/bits/br_mag Wed Oct 9 20:37:18 1996 @@ -0,0 +1,27 @@ +#define br_mag_width 48 +#define br_mag_height 48 +static unsigned char br_mag_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x0c, 0x86, 0xc1, 0x0f, 0x02, + 0x20, 0x0c, 0xc6, 0xe3, 0x1f, 0x02, 0x20, 0x1c, 0xe7, 0x67, 0x18, 0x02, + 0x20, 0x1c, 0x77, 0x6e, 0x18, 0x02, 0x20, 0xbc, 0x37, 0x6c, 0x00, 0x02, + 0x20, 0xbc, 0x37, 0x6c, 0x00, 0x02, 0x20, 0xec, 0x36, 0x6c, 0x1e, 0x02, + 0x20, 0xec, 0xf6, 0x6f, 0x1e, 0x02, 0x20, 0x4c, 0xf6, 0x6f, 0x18, 0x02, + 0x20, 0x4c, 0x36, 0x6c, 0x18, 0x02, 0x20, 0x0c, 0x36, 0x6c, 0x18, 0x02, + 0x20, 0x0c, 0x36, 0xec, 0x1f, 0x02, 0x20, 0x0c, 0x36, 0xcc, 0x0f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03}; diff -urN xv-3.10a/bits/br_maki xv-3.10a-jp-extension-current/bits/br_maki --- xv-3.10a/bits/br_maki +++ xv-3.10a-jp-extension-current/bits/br_maki Wed Oct 9 20:37:19 1996 @@ -0,0 +1,27 @@ +#define br_maki_width 48 +#define br_maki_height 48 +static unsigned char br_maki_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x83, 0x61, 0x18, 0x33, 0x02, + 0x20, 0x83, 0xf1, 0x98, 0x33, 0x02, 0x20, 0xc7, 0xf9, 0x99, 0x31, 0x02, + 0x20, 0xc7, 0x9d, 0xdb, 0x30, 0x02, 0x20, 0xef, 0x0d, 0xfb, 0x30, 0x02, + 0x20, 0xef, 0x0d, 0x7b, 0x30, 0x02, 0x20, 0xbb, 0x0d, 0x7b, 0x30, 0x02, + 0x20, 0xbb, 0xfd, 0xdb, 0x30, 0x02, 0x20, 0x93, 0xfd, 0xdb, 0x30, 0x02, + 0x20, 0x93, 0x0d, 0x9b, 0x31, 0x02, 0x20, 0x83, 0x0d, 0x9b, 0x31, 0x02, + 0x20, 0x83, 0x0d, 0x1b, 0x33, 0x02, 0x20, 0x83, 0x0d, 0x1b, 0x33, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03}; diff -urN xv-3.10a/bits/br_mgcsfx xv-3.10a-jp-extension-current/bits/br_mgcsfx --- xv-3.10a/bits/br_mgcsfx +++ xv-3.10a-jp-extension-current/bits/br_mgcsfx Wed Oct 9 20:37:19 1996 @@ -0,0 +1,27 @@ +#define br_mgcsfx_width 48 +#define br_mgcsfx_height 48 +static unsigned char br_mgcsfx_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x3c, 0xcf, 0x71, 0x00, 0x02, + 0x20, 0x6c, 0x61, 0xda, 0x00, 0x02, 0x20, 0x6c, 0x67, 0xd8, 0x1e, 0x02, + 0x20, 0x3c, 0x61, 0xd8, 0x1e, 0x02, 0x20, 0x6c, 0x61, 0xda, 0x00, 0x02, + 0x20, 0x6c, 0xcf, 0x71, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x4e, 0x7a, 0xef, 0x3d, 0x02, 0x20, 0xd3, 0x32, 0x68, 0x6c, 0x02, + 0x20, 0xc3, 0x32, 0xe4, 0x6c, 0x02, 0x20, 0x5b, 0x33, 0x62, 0x6c, 0x02, + 0x20, 0x53, 0x33, 0x61, 0x6c, 0x02, 0x20, 0x4e, 0x7a, 0xef, 0x3d, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x7f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03}; diff -urN xv-3.10a/bits/br_pcd xv-3.10a-jp-extension-current/bits/br_pcd --- xv-3.10a/bits/br_pcd +++ xv-3.10a-jp-extension-current/bits/br_pcd Wed Oct 9 20:37:19 1996 @@ -0,0 +1,27 @@ +#define br_pcd_width 48 +#define br_pcd_height 48 +static unsigned char br_pcd_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x37, 0x00, 0xc0, 0x1c, 0x02, + 0x20, 0x3f, 0x00, 0xe0, 0x3d, 0x02, 0x20, 0x3b, 0x00, 0x60, 0x2d, 0x02, + 0x20, 0x3b, 0x60, 0x60, 0x2c, 0x02, 0x20, 0x3b, 0x60, 0x60, 0x2c, 0x02, + 0x20, 0x7b, 0xf6, 0x66, 0x2c, 0x02, 0x20, 0xff, 0xff, 0x6f, 0x2c, 0x02, + 0x20, 0xb7, 0x6b, 0x6b, 0x2c, 0x02, 0x20, 0xb3, 0x6b, 0x6b, 0x2c, 0x02, + 0x20, 0xb3, 0x6b, 0x6b, 0x2c, 0x02, 0x20, 0xb3, 0x6b, 0x6b, 0x2d, 0x02, + 0x20, 0xb3, 0xef, 0xef, 0x3d, 0x02, 0x20, 0xb3, 0xc6, 0xc6, 0x1c, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03}; diff -urN xv-3.10a/bits/br_pi xv-3.10a-jp-extension-current/bits/br_pi --- xv-3.10a/bits/br_pi +++ xv-3.10a-jp-extension-current/bits/br_pi Wed Oct 9 20:37:19 1996 @@ -0,0 +1,27 @@ +#define br_pi_width 48 +#define br_pi_height 48 +static unsigned char br_pi_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x80, 0x1f, 0x7e, 0x00, 0x02, + 0x20, 0x80, 0x3f, 0x7e, 0x00, 0x02, 0x20, 0x80, 0x31, 0x18, 0x00, 0x02, + 0x20, 0x80, 0x31, 0x18, 0x00, 0x02, 0x20, 0x80, 0x31, 0x18, 0x00, 0x02, + 0x20, 0x80, 0x39, 0x18, 0x00, 0x02, 0x20, 0x80, 0x1f, 0x18, 0x00, 0x02, + 0x20, 0x80, 0x0f, 0x18, 0x00, 0x02, 0x20, 0x80, 0x01, 0x18, 0x00, 0x02, + 0x20, 0x80, 0x01, 0x18, 0x00, 0x02, 0x20, 0x80, 0x01, 0x18, 0x00, 0x02, + 0x20, 0x80, 0x01, 0x7e, 0x00, 0x02, 0x20, 0x80, 0x01, 0x7e, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03}; diff -urN xv-3.10a/bits/br_pic xv-3.10a-jp-extension-current/bits/br_pic --- xv-3.10a/bits/br_pic +++ xv-3.10a-jp-extension-current/bits/br_pic Wed Oct 9 20:37:19 1996 @@ -0,0 +1,27 @@ +#define br_pic_width 48 +#define br_pic_height 48 +static unsigned char br_pic_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xf0, 0xf3, 0xf3, 0x01, 0x02, + 0x20, 0xf0, 0xf7, 0xfb, 0x03, 0x02, 0x20, 0x30, 0xc6, 0x18, 0x03, 0x02, + 0x20, 0x30, 0xc6, 0x18, 0x00, 0x02, 0x20, 0x30, 0xc6, 0x18, 0x00, 0x02, + 0x20, 0x30, 0xc7, 0x18, 0x00, 0x02, 0x20, 0xf0, 0xc3, 0x18, 0x00, 0x02, + 0x20, 0xf0, 0xc1, 0x18, 0x00, 0x02, 0x20, 0x30, 0xc0, 0x18, 0x00, 0x02, + 0x20, 0x30, 0xc0, 0x18, 0x00, 0x02, 0x20, 0x30, 0xc0, 0x18, 0x03, 0x02, + 0x20, 0x30, 0xf0, 0xfb, 0x03, 0x02, 0x20, 0x30, 0xf0, 0xf3, 0x01, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03}; diff -urN xv-3.10a/bits/br_pic2 xv-3.10a-jp-extension-current/bits/br_pic2 --- xv-3.10a/bits/br_pic2 +++ xv-3.10a-jp-extension-current/bits/br_pic2 Wed Oct 9 20:37:19 1996 @@ -0,0 +1,27 @@ +#define br_pic2_width 48 +#define br_pic2_height 48 +static unsigned char br_pic2_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x3f, 0x3f, 0x1f, 0x1f, 0x02, + 0x20, 0x7f, 0xbf, 0xbf, 0x3f, 0x02, 0x20, 0x63, 0x8c, 0xb1, 0x31, 0x02, + 0x20, 0x63, 0x8c, 0x01, 0x30, 0x02, 0x20, 0x63, 0x8c, 0x01, 0x30, 0x02, + 0x20, 0x73, 0x8c, 0x01, 0x30, 0x02, 0x20, 0x3f, 0x8c, 0x01, 0x18, 0x02, + 0x20, 0x1f, 0x8c, 0x01, 0x0c, 0x02, 0x20, 0x03, 0x8c, 0x01, 0x06, 0x02, + 0x20, 0x03, 0x8c, 0x01, 0x03, 0x02, 0x20, 0x03, 0x8c, 0xb1, 0x01, 0x02, + 0x20, 0x03, 0xbf, 0xbf, 0x3f, 0x02, 0x20, 0x03, 0x3f, 0x9f, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03}; diff -urN xv-3.10a/bits/xv_jpext xv-3.10a-jp-extension-current/bits/xv_jpext --- xv-3.10a/bits/xv_jpext +++ xv-3.10a-jp-extension-current/bits/xv_jpext Wed Oct 9 20:37:19 1996 @@ -0,0 +1,29 @@ +#define xv_jpext_width 111 +#define xv_jpext_height 22 +static unsigned char xv_jpext_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x23, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x20, 0x4e, 0xe3, 0x64, + 0x18, 0x0f, 0x06, 0x81, 0xd2, 0x03, 0x93, 0x79, 0xe2, 0x64, 0x20, 0xd1, + 0x14, 0x5d, 0xa6, 0x8c, 0x09, 0x1f, 0x0c, 0xc1, 0x74, 0x65, 0x12, 0x5d, + 0x20, 0x5c, 0xc4, 0x45, 0x9e, 0x92, 0x07, 0x01, 0x04, 0xc1, 0x13, 0x95, + 0x0a, 0x45, 0x20, 0x53, 0x32, 0x45, 0x01, 0x51, 0x00, 0x01, 0x06, 0x29, + 0x10, 0x89, 0x0a, 0x45, 0xa1, 0x58, 0x8a, 0x45, 0x31, 0x48, 0x0c, 0x01, + 0x25, 0x25, 0x16, 0x41, 0x8a, 0x44, 0x11, 0xd7, 0x71, 0x45, 0x8e, 0x87, + 0x03, 0xbf, 0x18, 0xc3, 0x11, 0x3d, 0x72, 0x44, 0x0e, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff -urN xv-3.10a/bits/xv_jprev xv-3.10a-jp-extension-current/bits/xv_jprev --- xv-3.10a/bits/xv_jprev +++ xv-3.10a-jp-extension-current/bits/xv_jprev Wed Oct 9 20:40:21 1996 @@ -0,0 +1,22 @@ +#define xv_jprev_width 78 +#define xv_jprev_height 22 +static unsigned char xv_jprev_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, + 0x20, 0x40, 0x00, 0x00, 0x7c, 0xf0, 0x83, 0x1f, 0x23, 0x00, 0x20, 0x40, + 0x00, 0x00, 0x02, 0x10, 0x81, 0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x80, 0x00, 0x04, 0x07, 0x4c, 0x28, 0x4f, 0x9c, 0x0c, 0x7a, 0x80, + 0x03, 0x1c, 0x03, 0x53, 0xa4, 0x4c, 0xa2, 0x0b, 0x86, 0x60, 0x04, 0x23, + 0x05, 0x8f, 0xa2, 0x52, 0xa1, 0x08, 0x80, 0x00, 0x04, 0x20, 0x89, 0x80, + 0x22, 0x51, 0xa1, 0x08, 0x80, 0x08, 0x44, 0x20, 0xb1, 0x18, 0x21, 0x48, + 0x91, 0x08, 0x61, 0x0a, 0x53, 0x18, 0x41, 0x07, 0xa1, 0x47, 0x8e, 0x08, + 0x1e, 0xf2, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; diff -urN xv-3.10a/config.h xv-3.10a-jp-extension-current/config.h --- xv-3.10a/config.h Fri Jan 6 03:49:21 1995 +++ xv-3.10a-jp-extension-current/config.h Tue Oct 22 18:45:59 1996 @@ -19,7 +19,15 @@ # ifdef VMS # define GUNZIP "UNCOMPRESS" # else -# define GUNZIP "/usr/local/bin/gunzip -q" +# if defined(__FreeBSD__) || defined(__NetBSD__) +# define GUNZIP "/usr/bin/gunzip -q" +# else +# if defined(__linux__) +# define GUNZIP "/bin/gunzip -q" +# else +# define GUNZIP "/usr/local/bin/gunzip -q" +# endif +# endif # endif #endif @@ -37,7 +45,14 @@ */ #define UNCOMPRESS "/usr/ucb/uncompress" -#if defined(hpux) || defined(SVR4) || defined(__386BSD__) +#if defined(hpux) || defined(SVR4) || \ + defined(__386BSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__linux__) + /* + I want to use BSD macro for checking if this OS is *BSD or not, + but the macro is defined in , which I don't know all + machine has or not. + */ # undef UNCOMPRESS # define UNCOMPRESS "/usr/bin/uncompress" #endif @@ -119,3 +134,196 @@ #define BACKING_STORE + +/*************************************************************************** + * MAG/PIC/MAKI/Pi/PIC2/PhotoCD format Support: + * + * if, for whatever reason, you're unable to get the + * MAG/PIC/MAKI/Pi/PIC2/PhotoCD support to compile, *COMMENT OUT* the + * following apropriate line(s). + */ + +#define HAVE_MAG +#define HAVE_PIC +#define HAVE_MAKI +#define HAVE_PI +#define HAVE_PIC2 +#define HAVE_PCD + + +/*************************************************************************** + * MacBinary file support: + * + * if you want XV to be able to handle ``MacBinary'' files (which have + * 128 byte info file header at the head), change 'undef' to 'define' + * in the following line. + */ + +#undef MACBINARY + + +/*************************************************************************** + * Auto Expand support: + * + * if you want to extract archived file automatically and regard it as + * a directory, change 'undef' to 'define' in the AUTO_EXPAND line. + * + * Virtual Thumbdir support: + * + * if you want Virtual directory based Thumbdir(It means that XV + * does't forget builded Icons still be quited even if the directory + * is read-only), change 'undef' to 'define' the VIRTUAL_TD line. + */ + +#undef AUTO_EXPAND +#undef VIRTUAL_TD + +#if !defined(AUTO_EXPAND) && defined(VIRTUAL_TD) +# undef VIRTUAL_TD +#endif + + +/*************************************************************************** + * Adjust the aspect ratio of Icons: + * + * if you want to adjust the aspect ratio of Icons in Visual + * Shunauzer, change 'undef' to 'define' in the following line. + */ + +#undef VS_ADJUST + + +/*************************************************************************** + * Restore original colormap: + * + * if you want to restore original colormap when icons in Visual + * Shunauzer is double-clicked, change 'undef' to 'define' in the + * following line. + */ + +#undef VS_RESCMAP + + +/*************************************************************************** + * TextViewer l10n support: + * + * if you want XV to show the text in Japanese on TextViewer, change + * 'undef' to 'define' in the following line. + */ + +#undef TV_L10N + +#ifdef TV_L10N +/* + * if you want to change the default code-set used in case that XV + * fails to select correct code-set, uncomment the '#define + * LOCALE_DEFAULT' line and change the 'LOCALE_DEFAULT' definition + * appropriately. + * (0:ASCII, 1:EUC-j, 2:JIS, 3:MS Kanji) */ + +/* # define LOCALE_DEFAULT 0 */ + +/* + * Uncomment and edit the following lines, if your X Window System was + * not compiled with -DX_LOCALE and you failed to display the Japanese + * text in TextViewer. You don't have to write locale name of JIS code-set + * and MicroSoft code-set, if your system doesn't support those code-sets. + */ + +/* +# define LOCALE_NAME_EUC "ja_JP.EUC" +# define LOCALE_NAME_JIS "ja_JP.JIS" +# define LOCALE_NAME_MSCODE "ja_JP.SJIS" +*/ + +/* + * if your system doesn't have the Japanese fonts in the sizes, + * Uncomment and edit the following font size entries. + */ + +/* # define TV_FONTSIZE 14,16,24 */ + +/* + * If you need, uncomment and modify the following font name. + */ + +/* # define TV_FONTSET "-*-fixed-medium-r-normal--%d-*" */ +#endif /* TV_L10N */ + + +/*************************************************************************** + * User definable filter support: + * + * Use the filters as input and output method for load and save unsupported + * image format file. The filter command is recognized by definition of + * magic number or suffix in "~/.xv_mgcsfx" . + * To enable this feature, change 'undef' to 'define' in the following line. + */ +#undef HAVE_MGCSFX + +#ifdef HAVE_MGCSFX +/* + * Support symbol 'auto' as in startup file. This type + * is not use pipe as input, but write to temporary and recognize by xv + * processing. + */ +#define HAVE_MGCSFX_AUTO + +/* + * The startup file of definition for MgcSfx. 'MGCSFX_SITE_RC' is read + * first and '~/MGCSFX_RC' is second. So same definitions in both files + * are overrided by '~/MGCSFX_RC' + * To define startup file, see the sample of startup file 'xv_mgcsfx.sample'. + */ +# define MGCSFX_SITE_RC "xv_mgcsfx" +# define MGCSFX_RC ".xv_mgcsfx" + +/* + * If you want startup file to pass preprocessor in reading time, then + * change 'undef' to 'define' in the following line. + * + * WARNING : If you decide to use preprocessor, you must not write + * '# ' style comment in startup file. Because, + * preprocessor can't recognize. */ +# undef USE_MGCSFX_PREPROCESSOR + +# ifdef USE_MGCSFX_PREPROCESSOR +/* + * This is used like "system("MGCSFX_PREPROCESSOR MGCSFX_RC > tmp_name");", + * and read tmp_name instead of MGCSFX_RC. + */ +# define MGCSFX_PREPROCESSOR "/usr/lib/cpp" +/* # define MGCSFX_PREPROCESSOR "cc -E" */ + +# endif /* USE_MGCSFX_PREPROCESSOR */ + +/* + * Default string of command. If input command is required for undefined file, + * dialog is popuped with 'MGCSFX_DEFAULT_INPUT_COMMAND'. And, if output + * command is required in save dialog of MgcSfx, dialog is popuped with + * 'MGCSFX_DEFAULT_OUTPUT_COMMAND'. + * + * WARNING : Now, supported only 'PNM' image format, when command input is + * required. You should define filter which use 'PNM' image format + * as input or output. + */ +# define MGCSFX_DEFAULT_INPUT_COMMAND "tifftopnm" +# define MGCSFX_DEFAULT_OUTPUT_COMMAND "pnmtotiff" + +#endif /* HAVE_MGCSFX */ + + +/*************************************************************************** + * Multi-Lingual TextViewer + * + * if you want XV to show the text in multi-lingual on TextViewer, change + * 'undef' to 'define' in the following line. + */ + +#undef TV_MULTILINGUAL + +#define TV_DEFAULT_CODESET TV_EUC_JAPAN + +#ifdef TV_MULTILINGUAL +# undef TV_L10N +#endif diff -urN xv-3.10a/vdcomp.c xv-3.10a-jp-extension-current/vdcomp.c --- xv-3.10a/vdcomp.c Fri Dec 23 07:34:47 1994 +++ xv-3.10a-jp-extension-current/vdcomp.c Wed Oct 9 20:36:27 1996 @@ -106,6 +106,7 @@ !defined(pyr) && \ !defined(__UMAXV__) && \ !defined(bsd43) && \ + !defined(__bsd43) && \ !defined(aux) && \ !defined(__bsdi__) && \ !defined(sequent) @@ -113,7 +114,14 @@ # if defined(hp300) || defined(hp800) || defined(NeXT) # include /* it's in 'sys' on HPs and NeXT */ # else -# include +# if !defined(__386BSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) + /* + I want to use BSD macro for checking if this OS is *BSD or not, + but the macro is defined in , which I don't know all + machine has or not. + */ +# include +# endif # endif # endif #endif /* !VMS */ diff -urN xv-3.10a/xv.c xv-3.10a-jp-extension-current/xv.c --- xv-3.10a/xv.c Fri Jan 20 03:08:43 1995 +++ xv-3.10a-jp-extension-current/xv.c Wed Oct 9 20:36:20 1996 @@ -62,6 +62,19 @@ static char basefname[128]; /* just the current fname, no path */ +#ifdef TV_L10N +# ifndef TV_FONTSET +# define TV_FONTSET "-*-fixed-medium-r-normal--%d-*" +# endif +# ifndef TV_FONTSIZE +# define TV_FONTSIZE 14,16 +# endif + +static int mfontsize[] = { TV_FONTSIZE, 0 }; +static char mfontset[256]; +#endif + + /* things to do upon successfully loading an image */ static int autoraw = 0; /* force raw if using stdcmap */ static int autodither = 0; /* dither */ @@ -78,6 +91,9 @@ static int force8 = 0; /* force 8-bit mode */ static int force24 = 0; /* force 24-bit mode */ +#ifdef HAVE_PCD +static int PcdSize = -1; /* force 24-bit mode */ +#endif /* HAVE_PCD */ /* used in DeleteCmd() and Quit() */ static char **mainargv; @@ -122,6 +138,10 @@ *infogeom, *fgstr, *bgstr, *ctrlgeom, *gamgeom, *browgeom, *tmpstr; char *rootfgstr, *rootbgstr, *visualstr, *textgeom, *cmtgeom; char *monofontname, *flistName; +#ifdef TV_L10N +char **misscharset, *defstr; +int nmisscharset; +#endif int curstype, stdinflag, browseMode, savenorm, preview, pscomp, preset, rmodeset, gamset, cgamset, perfect, owncmap, rwcolor, stdcmap; int nodecor; @@ -137,6 +157,9 @@ /*******************************************/ { int i; +#ifdef TV_L10N + int j; +#endif XColor ecdef; Window rootReturn, parentReturn, *children; unsigned int numChildren, rootDEEP; @@ -153,6 +176,12 @@ /*** variable Initialization ***/ /*****************************************************/ +#ifdef TV_L10N + setlocale(LC_ALL, localeList[LOCALE_EUCJ]); + xlocale = (int)XSupportsLocale(); /* assume that (Bool) is (int) */ + /* if X doesn't support ja_JP.ujis text viewer l10n doesn't work. */ +#endif + xv_getwd(initdir, sizeof(initdir)); searchdir[0] = '\0'; fullfname[0] = '\0'; @@ -277,6 +306,18 @@ tiffW = (Window) NULL; tiffUp = 0; #endif +#ifdef HAVE_PIC2 + pic2W = (Window) NULL; pic2Up = 0; +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + pcdW = (Window) NULL; pcdUp = 0; +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + mgcsfxW = (Window) NULL; mgcsfxUp = 0; +#endif /* HAVE_MGCSFX */ + imap = ctrlmap = gmap = browmap = cmtmap = 0; ch_offx = ch_offy = p_offx = p_offy = 0; @@ -300,6 +341,10 @@ /* handle user-specified resources and cmd-line arguments */ parseResources(argc,argv); parseCmdLine(argc, argv); +#ifdef AUTO_EXPAND + Vdinit(); + vd_handler_setup(); +#endif verifyArgs(); @@ -649,7 +694,62 @@ } monofont=monofinfo->fid; - + +#ifdef TV_L10N + if (xlocale) { + i = 0; + while (mfontsize[i]) { + xlocale = 1; /* True */ + + sprintf(mfontset, TV_FONTSET, mfontsize[i]); +/*fprintf(stderr, "FontSet: %s\n", mfontset);*/ + + monofset = XCreateFontSet(theDisp, mfontset, + &misscharset, &nmisscharset, &defstr); +# if 0 /* not useful */ + if (!monofset) { + /* the current locale is not supported */ +/*fprintf(stderr, "Current locale `%s' is not supported.\n", localeList[i]);*/ + xlocale = 0; + break; + } +# endif +/*fprintf(stderr, "# of misscharset in mfontsize[%d]: %d\n", i,nmisscharset);*/ + + for (j = 0; j < nmisscharset; j++) { + if (!strncmp(misscharset[j], "jisx0208", 8)) { + /* font for JIS X 0208 is not found */ + xlocale = 0; + break; + } + } + + if (xlocale) { + monofsetinfo = XExtentsOfFontSet(monofset); + monofsetinfo->max_logical_extent.width = mfontsize[i]; + /* correct size of TextViewer + in case that JIS X 0208 is not found */ + break; + } + + i++; + } /* while (mfontsize[i]) */ + +# if 0 + if (nmisscharset > 0) { + sprintf(str,"missing %d charset:\n", nmisscharset); + for (i = 0; i < nmisscharset; i++) { + sprintf(str, "%s\t%s\n", str, misscharset[i]); + } +# if 0 + FatalError(str); +# else + fprintf(stderr, "%s", str); +# endif + } +# endif + } +#endif /* TV_L10N */ @@ -782,7 +882,21 @@ XSetTransientForHint(theDisp, tiffW, dirW); #endif - +#ifdef HAVE_PIC2 + CreatePIC2W(); + XSetTransientForHint(theDisp, pic2W, dirW); +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + CreatePCDW(); + XSetTransientForHint(theDisp, pcdW, dirW); +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + CreateMGCSFXW(); + XSetTransientForHint(theDisp, mgcsfxW, dirW); +#endif /* HAVE_MGCSFX */ + LoadFishCursors(); SetCursors(-1); @@ -1096,17 +1210,32 @@ if (rd_flag("infoMap")) imap = def_int; if (rd_flag("loadBrowse")) browseMode = def_int; if (rd_str ("lowlight")) lostr = def_str; +#ifdef MACBINARY + if (rd_flag("macbinary")) handlemacb = def_int; +#endif +#ifdef HAVE_MGCSFX + if (rd_flag("mgcsfx")) mgcsfx = def_int; +#endif /* HAVE_MGCSFX */ if (rd_flag("mono")) mono = def_int; if (rd_str ("monofont")) monofontname = def_str; if (rd_int ("ncols")) ncols = def_int; if (rd_flag("ninstall")) ninstall = def_int; if (rd_flag("nodecor")) nodecor = def_int; if (rd_flag("nolimits")) nolimits = def_int; +#ifdef HAVE_MGCSFX + if (rd_flag("nomgcsfx")) nomgcsfx = def_int; +#endif /* HAVE_MGCSFX */ +#if defined(HAVE_PIC) || defined(HAVE_PIC2) + if (rd_flag("nopicadjust")) nopicadjust = def_int; +#endif /* HAVE_PIC || HAVE_PIC2 */ if (rd_flag("nopos")) nopos = def_int; if (rd_flag("noqcheck")) noqcheck = def_int; if (rd_flag("nostat")) nostat = def_int; if (rd_flag("ownCmap")) owncmap = def_int; if (rd_flag("perfect")) perfect = def_int; +#ifdef HAVE_PIC2 + if (rd_flag("pic2split")) pic2split = def_int; +#endif /* HAVE_PIC2 */ if (rd_flag("popupKludge")) winCtrPosKludge = def_int; if (rd_str ("print")) strncpy(printCmd, def_str, (size_t) PRINTCMDLEN); @@ -1124,6 +1253,9 @@ if (rd_str ("textviewGeometry")) textgeom = def_str; if (rd_flag("useStdCmap")) stdcmap = def_int; if (rd_str ("visual")) visualstr = def_str; +#ifdef VS_ADJUST + if (rd_flag("vsadjust")) vsadjust = def_int; +#endif /* VS_ADJUST */ if (rd_flag("vsDisable")) novbrowse = def_int; if (rd_str ("vsGeometry")) browgeom = def_str; if (rd_flag("vsMap")) browmap = def_int; @@ -1158,7 +1290,13 @@ } if (numnames%s", icom, tmpname); + }else goto ms_auto_no; + +#ifndef VMS + if (system(tmp)) { +#else + if (!system(tmp)) { +#endif + SetISTR(ISTR_INFO, "Unable to convert '%s' by MgcSfx auto.", BaseName(filename +)); + Warning(); + filetype = RFT_ERROR; + goto ms_auto_no; + } + + filetype = ReadFileType(tmpname); + if (strcmp(fullname,filename)!=0) unlink(filename); + strcpy(filename, tmpname); + } +ms_auto_no: +#endif /* HAVE_MGCSFX_AUTO */ if (filetype == RFT_ERROR) { char foostr[512]; @@ -2027,7 +2284,12 @@ if (filetype == RFT_UNKNOWN) { /* view as a text/hex file */ - TextView(filename); +#ifdef MACBINARY + if (origname[0]) + TextView(origname); + else +#endif + TextView(filename); SetISTR(ISTR_INFO,"'%s' not in a recognized format.", basefname); /* Warning(); */ goto SHOWN_AS_TEXT; @@ -2540,6 +2802,9 @@ FILE *fp; byte magicno[30]; /* first 30 bytes of file */ int rv, n; +#ifdef MACBINARY + int macbin_alrchk = False; +#endif if (!fname) return RFT_ERROR; /* shouldn't happen */ @@ -2553,12 +2818,29 @@ rv = RFT_UNKNOWN; +#ifdef MACBINARY + macb_file = False; + while (1) { +#endif + +#ifdef HAVE_MGCSFX + if(is_mgcsfx(fname, magicno, 30) != 0) rv = RFT_MGCSFX; + + else 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,"GIF87a", (size_t) 6)==0 || strncmp((char *) magicno,"GIF89a", (size_t) 6)==0) rv = RFT_GIF; +#endif /* HAVE_MGCSFX */ else if (strncmp((char *) magicno,"VIEW", (size_t) 4)==0 || strncmp((char *) magicno,"WEIV", (size_t) 4)==0) rv = RFT_PM; +#ifdef HAVE_PIC2 + else if (magicno[0]=='P' && magicno[1]=='2' + &&magicno[2]=='D'&&magicno[3]=='T') rv = RFT_PIC2; +#endif /* HAVE_PIC2 */ + else if (magicno[0] == 'P' && magicno[1]>='1' && magicno[1]<='6') rv = RFT_PBM; @@ -2625,6 +2907,49 @@ strncmp((char *) magicno, "\004%!", (size_t) 3)==0) rv = RFT_PS; #endif +#ifdef HAVE_MAG + else if (strncmp((char *) magicno,"MAKI02 ", (size_t) 8)==0) rv = RFT_MAG; +#endif /* HAVE_MAG */ + +#ifdef HAVE_MAKI + else if (strncmp((char *) magicno,"MAKI01A ", (size_t) 8)==0 || + strncmp((char *) magicno,"MAKI01B ", (size_t) 8)==0) rv = RFT_MAKI; +#endif /* HAVE_MAKI */ + +#ifdef HAVE_PIC + else if (magicno[0]=='P' && magicno[1]=='I'&&magicno[2]=='C') rv = RFT_PIC; +#endif /* HAVE_PIC */ + +#ifdef HAVE_PI + else if (magicno[0]=='P' && magicno[1]=='i') rv = RFT_PI; +#endif /* HAVE_PI */ + +#ifdef HAVE_PCD + else if (magicno[0]==0xff && magicno[1]==0xff && + magicno[2]==0xff && magicno[3]==0xff) rv = RFT_PCD; +#endif /* HAVE_PCD */ + +#ifdef MACBINARY + /* Now, we became handled `MacBinary' files, but it way is VERY dirty... */ + if (macbin_alrchk == True) { + macb_file = True; + break; + } + + if (rv != RFT_UNKNOWN) + break; + + /* Skip MACBSIZE and recheck */ + macbin_alrchk = True; + fp = xv_fopen(fname, "r"); + if (!fp) return RFT_ERROR; + fseek(fp, MACBSIZE, SEEK_SET); + n = fread(magicno, (size_t) 1, (size_t) 30, fp); + fclose(fp); + + if (n<30) return RFT_UNKNOWN; /* files less than 30 bytes long... */ + } +#endif return rv; } @@ -2639,7 +2964,8 @@ /* 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 */ + generates the page file for the first page of the document . + Also now affects PCD which now only loads a thumbnail */ int rv = 0; @@ -2650,7 +2976,11 @@ switch (ftype) { case RFT_GIF: rv = LoadGIF (fname, pinfo); break; case RFT_PM: rv = LoadPM (fname, pinfo); break; +#ifdef HAVE_MGCSFX + case RFT_PBM: rv = LoadPBM (fname, pinfo, -1); break; +#else case RFT_PBM: rv = LoadPBM (fname, pinfo); break; +#endif /* HAVE_MGCSFX */ case RFT_XBM: rv = LoadXBM (fname, pinfo); break; case RFT_SUNRAS: rv = LoadSunRas(fname, pinfo); break; case RFT_BMP: rv = LoadBMP (fname, pinfo); break; @@ -2679,6 +3009,43 @@ case RFT_PS: rv = LoadPS (fname, pinfo, quick); break; #endif +#ifdef HAVE_MAG + case RFT_MAG: rv = LoadMAG (fname, pinfo); break; +#endif /* HAVE_MAG */ + +#ifdef HAVE_MAKI + case RFT_MAKI: rv = LoadMAKI (fname, pinfo); break; +#endif /* HAVE_MAKI */ + +#ifdef HAVE_PIC + case RFT_PIC: rv = LoadPIC (fname, pinfo); break; +#endif /* HAVE_PIC */ + +#ifdef HAVE_PI + case RFT_PI: rv = LoadPi (fname, pinfo); break; +#endif /* HAVE_PI */ + +#ifdef HAVE_PIC2 + case RFT_PIC2: rv = LoadPIC2 (fname, pinfo, quick); break; +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + case RFT_PCD: + if (quick == 1) + rv = LoadPCD(fname, pinfo, 0); + else + rv = LoadPCD(fname, pinfo, PcdSize); + break; + + /* If quick is switched on use the smallest image size don't ask + * the user. + */ +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + case RFT_MGCSFX: rv = LoadMGCSFX (fname, pinfo); break; +#endif /* HAVE_MGCSFX */ + } return rv; } @@ -2773,6 +3140,44 @@ return 1; } + +#ifdef MACBINARY +/********************************/ +int RemoveMacbinary(src, dst) + char *src, *dst; +{ + char tmpname[128], buffer[8192]; /* XXX */ + int n, eof; + FILE *sfp, *dfp; + + sprintf(dst, "%s/xvmXXXXXX", tmpdir); + mktemp(dst); + SetISTR(ISTR_INFO, "Removing MacBinary..."); + + sfp = xv_fopen(src, "r"); + dfp = xv_fopen(dst, "w"); + if (!sfp || !dfp) { + SetISTR(ISTR_INFO, "Unable to remove a InfoFile header form '%s'.", src); + Warning(); + return 0; + } + fseek(sfp, MACBSIZE, SEEK_SET); + while ((n = fread(buffer, 1, sizeof(buffer), sfp)) == 8192) /* XXX */ + fwrite(buffer, 1, n, dfp); + if (eof = feof(sfp)) + fwrite(buffer, 1, n, dfp); + fclose(sfp); + fclose(dfp); + if (!eof) { + SetISTR(ISTR_INFO, "Unable to remove a InfoFile header form '%s'.", src); + Warning(); + return 0; + } + + return 1; +} +#endif + /********************************/ void KillPageFiles(bname, numpages) diff -urN xv-3.10a/xv.h xv-3.10a-jp-extension-current/xv.h --- xv-3.10a/xv.h Tue Jan 24 05:22:23 1995 +++ xv-3.10a-jp-extension-current/xv.h Tue Oct 22 18:17:25 1996 @@ -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+jp5.3.3 Rev: 12/29/94" +#define VERSTR "3.10a+jp5.3.3" /* * uncomment the following, and modify for your site, but only if you've @@ -68,6 +68,20 @@ # endif #endif +#if defined(__sony_news) && defined(bsd43) && !defined(__bsd43) +# define __bsd43 +#elif defined(__sony_news) && (defined(SYSTYPE_BSD) || defined(__SYSTYPE_BSD)) && !defined(bsd43) && !defined(__bsd43) +# define bsd43 +# define __bsd43 +#endif + +#ifndef __osf__ +#undef SIGCHLD /* defined in both Xos.h and signal.h */ +#endif /* !__osf__ */ +#include /* for interrupt handling */ +#ifdef __linux__ +# define sigmask __sigmask +#endif #include /* need type declarations immediately */ @@ -99,6 +113,16 @@ #endif +#if defined(__sony_news) && defined(__bsd43) +# include +#endif + + +#if defined(__FreeBSD__) +# include +#endif + + /* include files */ #include #include @@ -115,7 +139,7 @@ #ifndef VMS # include extern int errno; /* SHOULD be in errno.h, but often isn't */ -# ifndef __NetBSD__ +# if !(defined(BSD) && (BSD >= 199103)) extern char *sys_errlist[]; /* this too... */ # endif #endif @@ -128,7 +152,9 @@ # define ERRSTR(x) strerror(x, vaxc$errno) #endif - +#ifdef __linux__ + extern char *strdup PARM((const char *)); +#endif #ifdef VMS /* VMS config, hacks & kludges */ @@ -157,6 +183,8 @@ !defined(pyr) && \ !defined(__UMAXV__) && \ !defined(bsd43) && \ + !defined(__bsd43) && \ + !(defined(BSD) && (BSD >= 199103)) && \ !defined(aux) && \ !defined(__bsdi__) && \ !defined(sequent) @@ -179,9 +207,10 @@ #include #include +#ifdef TV_L10N +# include +#endif -#undef SIGCHLD /* defined in both Xos.h and signal.h */ -#include /* for interrupt handling */ #include @@ -314,6 +343,9 @@ # endif #endif +#if (defined(SYSV) || defined(SVR4)) && !defined(USE_GETCWD) +# define USE_GETCWD +#endif /*****************************/ /* END OF CONFIGURATION INFO */ @@ -458,6 +490,45 @@ #define F_TIFINC 0 #endif +#ifdef HAVE_MAG +#define F_MAGINC 1 +#else +#define F_MAGINC 0 +#endif /* HAVE_MAG */ + +#ifdef HAVE_PIC +#define F_PICINC 1 +#else +#define F_PICINC 0 +#endif /* HAVE_PIC */ + +#ifdef HAVE_MAKI +#define F_MAKINC 1 +#else +#define F_MAKINC 0 +#endif /* HAVE_MAKI */ + +#ifdef HAVE_PI +#define F_PAIINC 1 +#else +#define F_PAIINC 0 +#endif /* HAVE_PI */ + +#ifdef HAVE_PIC2 +#define F_PC2INC 1 +#else +#define F_PC2INC 0 +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_MGCSFX +#define F_MGCSFXINC 1 +#else +#define F_MGCSFXINC 0 +#endif /* HAVE_MGCSFX */ + +#ifdef MACBINARY +#define MACBSIZE 128 +#endif #define F_GIF 0 #define F_JPEG ( 0 + F_JPGINC) @@ -473,9 +544,17 @@ #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 JP_EXT_F (F_PM) +#define F_MAG (JP_EXT_F + F_MAGINC) +#define F_PIC (JP_EXT_F + F_MAGINC + F_PICINC) +#define F_MAKI (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC) +#define F_PI (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC + F_PAIINC) +#define F_PIC2 (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC + F_PAIINC + F_PC2INC) +#define F_MGCSFX (JP_EXT_F + F_MAGINC + F_PICINC + F_MAKINC + F_PAIINC + F_PC2INC + F_MGCSFXINC) /* ----- */ +#define JP_EXT_F_END (F_MGCSFX) +#define F_DELIM1 (JP_EXT_F_END + 1) +#define F_FILELIST (JP_EXT_F_END + 2) +#define F_MAXFMTS (JP_EXT_F_END + 3) /* 16, normally */ @@ -505,6 +584,14 @@ #define RFT_XPM 17 #define RFT_XWD 18 #define RFT_FITS 19 +#define JP_EXT_RFT (RFT_FITS) +#define RFT_MAG (JP_EXT_RFT + 1) +#define RFT_MAKI (JP_EXT_RFT + 2) +#define RFT_PIC (JP_EXT_RFT + 3) +#define RFT_PI (JP_EXT_RFT + 4) +#define RFT_PIC2 (JP_EXT_RFT + 5) +#define RFT_PCD (JP_EXT_RFT + 6) +#define RFT_MGCSFX (JP_EXT_RFT + 7) /* definitions for page up/down, arrow up/down list control */ #define LS_PAGEUP 0 @@ -942,6 +1029,10 @@ WHERE u_long blkRGB, whtRGB; WHERE Font mfont, monofont; WHERE XFontStruct *mfinfo, *monofinfo; +#ifdef TV_L10N +WHERE XFontSet monofset; +WHERE XFontSetExtents *monofsetinfo; +#endif WHERE Visual *theVisual; WHERE Cursor arrow, cross, tcross, zoom, inviso; WHERE Pixmap iconPix, iconmask; @@ -960,6 +1051,10 @@ WHERE int picType; /* CONV24_8BIT,CONV24_24BIT,etc.*/ WHERE char *picComments; /* text comments on current pic */ +#ifdef TV_L10N +WHERE int xlocale; /* true if Xlib supports locale */ +#endif + WHERE int numPages, curPage; /* for multi-page files */ WHERE char pageBaseName[64]; /* basename for multi-page files */ @@ -993,6 +1088,23 @@ WHERE unsigned long cols[256]; /* maps pic pixel values to X pixel vals */ WHERE int fc2pcol[256]; /* maps freecols into pic pixel values */ WHERE int numcols; /* # of desired colors in picture */ +#ifdef MACBINARY +WHERE char macb_file; /* True if this file type is MacBinary */ +WHERE int handlemacb; /* True if we want to handle MacBinary */ +#endif /* MACBINARY */ +#if defined(HAVE_PIC) || defined(HAVE_PIC2) +WHERE int nopicadjust; /* True if we don't want to adjust aspect */ +#endif /* HAVE_PIC || HAVE_PIC2 */ +#ifdef HAVE_PIC2 +WHERE int pic2split; /* True if we want to split multiblocks */ +#endif /* HAVE_PIC2 */ +#ifdef VS_ADJUST +WHERE int vsadjust; /* True if we want to adjust aspect of icons */ +#endif /* VS_ADJUST */ +#ifdef HAVE_MGCSFX +WHERE int mgcsfx; /* True if we want to force use MgcSfx */ +WHERE int nomgcsfx; /* True if we don't want to use MgcSfx */ +#endif /* HAVE_MGCSFX */ /* Std Cmap stuff */ WHERE byte stdr[256], stdg[256], stdb[256]; /* std 3/3/2 cmap */ @@ -1153,6 +1265,77 @@ WHERE int tiffUp; /* is tiffW mapped, or what? */ #endif +#ifdef HAVE_PIC2 +/* stuff used for 'pic2' box */ +WHERE Window pic2W; +WHERE int pic2Up; /* is pic2W mapped, or what? */ +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD +/* stuff used for 'pcd' box */ +WHERE Window pcdW; +WHERE int pcdUp; /* is pcdW mapped, or what? */ +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX +/* stuff used for 'mgcsfx' box */ +WHERE Window mgcsfxW; +WHERE Window mgcsfxNameW; +WHERE int mgcsfxUp; /* is mgcsfxW mapped, or what? */ +#endif /* HAVE_MGCSFX */ + +#ifdef TV_L10N +/* stuff used for TextViewer Japanization */ +# define LOCALE_USASCII 0 +# define LOCALE_EUCJ 1 +# define LOCALE_JIS 2 +# define LOCALE_MSCODE 3 + +# ifndef LOCALE_DEFAULT +# define LOCALE_DEFAULT 0 +# endif /* !LOCALE_DEFAULT */ + +# ifndef MAIN + extern char *localeList[]; +# else +# ifndef LOCALE_NAME_EUC +# ifndef X_LOCALE +# if defined(__FreeBSD__) + char *localeList[] = {"", "ja_JP.EUC", "none", "none"}; +# elif defined(__sun) || defined(sun) + char *localeList[] = {"", "ja", "none", "none"}; +# elif defined(__sgi) /* sgi, __sgi, __sgi__ (gcc) */ + char *localeList[] = {"", "ja_JP.EUC", "none", "none"}; +# elif defined(sony_news) + char *localeList[] = {"", "ja_JP.EUC", "none", "ja_JP.SJIS"}; +# elif defined(nec) + char *localeList[] = {"", "japan", "none", "none"}; +# elif defined(__hpux) + char *localeList[] = {"", "japanese.euc", "none", "japanese"}; +# elif defined(__osf__) + char *localeList[] = {"", "ja_JP.deckanji", "none", "ja_JP.SJIS"}; +# elif defined(_AIX) + char *localeList[] = {"", "ja_JP", "none", "Ja_JP" }; +# elif defined(__bsdi) + char *localeList[] = {"", "Japanese-EUC", "none", "none" }; +# else + char *localeList[] = {"", "ja_JP.EUC", "ja_JP.JIS", "ja_JP.SJIS"}; +# endif +# else +# if (XlibSpecificationRelease > 5) + char *localeList[] = {"", "ja_JP.eucJP", "ja_JP.JIS7", + "ja_JP.SJIS"}; +# else + char *localeList[] = {"", "ja_JP.ujis", "ja_JP.jis7", + "ja_JP.mscode"}; +# endif +# endif /* X_LOCALE */ +# else + char *localeList[] = {"", LOCALE_NAME_EUC, + LOCALE_NAME_JIS, LOCALE_NAME_MSCODE}; +# endif /* LOCALE_NAME_EUC */ +# endif /* MAIN */ +#endif /* TV_L10N */ #undef WHERE @@ -1165,6 +1348,9 @@ int ReadPicFile PARM((char *, int, PICINFO *, int)); int UncompressFile PARM((char *, char *)); void KillPageFiles PARM((char *, int)); +#ifdef MACBINARY +int RemoveMacbinary PARM((char *, char *)); +#endif void NewPicGetColors PARM((int, int)); void FixAspect PARM((int, int *, int *)); @@ -1392,6 +1578,9 @@ int CheckPoll PARM((int)); void DIRDeletedFile PARM((char *)); void DIRCreatedFile PARM((char *)); +FILE *pic2_OpenOutFile PARM((char *, int *)); +void pic2_KillNullFile PARM((FILE *)); +int OpenOutFileDesc PARM((char *)); /*************************** XVBROWSE.C ************************/ @@ -1429,6 +1618,8 @@ int TextCheckEvent PARM((XEvent *, int *, int *)); int TextDelWin PARM((Window)); +int CharsetCheckEvent PARM((XEvent *)); +int CharsetDelWin PARM((Window)); /**************************** XVGAM.C **************************/ @@ -1548,7 +1739,11 @@ byte *, byte *, int, int, char *)); /**************************** XVPBM.C ***************************/ +#ifdef HAVE_MGCSFX +int LoadPBM PARM((char *, PICINFO *, int)); +#else int LoadPBM PARM((char *, PICINFO *)); +#endif /* HAVE_MGCSFX */ int WritePBM PARM((FILE *, byte *, int, int, int, byte *, byte *, byte *, int, int, int, char *)); @@ -1624,6 +1819,71 @@ void PSResize PARM((void)); int LoadPS PARM((char *, PICINFO *, int)); +/*************************** XVMAG.C ***************************/ +int LoadMAG PARM((char *, PICINFO *)); +int WriteMAG PARM((FILE *, byte *, int, int, int, + byte *, byte *, byte *, int, int, char *)); + +/*************************** XVMAKI.C ***************************/ +int LoadMAKI PARM((char *, PICINFO *)); +int WriteMAKI PARM((FILE *, byte *, int, int, int, + byte *, byte *, byte *, int, int)); + +/*************************** XVPIC.C ***************************/ +int LoadPIC PARM((char *, PICINFO *)); +int WritePIC PARM((FILE *, byte *, int, int, int, + byte *, byte *, byte *, int, int, char *)); + +/*************************** XVPI.C ***************************/ +int LoadPi PARM((char *, PICINFO *)); +int WritePi PARM((FILE *, byte *, int, int, int, + byte *, byte *, byte *, int, int, char *)); + +/*************************** XVPIC2.C ***************************/ +int LoadPIC2 PARM((char *, PICINFO *, int)); +void CreatePIC2W PARM((void)); +void PIC2Dialog PARM((int)); +int PIC2CheckEvent PARM((XEvent *)); +int PIC2SetParamOptions PARM((char *)); + +/**************************** XVPCD.C ***************************/ +int LoadPCD PARM((char *, PICINFO *,int)); +void CreatePCDW PARM((void)); +void PCDDialog PARM((int)); +int PCDCheckEvent PARM((XEvent *)); +void PCDSetParamOptions PARM((char *)); + +/*************************** XVMGCSFX.C ***************************/ +int is_mgcsfx PARM((char *, unsigned char *, int)); +char *mgcsfx_auto_input_com PARM((char *)); +int LoadMGCSFX PARM((char *, PICINFO *)); +void CreateMGCSFXW PARM((void)); +void MGCSFXDialog PARM((int)); +int MGCSFXCheckEvent PARM((XEvent *)); +int MGCSFXSaveParams PARM((char *, int)); + +int getInputCom PARM((void)); +int getOutputCom PARM((void)); + +/**************************** XVVD.C ****************************/ +void Vdinit PARM((void)); +void Vdsettle PARM((void)); +int Chvdir PARM((char *)); +void Dirtovd PARM((char *)); +void Vdtodir PARM((char *)); +void Dirtosubst PARM((char *)); +int Mkvdir PARM((char *)); +void Mkvdir_force PARM((char *)); +int Rmvdir PARM((char *)); +int Movevdir PARM((char *, char *)); +int Isarchive PARM((char *)); +int Isvdir PARM((char *)); +void vd_HUPhandler PARM((void)); +void vd_handler PARM((int)); +int vd_Xhandler PARM((Display *, XErrorEvent *)); +int vd_XIOhandler PARM((Display *)); +void vd_handler_setup PARM((void)); + /*************************** XVPOPUP.C ***************************/ void CenterMapWindow PARM((Window, int, int, int, int)); int PopUp PARM((char *, char **, int)); @@ -1677,3 +1937,13 @@ void CoordP2E PARM((int, int, int *, int *)); void CoordE2P PARM((int, int, int *, int *)); +#if defined(__mips) && defined(__SYSTYPE_BSD43) +# define strstr(A,B) pds_strstr((A),(B)) +# undef S_IFIFO +#endif /* !mips_bsd */ + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif diff -urN xv-3.10a/xv_mgcsfx.sample xv-3.10a-jp-extension-current/xv_mgcsfx.sample --- xv-3.10a/xv_mgcsfx.sample +++ xv-3.10a-jp-extension-current/xv_mgcsfx.sample Wed Oct 9 20:37:19 1996 @@ -0,0 +1,125 @@ +#/* +# Configuration file for XV with recognition of 'Magic and Suffix' +# +# +# $Id: xv_mgcsfx.sample,v 1.11 95/10/03 17:00:05 tin329 Exp Locker: tin329 $ +# +# Author: Tetsuya INOUE +# +# +# MgcSfx definition should write in one line. +# Format: +# :::::::: +# If you decide to not use preprocessor, comment style is allowed. +# # +# +# Description of your recognized image format. +# Type ID for recognition. (You should use 'magic'.) +# * magic Data of string style. +# `\' escape for special characters: +# \b \f \n \r \t \v \\ \' \" \a \? +# \0 ...\377 octal value +# \x0 ...\xff hexadecimal value +# * suffix Suffix of file name. +# This type check instead +# of . +# * [b|l]eint16 2 byte integer of [big|little] endian. +# * [b|l]eint32 4 byte integer of [big|little] endian. +# Offset of magic number in the target image file. +# Data(magic number) of to match at . +# Suffix of filename with '.'start. +# +# Input image format type (output from ). +# * PNM (PPM, PGM, PBM) +# * AUTO Recognized by xv management, and load. +# This is different from others, because +# this write file to temporary. +# Output image format type (input to ). +# * PNM_RAW (PPM_RAW, PGM_RAW, PBM_RAW) +# * PNM_ASCII (PPM_ASCII, PGM_ASCII, PBM_ASCII) +# +# Command to get the input image. +# * Command mast read stdin or file(specified by +# argument), and write to stdout. +# * Use %s to represent the file name. Without %s, +# get file on stdin. +# Command to put the output image. +# * Command mast read stdin and write to stdout. +# +# Any message. +#*/ + +#/*############################################################################ +# +# definition of the rule with Magic and Suffix +# +#*/ + +# /* Canon View Station Image Format */ +ViewStation(std):magic:0:VsStdImf V0.2:.vs:PNM:VStopnm %s:PNM_RAW:pnmtoVS +ViewStation(obj):magic:0:VsObjFormat V1.0:.vs:PNM:VSobjtopnm -:PNM_RAW:pnmtoVSobj + +# /* CERN httpd cache */ +# /* unchc skip header of CERN httpd cache file, and write data to stdout. */ +CERN httpd cache:magic:0:HTTP/1.0::AUTO:unchc %s:: + +# /* XLD4(Q4) image format */ +XLD(Q4):magic:11:MAJYO:.q4:PNM:q4toppm:: + +# /* ML1 image format */ +ML1:magic:0:\1\0\0\x1a:.ml1:PNM:ml1toppm %s:: + +# /* Pict image format, 256 color only */ +PICT:suffix:::.pict:PNM:picttoppm:PNM_RAW:ppmquant 256 | ppmtopict +PICT(gzip):suffix:::.pict.gz:PNM:gzip -dc | picttoppm:PNM_RAW:ppmquant 256 | ppmtopict | gzip +PICT(compress):suffix:::.pict.Z:PNM:compress -dc | picttoppm:PNM_RAW:ppmquant 256 | ppmtopict | compress + +# /* Tim image format(used by SONY PlayStation) */ +TIM:magic:0:\x10\x00\x00\x00:.tim:PNM:timtoppm:: + +# /* Cam image format(used by CASIO QV-10) */ +# /* CAM:magic:0:\x07\x20\x4d\x4d:.cam:AUTO:camtoppm -j:PNM_RAW */ +CAM:magic:0:\x07\x20\x4d\x4d:.cam:PNM:camtoppm:: + +# /* Portable Network Graphics (PNG) format : magic is "0x89 PNG" */ +PNG:magic:0:\x89\x50\x4e\x47:.png:PNM:pngtopnm %s:PNM_RAW:pnmtopng +# /* PNG(interlace):magic:0:\x89\x50\x4e\x47:.png:PNM:pngtopnm %s:PNM_RAW:pnmtopng -interlace */ + +# /* DB-Z, SAURUS Freehand Memo, PV-F1 Action Board, Wiz Quick Memo format */ +# /* Use xbm2free-1.10 or later. Old version is NOT a filter. */ +# /* To show version of xbm2free, type "xbm2free" (with no argument). */ +ZAURUS:magic:19:IMG1:.zau:PBM_ASCII:free2pbm:PBM:pbmtoxbm|xbm2free -s - +DBZ:magic:19:IMG1:.dbz:::PBM:pbmtoxbm|xbm2free -d - +PVF1:magic:12:IMG1:.pvf1:PBM_ASCII:free2pbm:PBM:pbmtoxbm|xbm2free -v - +# /* WIZ:magic:19:IMG1:.wiz:::PBM:pbmtoxbm|xbm2free -w - */ + + + +# /* Compress:magic:0:\037\235:.Z:AUTO:uncompress %s:: */ +# /* Gzip:magic:0:\037\213:.gz:AUTO:gunzip %s:: */ +# /* Gzip(old):magic:0:\037\236:.z:AUTO:gunzip %s:: */ + +# /* MAKI:magic:0:MAKI01A\040:.mki:::: */ +# /* MAKI:magic:0:MAKI01B\040:.mki:::: */ +# /* MAG:magic:0:MAKI02\040\040:.mag:::: */ +# /* Pi:magic:0:Pi:.pi:::: */ +# /* PIC:magic:0:PIC:.pic:::: */ +# /* PIC2:magic:0:P2DT:.p2:::: */ +# /* PhotoCD:magic:0:\xff\xff\xff\xff:.pcd:::: */ + +# /* PBM(ascii):magic:0:P1:.pbm:::: */ +# /* PGM(ascii):magic:0:P2:.pgm:::: */ +# /* PPM(ascii):magic:0:P3:.ppm:::: */ +# /* PBM(raw):magic:0:P4:.pbm:::: */ +# /* PGM(raw):magic:0:P5:.pgm:::: */ +# /* PPM(raw):magic:0:P6:.ppm:::: */ + +# /* Sun raster:magic:0:\131\246\152\225:.sun:::: */ +# /* JFIF(JPEG):magic:0:\xff\xd8\xff:.jpg:::: */ +# /* TIFF big-endian:magic:0:\115\115:.tif:::: */ +# /* TIFF little-endian:magic:0:\111\111:.tif:::: */ +# /* GIF(87):magic:0:GIF87a:.gif:::: */ +# /* GIF(89):magic:0:GIF89a:.gif:::: */ +# /* SGI(1):magic:0:\x01\xda:.rgb:::: */ +# /* SGI(2):magic:0:\xda\x01:.rgb:::: */ +# /* XWD:magic:0:\0\0\0\7: :::: */ diff -urN xv-3.10a/xvbrowse.c xv-3.10a-jp-extension-current/xvbrowse.c --- xv-3.10a/xvbrowse.c Fri Jan 20 02:49:17 1995 +++ xv-3.10a-jp-extension-current/xvbrowse.c Thu Nov 21 16:34:02 1996 @@ -20,7 +20,7 @@ #define NEEDSDIR #include "xv.h" -#if defined(VMS) || defined(isc) +#if defined(VMS) || defined(isc) || (defined(__sony_news) && defined(__bsd43)) typedef unsigned int mode_t; /* file mode bits */ #endif @@ -55,6 +55,13 @@ #include "bits/br_xpm" #include "bits/br_xwd" #include "bits/br_fits" +#include "bits/br_mag" +#include "bits/br_maki" +#include "bits/br_pic" +#include "bits/br_pi" +#include "bits/br_pic2" +#include "bits/br_pcd" +#include "bits/br_mgcsfx" #include "bits/br_trash" #include "bits/fcurs" @@ -94,7 +101,16 @@ #define BF_XPM 25 #define BF_XWD 26 #define BF_FITS 27 -#define BF_MAX 28 /* # of built-in icons */ +#define JP_EXT_BF (BF_FITS) +#define BF_MAG (JP_EXT_BF + 1) +#define BF_MAKI (JP_EXT_BF + 2) +#define BF_PIC (JP_EXT_BF + 3) +#define BF_PI (JP_EXT_BF + 4) +#define BF_PIC2 (JP_EXT_BF + 5) +#define BF_PCD (JP_EXT_BF + 6) +#define BF_MGCSFX (JP_EXT_BF + 7) +#define JP_EXT_BF_END (BF_MGCSFX) +#define BF_MAX (JP_EXT_BF_END + 1) /* # of built-in icons */ #define ISLOADABLE(ftyp) (ftyp!=BF_DIR && ftyp!=BF_CHR && ftyp!=BF_BLK && \ ftyp!=BF_SOCK && ftyp!=BF_FIFO) @@ -140,8 +156,14 @@ #define BR_NBUTTS 13 /* # of command buttons */ #define BR_SEP1 13 /* separator */ #define BR_HIDDEN 14 +#ifdef AUTO_EXPAND +#define BR_CLEARVD 15 +#define BR_SELFILES 16 +#define BR_NCMDS 17 /* # of menu commands */ +#else #define BR_SELFILES 15 #define BR_NCMDS 16 /* # of menu commands */ +#endif #define BUTTW 80 #define BUTTH 24 @@ -164,6 +186,9 @@ "Close window\t^c", MBSEP, "Show hidden files", /* no equiv */ +#ifdef AUTO_EXPAND + "Clear virtual directory", +#endif "Select files...\t^f" }; @@ -294,7 +319,11 @@ static void cp_special PARM((struct stat *, int)); static void cp_fifo PARM((struct stat *, int)); +#ifdef AUTO_EXPAND +static int stat2bf PARM((u_int, char *)); +#else static int stat2bf PARM((u_int)); +#endif static int selmatch PARM((char *, char *)); static int selmatch1 PARM((char *, char *)); @@ -524,6 +553,15 @@ 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_MAG] = MakePix1(br->win,br_mag_bits,br_mag_width,br_mag_height); + bfIcons[BF_MAKI] = MakePix1(br->win,br_maki_bits, + br_maki_width,br_maki_height); + bfIcons[BF_PIC] = MakePix1(br->win,br_pic_bits,br_pic_width,br_pic_height); + bfIcons[BF_PI] = MakePix1(br->win,br_pi_bits,br_pi_width,br_pi_height); + bfIcons[BF_PIC2]=MakePix1(br->win,br_pic2_bits,br_pic2_width,br_pic2_height); + bfIcons[BF_PCD] = MakePix1(br->win,br_pcd_bits,br_pcd_width,br_pcd_height); + bfIcons[BF_MGCSFX] = MakePix1(br->win,br_mgcsfx_bits, + br_mgcsfx_width,br_mgcsfx_height); /* check that they all got built */ @@ -698,6 +736,9 @@ } } +#ifdef VS_RESCMAP +static int _IfTempOut=0; +#endif /***************************************************************/ void KillBrowseWindows() @@ -730,7 +771,6 @@ return 0; } - /***************************************************************/ static int brChkEvent(br, xev) BROWINFO *br; @@ -746,6 +786,23 @@ if (!hasBeenSized) return 0; /* ignore evrythng until we get 1st Resize */ + +#ifdef VS_RESCMAP + /* force change color map if have LocalCmap */ + if (browPerfect && browCmap && (_IfTempOut==2)) + { + XSetWindowAttributes xswa; + if(LocalCmap) + xswa.colormap = LocalCmap; + else + xswa.colormap = theCmap; + for(i=0;itype == Expose) { int x,y,w,h; XExposeEvent *e = (XExposeEvent *) xev; @@ -807,7 +864,20 @@ int i,x,y; x = e->x; y = e->y; - if (e->button == Button1) { +#ifdef VS_RESCMAP + if (browCmap && browPerfect && (_IfTempOut!=0)) + { + XSetWindowAttributes xswa; + _IfTempOut--; + xswa.colormap = browCmap; + for(i=0;ibutton == 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) { @@ -1101,6 +1171,10 @@ case BR_SELFILES: doSelFilesCmd(br); break; case BR_RECURSUP: doRecurseCmd(br); break; + +#ifdef AUTO_EXPAND + case BR_CLEARVD: Vdsettle(); break; +#endif } } @@ -1250,6 +1324,18 @@ int i, allowtext; if (!nostr) setSelInfoStr(br, sel); +#ifdef AUTO_EXPAND + if (Isvdir(br->path)) { + BTSetActive(&br->but[BR_DELETE], 0); + br->cmdMB.dim[BR_DELETE] = 1; + + BTSetActive(&br->but[BR_RENAME], 0); + br->cmdMB.dim[BR_RENAME] = 1; + + BTSetActive(&br->but[BR_MKDIR], 0); + br->cmdMB.dim[BR_MKDIR] = 1; + } else { +#endif BTSetActive(&br->but[BR_DELETE], br->numlit>0); br->cmdMB.dim[BR_DELETE] = !(br->numlit>0); @@ -1258,6 +1344,11 @@ BTSetActive(&br->but[BR_GENICON], br->numlit>0); br->cmdMB.dim[BR_GENICON] = !(br->numlit>0); +#ifdef AUTO_EXPAND + BTSetActive(&br->but[BR_MKDIR], 1); + br->cmdMB.dim[BR_MKDIR] = 0; + } +#endif /* turn on 'text view' cmd if exactly one non-dir is lit */ allowtext = 0; @@ -1318,6 +1409,9 @@ struct stat st; sprintf(buf, "%s%s", br->path, bf->name); /* build filename */ +#ifdef AUTO_EXPAND + Dirtovd(buf); +#endif if (stat(buf, &st) == 0) { sprintf(buf, "%s: %ld bytes", bf->name, st.st_size); strcat(buf, buf1); @@ -2165,13 +2259,32 @@ else sprintf(buf, "%s%s", br->path, br->bfList[sel].name); #endif +#ifdef AUTO_EXPAND + if (Chvdir(buf)) { +#else if (chdir(buf)) { +#endif char str[512]; sprintf(str,"Unable to cd to '%s'\n", br->bfList[sel].name); setBrowStr(br, str); XBell(theDisp, 50); } else { +#ifdef AUTO_EXPAND + if (Isvdir(buf)) { + BTSetActive(&br->but[BR_DELETE], 0); + br->cmdMB.dim[BR_DELETE] = 1; + + BTSetActive(&br->but[BR_RENAME], 0); + br->cmdMB.dim[BR_RENAME] = 1; + + BTSetActive(&br->but[BR_MKDIR], 0); + br->cmdMB.dim[BR_MKDIR] = 1; + } else { + BTSetActive(&br->but[BR_MKDIR], 1); + br->cmdMB.dim[BR_MKDIR] = 0; + } +#endif scanDir(br); SCSetVal(&(br->scrl), 0); /* reset to top on a chdir */ } @@ -2193,7 +2306,29 @@ *event_retP = THISNEXT; } else { *event_retP = LOADPIC; SetDirFName(buf); } - + +#ifdef VS_RESCMAP + /* Change Colormap for browser */ + if (browPerfect && browCmap) + { + int i; + XSetWindowAttributes xswa; + if(LocalCmap) + { + xswa.colormap = LocalCmap; + _IfTempOut=2; + } + else + { + xswa.colormap = theCmap; + _IfTempOut=2; + } + for(i=0;ipath, br->bfList[i].name); +#ifdef AUTO_EXPAND + Dirtovd(foo); +#endif for (j=0; jbfLen && !br->bfList[i].lit; i++); /* find lit one */ sprintf(fname, "%s%s", br->path, br->bfList[i].name); +#ifdef AUTO_EXPAND + Dirtovd(fname); +#endif viewsel = !(strcmp(fname, fullfname)); if (viewsel) { @@ -2554,7 +2695,11 @@ } #endif +#ifdef AUTO_EXPAND + if (Chvdir(tmppath)) { +#else if (chdir(tmppath)) { +#endif char str[512]; sprintf(str,"Unable to cd to '%s'\n", tmppath); MBRedraw(&(br->dirMB)); @@ -2562,6 +2707,21 @@ XBell(theDisp, 50); } else { +#ifdef AUTO_EXPAND + if (Isvdir(tmppath)) { + BTSetActive(&br->but[BR_DELETE], 0); + br->cmdMB.dim[BR_DELETE] = 1; + + BTSetActive(&br->but[BR_RENAME], 0); + br->cmdMB.dim[BR_RENAME] = 1; + + BTSetActive(&br->but[BR_MKDIR], 0); + br->cmdMB.dim[BR_MKDIR] = 1; + } else { + BTSetActive(&br->but[BR_MKDIR], 1); + br->cmdMB.dim[BR_MKDIR] = 0; + } +#endif scanDir(br); SCSetVal(&br->scrl, 0); /* reset to top of window on a chdir */ } @@ -2582,7 +2742,11 @@ if ((strlen(br->path) > (size_t) 2) && br->path[strlen(br->path)-1] == '/') br->path[strlen(br->path)-1] = '\0'; +#ifdef AUTO_EXPAND + rv = Chvdir(br->path); +#else rv = chdir(br->path); +#endif if (rv) { char str[512]; sprintf(str, "Unable to cd to '%s'\n", br->path); @@ -2590,6 +2754,22 @@ XBell(theDisp, 50); } +#ifdef AUTO_EXPAND + if (Isvdir(br->path)) { + BTSetActive(&br->but[BR_DELETE], 0); + br->cmdMB.dim[BR_DELETE] = 1; + + BTSetActive(&br->but[BR_RENAME], 0); + br->cmdMB.dim[BR_RENAME] = 1; + + BTSetActive(&br->but[BR_MKDIR], 0); + br->cmdMB.dim[BR_MKDIR] = 1; + } else { + BTSetActive(&br->but[BR_MKDIR], 1); + br->cmdMB.dim[BR_MKDIR] = 0; + } +#endif + strcat(br->path, "/"); /* put trailing '/' back on */ return rv; } @@ -2616,8 +2796,10 @@ strcpy(dstbr->mblist[i], srcbr->mblist[i]); } - dstbr->dirMB.list = srcbr->mblist; - dstbr->dirMB.nlist = srcbr->ndirs; +/* dstbr->dirMB.list = srcbr->mblist; /* original bug..? */ +/* dstbr->dirMB.nlist = srcbr->ndirs; */ + dstbr->dirMB.list = dstbr->mblist; /* fixed by */ + dstbr->dirMB.nlist = dstbr->ndirs; /* jp-extension. */ XClearArea(theDisp, dstbr->dirMB.win, dstbr->dirMB.x, dstbr->dirMB.y, dstbr->dirMB.w+3, dstbr->dirMB.h+3, False); @@ -2975,7 +3157,11 @@ if (stat(bf->name, &st)==0) { +#ifdef AUTO_EXPAND + bf->ftype = stat2bf((u_int) st.st_mode , bf->name); +#else bf->ftype = stat2bf((u_int) st.st_mode); +#endif if (bf->ftype == BF_FILE && (st.st_mode & 0111)) bf->ftype = BF_EXE; switch (bf->ftype) { @@ -3020,6 +3206,13 @@ 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_MAG: bf->ftype = BF_MAG; break; + case RFT_MAKI: bf->ftype = BF_MAKI; break; + case RFT_PIC: bf->ftype = BF_PIC; break; + case RFT_PI: bf->ftype = BF_PI; break; + case RFT_PIC2: bf->ftype = BF_PIC2; break; + case RFT_PCD: bf->ftype = BF_PCD; break; + case RFT_MGCSFX: bf->ftype = BF_MGCSFX; break; } } } @@ -3406,7 +3599,7 @@ double wexpand,hexpand; int iwide, ihigh; byte *icon24, *icon8; - char str[256], str1[256], *readname, uncompname[128]; + char str[256], str1[256], readname[128], uncompname[128]; char basefname[128], *uncName; @@ -3415,7 +3608,7 @@ basefname[0] = '\0'; pinfo.pic = (byte *) NULL; pinfo.comment = (char *) NULL; - readname = bf->name; + strcpy(readname, bf->name); /* free any old info in 'bf' */ if (bf->imginfo) free (bf->imginfo); @@ -3445,7 +3638,7 @@ if (UncompressFile(uncName, uncompname)) { filetype = ReadFileType(uncompname); - readname = uncompname; + strcpy(readname, uncompname); } else { sprintf(str, "Couldn't uncompress file '%s'", bf->name); @@ -3454,6 +3647,51 @@ } } +#ifdef MACBINARY + if (handlemacb && macb_file == True && bf->ftype != BF_ERROR) { + if (RemoveMacbinary(readname, uncompname)) { + if (strcmp(readname, bf->name)!=0) unlink(readname); + strcpy(readname, uncompname); + } + else { + sprintf(str, "Unable to remove a InfoFile header form '%s'.", bf->name); + setBrowStr(br, str); + bf->ftype = BF_ERROR; + } + } +#endif + +#ifdef HAVE_MGCSFX_AUTO + if (bf->ftype != BF_ERROR) { + if(filetype == RFT_MGCSFX){ + char tmpname[128]; + char *icom; + + if((icom = mgcsfx_auto_input_com(bf->name)) != NULL){ + sprintf(tmpname, "%s/xvmsautoXXXXXX", tmpdir); + mktemp(tmpname); + SetISTR(ISTR_INFO, "Converting to known format by MgcSfx auto..."); + sprintf(str,"%s >%s", icom, tmpname); + }else goto ms_auto_no; + +#ifndef VMS + if (system(str)) { +#else + if (!system(str)) { +#endif + sprintf(str, "Unable to convert '%s' by MgcSfx auto.", bf->name); + setBrowStr(br, str); + bf->ftype = BF_ERROR; + } else { + filetype = ReadFileType(tmpname); + if (strcmp(readname, bf->name)!=0) unlink(readname); + strcpy(readname, tmpname); + } + } + } +ms_auto_no: +#endif /* HAVE_MGCSFX_AUTO */ + /* get rid of comments. don't need 'em */ if (pinfo.comment) free(pinfo.comment); pinfo.comment = (char *) NULL; @@ -3471,6 +3709,9 @@ else { /* otherwise it's a known filetype... do the *hard* part now... */ +#ifdef VS_ADJUST + normaspect = defaspect; +#endif /* VS_ADJUST */ i = ReadPicFile(readname, filetype, &pinfo, 1); KillPageFiles(pinfo.pagebname, pinfo.numpages); @@ -3490,7 +3731,7 @@ } /* if we made an uncompressed file, we can rm it now */ - if (readname != bf->name) unlink(readname); + if (strcmp(readname, bf->name)!=0) unlink(readname); /* at this point either BF_ERROR, BF_UNKNOWN, BF_EXE or pic */ @@ -3508,21 +3749,39 @@ /* compute size of icon (iwide,ihigh) */ +#ifdef VS_ADJUST + if (!vsadjust) normaspect = 1; + + wexpand = (double) (pinfo.w * normaspect) / (double) ISIZE_WIDE; +#else wexpand = (double) pinfo.w / (double) ISIZE_WIDE; +#endif /* VS_ADJUST */ hexpand = (double) pinfo.h / (double) ISIZE_HIGH; if (wexpand >= 1.0 || hexpand >= 1.0) { /* don't expand small icons */ if (wexpand>hexpand) { +#ifdef VS_ADJUST + iwide = (int) ((pinfo.w * normaspect) / wexpand + 0.5); +#else iwide = (int) (pinfo.w / wexpand + 0.5); +#endif /* VS_ADJUST */ ihigh = (int) (pinfo.h / wexpand + 0.5); } else { +#ifdef VS_ADJUST + iwide = (int) ((pinfo.w * normaspect) / hexpand + 0.5); +#else iwide = (int) (pinfo.w / hexpand + 0.5); +#endif /* VS_ADJUST */ ihigh = (int) (pinfo.h / hexpand + 0.5); } } else { /* smaller than ISIZE. Leave it that way. */ +#ifdef VS_ADJUST + iwide = pinfo.w * normaspect; ihigh = pinfo.h; +#else iwide = pinfo.w; ihigh = pinfo.h; +#endif /* VS_ADJUST */ } @@ -3567,6 +3826,13 @@ 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_MAG: strcat(str,"MAG file"); break; + case RFT_MAKI: strcat(str,"MAKI file"); break; + case RFT_PIC: strcat(str,"PIC file"); break; + case RFT_PI: strcat(str,"PI file"); break; + case RFT_PIC2: strcat(str,"PIC2 file"); break; + case RFT_PCD: strcat(str,"Photo CD file"); break; + case RFT_MGCSFX: strcat(str,"Magic Suffix file"); break; default: strcat(str,"file of unknown type"); break; } @@ -3670,6 +3936,10 @@ sprintf(thFname, "%s%s/%s", br->path, THUMBDIR, bf->name); +#ifdef AUTO_EXPAND + Dirtovd(thFname); +#endif + fp = fopen(thFname, "r"); if (!fp) return; /* nope, it doesn't have one */ @@ -3785,6 +4055,10 @@ sprintf(thFname, "%s%s/%s", br->path, THUMBDIR, bf->name); +#ifdef AUTO_EXPAND + Dirtovd(thFname); +#endif + fp = fopen(thFname, "w"); if (!fp) { sprintf(buf, "Can't create thumbnail file '%s': %s", thFname, @@ -3849,15 +4123,30 @@ sprintf(thFname, "%s%s", br->path, THUMBDIRNAME); +#ifdef AUTO_EXPAND + Dirtovd(thFname); +#endif + i = stat(thFname, &st); if (i) { /* failed, let's create it */ sprintf(thFname, "%s.", br->path); +#ifdef AUTO_EXPAND + Dirtovd(thFname); +#endif i = stat(thFname, &st); /* get permissions of parent dir */ if (!i) perm = st.st_mode & 07777; else perm = 0755; sprintf(thFname, "%s%s", br->path, THUMBDIRNAME); +#ifdef AUTO_EXPAND + Dirtovd(thFname); +# ifdef VIRTUAL_TD + if (mkdir(thFname, (mode_t) perm) < 0) + Mkvdir_force(thFname); +# else mkdir(thFname, (mode_t) perm); +# endif +#endif } } @@ -3964,7 +4253,11 @@ sprintf(thfname, "%s/%s", THUMBDIR, dp->d_name); if (stat(thfname, &thumbst)==0) { /* success */ int tmp; +#ifdef AUTO_EXPAND + tmp = stat2bf((u_int) thumbst.st_mode , thfname); +#else tmp = stat2bf((u_int) thumbst.st_mode); +#endif if (tmp == BF_FILE) { /* a plain file */ /* see if this thumbfile has an associated pic file */ @@ -4043,6 +4336,15 @@ static char *labels[] = { "\nOk", "\033Cancel" }; struct stat st; +#ifdef AUTO_EXPAND + if (Isvdir(br->path)) { + sprintf(buf,"Sorry, you can't rename file in the virtual directory, '%s'", + br->path); + ErrPopUp(buf, "\nBummer!"); + return; + } +#endif + if (cdBrow(br)) return; /* find the selected file */ @@ -4130,6 +4432,15 @@ static char *labels[] = { "\nOk", "\033Cancel" }; struct stat st; +#ifdef AUTO_EXPAND + if (Isvdir(br->path)) { + sprintf(buf,"Sorry, you can't mkdir in the virtual directory, '%s'", + br->path); + ErrPopUp(buf, "\nBummer!"); + return; + } +#endif + if (cdBrow(br)) return; buf[0] = '\0'; @@ -4198,12 +4509,31 @@ if (cdBrow(br)) return; /* prints its own error message */ } +#ifdef AUTO_EXPAND + if (Chvdir(buf)) { +#else if (chdir(buf)) { +#endif sprintf(str,"Unable to cd to '%s'\n", buf); setBrowStr(br, str); XBell(theDisp, 50); } else { +#ifdef AUTO_EXPAND + if (Isvdir(buf)) { + BTSetActive(&br->but[BR_DELETE], 0); + br->cmdMB.dim[BR_DELETE] = 1; + + BTSetActive(&br->but[BR_RENAME], 0); + br->cmdMB.dim[BR_RENAME] = 1; + + BTSetActive(&br->but[BR_MKDIR], 0); + br->cmdMB.dim[BR_MKDIR] = 1; + } else { + BTSetActive(&br->but[BR_MKDIR], 1); + br->cmdMB.dim[BR_MKDIR] = 0; + } +#endif scanDir(br); SCSetVal(&(br->scrl), 0); /* reset to top on a chdir */ } @@ -4230,6 +4560,15 @@ char buf[512]; static char *yesno[] = { "\004Delete", "\033Cancel" }; +#ifdef AUTO_EXPAND + if (Isvdir(br->path)) { + sprintf(buf,"Sorry, you can't delete file at the virtual directory, '%s'", + br->path); + ErrPopUp(buf, "\nBummer!"); + return; + } +#endif + if (!br->bfLen || !br->bfList || !br->numlit) return; if (cdBrow(br)) return; /* can't cd to this directory. screw it! */ @@ -4252,7 +4591,11 @@ for (i=0, bf=br->bfList; ibfLen; i++,bf++) { if (bf->lit) { if (firstdel == -1) firstdel = i; - if (bf->ftype == BF_DIR) numdirs++; + if (bf->ftype == BF_DIR +#ifdef AUTO_EXPAND + && (!Isarchive(bf->name)) +#endif + ) numdirs++; else numfiles++; } } @@ -4266,7 +4609,12 @@ slen = strlen(buf); for (i=0, bf=br->bfList; ibfLen; i++,bf++) { +#ifdef AUTO_EXPAND + if (bf->lit && (bf->ftype != BF_DIR || Isarchive(bf->name))) { +#else if (bf->lit && bf->ftype != BF_DIR) { +#endif + if ( (slen + strlen(bf->name) + 1) > 256) { strcat(buf,"..."); break; @@ -4291,7 +4639,11 @@ slen = strlen(buf); for (i=0, bf=br->bfList; ibfLen; i++,bf++) { +#ifdef AUTO_EXPAND + if (bf->lit && (bf->ftype == BF_DIR || !Isarchive(bf->name))) { +#else if (bf->lit && bf->ftype == BF_DIR) { +#endif if ( (slen + strlen(bf->name) + 1) > 256) { strcat(buf,"..."); break; @@ -4312,7 +4664,11 @@ for (i=0, bf=br->bfList; ibfLen; i++,bf++) { if (bf->lit) { - if (bf->ftype == BF_DIR) rm_dir (br, bf->name); + if (bf->ftype == BF_DIR +#ifdef AUTO_EXPAND + && !Isarchive(bf->name) +#endif + ) rm_dir (br, bf->name); else rm_file(br, bf->name); } } @@ -4441,7 +4797,11 @@ xv_getwd(orgDir, sizeof(orgDir)); sprintf(curDir, "%s%s", br->path, subdir); +#ifdef AUTO_EXPAND + if (Chvdir(curDir)) { +#else if (chdir(curDir)) { +#endif char str[512]; sprintf(str, "Unable to cd to '%s'\n", curDir); setBrowStr(br, str); @@ -4453,14 +4813,22 @@ /* have we looped? */ for (i=0; i mouse button for menu."); DrawStr2Pic(str, DWIDE/2+1, 241+1, dfltpic, DWIDE, DHIGH, 252); DrawStr2Pic(str, DWIDE/2, 241, dfltpic, DWIDE, DHIGH, 250); @@ -194,15 +209,23 @@ dfltpic, DWIDE, DHIGH, DWIDE/2, 160, 102); xbm2pic((byte *) xv_cpyrt_bits, xv_cpyrt_width, xv_cpyrt_height, - dfltpic, DWIDE, DHIGH, DWIDE/2, 203, 102); + dfltpic, DWIDE, DHIGH, DWIDE/2, 194, 102); i = xv_ver_width + xv_rev_width + 30; xbm2pic((byte *) xv_ver_bits, xv_ver_width, xv_ver_height, - dfltpic, DWIDE, DHIGH, DWIDE/2 - (i/2) + xv_ver_width/2, 220, 102); + dfltpic, DWIDE, DHIGH, DWIDE/2 - (i/2) + xv_ver_width/2, 209, 102); xbm2pic((byte *) xv_rev_bits, xv_rev_width, xv_rev_height, - dfltpic, DWIDE, DHIGH, DWIDE/2 + (i/2) - xv_rev_width/2, 220, 102); + dfltpic, DWIDE, DHIGH, DWIDE/2 + (i/2) - xv_rev_width/2, 209, 102); + + /* Japanese Extension Revision */ + i = xv_jpext_width + xv_jprev_width + 30; + + xbm2pic((byte *) xv_jpext_bits, xv_jpext_width, xv_jpext_height, + dfltpic, DWIDE, DHIGH, DWIDE/2 - (i/2) + xv_jpext_width/2, 222, 102); + xbm2pic((byte *) xv_jprev_bits, xv_jprev_width, xv_jprev_height, + dfltpic, DWIDE, DHIGH, DWIDE/2 + (i/2) - xv_jprev_width/2, 222, 102); strcpy(str,"Press mouse button for menu."); DrawStr2Pic(str, DWIDE/2, 241, dfltpic, DWIDE, DHIGH, 102); diff -urN xv-3.10a/xvdir.c xv-3.10a-jp-extension-current/xvdir.c --- xv-3.10a/xvdir.c Wed Jan 4 06:21:39 1995 +++ xv-3.10a-jp-extension-current/xvdir.c Wed Oct 9 20:36:22 1996 @@ -73,6 +73,24 @@ "Targa (24-bit)", "FITS", "PM", +#ifdef HAVE_MAG + "MAG", +#endif /* HAVE_MAG */ +#ifdef HAVE_PIC + "PIC", +#endif /* HAVE_PIC */ +#ifdef HAVE_MAKI + "MAKI", +#endif /* HAVE_MAKI */ +#ifdef HAVE_PI + "PI", +#endif /* HAVE_PI */ +#ifdef HAVE_PIC2 + "PIC2", +#endif /* HAVE_PIC2 */ +#ifdef HAVE_MGCSFX + "MgcSfx", +#endif /* HAVE_MGCSFX */ MBSEP, "Filename List"}; @@ -571,7 +589,11 @@ } #endif +#ifdef AUTO_EXPAND + if (Chvdir(tmppath)) { +#else if (chdir(tmppath)) { +#endif char str[512]; sprintf(str,"Unable to cd to '%s'\n", tmppath); *trunc_point = '/'; /* restore the path */ @@ -636,7 +658,11 @@ xv_getwd(path, sizeof(path)); #endif +#ifdef AUTO_EXPAND + if (Chvdir(path)) { +#else if (chdir(path)) { +#endif ErrPopUp("Current load/save directory seems to have gone away!", "\nYikes!"); #ifdef apollo @@ -644,7 +670,11 @@ #else strcpy(path,"/"); #endif +#ifdef AUTO_EXPAND + Chvdir(path); +#else chdir(path); +#endif } changedDir = strcmp(path, oldpath); @@ -749,6 +779,9 @@ else if (S_ISFIFO(ftype)) fnames[i][0] = C_FIFO; else if (S_ISSOCK(ftype)) fnames[i][0] = C_SOCK; else if (fnames[i][0] == C_REG && (mode&0111)) fnames[i][0] = C_EXE; +#ifdef AUTO_EXPAND + else if (Isarchive(fnames[i]+1)) fnames[i][0] = C_DIR; +#endif } else { /* fprintf(stderr,"problems 'stat-ing' files\n");*/ @@ -1054,6 +1087,25 @@ fullname = GetDirFullName(); +#ifdef AUTO_EXPAND + { + char path[MAXPATHLEN]; + + GetDirPath(path); + Mkvdir(path); + if ((i = Isvdir(fullname)) & 01) { + char buf[128]; + sprintf(buf, + "Sorry, you can't save file in the virtual directory, '%s'", + path); + ErrPopUp(buf, "\nBummer!"); + return -1; + } + if (i & 06) + Rmvdir(fullname); + } +#endif + fmt = MBWhich(&fmtMB); col = MBWhich(&colMB); @@ -1115,7 +1167,25 @@ } #endif +#ifdef HAVE_PIC2 + else if (fmt == F_PIC2) { /* PIC2 */ + if (PIC2SaveParams(fullname, col) < 0) + return 0; + PIC2Dialog(1); /* open PIC2 Dialog box */ + dbut[S_BOK].lit = 0; BTRedraw(&dbut[S_BOK]); + return 0; /* always 'succeeds' */ + } +#endif /* HAVE_PIC2 */ +#ifdef HAVE_MGCSFX + else if (fmt == F_MGCSFX) { /* MGCSFX */ + if (MGCSFXSaveParams(fullname, col) < 0) + return 0; + MGCSFXDialog(1); /* open MGCSFX Dialog box */ + dbut[S_BOK].lit = 0; BTRedraw(&dbut[S_BOK]); + return 0; /* always 'succeeds' */ + } +#endif /* HAVE_MGCSFX */ WaitCursor(); @@ -1169,12 +1239,34 @@ 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; +#ifdef HAVE_MAG + case F_MAG: + rv = WriteMAG (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, + picComments); break; +#endif /* HAVE_MAG */ +#ifdef HAVE_PIC + case F_PIC: + rv = WritePIC (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, + picComments); break; +#endif /* HAVE_PIC */ +#ifdef HAVE_MAKI + case F_MAKI: + rv = WriteMAKI (fp, thepic, ptype, w, h, rp, gp, bp, nc, col); break; +#endif /* HAVE_MAKI */ + +#ifdef HAVE_PI + case F_PI: + rv = WritePi (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, + picComments); break; +#endif /* HAVE_PI */ + } - + if (CloseOutFile(fp, fullname, rv) == 0) { DirBox(0); @@ -1387,7 +1479,13 @@ (strcmp(lowsuf,"jpeg")==0) || (strcmp(lowsuf,"jfif")==0) || (strcmp(lowsuf,"tif" )==0) || - (strcmp(lowsuf,"tiff")==0)) { + (strcmp(lowsuf,"tiff")==0) || + (strcmp(lowsuf,"mag" )==0) || + (strcmp(lowsuf,"pic" )==0) || + (strcmp(lowsuf,"mki" )==0) || + (strcmp(lowsuf,"pi" )==0) || + (strcmp(lowsuf,"p2" )==0) || + (strcmp(lowsuf,"pcd" )==0)){ /* found one. set lowsuf = to the new suffix, and tack on to filename */ @@ -1423,8 +1521,29 @@ #ifdef HAVE_TIFF case F_TIFF: strcpy(lowsuf,"tif"); break; #endif + +#ifdef HAVE_MAG + case F_MAG: strcpy(lowsuf,"mag"); break; +#endif /* HAVE_MAG */ + +#ifdef HAVE_PIC + case F_PIC: strcpy(lowsuf,"pic"); break; +#endif /* HAVE_PIC */ + +#ifdef HAVE_MAKI + case F_MAKI: strcpy(lowsuf,"mki"); break; +#endif /* HAVE_MAKI */ + +#ifdef HAVE_PI + case F_PI: strcpy(lowsuf,"pi"); break; +#endif /* HAVE_PI */ + +#ifdef HAVE_PIC2 + case F_PIC2: strcpy(lowsuf,"p2"); break; +#endif /* HAVE_PIC2 */ } + if (allcaps) { /* upper-caseify lowsuf */ for (sp=lowsuf; *sp; sp++) *sp = (islower(*sp)) ? toupper(*sp) : *sp; @@ -1490,6 +1609,11 @@ } #endif +#ifdef AUTO_EXPAND + Mkvdir(newpath); + Dirtovd(newpath); +#endif + if (stat(newpath, &st)==0) { int isdir; @@ -1587,7 +1711,11 @@ dopipe = 0; /* make sure we're in the correct directory */ +#ifdef AUTO_EXPAND + if (strlen(path)) Chvdir(path); +#else if (strlen(path)) chdir(path); +#endif if (ISPIPE(filename[0])) { /* do piping */ /* make up some bogus temp file to put this in */ @@ -2062,3 +2190,150 @@ } +#ifdef HAVE_PIC2 +/**** Stuff for PIC2Dialog box ****/ +FILE *pic2_OpenOutFile(filename, append) +char *filename; +int *append; +{ + /* opens file for output. does various error handling bits. Returns + an open file pointer if success, NULL if failure */ + + FILE *fp; + struct stat st; + + if (!filename || filename[0] == '\0') + return (NULL); + strcpy(outFName, filename); + dopipe = 0; + + /* make sure we're in the correct directory */ +#ifdef AUTO_EXPAND + if (strlen(path)) Chvdir(path); +#else + if (strlen(path)) chdir(path); +#endif + + if (ISPIPE(filename[0])) { /* do piping */ + /* make up some bogus temp file to put this in */ +#ifndef VMS + sprintf(outFName, "%s/xvXXXXXX", tmpdir); +#else + strcpy(outFName, "[]xvXXXXXX.lis"); +#endif + mktemp(outFName); + dopipe = 1; + } + + + /* see if file exists (ie, we're overwriting) */ + *append = 0; + if (stat(outFName, &st)==0) /* stat succeeded, file must exist */ + if (ReadFileType(outFName) != RFT_PIC2) { + static char *foo[] = { "\nOk", "\033Cancel" }; + char str[512]; + + sprintf(str,"Overwrite existing file '%s'?", outFName); + if (PopUp(str, foo, 2)) + return (NULL); + } else { + static char *foo[] = { "\nOk", "\033Cancel" }; + char str[512]; + + sprintf(str,"Append to existing file '%s'?", outFName); + if (PopUp(str, foo, 2)) { + sprintf(str,"Overwrite existing file '%s'?", outFName); + if (PopUp(str, foo, 2)) + return (NULL); + } else + *append = 1; + } + + + /* Open file */ + fp = *append ? fopen(outFName, "r+") : fopen(outFName, "w"); + if (!fp) { + char str[512]; + sprintf(str,"Can't write file '%s'\n\n %s.",outFName, ERRSTR(errno)); + ErrPopUp(str, "\nBummer"); + return (NULL); + } + + return (fp); +} + + +/***************************************/ +void pic2_KillNullFile(fp) +FILE *fp; +{ + fseek(fp, (size_t) 0, SEEK_END); + if (ftell(fp) > 0) { + fclose(fp); + return; + } else { + fclose(fp); + unlink(outFName); + return; + } +} +#endif /* HAVE_PIC2 */ + + +#ifdef HAVE_MGCSFX +/**** Stuff for MGCSFX Dialog box ****/ +/***************************************/ +int OpenOutFileDesc(filename) + char *filename; +{ + /* opens file for output. does various error handling bits. Returns + an open file pointer if success, NULL if failure */ + + int fd; + struct stat st; + + if (!filename || filename[0] == '\0') return -1; + strcpy(outFName, filename); + dopipe = 0; + + /* make sure we're in the correct directory */ +#ifdef AUTO_EXPAND + if (strlen(path)) Chvdir(path); +#else + if (strlen(path)) chdir(path); +#endif + + if (ISPIPE(filename[0])) { /* do piping */ + /* make up some bogus temp file to put this in */ +#ifndef VMS + sprintf(outFName, "%s/xvXXXXXX", tmpdir); +#else + strcpy(outFName, "[]xvXXXXXX.lis"); +#endif + 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 -1; + } + + + /* Open file */ + fd = open(outFName, O_WRONLY | O_CREAT | O_TRUNC, (0644)); + if (fd < 0) { + char str[512]; + sprintf(str,"Can't write file '%s'\n\n %s.",outFName, ERRSTR(errno)); + ErrPopUp(str, "\nBummer"); + return -1; + } + + return fd; +} +#endif /* HAVE_MGCSFX */ diff -urN xv-3.10a/xvevent.c xv-3.10a-jp-extension-current/xvevent.c --- xv-3.10a/xvevent.c Tue Jan 24 08:20:24 1995 +++ xv-3.10a-jp-extension-current/xvevent.c Sat Oct 12 16:32:46 1996 @@ -155,6 +155,8 @@ { static int wasInfoUp=0, wasCtrlUp=0, wasDirUp=0, wasGamUp=0, wasPsUp=0; static int wasJpegUp=0, wasTiffUp=0; + static int wasPic2Up=0, wasPcdUp=0; + static int wasMgcSfxUp=0; static int mainWKludge=0; /* force first mainW expose after a mainW config to redraw all of mainW */ @@ -233,6 +235,22 @@ if (TIFFCheckEvent(event)) break; /* event has been processed */ #endif +#ifdef HAVE_PIC2 + if (PIC2CheckEvent(event)) break; /* event has been processed */ +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (PCDCheckEvent (event)) break; /* event has been processed */ +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (MGCSFXCheckEvent(event)) break; /* event has been processed */ +#endif /* HAVE_MGCSFX */ + +#ifdef TV_MULTILINGUAL + if (CharsetCheckEvent(event)) break; /* event has been processed */ +#endif + if (GamCheckEvent (event)) break; /* event has been processed */ if (BrowseCheckEvent (event, &retval, &done)) break; /* event eaten */ if (TextCheckEvent (event, &retval, &done)) break; /* event eaten */ @@ -344,6 +362,9 @@ if (BrowseDelWin(client_event->window)) break; if (TextDelWin(client_event->window)) break; +#ifdef TV_MULTILINGUAL + if (CharsetDelWin(client_event->window)) break; +#endif if (client_event->window == infoW) InfoBox(0); else if (client_event->window == gamW) GamBox(0); @@ -359,6 +380,18 @@ else if (client_event->window == tiffW) TIFFDialog(0); #endif +#ifdef HAVE_PIC2 + else if (client_event->window == pic2W) PIC2Dialog(0); +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + else if (client_event->window == pcdW) PCDDialog(0); +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + else if (client_event->window == mgcsfxW) MGCSFXDialog(0); +#endif /* HAVE_MGCSFX */ + else if (client_event->window == mainW) Quit(0); } } @@ -538,6 +571,19 @@ #ifdef HAVE_TIFF if (wasTiffUp) { TIFFDialog(wasTiffUp); wasTiffUp=0; } #endif + +#ifdef HAVE_PIC2 + if (wasPic2Up) { PIC2Dialog(wasPic2Up); wasPic2Up=0; } +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (wasPcdUp) { PCDDialog(wasPcdUp); wasPcdUp=0; } +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (wasMgcSfxUp) { MGCSFXDialog(wasMgcSfxUp); wasMgcSfxUp=0; } +#endif /* HAVE_MGCSFX */ + } } } @@ -576,6 +622,19 @@ #ifdef HAVE_TIFF if (tiffUp) { wasTiffUp = tiffUp; TIFFDialog(0); } #endif + +#ifdef HAVE_PIC2 + if (pic2Up) { wasPic2Up = pic2Up; PIC2Dialog(0); } +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (pcdUp) { wasPcdUp = pcdUp; PCDDialog(0); } +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (mgcsfxUp) { wasMgcSfxUp = mgcsfxUp; MGCSFXDialog(0); } +#endif /* HAVE_MGCSFX */ + } } } @@ -1147,6 +1206,22 @@ if (TIFFCheckEvent(event)) break; #endif +#ifdef HAVE_PIC2 + if (PIC2CheckEvent(event)) break; +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (PCDCheckEvent (event)) break; +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (MGCSFXCheckEvent(event)) break; +#endif /* HAVE_MGCSFX */ + +#ifdef TV_MULTILINGUAL + if (CharsetCheckEvent(event)) break; +#endif + if (GamCheckEvent (event)) break; if (BrowseCheckEvent (event, &retval, &done)) break; if (TextCheckEvent (event, &retval, &done)) break; @@ -1366,6 +1441,18 @@ if (TIFFCheckEvent(event)) break; #endif +#ifdef HAVE_PIC2 + if (PIC2CheckEvent(event)) break; +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (PCDCheckEvent (event)) break; +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (MGCSFXCheckEvent(event)) break; +#endif /* HAVE_MGCSFX */ + if (GamCheckEvent (event)) break; if (BrowseCheckEvent (event, &retval, &done)) break; if (TextCheckEvent (event, &retval, &done)) break; @@ -2372,6 +2459,18 @@ if (tiffUp) TIFFDialog(0); /* close tiff window */ #endif +#ifdef HAVE_PIC2 + if (pic2Up) PIC2Dialog(0); /* close pic2 window */ +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (pcdUp) PCDDialog(0); /* close pcd window */ +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (mgcsfxUp) MGCSFXDialog(0); /* close mgcsfx window */ +#endif /* HAVE_MGCSFX */ + ClosePopUp(); /* make the interrupt signal look like a '\n' keypress in ctrlW */ diff -urN xv-3.10a/xvmag.c xv-3.10a-jp-extension-current/xvmag.c --- xv-3.10a/xvmag.c +++ xv-3.10a-jp-extension-current/xvmag.c Wed Oct 9 20:37:19 1996 @@ -0,0 +1,867 @@ +/* + * xvmag.c - load routine for `MAG' format pictures. + * + * The `MAG' format is used by many Japanese personal computer users. + * This program is based on MAGBIBLE.DOC which is the specification + * for `MAG' format written by Woody RINN. It is written in Japanese, + * and exists in some anon-ftp sites. + */ + +#include "xv.h" +#include + +#ifdef HAVE_MAG + +typedef unsigned short data16; + +struct mag { + jmp_buf jmp; + FILE *fp; + long fsize; + int m_256, m_dig, m_8, m_200; + int x1, y1, x2, y2, left_pad, right_pad; + int p_width, p_height, width, height; + long h_off, a_off, a_size, b_off, b_size, p_off, p_size; + byte *a, *b, *p; +}; + +static void mag_open_file PARM((struct mag*, char*)); +static void mag_read_check_data PARM((struct mag*)); +static void mag_read_comment PARM((struct mag*, char**)); +static void mag_read_header PARM((struct mag*)); +static void mag_read_palette PARM((struct mag*, byte*, byte*, byte*)); +static void mag_read_flags PARM((struct mag*)); +static void mag_read_pixel_data PARM((struct mag*)); +static void mag_expand_body PARM((struct mag*, byte**)); + +static void mag_compress_data PARM((struct mag*, byte*)); +static void mag_write_check_data PARM((struct mag*)); +static void mag_write_comment PARM((struct mag*, char *)); +static void mag_write_palette PARM((struct mag*, int, + byte*, byte*, byte*, int)); +static void mag_write_flags PARM((struct mag*)); +static void mag_write_pixel_data PARM((struct mag*)); +static void mag_write_header PARM((struct mag*)); +static void mag_set_double_word PARM((long, byte *)); + +static void mag_init_info PARM((struct mag*)); +static void mag_cleanup_mag_info PARM((struct mag*, int)); +static void mag_cleanup_pinfo PARM((PICINFO*)); +static void mag_memory_error PARM((char*, char*)); +static void mag_error PARM((struct mag*, int)); +static void mag_file_error PARM((struct mag*, int)); +static void mag_file_warning PARM((struct mag*, int)); +static void mag_show_struct PARM((struct mag*)); +static void *mag_malloc PARM((size_t, char*)); +static void *mag_realloc PARM((void*, size_t, char*)); + + +static char *mag_id = "MAKI02 "; +static struct{ + int dx, dy; +}points[16] = { + { 0, 0}, { 1, 0}, { 2, 0}, { 4, 0}, + { 0, 1}, { 1, 1}, + { 0, 2}, { 1, 2}, { 2, 2}, + { 0, 4}, { 1, 4}, { 2, 4}, + { 0, 8}, { 1, 8}, { 2, 8}, + { 0, 16}, +}; +static int try[15] = {1, 4, 5, 6, 7, 9, 10, 2, 8, 11, 12, 13, 14, 3, 15}; + +static char *mag_msgs[] = { + NULL, +#define MAG_OPEN 1 + "can't open file", +#define MAG_CORRUPT 2 + "file currupted.", +#define MAG_FORMAT 3 + "not MAG format.", +#define MAG_WRITE 4 + "write failed.", +}; + + +#define H4(x) (((int) (x) >> 4) & 0x0f) /* operates on a byte */ +#define L4(x) ((x) & 0x0f) +#define H8(x) (((x) >> 8) & 0xff) /* operates on a data16 */ +#define L8(x) ((x) & 0xff) + +#define error(msgnum) longjmp(mi->jmp, msgnum) + + +/* The main routine to load a MAG file. */ +int LoadMAG(fname, pinfo) + char *fname; + PICINFO *pinfo; +{ + struct mag mag; + int e; + + if(DEBUG) fputs("LoadMAG:\n", stderr); + + pinfo->comment = NULL; + mag_init_info(&mag); + if((e = setjmp(mag.jmp)) != 0){ + /* When an error occurs, comes here. */ + mag_cleanup_mag_info(&mag, 0); + mag_cleanup_pinfo(pinfo); + return 0; + } + + mag_open_file(&mag, fname); + mag_read_check_data(&mag); + mag_read_comment(&mag, &pinfo->comment); + mag_read_header(&mag); + mag_read_palette(&mag, pinfo->r, pinfo->g, pinfo->b); + mag_read_flags(&mag); + mag_read_pixel_data(&mag); + mag_expand_body(&mag, &pinfo->pic); + + pinfo->w = pinfo->normw = mag.width; + pinfo->h = pinfo->normh = mag.height; + pinfo->type = PIC8; + pinfo->frmType = F_MAG; + pinfo->colType = F_FULLCOLOR; + sprintf(pinfo->fullInfo, "MAG, %d colors%s (%ld bytes)", + mag.m_256 ? 256 : (mag.m_8 ? 8 : 16), + mag.m_200 ? ", aspect 0.5" : "", mag.fsize); + sprintf(pinfo->shrtInfo, "%dx%d MAG", mag.width, mag.height); + if(mag.m_200) + normaspect = 0.5; + + mag_cleanup_mag_info(&mag, 0); + return 1; +} + +static void mag_open_file(mi, fname) + struct mag *mi; + char *fname; +{ + if((mi->fp = fopen(fname, "rb")) == NULL) + mag_file_error(mi, MAG_OPEN); + fseek(mi->fp, (size_t) 0, SEEK_END); + mi->fsize = ftell(mi->fp); + fseek(mi->fp, (size_t) 0, SEEK_SET); +} + +static void mag_read_check_data(mi) + struct mag *mi; +{ + char buffer[8]; + + if(fread(buffer, (size_t) 8, (size_t) 1, mi->fp) != 1) + mag_file_error(mi, MAG_CORRUPT); + if(strncmp(buffer, mag_id, (size_t) 8) != 0) + mag_error(mi, MAG_FORMAT); +} + +static void mag_read_comment(mi, p) + struct mag *mi; + char **p; +{ + int max = -1, i = 0; + int c; + + while((c = fgetc(mi->fp)) != EOF){ + if(c == 0x1a) + break; + if(max < i){ + max += 16; + *p = mag_realloc(*p, (size_t) max + 1, "mag_read_comment#1"); + } + (*p)[i++] = c; + } + + if(c == EOF) + mag_file_error(mi, MAG_CORRUPT); + + if(max < i){ + *p = mag_realloc(*p, (size_t) max + 2, "mag_read_comment#2"); + } + if(i > 24){ + (*p)[i] = '\0'; + strcpy(*p, &(*p)[24]); + }else{ + (*p)[0] = '\0'; + } +} + +static void mag_read_header(mi) + struct mag *mi; +{ + byte buf[32]; + + mi->h_off = ftell(mi->fp); + + if(fread(buf, (size_t) 32, (size_t) 1, mi->fp) != 1) + mag_file_error(mi, MAG_CORRUPT); + + mi->m_256 = buf[3] & 0x80; + mi->m_dig = buf[3] & 0x04; + mi->m_8 = buf[3] & 0x02; + mi->m_200 = buf[3] & 0x01; + + mi->x1 = buf[ 4] + buf[ 5] * 256; + mi->y1 = buf[ 6] + buf[ 7] * 256; + mi->x2 = buf[ 8] + buf[ 9] * 256; + mi->y2 = buf[10] + buf[11] * 256; + +#define get_dword(a, b, c, d) \ + ((long)(a) << 24 | (long)(b) << 16 | (long)(c) << 8 | (long)(d)) + + mi->a_off = get_dword(buf[15], buf[14], buf[13], buf[12]); + mi->b_off = get_dword(buf[19], buf[18], buf[17], buf[16]); + mi->b_size = get_dword(buf[23], buf[22], buf[21], buf[20]); + mi->p_off = get_dword(buf[27], buf[26], buf[25], buf[24]); + mi->p_size = get_dword(buf[31], buf[30], buf[29], buf[28]); +#undef get_dword + + mi->a_size = mi->b_off - mi->a_off; + mi->a_off += mi->h_off; + mi->b_off += mi->h_off; + mi->p_off += mi->h_off; + + mi->width = mi->x2 - mi->x1 + 1; + mi->height = mi->y2 - mi->y1 + 1; + mi->left_pad = mi->x1 & 07; + mi->right_pad = 07 - (mi->x2 & 07); + mi->x1 -= mi->left_pad; /* x1 = 8m */ + mi->x2 += mi->right_pad; /* x2 = 8n+7 */ + mi->p_width = ((mi->x2 + 1) - mi->x1) / (mi->m_256 ? 2 : 4); + mi->p_height = (mi->y2 + 1) - mi->y1; + + if(DEBUG) mag_show_struct(mi); +} + +static void mag_read_palette(mi, r, g, b) + struct mag *mi; + byte *r, *g, *b; +{ + int num_palettes; + int i; + byte *buf; + + if(mi->m_256) + num_palettes = 256; + else + num_palettes = 16; + + buf = mag_malloc((size_t)num_palettes * 3, "mag_read_palette"); + + if(fread(buf, (size_t) 3, (size_t) num_palettes, mi->fp) != num_palettes){ + free(buf); + mag_file_error(mi, MAG_CORRUPT); + } + + for(num_palettes--; num_palettes >= 0; num_palettes--){ + g[num_palettes] = buf[num_palettes * 3 ]; + r[num_palettes] = buf[num_palettes * 3 + 1]; + b[num_palettes] = buf[num_palettes * 3 + 2]; + } + + free(buf); +} + +static void mag_read_flags(mi) + struct mag *mi; +{ + mi->a = mag_malloc((size_t) mi->a_size, "mag_read_flags#1"); + mi->b = mag_malloc((size_t) mi->b_size, "mag_read_flags#2"); + + fseek(mi->fp, mi->a_off, SEEK_SET); + if(fread(mi->a, (size_t) mi->a_size, (size_t) 1, mi->fp) != 1) + mag_file_warning(mi, MAG_CORRUPT); + if(fread(mi->b, (size_t) mi->b_size, (size_t) 1, mi->fp) != 1) + mag_file_warning(mi, MAG_CORRUPT); +} + +static void mag_read_pixel_data(mi) + struct mag *mi; +{ + mi->p = mag_malloc((size_t) mi->p_size, "mag_read_pixel_data"); + + fseek(mi->fp, mi->p_off, SEEK_SET); + if(fread(mi->p, (size_t) mi->p_size, (size_t) 1, mi->fp) != 1) + mag_file_warning(mi, MAG_CORRUPT); +} + +/* MAG expanding routine */ +static void mag_expand_body(mi, pic0) + struct mag *mi; + byte **pic0; +{ + int ai, bi, fi, pi, i; + int px, py, x, y; + byte *flag; + byte mask; + data16 *pixel0; + + flag = mag_malloc((size_t) mi->p_width / 2, "mag_expand_body#1"); + *pic0 = mag_malloc((size_t) mi->width * mi->height, "mag_expand_body#2"); + pixel0 = mag_malloc((size_t) 2 * mi->p_width * 17, "mag_expand_body#3"); + +#define pixel(x, y) pixel0[(y) % 17 * mi->p_width + (x)] + + ai = bi = pi = 0; + mask = 0x80; + for(y = py = 0; py < mi->p_height; py++){ + for(fi = 0; fi < mi->p_width / 2; fi++){ + if(py == 0){ + if(mi->a[ai] & mask) + flag[fi] = mi->b[bi++]; + else + flag[fi] = 0; + }else{ + if(mi->a[ai] & mask) + flag[fi] ^= mi->b[bi++]; + } + if((mask >>= 1) == 0){ + mask = 0x80; + ai++; + } + } + + for(px = fi = 0; fi < mi->p_width / 2; fi++){ + int f = H4(flag[fi]); + if(f == 0){ + pixel(px, py) = mi->p[pi] + mi->p[pi + 1] * 256; + px++; + pi+=2; + }else{ + int dx = points[f].dx, dy = points[f].dy; + pixel(px, py) = pixel(px - dx, py - dy); + px++; + } + + f = L4(flag[fi]); + if(f == 0){ + pixel(px, py) = mi->p[pi] + mi->p[pi + 1] * 256; + px++; + pi+=2; + }else{ + int dx = points[f].dx, dy = points[f].dy; + pixel(px, py) = pixel(px - dx, py - dy); + px++; + } + } + +#define inside(x) ((unsigned int)(x) < mi->width) +#define pic(x, y) (*pic0)[(y) * mi->width + (x)] + for(x = -mi->left_pad, px = 0; px < mi->p_width; px++){ + data16 p = pixel(px, py); + if(mi->m_256){ + if(inside(x)) + pic(x, y) = L8(p); + x++; + if(inside(x)) + pic(x, y) = H8(p); + x++; + }else{ + if(inside(x)) + pic(x, y) = H4(L8(p)); + x++; + if(inside(x)) + pic(x, y) = L4(L8(p)); + x++; + if(inside(x)) + pic(x, y) = H4(H8(p)); + x++; + if(inside(x)) + pic(x, y) = L4(H8(p)); + x++; + } + } + y++; + } +#undef pic +#undef inside +#undef pixel + + free(flag); + free(pixel0); +} + + +/* The main routine to write a MAG file. */ +int WriteMAG(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle, + comment) + FILE *fp; + byte *pic; + int ptype, w, h; + byte *rmap, *gmap, *bmap; + int numcols, colorstyle; + char *comment; +{ + byte rtemp[256], gtemp[256], btemp[256]; + struct mag mag; + int e; + + if(DEBUG) fputs("WriteMag\n", stderr); + + mag_init_info(&mag); + mag.fp = fp; + + if(ptype == PIC24){ + if(!(pic = Conv24to8(pic, w, h, 256, rtemp, gtemp, btemp))) + mag_memory_error("Conv24to8", "WriteMAG"); + rmap = rtemp; + gmap = gtemp; + bmap = btemp; + numcols = 256; + mag.m_256 = 1; + }else{ + if(numcols > 16) + mag.m_256 = 1; + } + + if((e = setjmp(mag.jmp)) != 0){ + /* When an error occurs, comes here. */ + mag_cleanup_mag_info(&mag, 1); + return -1; + } + + mag.x2 = w - 1; + mag.y2 = h - 1; + mag.right_pad = 07 - (mag.x2 & 07); + mag.p_width = (w + mag.right_pad) / (mag.m_256 ? 2 : 4); + mag.p_height = h; + mag.width = w; + mag.height = h; + mag.a_size = (mag.p_width * mag.p_height + 15) / 16; /* x/2/8 */ + if(mag.a_size % 2) + mag.a_size++; + + mag_compress_data(&mag, pic); + mag_write_check_data(&mag); + mag_write_comment(&mag, comment); + + mag.h_off = ftell(mag.fp); + + mag_write_palette(&mag, numcols, rmap, gmap, bmap, + colorstyle == F_GREYSCALE); + mag_write_flags(&mag); + mag_write_pixel_data(&mag); + mag_write_header(&mag); + + mag_cleanup_mag_info(&mag, 1); + return 0; +} + +/* MAG compressing routine */ +static void mag_compress_data(mi, pic0) + struct mag *mi; + byte *pic0; +{ + int ai, bi, pi, i; + int bmax, pmax; + byte mask; + byte *flag0; + data16 *pixel0; + int px, py, x, y; + + pixel0 = mag_malloc((size_t) 2 * mi->p_width * mi->p_height, + "mag_compress_data#1"); + flag0 = mag_malloc((size_t) mi->p_width * mi->p_height, + "mag_compress_data#2"); + +#define pic(x, y) pic0[(y) * mi->width + (x)] + /* convert dots to pixels */ + i = 0; + for(y = py = 0; py < mi->p_height; py++){ + for(x = px = 0; px < mi->p_width; px++){ + data16 p = 0; + if(mi->m_256){ + if(x < mi->width) + p += pic(x, y); + x++; + if(x < mi->width) + p += pic(x, y) * 256; + x++; + }else{ + if(x < mi->width) + p += pic(x, y) * 16; + x++; + if(x < mi->width) + p += pic(x, y); + x++; + if(x < mi->width) + p += pic(x, y) * 4096; + x++; + if(x < mi->width) + p += pic(x, y) * 256; + x++; + } + pixel0[i++] = p; + } + y++; + } +#undef pic + +#define pixel(x, y) pixel0[(y) * mi->p_width + (x)] +#define flag(x, y) flag0[(y) * mi->p_width + (x)] + /* get flags */ + pmax = pi = 0; + for(py = 0; py < mi->p_height; py++){ + for(px = 0; px < mi->p_width; px++){ + int t; + for(t = 0; t < 15; t++){ + int dx = points[try[t]].dx, dy = points[try[t]].dy; + if(dx <= px && dy <= py){ + if(pixel(px - dx, py - dy) == pixel(px, py)) + break; + } + } + if(t < 15){ + flag(px, py) = try[t]; + }else{ + flag(px, py) = 0; + if(pmax <= pi + 1){ + pmax += 128; + mi->p = mag_realloc(mi->p, (size_t) pmax, + "mag_compress_data#3"); + } + mi->p[pi++] = L8(pixel(px, py)); + mi->p[pi++] = H8(pixel(px, py)); + } + } + } +#undef flag +#undef pixel + + /* pack 2 flags into 1 byte */ + for(i = 0; i < mi->p_width / 2 * mi->p_height; i++) + flag0[i] = flag0[i * 2] * 16 + flag0[i * 2 + 1]; + +#define flag(x, y) flag0[(y) * mi->p_width / 2 + (x)] + for(py = mi->p_height - 1; py >= 1; py--){ + for(px = 0; px < mi->p_width / 2; px++) + flag(px, py) ^= flag(px, py - 1); + } +#undef flag + + mask = 0x80; + ai = bi = bmax = 0; + mi->a = mag_malloc((size_t) mi->a_size, "mag_compress_data#4"); + for(i = 0; i < mi->p_width / 2 * mi->p_height; i++){ + if(flag0[i] == 0){ + mi->a[ai] &= ~mask; + }else{ + if(bmax == bi){ + bmax += 128; + mi->b = mag_realloc(mi->b, (size_t) bmax, + "mag_compress_data#4"); + } + mi->b[bi++] = flag0[i]; + mi->a[ai] |= mask; + } + + if((mask >>= 1) == 0){ + mask = 0x80; + ai++; + } + } + + if(bi % 2) + bi++; + mi->b_size = bi; + + mi->p_size = pi; + + free(pixel0); + free(flag0); +} + +static void mag_write_check_data(mi) + struct mag *mi; +{ + if(fwrite(mag_id, (size_t) 8, (size_t) 1, mi->fp) != 1) + mag_file_error(mi, MAG_WRITE); +} + +static void mag_write_comment(mi, comment) + struct mag *mi; + char *comment; +{ + char *p; + int i; + + if(fputs("XV ", mi->fp) == EOF) + mag_file_error(mi, MAG_WRITE); + + if((p = (char *) getenv("USER")) == NULL) + p = "????????"; + for(i = 5; i < 24; i++){ + if(*p == '\0') + break; + if(fputc(*p++, mi->fp) == EOF) + mag_file_error(mi, MAG_WRITE); + } + for( ; i < 24; i++){ + if(fputc(' ', mi->fp) == EOF) + mag_file_error(mi, MAG_WRITE); + } + + if(comment){ + int l = strlen(comment); + if(l > 0){ + int i; + for(i = 0; i < l; i++){ + if(comment[i] == 0x1a) + comment[i] = ' '; + } + if(fwrite(comment, (size_t) l, (size_t) 1, mi->fp) != 1) + mag_file_error(mi, MAG_WRITE); + } + } + + if(fputc(0x1a, mi->fp) == EOF) + mag_file_error(mi, MAG_WRITE); +} + +static void mag_write_palette(mi, num, r, g, b, grey) + struct mag *mi; + int num; + byte *r, *g, *b; + int grey; +{ + int i, left; + char buf[3]; + + fseek(mi->fp, 32L, SEEK_CUR); /* skip header area */ + for(i = 0; i < num; i++){ + buf[0] = *g++; + buf[1] = *r++; + buf[2] = *b++; + if(grey) + buf[0] = buf[1] = buf[2] = MONO(buf[1], buf[0], buf[2]); + if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1) + mag_file_error(mi, MAG_WRITE); + } + if(num < 16){ + left = 16 - num; + }else if(num == 16){ + left = 0; + }else if(num < 256){ + left = 256 - num; + }else if(num == 256){ + left = 0; + }else + left = 0; /* shouldn't happen */ + + if(left > 0){ + for(i = 0; i < left; i++){ + if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1) + mag_file_error(mi, MAG_WRITE); + } + } +} + +static void mag_write_flags(mi) + struct mag *mi; +{ + int i; + + mi->a_off = ftell(mi->fp); + for(i = 0; i < mi->a_size; i++){ + if(fputc(mi->a[i], mi->fp) == EOF) + mag_file_error(mi, MAG_WRITE); + } + + mi->b_off = ftell(mi->fp); + for(i = 0; i < mi->b_size; i++){ + if(fputc(mi->b[i], mi->fp) == EOF) + mag_file_error(mi, MAG_WRITE); + } +} + +static void mag_write_pixel_data(mi) + struct mag *mi; +{ + int i; + + mi->p_off = ftell(mi->fp); + for(i = 0; i < mi->p_size; i++){ + if(fputc(mi->p[i], mi->fp) == EOF) + mag_file_error(mi, MAG_WRITE); + } +} + +static void mag_write_header(mi) + struct mag *mi; +{ + byte buf[32]; + + if(DEBUG) mag_show_struct(mi); + + mi->a_off -= mi->h_off; + mi->b_off -= mi->h_off; + mi->p_off -= mi->h_off; + + buf[ 0] = buf[1] = buf[2] = 0; + buf[ 3] = (mi->m_256 ? 0x80 : 0); + buf[ 4] = buf[5] = 0; + buf[ 6] = buf[7] = 0; + buf[ 8] = L8(mi->x2); + buf[ 9] = H8(mi->x2); + buf[10] = L8(mi->y2); + buf[11] = H8(mi->y2); + mag_set_double_word(mi->a_off, &buf[12]); + mag_set_double_word(mi->b_off, &buf[16]); + mag_set_double_word(mi->b_size, &buf[20]); + mag_set_double_word(mi->p_off, &buf[24]); + mag_set_double_word(mi->p_size, &buf[28]); + + fseek(mi->fp, mi->h_off, SEEK_SET); + if(fwrite(buf, (size_t) 32, (size_t) 1, mi->fp) != 1) + mag_file_error(mi, MAG_WRITE); +} + +static void mag_set_double_word(n, p) + long n; + byte *p; +{ + p[0] = n % 256; + p[1] = n / 256 % 256; + p[2] = n / 256 / 256 % 256; + p[3] = n / 256 / 256 / 256 % 256; +} + +/* + * The routines to initialize or clean up. + * mag_init_info: + * initializes a mag structure. + * mag_cleanup_mag_info: + * cleans up a mag structure. + * mag_cleanup_pinfo: + * cleans up a PICINFO structure. + */ +static void mag_init_info(mi) + struct mag *mi; +{ + mi->fp = NULL; + mi->fsize = 0; + mi->m_256 = mi->m_dig = mi->m_8 = mi->m_200 = 0; + mi->x1 = mi->y1 = mi->x2 = mi->y2 = 0; + mi->left_pad = mi->right_pad = 0; + mi->p_width = mi->p_height = mi->width = mi->height = 0; + mi->h_off = mi->p_off = mi->p_size = 0; + mi->a_off = mi->a_size = mi->b_off = mi->b_size = 0; + mi->a = NULL; + mi->b = NULL; + mi->p = NULL; +} + +static void mag_cleanup_mag_info(mi, writing) + struct mag *mi; + int writing; +{ + if(mi->fp && !writing) + fclose(mi->fp); + if(mi->a) + free(mi->a); + if(mi->b) + free(mi->b); + if(mi->p) + free(mi->p); +} + +static void mag_cleanup_pinfo(pinfo) + PICINFO *pinfo; +{ + if(pinfo->comment){ + free(pinfo->comment); + pinfo->comment = NULL; + } + if(pinfo->pic){ + free(pinfo->pic); + pinfo->pic = NULL; + } +} + +/* + * Error handler. + * mag_memory_error: + * shows an error message, and terminates. + * mag_error: + * shows an non-file error message, and jumps to the entry for errors. + * mag_file_error: + * shows an file error message, and jumps to the entry for errors. + * mag_file_warning: + * shows an file warning message. + */ +static void mag_memory_error(scm, fn) + char *scm, *fn; +{ + char buf[128]; + sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn); + FatalError(buf); +} + +static void mag_error(mi, mn) + struct mag *mi; + int mn; +{ + SetISTR(ISTR_WARNING, "%s", mag_msgs[mn]); + longjmp(mi->jmp, 1); +} + +static void mag_file_error(mi, mn) + struct mag *mi; + int mn; +{ + if(feof(mi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", mag_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", mag_msgs[mn], ERRSTR(errno)); + longjmp(mi->jmp, 1); +} + +static void mag_file_warning(mi, mn) + struct mag *mi; + int mn; +{ + if(feof(mi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", mag_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", mag_msgs[mn], ERRSTR(errno)); +} + +static void mag_show_struct (mi) + struct mag *mi; +{ + fprintf(stderr, " 256 colors: %s\n", mi->m_256 ? "true" : "false"); + fprintf(stderr, " 8 colors: %s\n", mi->m_8 ? "true" : "false"); + fprintf(stderr, " digital colors: %s\n", mi->m_dig ? "true" : "false"); + fprintf(stderr, " aspect ratio: %f\n", mi->m_200 ? 0.5 : 1.0); + fprintf(stderr, " image size: %dx%d\n", mi->width, mi->height); + fprintf(stderr, " left pad: %d\n", mi->left_pad); + fprintf(stderr, " right pad: %d\n", mi->right_pad); + fprintf(stderr, " h_off: %ld\n", mi->h_off); + fprintf(stderr, " A: off:%ld, size:%ld\n", mi->a_off, mi->a_size); + fprintf(stderr, " B: off:%ld, size:%ld\n", mi->b_off, mi->b_size); + fprintf(stderr, " P: off:%ld, size:%ld\n", mi->p_off, mi->p_size); +} + +/* Memory related routines. */ +static void *mag_malloc(n, fn) + size_t n; + char *fn; +{ + void *r = (void *) malloc(n); + if(r == NULL) + mag_memory_error("malloc", fn); + return r; +} + +static void *mag_realloc(p, n, fn) + void *p; + size_t n; + char *fn; +{ + void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n); + if(r == NULL) + mag_memory_error("realloc", fn); + return r; +} +#endif /* HAVE_MAG */ diff -urN xv-3.10a/xvmaki.c xv-3.10a-jp-extension-current/xvmaki.c --- xv-3.10a/xvmaki.c +++ xv-3.10a-jp-extension-current/xvmaki.c Wed Oct 9 20:37:19 1996 @@ -0,0 +1,789 @@ +/* + * xvmaki.c - load routine for `MAKI' format pictures. + * + * The `MAKI' format was used by some Japanese personal computer users. + */ + +#include "xv.h" +#include + +#ifdef HAVE_MAKI + +typedef unsigned short data16; +typedef unsigned int data32; + +struct maki_info { + jmp_buf jmp; + FILE *fp; + long fsize; + int x0, y0, x1, y1; + int width, height; + float aspect; + long fb_size; + long pa_size, pb_size; + int m_maki01b, m_200, m_dig8; + data16 ext_flag; + byte *fa, *fb, *pa, *pb; + byte *vs; + int numcols; + byte *forma, *formb; +}; + + +static void maki_open_file PARM((struct maki_info*, char*)); +static void maki_check_id PARM((struct maki_info*)); +static void maki_skip_comment PARM((struct maki_info*)); +static void maki_read_header PARM((struct maki_info*)); +static void maki_read_palette PARM((struct maki_info*, + byte*, byte*, byte*)); +static void maki_read_flags PARM((struct maki_info*)); +static void maki_read_pixel_data PARM((struct maki_info*)); +static void maki_expand_virtual_screen PARM((struct maki_info*)); +static void maki_expand_pixel_data PARM((struct maki_info*, byte**)); +static void maki_init_info PARM((struct maki_info*)); + +static void maki_make_pixel_data PARM((struct maki_info*, byte*)); +static void maki_make_virtual_screen PARM((struct maki_info*)); +static void maki_make_flags PARM((struct maki_info*)); +static void maki_write_check_id PARM((struct maki_info*)); +static void maki_write_comment PARM((struct maki_info*)); +static void maki_write_header PARM((struct maki_info*)); +static void maki_write_palette PARM((struct maki_info*, + byte*, byte*, byte*, int)); +static void maki_write_flags PARM((struct maki_info*)); +static void maki_write_pixel_data PARM((struct maki_info*)); + +static void maki_cleanup_maki_info PARM((struct maki_info*, int)); +static void maki_cleanup_pinfo PARM((PICINFO*)); +static void maki_memory_error PARM((char*, char*)); +static void maki_error PARM((struct maki_info*, int)); +static void maki_file_error PARM((struct maki_info*, int)); +static void maki_file_warning PARM((struct maki_info*, int)); +static void maki_show_maki_info PARM((struct maki_info*)); +static void *maki_malloc PARM((size_t, char*)); +static void *maki_realloc PARM((void *, size_t, char*)); + +static char maki_id_a[] = "MAKI01A "; +static char maki_id_b[] = "MAKI01B "; + +static char *maki_msgs[] = { + NULL, +#define MAKI_OPEN 1 + "can't open file.", +#define MAKI_CORRUPT 2 + "file corrupted.", +#define MAKI_FORMAT 3 + "not MAKI format.", +#define MAKI_BAD_DATA 4 + "bad data.", +#define MAKI_COMMENT 5 + "no '^Z' after comment.", +#define MAKI_SIZE 6 + "bad size.", +#define MAKI_WRITE 7 + "write failed.", +}; + +#define H4(b) ((b) >> 4 & 0xf) +#define L4(b) ((b) & 0xf) +#define error(msg_num) longjmp(mi->jmp, msg_num) + +int LoadMAKI(fname, pinfo) + char *fname; + PICINFO *pinfo; +{ + struct maki_info maki; + int e; + + if(DEBUG) fputs("LoadMAKI:\n", stderr); + + pinfo->comment = NULL; + maki_init_info(&maki); + if((e = setjmp(maki.jmp)) != 0){ + /* When an error occurs, comes here. */ + maki_cleanup_maki_info(&maki, 0); + maki_cleanup_pinfo(pinfo); + return 0; + } + + maki_open_file(&maki, fname); + maki_check_id(&maki); + maki_skip_comment(&maki); + maki_read_header(&maki); + maki_read_palette(&maki, pinfo->r, pinfo->g, pinfo->b); + maki_read_flags(&maki); + maki_read_pixel_data(&maki); + maki_expand_virtual_screen(&maki); + maki_expand_pixel_data(&maki, &pinfo->pic); + + pinfo->w = pinfo->normw = maki.width; + pinfo->h = pinfo->normh = maki.height; + pinfo->type = PIC8; + pinfo->frmType = F_MAKI; + pinfo->colType = F_FULLCOLOR; + sprintf(pinfo->fullInfo, "MAKI, 16 colors (%ld bytes)", maki.fsize); + sprintf(pinfo->shrtInfo, "%dx%d MAKI", maki.width, maki.height); + normaspect = maki.aspect; + + maki_cleanup_maki_info(&maki, 0); + return 1; +} + +static void maki_open_file(mi, fname) + struct maki_info *mi; + char *fname; +{ + if((mi->fp = fopen(fname, "rb")) == NULL) + maki_file_error(mi, MAKI_OPEN); + fseek(mi->fp, (size_t) 0, SEEK_END); + mi->fsize = ftell(mi->fp); + fseek(mi->fp, (size_t) 0, SEEK_SET); +} + +static void maki_check_id(mi) + struct maki_info *mi; +{ + char buf[8]; + if(fread(buf, (size_t) 8, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_CORRUPT); + if(strncmp(buf, maki_id_a, (size_t) 8) != 0 && + strncmp(buf, maki_id_b, (size_t) 8) != 0) + maki_error(mi, MAKI_FORMAT); + mi->m_maki01b = (buf[6] == 'B'); +} + +static void maki_skip_comment(mi) + struct maki_info *mi; +{ + int i; + int c; + + for(i = 0; i < 24; i++){ + if((c = fgetc(mi->fp)) == EOF) + maki_file_error(mi, MAKI_CORRUPT); + if(c == '\032') /* ^Z, 0x1a */ + break; + } + if(c != '\032') + maki_file_error(mi, MAKI_COMMENT); + + fseek(mi->fp, 32L, SEEK_SET); +} + +static void maki_read_header(mi) + struct maki_info *mi; +{ + byte buf[16]; + + if(fread(buf, (size_t) 16, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_CORRUPT); + + mi->fb_size = (long)buf[ 0] << 8 | (long)buf[ 1]; + mi->pa_size = (long)buf[ 2] << 8 | (long)buf[ 3]; + mi->pb_size = (long)buf[ 4] << 8 | (long)buf[ 5]; + mi->ext_flag = (long)buf[ 6] << 8 | (long)buf[ 7]; + mi->x0 = (long)buf[ 8] << 8 | (long)buf[ 9]; + mi->y0 = (long)buf[10] << 8 | (long)buf[11]; + mi->x1 = (long)buf[12] << 8 | (long)buf[13]; + mi->y1 = (long)buf[14] << 8 | (long)buf[15]; + + mi->width = mi->x1-- - mi->x0; + mi->height = mi->y1-- - mi->y0; + mi->m_200 = mi->ext_flag & 1; + mi->m_dig8 = mi->ext_flag & 2; + mi->aspect = mi->m_200 ? 0.5 : 1.0; + + if(DEBUG) maki_show_maki_info(mi); +} + +static void maki_read_palette(mi, r, g, b) + struct maki_info *mi; + byte *r, *g, *b; +{ + byte buf[48], *p; + + if(fread(buf, (size_t) 48, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_CORRUPT); + + for(p = buf; p < &buf[48]; ){ + *g++ = *p++; + *r++ = *p++; + *b++ = *p++; + } +} + +static void maki_read_flags(mi) + struct maki_info *mi; +{ + mi->fa = maki_malloc((size_t) 1000 , "maki_read_flags#1"); + mi->fb = maki_malloc((size_t) mi->fb_size, "maki_read_flags#2"); + + if(fread(mi->fa, (size_t) 1000, (size_t) 1, mi->fp) != 1) + maki_file_warning(mi, MAKI_CORRUPT); + if(fread(mi->fb, (size_t) mi->fb_size, (size_t) 1, mi->fp) != 1) + maki_file_warning(mi, MAKI_CORRUPT); +} + +static void maki_read_pixel_data(mi) + struct maki_info *mi; +{ + mi->pa = maki_malloc((size_t) mi->pa_size, "maki_read_pixel_data#1"); + mi->pb = maki_malloc((size_t) mi->pb_size, "maki_read_pixel_data#2"); + + if(fread(mi->pa, (size_t) mi->pa_size, (size_t) 1, mi->fp) != 1) + maki_file_warning(mi, MAKI_CORRUPT); + if(fread(mi->pb, (size_t) mi->pb_size, (size_t) 1, mi->fp) != 1) + maki_file_warning(mi, MAKI_CORRUPT); +} + +static void maki_expand_virtual_screen(mi) + struct maki_info *mi; +{ + int x, y, fai, fbi; + int bpl = mi->width / 2 / 8; /* bytes per line */ + byte mask; + mi->vs = maki_malloc((size_t) bpl * mi->height, + "maki_expand_virtual_screen"); + + fai = fbi = 0; + mask = 0x80; + for(y = 0; y < mi->height; y += 4){ + for(x = 0; x < mi->width / 2; x += 4){ + if(mi->fa[fai] & mask){ + byte bh, bl; + bh = mi->fb[fbi++]; + bl = mi->fb[fbi++]; + if(x % 8 == 0){ + mi->vs[ y * bpl + x / 8] = H4(bh) << 4; + mi->vs[(y + 1) * bpl + x / 8] = L4(bh) << 4; + mi->vs[(y + 2) * bpl + x / 8] = H4(bl) << 4; + mi->vs[(y + 3) * bpl + x / 8] = L4(bl) << 4; + }else{ + mi->vs[ y * bpl + x / 8] |= H4(bh); + mi->vs[(y + 1) * bpl + x / 8] |= L4(bh); + mi->vs[(y + 2) * bpl + x / 8] |= H4(bl); + mi->vs[(y + 3) * bpl + x / 8] |= L4(bl); + } + }else{ + if(x % 8 == 0){ + mi->vs[ y * bpl + x / 8] = 0; + mi->vs[(y + 1) * bpl + x / 8] = 0; + mi->vs[(y + 2) * bpl + x / 8] = 0; + mi->vs[(y + 3) * bpl + x / 8] = 0; + }else{ +/* mi->vs[ y * bpl + x / 8] |= 0; + mi->vs[(y + 1) * bpl + x / 8] |= 0; + mi->vs[(y + 2) * bpl + x / 8] |= 0; + mi->vs[(y + 3) * bpl + x / 8] |= 0; */ + } + } + + if((mask >>= 1) == 0){ + mask = 0x80; + fai++; + } + } + } +} + +static void maki_expand_pixel_data(mi, pic) + struct maki_info *mi; + byte **pic; +{ + int x, y; + int vsi, pi, max_pi; + byte *p; + byte mask; + int gap; + *pic = maki_malloc((size_t) mi->width * mi->height, + "maki_expand_pixel_data"); + + vsi = pi = 0; + p = mi->pa; + max_pi = mi->pa_size - 1; + mask = 0x80; + for(y = 0; y < mi->height; y++){ + for(x = 0; x < mi->width; x += 2){ + if(mi->vs[vsi] & mask){ + if(pi > max_pi){ + if(p == mi->pb) + maki_error(mi, MAKI_BAD_DATA); + pi = 0; + p = mi->pb; + max_pi = mi->pb_size - 1; + } + (*pic)[y * mi->width + x ] = H4(p[pi]); + (*pic)[y * mi->width + x + 1] = L4(p[pi]); + pi++; + }else{ + (*pic)[y * mi->width + x ] = 0; + (*pic)[y * mi->width + x + 1] = 0; + } + + if((mask >>= 1) == 0){ + mask = 0x80; + vsi++; + } + } + } + + gap = mi->m_maki01b ? 4 : 2; + + for(y = gap; y < mi->height; y++){ + for(x = 0; x < mi->width; x++) + (*pic)[y * mi->width + x] ^= (*pic)[(y - gap) * mi->width + x]; + } +} + + +int WriteMAKI(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle) + FILE *fp; + byte *pic; + int ptype, w, h; + byte *rmap, *gmap, *bmap; + int numcols, colorstyle; +{ + byte rtemp[256], gtemp[256], btemp[256]; + struct maki_info maki, *mi = &maki; + int e; + + if(DEBUG) fputs("WriteMAKI:\n", stderr); + + maki_init_info(&maki); + if((e = setjmp(maki.jmp)) != 0){ + /* An error occurs */ + maki_cleanup_maki_info(&maki, 1); + return -1; + } + + if(w != 640 || h != 400) + maki_error(mi, MAKI_SIZE); + + maki.fp = fp; + maki.width = w; + maki.height = h; + maki.x1 = w - 1; + maki.y1 = h - 1; + + if(ptype == PIC24){ + if(!(pic = Conv24to8(pic, w, h, 16, rtemp, gtemp, btemp))) + maki_memory_error("Conv24to8#1", "WriteMAKI"); + rmap = rtemp; + gmap = gtemp; + bmap = btemp; + }else if(numcols > 16){ + if(!(pic = Conv8to24(pic, w, h, rmap, gmap, bmap))) + maki_memory_error("Conv8to24", "WriteMAKI"); + if(!(pic = Conv24to8(pic, w, h, 16, rtemp, gtemp, btemp))) + maki_memory_error("Conv24to8#2", "WriteMAKI"); + rmap = rtemp; + gmap = gtemp; + bmap = btemp; + }else + maki.numcols = numcols; + + maki_make_pixel_data(&maki, pic); + maki_make_virtual_screen(&maki); + maki_make_flags(&maki); + maki_write_check_id(&maki); + maki_write_comment(&maki); + maki_write_header(&maki); + maki_write_palette(&maki, rmap, gmap, bmap, colorstyle == F_GREYSCALE); + maki_write_flags(&maki); + maki_write_pixel_data(&maki); + + maki_cleanup_maki_info(&maki, 1); + return 0; +} + +static void maki_make_pixel_data(mi, pic) + struct maki_info *mi; + byte *pic; +{ + int x, y, i; + int nza, nzb; + + mi->forma = maki_malloc((size_t) mi->width / 2 * mi->height, + "maki_make_pixel_data#1"); + mi->formb = maki_malloc((size_t) mi->width / 2 * mi->height, + "maki_make_pixel_data#2"); + + for(y = 0; y < mi->height; y++){ + for(x = 0; x < mi->width; x += 2){ + byte b; + b = pic[y * mi->width + x] << 4 | pic[y * mi->width + x + 1]; + mi->forma[y * mi->width / 2 + x / 2] = b; + mi->formb[y * mi->width / 2 + x / 2] = b; + } + } + + for(y = mi->height - 1; y >= 2; y--){ + for(x = 0; x < mi->width / 2; x++){ + mi->forma[y * mi->width / 2 + x] ^= + mi->forma[(y - 2) * mi->width / 2 + x]; + } + } + + for(y = mi->height - 1; y >= 4; y--){ + for(x = 0; x < mi->width / 2; x++){ + mi->formb[y * mi->width / 2 + x] ^= + mi->formb[(y - 4) * mi->width / 2 + x]; + } + } + + nza = nzb = 0; + for(i = 0; i < mi->width / 2 * mi->height; i++){ + if(mi->forma[i] != 0) + nza++; + if(mi->formb[i] != 0) + nzb++; + } + if(nza > nzb){ + mi->m_maki01b = 1; + free(mi->forma); + mi->forma = NULL; + }else{ + mi->m_maki01b = 0; + free(mi->formb); + mi->formb = NULL; + } +} + +static void maki_make_virtual_screen(mi) + struct maki_info *mi; +{ + int bpl = mi->width / 2 / 8; + int vsi, pai, pbi, max_pai, max_pbi; + byte mask; + byte *pixels; + int x, y; + + mi->vs = maki_malloc((size_t) bpl * mi->height, + "maki_make_virtual_screen#1"); + + if(mi->m_maki01b) + pixels = mi->formb; + else + pixels = mi->forma; + + vsi = pai = pbi = 0; + max_pai = max_pbi = -1; + mask = 0x80; + for(y = 0; y < mi->height; y++){ + for(x = 0; x < mi->width / 2; x++){ + if(pixels[y * mi->width / 2 + x] == 0){ + mi->vs[vsi] &= ~mask; + }else{ + mi->vs[vsi] |= mask; + if(y < 200){ + if(pai > max_pai){ + max_pai += 1024; + mi->pa = maki_realloc(mi->pa, (size_t) max_pai + 1, + "maki_make_virtual_screen#2"); + } + mi->pa[pai++] = pixels[y * mi->width / 2 + x]; + }else{ + if(pbi > max_pbi){ + max_pbi += 1024; + mi->pb = maki_realloc(mi->pb, (size_t) max_pbi + 2, + "maki_make_virtual_screen#3"); + } + mi->pb[pbi++] = pixels[y * mi->width / 2 + x]; + } + } + + if((mask >>= 1) == 0){ + mask = 0x80; + vsi++; + } + } + } + + mi->pa_size = pai; + mi->pb_size = pbi; +} + +static void maki_make_flags(mi) + struct maki_info *mi; +{ + int bpl = mi->width / 2 / 8; + int fbi, max_fbi; + int fai; + int x, y; + byte mask; + + mi->fa = maki_malloc((size_t) bpl * mi->height, "maki_make_flags#1"); + + fbi = fai = 0; + max_fbi = -1; + mask = 0x80; + for(y = 0; y < mi->height; y += 4){ + for(x = 0; x < mi->width / 2; x += 4){ + if(x % 8 == 0){ + if(H4(mi->vs[ y * bpl + x / 8]) == 0 && + H4(mi->vs[(y + 1) * bpl + x / 8]) == 0 && + H4(mi->vs[(y + 2) * bpl + x / 8]) == 0 && + H4(mi->vs[(y + 3) * bpl + x / 8]) == 0){ + mi->fa[fai] &= ~mask; + }else{ + mi->fa[fai] |= mask; + if(fbi + 1 > max_fbi){ + max_fbi += 1024; + mi->fb = maki_realloc(mi->fb, (size_t) max_fbi + 1, + "maki_make_flags#2"); + } + mi->fb[fbi++] = H4(mi->vs[ y * bpl + x / 8]) << 4 + | H4(mi->vs[(y + 1) * bpl + x / 8]); + mi->fb[fbi++] = H4(mi->vs[(y + 2) * bpl + x / 8]) << 4 + | H4(mi->vs[(y + 3) * bpl + x / 8]); + } + }else{ + if(L4(mi->vs[ y * bpl + x / 8]) == 0 && + L4(mi->vs[(y + 1) * bpl + x / 8]) == 0 && + L4(mi->vs[(y + 2) * bpl + x / 8]) == 0 && + L4(mi->vs[(y + 3) * bpl + x / 8]) == 0){ + mi->fa[fai] &= ~mask; + }else{ + mi->fa[fai] |= mask; + if(fbi + 1 > max_fbi){ + max_fbi += 1024; + mi->fb = maki_realloc(mi->fb, (size_t) max_fbi + 1, + "maki_make_flags#3"); + } + mi->fb[fbi++] = L4(mi->vs[ y * bpl + x / 8]) << 4 + | L4(mi->vs[(y + 1) * bpl + x / 8]); + mi->fb[fbi++] = L4(mi->vs[(y + 2) * bpl + x / 8]) << 4 + | L4(mi->vs[(y + 3) * bpl + x / 8]); + } + } + + if((mask >>= 1) == 0){ + mask = 0x80; + fai++; + } + } + } + + mi->fb_size = fbi; +} + +static void maki_write_check_id(mi) + struct maki_info *mi; +{ + char *id = mi->m_maki01b ? maki_id_b : maki_id_a; + if(fwrite(id, (size_t) 8, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); +} + +static void maki_write_comment(mi) + struct maki_info *mi; +{ + char buf[24]; + char *p; + int i = 0; + + strcpy(buf, "XV "); + + if((p = (char *) getenv("USER")) == NULL) + p = "????????"; + for(i = 5; i < 23; i++){ + if(*p == '\0') + break; + buf[i] = *p++; + } + for( ; i < 23; i++) + buf[i] = ' '; + + buf[i] = '\032'; /* ^Z, 0x1a */ + + if(fwrite(buf, (size_t) 24, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); +} + +static void maki_write_header(mi) + struct maki_info *mi; +{ + byte buf[16]; + + if(DEBUG) maki_show_maki_info(mi); + +#define set_word(i, v) {buf[i]=(v)>>8&0xff;buf[i+1]=(v)&0xff;} + set_word(0, mi->fb_size); + set_word(2, mi->pa_size); + set_word(4, mi->pb_size); + set_word(6, mi->ext_flag); + set_word(8, mi->x0); + set_word(10, mi->y0); + set_word(12, mi->x1 + 1); + set_word(14, mi->y1 + 1); +#undef set_word + + if(fwrite(buf, (size_t) 16, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); +} + +static void maki_write_palette(mi, r, g, b, grey) + struct maki_info *mi; + byte *r, *g, *b; + int grey; +{ + int i; + char buf[3]; + for(i = 0; i < mi->numcols; i++){ + buf[0] = *g++; + buf[1] = *r++; + buf[2] = *b++; + if(grey) + buf[0] = buf[1] = buf[2] = MONO(buf[1], buf[0], buf[2]); + if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); + } + for( ; i < 16; i++){ + if(fwrite(buf, (size_t) 3, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); + } +} + +static void maki_write_flags(mi) + struct maki_info *mi; +{ + int bpl = mi->width / 2 / 8; + if(fwrite(mi->fa, (size_t) bpl * mi->height / 16, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); + + if(fwrite(mi->fb, (size_t) mi->fb_size, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); +} + +static void maki_write_pixel_data(mi) + struct maki_info *mi; +{ + if(fwrite(mi->pa, (size_t) mi->pa_size, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); + + if(fwrite(mi->pb, (size_t) mi->pb_size, (size_t) 1, mi->fp) != 1) + maki_file_error(mi, MAKI_WRITE); +} + + + +static void maki_init_info(mi) + struct maki_info *mi; +{ + mi->fp = NULL; + mi->fsize = 0; + mi->x0 = mi->y0 = mi->x1 = mi->y1 = 0; + mi->width = mi->height = 0; + mi->aspect = 1.0; + mi->fb_size = mi->pa_size = mi->pb_size = 0; + mi->m_maki01b = mi->m_200 = mi->m_dig8 = 0; + mi->ext_flag = 0; + mi->fa = mi->fb = mi->pa = mi->pb = NULL; + mi->vs = NULL; + mi->numcols = 16; + mi->forma = mi->formb = NULL; +} + +static void maki_cleanup_maki_info(mi, writing) + struct maki_info *mi; + int writing; +{ + if(mi->fp && !writing) + fclose(mi->fp); + if(mi->fa) + free(mi->fa); + if(mi->fb) + free(mi->fb); + if(mi->pa) + free(mi->pa); + if(mi->pb) + free(mi->pb); + if(mi->vs) + free(mi->vs); + if(mi->forma) + free(mi->forma); + if(mi->formb) + free(mi->formb); +} + +static void maki_cleanup_pinfo(pi) + PICINFO *pi; +{ + if(pi->pic){ + free(pi->pic); + pi->pic = NULL; + } +} + +static void maki_memory_error(scm, fn) + char *scm, *fn; +{ + char buf[128]; + sprintf(buf, "%s: coulndn't allocate memory. (%s)", scm, fn); + FatalError(buf); +} + +static void maki_error(mi, mn) + struct maki_info *mi; + int mn; +{ + SetISTR(ISTR_WARNING, "%s", maki_msgs[mn]); + longjmp(mi->jmp, 1); +} + +static void maki_file_error(mi, mn) + struct maki_info *mi; + int mn; +{ + if(feof(mi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", maki_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", maki_msgs[mn], ERRSTR(errno)); + longjmp(mi->jmp, 1); +} + +static void maki_file_warning(mi, mn) + struct maki_info *mi; + int mn; +{ + if(feof(mi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", maki_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", maki_msgs[mn], ERRSTR(errno)); +} + +static void maki_show_maki_info(mi) + struct maki_info *mi; +{ + fprintf(stderr, " file size: %ld.\n", mi->fsize); + fprintf(stderr, " image size: %dx%d.\n", mi->width, mi->height); + fprintf(stderr, " aspect: %f.\n", mi->aspect); + fprintf(stderr, " flag B size: %ld.\n", mi->fb_size); + fprintf(stderr, " pixel data size: A:%ld, B:%ld.\n", + mi->pa_size, mi->pb_size); + fprintf(stderr, " MAKI01B: %s.\n", mi->m_maki01b ? "true" : "false"); + fprintf(stderr, " 200 line mode: %s.\n", mi->m_200 ? "true" : "false"); + fprintf(stderr, " digital 8 colors: %s.\n", mi->m_dig8 ? "true" : "false"); +} + +static void *maki_malloc(n, fn) + size_t n; + char *fn; +{ + void *r = (void *) malloc(n); + if(r == NULL) + maki_memory_error("malloc", fn); + return r; +} + +static void *maki_realloc(p, n, fn) + void *p; + size_t n; + char *fn; +{ + void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n); + if(r == NULL) + maki_memory_error("realloc", fn); + return r; +} +#endif /* HAVE_MAKI */ diff -urN xv-3.10a/xvmgcsfx.c xv-3.10a-jp-extension-current/xvmgcsfx.c --- xv-3.10a/xvmgcsfx.c +++ xv-3.10a-jp-extension-current/xvmgcsfx.c Wed Oct 9 20:37:20 1996 @@ -0,0 +1,2263 @@ +/* + * $Id: xvmgcsfx.c,v 1.23 95/11/27 19:03:36 tin329 Exp Locker: tin329 $ + * xvmgcsfx.c - Use the filters as input and output method. + * + * Features + * ======== + * Use the filters as input and output method for load and save unsupported + * image format file. The filter command is recognized by definition of + * magic number or suffix in "~/.xv_mgcsfx" . + * + * Bugs + * ==== + * There are many bugs. + * Let's go hunting for insects with an insect net. (it's all joke.) + * + * Author + * ====== + * Tetsuya INOUE + */ + +/* + * Known Bugs and Todo / $B$"$l$3$l5$$K$J$k$3$H(B + * + * ~/.xv_mgcsfx $BFb(B + * $B!&Dj5A$,IT40A4$@$H%(%i!<(B (':'$B$N?t(B)$B!#(B + * $B!&%G%j%_%?$H$7$F(B ':' $B$r;H$&$N$G!"%9%?!<%H%"%C%W%U%!%$%kFb$G(B + * ':' $B$rMQ$$$FDj5A$O$G$-$J$$!#(B'\:'$B$G$b%@%a!#(B + * $B!&(B magic $B%?%$%W$G!"#8?J?t$O#37eJ,#0!A#7$rD4$Y!"#1#6?J?t$O(B + * isxdigit $B$,??$rJV$94VCf=hM}$5$l$k!#$7$+$7!"#1#b#y#t#e$H(B + * $B$7$F$7$+I>2A$5$l$J$$!#(B + * $B!&%W%j%W%m%;%C%5$r;H$&$H$-$O!"%3%a%s%H$N=q$-J}$KCm0U$7$J$1$l$P$J(B + * $B$i$J$$!#%W%j%W%m%;%C%5$K$h$C$F$O%3%a%s%H$,%(%i!<$K$J$k!#(B + * $B!&%Q%$%W$X$NF~=PNO$N%U%)!<%^%C%H$Nl9g$rG'$a$k$+!)(B + * $B!&(Bcompress(gzip)$B$N%U%!%$%k$O%F%s%]%i%j$G$O(B xvtmp??? $B$H$$$&L>A0$J(B + * $B$N$G(B suffix $B$G$O<1JL$G$-$J$$!#(B + * + * $BG'<1$9$k;~$K(B MACBINARY $B$K$OIi$1$k(B(in xv.c)$B!#(B + * + * $BB?=E$K(B pipe $B$rDL$9$3$H$,$G$-$J$$!#(B(pipe $B$,(B seek $B$G$-$J$$$+$i(B) + * $B!&(Bsocketpair $B$G!"(Brecv $B$K(B MSG_PEEK $B%U%i%0$r$D$+$C$F6uFI$_$9$k!#(B + * $B!&$3$l$r$d$k$H%U%!%$%k$NG'<1$,$a$A$c$a$A$cCY$/$J$k!#(B + * + * $B%j%=!<%9$G@_Dj(B + * $B!&%j%=!<%9$G@_Dj$9$kJ}$,LLE]$/$5$$(B + * + * $B%^%8%C%/%J%s%P!<$N@_Dj$K@55,I=8=(B + * + * $B%;!<%VMQ%W%m%;%9$,<:GT$9$k>l9g$NBP:v$,:#0l$D(B + * + * DEC OSF/1 V3.0 $B$G$O!"%Q%$%W$K%G!<%?$,$^$@$J$$;~$KFI$_9~$b$&$H$9$k$H!"(B + * read $B$,IT40A4$K$J$k!#(B(in xvpbm.c) + * $BF1MM$K=q$-9~$_;~$K$bLdBj$,@8$8$k$+$b$7$l$J$$!#(B + */ + +#define NEEDSDIR /* for stat() */ +#include "xv.h" + + +#ifdef HAVE_MGCSFX + + +#ifdef __osf__ +#ifdef __alpha +#define ARCHITECTURE64 1 +#endif /* __alpha */ +#endif /* __osf__ */ + +#ifdef ARCHITECTURE64 +typedef short int16; +typedef int int32; +typedef long int64; +#else +typedef short int16; +typedef long int32; +#endif /* ARCHITECTURE64 */ + +#ifdef sgi +#define vfork fork +#endif + +#define USE_SIGCHLD +#if 0 +#undef USE_SIGCHLD +#endif + +typedef struct _mgcsfxtab +{ + struct _mgcsfxtab *next; + char *description; + int mgcsfx_type; + int offset; + union{ + int16 int16_data; + int32 int32_data; + char *string_data; + } dt; + int string_len; + char *suffix; + int input_image_type; + char *input_command; + int output_image_type; + char *output_command; +} mgcsfxtab; + + +#ifndef MGCSFXDIR +# define MGCSFXDIR "/usr/local/lib" +#endif +#ifndef MGCSFX_SITE_RC +# define MGCSFX_SITE_RC "xv_mgcsfx" +#endif +#ifndef MGCSFX_RC +# define MGCSFX_RC ".xv_mgcsfx" +#endif + +#ifdef USE_MGCSFX_PREPROCESSOR +#ifndef MGCSFX_PREPROCESSOR +#define MGCSFX_PREPROCESSOR "/usr/lib/cpp" +#endif +#endif + + +/* Check type for Magic number and Suffix */ +enum {T_UNKNOWN, + T_MAGIC, T_SUFFIX, + T_BEINT16, T_BEINT32, T_BEINT64, + T_LEINT16, T_LEINT32, T_LEINT64}; + +/* Image Type for input and output format */ +enum {IT_UNKNOWN, +#ifdef HAVE_MGCSFX_AUTO + IT_AUTO, +#endif /* HAVE_MGCSFX_AUTO */ + IT_PNM, IT_PPM, IT_PGM, IT_PBM, + IT_PNM_RAW, IT_PPM_RAW, IT_PGM_RAW, IT_PBM_RAW, + IT_PNM_ASCII, IT_PPM_ASCII, IT_PGM_ASCII, IT_PBM_ASCII, + IT_GIF, IT_JPEG, IT_TIFF, IT_JFIF, /* IT_PS, IT_COMPRESS,*/ + IT_XBM, IT_XPM, IT_BMP, IT_SUNRAS, IT_IRIS, IT_XWD, + /* IT_TARGA, IT_FITS, IT_PM, IT_UTAHRLE, IT_PCX, IT_PDSVICAR, IT_IFF, */ + IT_MAG, IT_MAKI, IT_PI, IT_PIC, IT_PIC2 /* , IT_PCD */}; + + +/*--------------------------------------------------------------------------*/ +void mgcsfx_handler PARM((int)); +void mgcsfx_handler_setup PARM((void)); + +#ifdef USE_MGCSFX_PREPROCESSOR +static char *get_tmp_fname PARM((void)); +static char *make_preprocessed_file PARM((char *)); +#endif /* USE_MGCSFX_PREPROCESSOR */ + +int is_mgcsfx PARM((char *, unsigned char *, int)); + +char *mgcsfx_auto_input_com PARM((char *)); + + +static mgcsfxtab *free_mgcsfx PARM((mgcsfxtab *)); +static char *fgettoken PARM((FILE*, int)); +static int string_fin PARM((char *)); +static int type_mgcsfx PARM((char *)); +static int type_image PARM((char *)); + +static void read_mgcsfx PARM((mgcsfxtab **, char *)); +static void init_mgcsfx PARM((void)); +static mgcsfxtab *find_mgcsfx PARM((char *, unsigned char *, int)); + +int LoadMGCSFX PARM((char *, PICINFO *)); + +#ifdef SVR4 +typedef void Sigfunc(int); +static Sigfunc *xv_signal PARM((int , Sigfunc *)); +#endif + +/*--------------------------------------------------------------------------*/ +mgcsfxtab *mgcsfx_table = NULL; +int mgcsfx_setup_flag = 0; + +int nitem_mgcsfx = 0; +int desc_width = 0; + +int max_offset_mgcsfx = 0; +int max_length_mgcsfx = 0; +int need_buf_size = 0; + +static char input_command_ex[1024]; +static int input_command_ex_flag = 0; + +#ifdef USE_SIGCHLD +static int w_p_fail=0; +#endif + +/*--------------------------------------------------------------------------*/ + +/***************************************************/ +void mgcsfx_handler(sig) + int sig; +{ + int pid, pst; + +#if defined(SYSV) || defined(SVR4) + sighold(sig); +#else + sigblock(sigmask(sig)); +#endif + +#ifdef USE_SIGCHLD + if(w_p_fail == 1){ + /* + * At this point, process write to broken pipe. + * Probably external command was can't exec. + */ + w_p_fail = 2; + pid = wait(&pst); + } +#endif + + return; + + /* Quit(1); */ /*exit(1);*/ +} + +void mgcsfx_handler_setup() +{ +#ifdef SVR4 + xv_signal(SIGPIPE, (void (*)PARM((int))) mgcsfx_handler); + xv_signal(SIGCHLD, (void (*)PARM((int))) mgcsfx_handler); +#else +# ifdef SYSV + sigset(SIGPIPE, (void (*)PARM((int))) mgcsfx_handler); + sigset(SIGCHLD, (void (*)PARM((int))) mgcsfx_handler); +# else + signal(SIGPIPE, (void (*)PARM((int))) mgcsfx_handler); + signal(SIGCHLD, (void (*)PARM((int))) mgcsfx_handler); +# endif +#endif +} + +/***************************************************/ +#ifdef USE_MGCSFX_PREPROCESSOR +static char *get_tmp_fname() +{ + static char tmp[MAXPATHLEN+1]; + +#ifndef VMS + sprintf(tmp, "%s/xvmgcsfxXXXXXX",tmpdir); +#else + /* sprintf(tmp, "Sys$Scratch:xvmgcsfxXXXXXX"); */ + strcpy(tmp, "[]xvmgcsfxXXXXXX"); +#endif /* VMS */ + + mktemp(tmp); + + return tmp; +} +#endif /* USE_MGCSFX_PREPROCESSOR */ + +#ifdef USE_MGCSFX_PREPROCESSOR +static char *make_preprocessed_file(fname) + char *fname; +{ + char buf[512]; + char *tmp_name; + + tmp_name = get_tmp_fname(); + +#ifndef VMS + sprintf(buf,"%s %s > %s", MGCSFX_PREPROCESSOR, fname, tmp_name); +#else /* it IS VMS */ + sprintf(buf,"%s %s > %s", MGCSFX_PREPROCESSOR, fname, tmp_name);/* realy OK? */ +#endif + + SetISTR(ISTR_INFO, "Preprocessing '%s'...", BaseName(fname)); +#ifndef VMS + if (system(buf)) { +#else + if (!system(buf)) { +#endif + SetISTR(ISTR_INFO, "Unable to preprocess '%s'.", BaseName(fname)); + Warning(); + return NULL; + } + + return tmp_name; +} +#endif /* USE_MGCSFX_PREPROCESSOR */ + +/***************************************************/ +/* $BG'<1$G$-$k%U%!%$%k$+$I$&$+D4$Y$k(B */ +int is_mgcsfx(fname,buffer,size) + char *fname; + unsigned char *buffer; + int size; +{ + mgcsfxtab *magic; + FILE *fp; + unsigned char *buf; + int s; + + if(nomgcsfx){ + return 0; + }else{ + if(size < need_buf_size){ + if((buf = (unsigned char *)calloc(need_buf_size, sizeof(char)))==NULL){ + fprintf(stderr,"Can't allocate memory\n"); + return 0; + } + if((fp = xv_fopen(fname, "r"))==NULL){ + fprintf(stderr,"Can't open file %s\n", fname); + free(buf); + return 0; + } + s = fread(buf, 1, need_buf_size, fp); + if((magic = find_mgcsfx(fname, buf, s))!=NULL && + magic->input_command != NULL){ + free(buf); + fclose(fp); + return 1; + }else{ + free(buf); + fclose(fp); + return 0; + } + }else{ + if((magic = find_mgcsfx(fname, buffer, size))!=NULL && + magic->input_command != NULL){ + return 1; + }else{ + return 0; + } + } + } +} + +#ifdef HAVE_MGCSFX_AUTO +char *mgcsfx_auto_input_com(fname) +char *fname; +{ + static char command[1024]; + mgcsfxtab *magic; + char *ptr; + + FILE *fp; + unsigned char *buf; + int s; + + if((buf = (unsigned char *)calloc(need_buf_size, sizeof(char)))==NULL){ + fprintf(stderr,"Can't allocate memory\n"); + return NULL; + } + if((fp = xv_fopen(fname, "r"))==NULL){ + fprintf(stderr,"Can't open file %s\n", fname); + free(buf); + return NULL; + } + s = fread(buf, 1, need_buf_size, fp); + if((magic = find_mgcsfx(fname, buf, s))!=NULL && + magic->input_command != NULL && magic->input_image_type == IT_AUTO){ + if (ptr = strstr(magic->input_command, "%s")){ + sprintf(command, magic->input_command, fname); + }else{ + sprintf(command, "%s < %s", magic->input_command, fname); + } + free(buf); + fclose(fp); + return command; + }else{ + free(buf); + fclose(fp); + return NULL; + } +} +#endif /* HAVE_MGCSFX_AUTO */ + +/***************************************************/ +static mgcsfxtab *free_mgcsfx(m) + mgcsfxtab *m; +{ + mgcsfxtab *next; + if(m == NULL) return NULL; + next = m->next; + if(m->description != NULL) free(m->description); + if(m->mgcsfx_type == T_MAGIC && m->dt.string_data != NULL) + free(m->dt.string_data); + if(m->suffix != NULL) free(m->suffix); + if(m->input_command != NULL) free(m->input_command); + if(m->output_command != NULL) free(m->output_command); + free(m); + return next; +} + + + +/***************************************************/ +/* char c $B$^$?$O(B '\n' $B$G6h@Z$i$l$?J8;zNs$rl9g$O(B '\n' $B$r%9%H%j!<%`$KLa$9(B) + */ +#define CBUF_SIZE 1024 +static char *fgettoken(fp, c) + FILE *fp; + int c; /* Real mean is char */ +{ + char *buf; + char *buf2; + int i; + int n=0; + int max=0; + int count = 1; + + char *ss; + char *se; + + if((buf = (char *)calloc(CBUF_SIZE, sizeof(char))) == NULL){ + fprintf(stderr,"Can't allocate memory\n"); + exit(1); + } + max = CBUF_SIZE; + count = 2; + + do{ + if((i = getc(fp))==EOF || i == '\n' || i == c) break; + + buf[n] = (char)i; + + if(i != c && n == max-1){ + buf[max] = '\0'; + if((buf2 = (char *)calloc(CBUF_SIZE * count, sizeof(char))) == NULL){ + fprintf(stderr,"Can't allocate memory\n"); + exit(1); + } + strcpy(buf2, buf); + free(buf); + buf = buf2; + buf2 = NULL; + max = CBUF_SIZE * count; + count++; + } + + n++; + }while(i != c); + + buf[n] = '\0'; + + /* $B:G=i$H:G8e$N6uGrJ8;z$r@Z$j5M$a$k(B */ + ss = buf + strspn(buf, " \t\b\r\n"); /* find the first non-white space */ + se = buf + strlen(buf); /* find the end of the string */ + + /* strip from the end first */ + while ((--se >= ss) && strchr(" \t\b\r\n", *se)); + *(++se) = '\0'; + + if(i == EOF && strlen(ss)==0){ /* EOF $B$J$i(B NULL $B$rJV$9(B */ + free(buf); + return NULL; + }else if(i == '\n' && strlen(ss)==0){ /* $B2~9T$N$_$N>l9g(B */ + static char cr[2] = {'\n','\0'}; + buf2 = strdup(cr); + free(buf); + return buf2; + }else{ /* $BDL>o(B */ + if(i == '\n' && strlen(ss)>0) ungetc(i,fp); + buf2 = strdup(ss); + free(buf); + return buf2; + } +} + + + +/***************************************************/ +/* $BJ8;zNsCf$NFC= '0') && (ptr[1] <= '7')){ + if ((ptr[2] >= '0') && (ptr[2] <= '7')){ /* \000 ...\377 */ + *cptr = ((*ptr - '0') * 64) +((ptr[1] - '0') * 8) +(ptr[1] - '0'); + ptr += 2; + }else{ /* \00 ...\77 */ + *cptr = ((*ptr - '0') * 8) + (ptr[1] - '0'); + ++ptr; + } + }else{ /* \0 ...\7 */ + *cptr = *ptr - '0'; + } + break; + case 'x': /* Hexadecimal constant \x0 .. \xff */ + if (isxdigit (ptr[1])){ + *cptr = 0; + while (isxdigit (*(++ptr))) + *cptr = (*cptr * 16) + + (*ptr > '9' ? tolower (*ptr) - ('a' - 10) : *ptr - '0'); + --ptr; + break; + } + default: + /* *(cptr++) = '\\'; No use for treat '\z' as 'z' */ + *cptr = *ptr; + break; + } + } + ++cptr; + } + *cptr = '\0'; + length = cptr - string_data; + return length; +} + +/***************************************************/ +static int type_mgcsfx(str) + char *str; +{ + if(str == NULL){ + return T_UNKNOWN; + }else if(!strcmp(str, "magic") || !strcmp(str, "MAGIC")){ + return T_MAGIC; + }else if(!strcmp(str, "string") || !strcmp(str, "STRING")){ + return T_MAGIC; + }else if(!strcmp(str, "suffix") || !strcmp(str, "SUFFIX")){ + return T_SUFFIX; + }else if(!strcmp(str, "beint16") || !strcmp(str, "BEINT16")){ + return T_BEINT16; + }else if(!strcmp(str, "leint16") || !strcmp(str, "LEINT16")){ + return T_LEINT16; + }else if(!strcmp(str, "beint32") || !strcmp(str, "BEINT32")){ + return T_BEINT32; + }else if(!strcmp(str, "leint32") || !strcmp(str, "LEINT32")){ + return T_LEINT32; + }else{ + return T_UNKNOWN; + } +} + +/***************************************************/ +static int type_image(str) + char *str; +{ + if(str == NULL){ + return IT_UNKNOWN; +#ifdef HAVE_MGCSFX_AUTO + }else if(!strcmp(str, "auto") || !strcmp(str, "AUTO")){ + return IT_AUTO; +#endif /* HAVE_MGCSFX_AUTO */ + }else if(!strcmp(str, "pnm") || !strcmp(str, "PNM")){ + return IT_PNM; + }else if(!strcmp(str, "ppm") || !strcmp(str, "PPM")){ + return IT_PPM; + }else if(!strcmp(str, "pgm") || !strcmp(str, "PGM")){ + return IT_PGM; + }else if(!strcmp(str, "pbm") || !strcmp(str, "PBM")){ + return IT_PBM; + }else if(!strcmp(str, "pnm_raw") || !strcmp(str, "PNM_RAW")){ + return IT_PNM_RAW; + }else if(!strcmp(str, "ppm_raw") || !strcmp(str, "PPM_RAW")){ + return IT_PPM_RAW; + }else if(!strcmp(str, "pgm_raw") || !strcmp(str, "PGM_RAW")){ + return IT_PGM_RAW; + }else if(!strcmp(str, "pbm_raw") || !strcmp(str, "PBM_RAW")){ + return IT_PBM_RAW; + }else if(!strcmp(str, "pnm_ascii") || !strcmp(str, "PNM_ASCII")){ + return IT_PNM_ASCII; + }else if(!strcmp(str, "ppm_ascii") || !strcmp(str, "PPM_ASCII")){ + return IT_PPM_ASCII; + }else if(!strcmp(str, "pgm_ascii") || !strcmp(str, "PGM_ASCII")){ + return IT_PGM_ASCII; + }else if(!strcmp(str, "pbm_ascii") || !strcmp(str, "PBM_ASCII")){ + return IT_PBM_ASCII; + + }else if(!strcmp(str, "gif") || !strcmp(str, "GIF")){ + return IT_GIF; + }else if(!strcmp(str, "jpeg") || !strcmp(str, "JPEG")){ + return IT_JPEG; + }else if(!strcmp(str, "tiff") || !strcmp(str, "TIFF")){ + return IT_TIFF; + }else if(!strcmp(str, "jfif") || !strcmp(str, "JFIF")){ + return IT_JFIF; + + }else if(!strcmp(str, "xbm") || !strcmp(str, "XBM")){ + return IT_XBM; + }else if(!strcmp(str, "xpm") || !strcmp(str, "XPM")){ + return IT_XPM; + }else if(!strcmp(str, "bmp") || !strcmp(str, "BMP")){ + return IT_BMP; + }else if(!strcmp(str, "sunras") || !strcmp(str, "SUNRAS")){ + return IT_SUNRAS; + }else if(!strcmp(str, "iris") || !strcmp(str, "IRIS")){ + return IT_IRIS; + }else if(!strcmp(str, "xwd") || !strcmp(str, "XWD")){ + return IT_XWD; + + }else if(!strcmp(str, "mag") || !strcmp(str, "MAG")){ + return IT_MAG; + }else if(!strcmp(str, "maki") || !strcmp(str, "MAKI")){ + return IT_MAKI; + }else if(!strcmp(str, "pi") || !strcmp(str, "PI")){ + return IT_PI; + }else if(!strcmp(str, "pic") || !strcmp(str, "PIC")){ + return IT_PIC; + }else if(!strcmp(str, "pic2") || !strcmp(str, "PIC2")){ + return IT_PIC2; + + }else{ + return IT_UNKNOWN; + } +} + +/*--------------------------------------------------------------------------*/ +#define mgcsfx_read_error(FILENAME, LINENUM, AFTERFIELD) \ +fprintf (stderr,\ +"%s: line %d: missing fields of %s field\n",\ +FILENAME, LINENUM, AFTERFIELD); + +#define magic_type_error(FILENAME, LINENUM, MAGICNUMBER) \ +fprintf (stderr,\ +"%s: line %d: invalid field '%s'\n",\ +FILENAME, LINENUM, MAGICNUMBER); +/*--------------------------------------------------------------------------*/ + +/***************************************************/ +static void read_mgcsfx(mgcsfx_table, fname) + mgcsfxtab **mgcsfx_table; + char *fname; +{ + FILE *fp; + char *s; + int line_number = 0; + int str_len; + int reach_end; + int def_err; + + char *description; + char *mgcsfx_type; + char *offset; + char *magic; + char *suffix; + char *i_img; + char *i_com; + char *o_img; + char *o_com; + + mgcsfxtab *ent; + mgcsfxtab **entry; + + + if((fp=fopen(fname, "r"))==NULL){ + /* fprintf(stderr, "Can't open %s\n",fname); */ + return; + } + + while(1){ +retry: + line_number++; + def_err = 0; + + s= NULL; + description = mgcsfx_type = offset = magic = suffix + = i_img = i_com = o_img = o_com = NULL; + reach_end = 0; + + if((s = fgettoken(fp, ':'))==NULL) break; /* EOF $B$J$i=*$j(B */ + if(*s == '#'){/* $B@hF,$,(B '#' $B$J$iFI$_$H$P$9(B */ + while((s = fgettoken(fp, '\n'))!=NULL){ + if(*s == '\n'){ + free(s); + goto retry; + } + free(s); + } + if(s == NULL) break; + }else if(*s == '\n'){/* $B6u9T$OL5;k(B */ + free(s); + goto retry; + } + if(strlen(s) > 0) description = s; + else free(s); + + if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + if(s != NULL) free(s); + mgcsfx_read_error(fname, line_number, "data type"); + goto next; + } + if(strlen(s) > 0) mgcsfx_type = s; + else free(s); + + if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + if(s != NULL) free(s); + mgcsfx_read_error(fname, line_number, "byte offset"); + goto next; + } + if(strlen(s) > 0) offset = s; + else free(s); + + if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + if(s != NULL) free(s); + mgcsfx_read_error(fname, line_number, "magic number"); + goto next; + } + if(strlen(s) > 0) magic = s; + else free(s); + + if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + if(s != NULL) free(s); + mgcsfx_read_error(fname, line_number, "suffix"); + goto next; + } + if(strlen(s) > 0) suffix = s; + else free(s); + + if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + if(s != NULL) free(s); + mgcsfx_read_error(fname, line_number, "input image type"); + goto next; + } + if(strlen(s) > 0) i_img = s; + else free(s); + + if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + if(s != NULL) free(s); + mgcsfx_read_error(fname, line_number, "input command"); + goto next; + } + if(strlen(s) > 0) i_com = s; + else free(s); + + if((s = fgettoken(fp, ':'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + if(s != NULL) free(s); + mgcsfx_read_error(fname, line_number, "output image type"); + goto next; + } + if(strlen(s) > 0) o_img = s; + else free(s); + + if((s = fgettoken(fp, '#'))==NULL || *s == '\n'){/* $B2?$b$J$$$J$i@_Dj%_%9(B */ + /* + free(s); + mgcsfx_read_error(fname, line_number, "output command"); + goto next; + */ + if(s != NULL){ + *s = '\0'; + reach_end = 1; + } + } + if(s != NULL){ + if(strlen(s) > 0) o_com = s; + else free(s); + } + + if(reach_end == 0){ + while((s = fgettoken(fp, '\n'))!=NULL){/* $B9TKv$N%4%_$rnext = NULL; + ent->description = NULL; + ent->mgcsfx_type = T_UNKNOWN; + ent->offset = 0; + ent->string_len = 0; + ent->suffix = NULL; + ent->input_image_type = IT_UNKNOWN; + ent->input_command = NULL; + ent->output_image_type = IT_UNKNOWN; + ent->output_command = NULL; + + if(description != NULL){ + ent->description = description; + description = NULL; + }else{ + fprintf (stderr,"%s: line %d: undefined field.\n", + fname, line_number); + def_err ++; + goto next2; + } + + if(mgcsfx_type == NULL){ + fprintf (stderr,"%s: line %d: undefined field.\n", + fname, line_number); + def_err ++; + goto next2; + } + ent->mgcsfx_type = type_mgcsfx(mgcsfx_type); + switch(ent->mgcsfx_type){ + case T_SUFFIX: + if(suffix == NULL){ + fprintf (stderr, + "%s: line %d: conflict definition : undefined field.\n", + fname, line_number); + def_err ++; + goto next2; + } + break; + case T_BEINT16: + if (sscanf(magic, "%hi", &(ent->dt.int16_data)) != 1){ + magic_type_error(fname, line_number, magic); + def_err ++; + goto next2; + } + break; + case T_LEINT16: + if (sscanf(magic, "%hi", &(ent->dt.int16_data)) != 1){ + magic_type_error(fname, line_number, magic); + def_err ++; + goto next2; + } + break; +#ifdef ARCHITECTURE64 + case T_BEINT32: + if (sscanf(magic, "%i", &(ent->dt.int32_data)) != 1){ + magic_type_error(fname, line_number, magic); + def_err ++; + goto next2; + } + break; + case T_LEINT32: + if (sscanf(magic, "%i", &(ent->dt.int32_data)) != 1){ + magic_type_error(fname, line_number, magic); + def_err ++; + goto next2; + } + break; +#else + case T_BEINT32: + if (sscanf(magic, "%li", &(ent->dt.int32_data)) != 1){ + magic_type_error(fname, line_number, magic); + def_err ++; + goto next2; + } + break; + case T_LEINT32: + if (sscanf(magic, "%li", &(ent->dt.int32_data)) != 1){ + magic_type_error(fname, line_number, magic); + def_err ++; + goto next2; + } + break; +#endif /* ARCHITECTURE64 */ + case T_MAGIC: + if(magic == NULL){ + fprintf (stderr,"%s: line %d: undefined field.\n", + fname, line_number); + def_err ++; + goto next2; + } + if((str_len = string_fin(magic))<=0){ + fprintf (stderr,"%s: line %d: invalid field.\n", + fname, line_number); + def_err ++; + goto next2; + } + + ent->string_len = str_len; + if((ent->dt.string_data = (char *)malloc(str_len + 1))==NULL){ + fprintf(stderr,"Can't allocate memory\n"); + exit(1); + } + memcpy(ent->dt.string_data, magic, str_len + 1); + break; + case T_UNKNOWN: + default: + fprintf (stderr,"%s: line %d: invalid field.\n", + fname, line_number); + def_err ++; + goto next2; + break; + }; + + + if(offset == NULL){ + if(ent->mgcsfx_type == T_MAGIC || + ent->mgcsfx_type == T_BEINT16 || + ent->mgcsfx_type == T_LEINT16 || + ent->mgcsfx_type == T_BEINT32 || + ent->mgcsfx_type == T_LEINT32){ + fprintf (stderr, + "%s: line %d: conflict definition : undefined field.\n", + fname, line_number); + def_err ++; + goto next2; + } + }else{ + if(ent->mgcsfx_type != T_SUFFIX) sscanf(offset, "%i", &(ent->offset)); + } + + if(suffix != NULL){ + ent->suffix = suffix; + suffix = NULL; + } + + if((i_img == NULL && i_com == NULL) && (o_img == NULL || o_com == NULL)){ + fprintf (stderr,"%s: line %d: invalid definition.\n", + fname, line_number); + def_err ++; + goto next2; + } + if((o_img == NULL && o_com == NULL) && (i_img == NULL || i_com == NULL)){ + fprintf (stderr,"%s: line %d: invalid definition.\n", + fname, line_number); + def_err ++; + goto next2; + } + + if(i_img != NULL && i_com != NULL){ + ent->input_image_type = type_image(i_img); + ent->input_command = i_com; + i_com = NULL; + }else{ + ent->input_image_type = IT_UNKNOWN; + ent->input_command = NULL; + } + + if(o_img != NULL && o_com != NULL){ + ent->output_image_type = type_image(o_img); + ent->output_command = o_com; + o_com = NULL; + }else{ + ent->output_image_type = IT_UNKNOWN; + ent->output_command = NULL; + } + /* end of create mgcsfxtab */ + + +next2:; + + if(def_err != 0 || DEBUG){ + fprintf(stderr,"Description : %s \t -> %s\n", + description ? description : "--+--", + ent->description ? ent->description : "-- error --"); + fprintf(stderr,"Type : %s \t -> %d\n", + mgcsfx_type ? mgcsfx_type : "--+--", + ent->mgcsfx_type); + fprintf(stderr,"Offset : %s \t -> %d\n", + offset ? offset : "--+--", + ent->offset); + + fprintf(stderr,"Magic : %s", magic ? magic : "--+--"); + switch(ent->mgcsfx_type){ + case T_BEINT16: + case T_LEINT16: + fprintf(stderr," \t -> %d\n",ent->dt.int16_data); + break; + case T_BEINT32: + case T_LEINT32: + fprintf(stderr," \t -> %d\n",ent->dt.int32_data); + break; + case T_MAGIC: + fprintf(stderr," \t -> %s\n",ent->dt.string_data); + break; + default: + fprintf(stderr,"\n"); + break; + }; + + fprintf(stderr,"Suffix : %s \t -> %s\n", + suffix ? suffix : "--+--", + ent->suffix ? ent->suffix : "--+--"); + fprintf(stderr,"i Image : %s \t -> %d\n", + i_img ? i_img : "--+--", + ent->input_image_type); + fprintf(stderr,"i Command : %s \t -> %s\n", + i_com ? i_com : "--+--", + ent->input_command ? ent->input_command : "--+--"); + fprintf(stderr,"o Image : %s \t -> %d\n", + o_img ? o_img : "--+--", + ent->output_image_type); + fprintf(stderr,"o Command : %s \t -> %s\n", + o_com ? o_com : "--+--", + ent->output_command ? ent->output_command : "--+--"); + fprintf(stderr,"\n"); + } + + if(description != NULL) free(description); + if(mgcsfx_type != NULL) free(mgcsfx_type); + if(offset != NULL) free(offset); + if(magic != NULL) free(magic); + if(suffix != NULL) free(suffix); + if(i_img != NULL) free(i_img); + if(i_com != NULL) free(i_com); + if(o_img != NULL) free(o_img); + if(o_com != NULL) free(o_com); + + + if(def_err != 0) goto next3; + + /* Override any existing entry for this magic number/file type */ + for(entry = mgcsfx_table; *entry; entry = &((*entry)->next)){ + if((ent->mgcsfx_type == (*entry)->mgcsfx_type) && + ( + ((ent->offset == (*entry)->offset) && + (((ent->mgcsfx_type == T_BEINT16) && + (ent->dt.int16_data == (*entry)->dt.int16_data)) || + ((ent->mgcsfx_type == T_BEINT32) && + (ent->dt.int32_data == (*entry)->dt.int32_data)) || + ((ent->mgcsfx_type == T_LEINT16) && + (ent->dt.int16_data == (*entry)->dt.int16_data)) || + ((ent->mgcsfx_type == T_LEINT32) && + (ent->dt.int32_data == (*entry)->dt.int32_data)) || + + ((ent->mgcsfx_type == T_MAGIC) && + !memcmp(ent->dt.string_data, (*entry)->dt.string_data, + ent->string_len)) + )) || + ((ent->mgcsfx_type == T_SUFFIX) && + !strcmp(ent->suffix, (*entry)->suffix)) + ) + ){ + + free ((*entry)->description); + (*entry)->description = ent->description; + ent->description = NULL; + + (*entry)->input_image_type = ent->input_image_type; + if ((*entry)->input_command) free ((*entry)->input_command); + (*entry)->input_command = ent->input_command; + ent->input_command = NULL; + + (*entry)->output_image_type = ent->output_image_type; + if ((*entry)->output_command) free ((*entry)->output_command); + (*entry)->output_command = ent->output_command; + ent->output_command = NULL; + + free_mgcsfx(ent); + break; + } + } + if (!*entry){ + ent->next = NULL; + *entry = ent; + } + + /* if(s == NULL) break; */ +next3:; + if(def_err != 0) free_mgcsfx(ent); + } /* end of while(1) */ +} + + +/***************************************************/ +/* $B%^%8%C%/%J%s%P!$rF@$F!"FI$_9~$^$;$k(B */ +static void init_mgcsfx () +{ + extern char *getenv (); + + char *home_dir; + char fname[1024]; + mgcsfxtab *entry; + int len; + struct stat st; + +#ifdef USE_MGCSFX_PREPROCESSOR + char *pp_fname; +#endif /* USE_MGCSFX_PREPROCESSOR */ + + mgcsfx_table = NULL; + + mgcsfx_handler_setup(); + + if(nomgcsfx){ + mgcsfx_setup_flag = 1; + nitem_mgcsfx = 0; + desc_width = 0; + }else{ + sprintf (fname, "%s/%s", MGCSFXDIR, MGCSFX_SITE_RC); + if(stat(fname, &st) == 0 && S_ISREG(st.st_mode)){ + /* Read the site MagicSuffix table into a linked list */ +#ifdef USE_MGCSFX_PREPROCESSOR + if((pp_fname = make_preprocessed_file(fname)) != NULL){ + read_mgcsfx (&mgcsfx_table, pp_fname); + } + unlink(pp_fname); +#else + read_mgcsfx (&mgcsfx_table, fname); +#endif /* USE_MGCSFX_PREPROCESSOR */ + } + + /* Read the personal MgcSfx table into the list overriding site entries */ + if (home_dir = getenv ("HOME")){ + sprintf (fname, "%s/%s", home_dir, MGCSFX_RC); + if(stat(fname, &st) == 0 && S_ISREG(st.st_mode)){ +#ifdef USE_MGCSFX_PREPROCESSOR + if((pp_fname = make_preprocessed_file(fname)) != NULL){ + read_mgcsfx (&mgcsfx_table, pp_fname); + } + unlink(pp_fname); +#else + read_mgcsfx (&mgcsfx_table, fname); +#endif /* USE_MGCSFX_PREPROCESSOR */ + } + } + + mgcsfx_setup_flag = 1; + + nitem_mgcsfx = 0; + desc_width = 0; + for (entry = mgcsfx_table; entry; entry = entry->next){ + nitem_mgcsfx ++; + len = strlen(entry->description); + if(len > desc_width) desc_width = len; + if(max_offset_mgcsfx < entry->offset) max_offset_mgcsfx = entry->offset; + if(entry->mgcsfx_type == T_MAGIC && + max_length_mgcsfx < entry->string_len) + max_length_mgcsfx = entry->string_len; + } + if(max_length_mgcsfx == 0) max_length_mgcsfx = sizeof(int32); + need_buf_size = max_offset_mgcsfx + max_length_mgcsfx + 1;/* 1 is safety */ + } +} + +/***************************************************/ +/* $B%^%8%C%/%J%s%P!<$rD4$Y$F!"Dj5A$7$F$$$k%F!<%V%k$r8!:w$9$k(B + $B%^%8%C%/%J%s%P!<$N%F!<%V%k$rFI$_9~$s$G$$$J$$$J$iFI$_9~$`(B */ +static mgcsfxtab *find_mgcsfx (fname, buffer, buffer_size) + char *fname; + unsigned char *buffer; + int buffer_size; +{ + mgcsfxtab *entry; + int16 buf16; + int32 buf32; + char *suf; + + if (mgcsfx_setup_flag == 0) init_mgcsfx (); + + for (entry = mgcsfx_table; entry; entry = entry->next){ + switch (entry->mgcsfx_type){ + case T_BEINT16: + if ((buffer_size > 0) && + ((entry->offset + sizeof (int16)) <= buffer_size)){ + buf16 = ((char)*(buffer + entry->offset) << 8) | + ((char)*(buffer + entry->offset +1)); + if(entry->dt.int16_data == buf16) return entry; + } + break; + case T_LEINT16: + if ((buffer_size > 0) && + ((entry->offset + sizeof (int16)) <= buffer_size)){ + buf16 = ((char)*(buffer + entry->offset +1) << 8) | + ((char)*(buffer + entry->offset)); + if(entry->dt.int16_data == buf16) return entry; + } + break; + case T_BEINT32: + if ((buffer_size > 0) && + ((entry->offset + sizeof (int32)) <= buffer_size)){ + buf32 = ((char)*(buffer + entry->offset) << 24) | + ((char)*(buffer + entry->offset +1) << 16) | + ((char)*(buffer + entry->offset +2) << 8) | + ((char)*(buffer + entry->offset +3)); + if(entry->dt.int32_data == buf32) return entry; + } + break; + case T_LEINT32: + if ((buffer_size > 0) && + ((entry->offset + sizeof (int32)) <= buffer_size)){ + buf32 = ((char)*(buffer + entry->offset +3) << 24) | + ((char)*(buffer + entry->offset +2) << 16) | + ((char)*(buffer + entry->offset +1) << 8) | + ((char)*(buffer + entry->offset)); + if(entry->dt.int32_data == buf32) return entry; + } + break; + case T_MAGIC: + if ((buffer_size > 0) && + ((entry->offset + entry->string_len) + <= buffer_size) && + !memcmp (entry->dt.string_data, buffer + entry->offset, + entry->string_len )) + return entry; + break; + case T_SUFFIX: + if(fname != NULL && entry->suffix != NULL){ + if(strlen(fname) - strlen(entry->suffix) > 0){ + suf = fname + (strlen(fname) - strlen(entry->suffix)); + if(!strcmp(suf, entry->suffix)) return entry; + } + } + break; + case T_UNKNOWN: + default: + return NULL; + break; + } + } + return NULL; +} + + + + + +/***************************************************/ +/* $B%^%8%C%/%J%s%P!<$NDj5A$rD4$Y$F!"$=$l$K$"$o$;$?%3%^%s%I$rinput_command) || + (magic == NULL && mgcsfx && input_command_ex_flag)){ + + if(magic == NULL){ + if (fname != NULL && (ptr = strstr(input_command_ex, "%s"))){ + sprintf (command, input_command_ex, fname); + }else{ + strcpy (command, input_command_ex); + fname=NULL; + } + }else{ + /* Use stdin or give file name */ + if (fname != NULL && (ptr = strstr(magic->input_command, "%s"))){ + sprintf (command, magic->input_command, fname); + }else{ + strcpy (command, magic->input_command); + fname=NULL; + } + } + + /* Do the pipe/fork/exec here */ + if (pipe (fd) < 0){ + fprintf (stderr, "Can't pipe : %s\n", file_name); + close(file); + return 0; + } + + if ((pid = vfork ()) < 0){ + fprintf (stderr, "Can't vfork : %s\n", file_name); + close (fd[0]); + close (fd[1]); + close(file); + return 0; + } + + if (!pid){ + close(0); + if (fname == NULL || (open ("/dev/null", O_RDONLY) < 0)){ + dup(file); + } + close(file); + close(1); + dup(fd[1]); + close(2); + open("/dev/null", O_WRONLY); + close(fd[0]); + execl("/bin/sh", "/bin/sh", "-c", command, 0); + _exit(127); + } + + close (fd[1]); + dup2(fd[0], file); + close (fd[0]); + fname = NULL; + magic_cur = magic; + } +/* } while(magic != NULL); */ + + free(buffer); + + if(magic_cur == NULL && mgcsfx && input_command_ex_flag){ + i_it = IT_PNM; + i_com = input_command_ex; + }else{ + i_it = magic_cur->input_image_type; + i_com = magic_cur->input_command; + } + + if((magic_cur != NULL && i_com) || + (magic_cur == NULL && mgcsfx && input_command_ex_flag)){ + switch(i_it){ + case IT_PNM: + case IT_PPM: + case IT_PGM: + case IT_PBM: + case IT_PNM_RAW: + case IT_PPM_RAW: + case IT_PGM_RAW: + case IT_PBM_RAW: + case IT_PNM_ASCII: + case IT_PPM_ASCII: + case IT_PGM_ASCII: + case IT_PBM_ASCII: + rv = LoadPBM(file_name, pinfo, file); + break; + case IT_GIF: + case IT_JPEG: + case IT_TIFF: + case IT_JFIF: + case IT_XBM: + case IT_XPM: + case IT_BMP: + case IT_SUNRAS: + case IT_IRIS: + case IT_XWD: + case IT_MAG: + case IT_MAKI: + case IT_PI: + case IT_PIC: + case IT_PIC2: + SetISTR(ISTR_WARNING, "Yet supported input image type (from filter output)"); + rv = 0; + break; + case IT_UNKNOWN: + SetISTR(ISTR_WARNING, "Unknown input image type (from filter output)"); + rv = 0; + break; +#ifdef HAVE_MGCSFX_AUTO + case IT_AUTO: +#endif /* HAVE_MGCSFX_AUTO */ + default: + SetISTR(ISTR_WARNING, "Error in input image type (from filter output)"); + rv = 0; + break; + } + }else{ + rv = 0; + } + + while(wait(&pst) != pid); + if( *((char *)&pst) != 0 ) rv = 0; + + input_command_ex_flag = 0; + + return rv; + + /* fclose(fp); close in Load??? */ + /* return 0; error */ + /* return 1; ok */ +} + + + + + +/*--------------------------------------------------------------------------*/ +#ifndef MGCSFX_DEFAULT_INPUT_COMMAND +#define MGCSFX_DEFAULT_INPUT_COMMAND "tifftopnm" +#endif +#ifndef MGCSFX_DEFAULT_OUTPUT_COMMAND +#define MGCSFX_DEFAULT_OUTPUT_COMMAND "pnmtotiff" +#endif + +int MSWIDE = 0; +int MSHIGH = 0; + +#define MS_NBUTTS 2 +#define MS_BOK 0 +#define MS_BCANC 1 +#define BUTTW 60 /* width of buttons (OK or Cancel) */ +#define BUTTH 24 /* height of buttons (OK or Cancel) */ +#define RBSIZE 15 /* width and height of RB button (select, ON or OFF)*/ +#define CWIDE 8 /* width of character */ +/* #define CHIGH height of character defined in xv.h */ +#define MARGIN 3 /* margin of button and label SPACING */ + +#define MSD_TITLE "Save file with external command..." +#define MSD_RBTITLE "Type of Magic and Suffix" +#define MSD_IC_TITLE "input command" + +static BUTT msbut[MS_NBUTTS]; +static RBUTT *typeRB; + +static char output_command_ex[1024]; +static int output_command_ex_flag = 0; + +static int colorType; + +static int w_pid; +static int w_pstatus; + +#define MSNAMWIDE 252 /* width of 'file name' entry window */ +#define MAXFNLEN 256 /* max len of filename being entered */ +static char DialogFileName[MAXFNLEN+100]; /* filename being entered */ +static int curPos, stPos, enPos; /* filename textedit stuff */ + + +static mgcsfxtab *get_mgcsfx PARM((int)); +static void changeSuffix PARM((int)); + +static int WriteMGCSFX PARM((FILE**,byte*,int,int,int, + byte*,byte*,byte*,int,int,char*, + int, int, char*)); +void CreateMGCSFXW PARM((void)); +void MGCSFXDialog PARM((int)); +int MGCSFXCheckEvent PARM((XEvent *)); +int MGCSFXSaveParams PARM((char *, int)); + +static void drawMSD PARM((int,int,int,int)); +static void clickMSD PARM((int,int)); +static void doCmd PARM((int)); +static int writeMGCSFX PARM((void)); + +static void changeSuffix PARM((int)); +static void redrawNamMSD PARM((void)); +static void showFNamMSD PARM((void)); +static int keyinMSD PARM((int)); + +int getInputCom PARM((void)); +int getOutputCom PARM((void)); +/*--------------------------------------------------------------------------*/ + +/***************************************************/ +/* $B$I$l$rA*$s$@$+D4$Y$k!##0$O%3%^%s%I$rF~NO$9$k$b$N$H$9$k(B */ +static mgcsfxtab *get_mgcsfx(ms_type) + int ms_type; +{ + mgcsfxtab *magic; + int i; + + magic = NULL; + if(ms_type != 0){ + i = 1; + for(magic = mgcsfx_table; (magic && inext){i++;} + } + return magic; +} + +/***************************************************/ +/* $B30It%3%^%s%I$routput_command)){ + + /* Do the pipe/fork/exec here */ + if (pipe (fd) < 0){ + fprintf (stderr, "Can't pipe : %s\n", file_name); + return -1; + } + + if ((pid = vfork ()) < 0){ + fprintf (stderr, "Can't vfork : %s\n", file_name); + close (fd[0]); + close (fd[1]); + return -1; + } + + if (!pid){ + close(1); + dup(file); + close(file); + close(0); + dup(fd[0]); + close(2); + open("/dev/null", O_WRONLY); + close(fd[1]); + if(ms_type == 0){ + execl("/bin/sh", "/bin/sh", "-c", output_command_ex, 0); + }else{ + execl("/bin/sh", "/bin/sh", "-c", magic->output_command, 0); + } + _exit(127); + } + + close (fd[0]); + dup2(fd[1], file); + close (fd[1]); + + }else{ + return -1; + } + + + *fp = fdopen(file, "w"); + + /* sleep(1); Best way is wait for checking SIGCHLD, but it's feel waist.*/ + +#ifdef USE_SIGCHLD + if(w_p_fail != 2){ +#endif + if(ms_type == 0){ + rv = WritePBM(*fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle, + 1, comment); + }else{ + switch(magic -> output_image_type){ + case IT_PNM: + case IT_PPM: + case IT_PGM: + case IT_PBM: + case IT_PNM_RAW: + case IT_PPM_RAW: + case IT_PGM_RAW: + case IT_PBM_RAW: + rv = WritePBM(*fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle, + 1, comment); + break; + case IT_PNM_ASCII: + case IT_PPM_ASCII: + case IT_PGM_ASCII: + case IT_PBM_ASCII: + rv = WritePBM(*fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle, + 0, comment); + break; + case IT_GIF: + case IT_JPEG: + case IT_TIFF: + case IT_JFIF: + case IT_XBM: + case IT_XPM: + case IT_BMP: + case IT_SUNRAS: + case IT_IRIS: + case IT_XWD: + case IT_MAG: + case IT_MAKI: + case IT_PI: + case IT_PIC: + case IT_PIC2: + SetISTR(ISTR_WARNING, "Yet supported output image type (to filter input)"); + rv = -1; + break; + case IT_UNKNOWN: + SetISTR(ISTR_WARNING, "Unknown output image type (to filter input)"); + rv = -1; + break; +#ifdef HAVE_MGCSFX_AUTO + case IT_AUTO: +#endif /* HAVE_MGCSFX_AUTO */ + default: + SetISTR(ISTR_WARNING, "Error in output image type (to filter input)"); + rv = -1; + break; + } + } +#ifdef USE_SIGCHLD + }else{ + rv = -1; + } +#endif + +#ifdef USE_SIGCHLD + if(w_p_fail != 2){ +#endif + w_pid = pid; +#ifdef USE_SIGCHLD + w_p_fail = 0; + }else{ + rv = -1; + } +#endif + + output_command_ex_flag = 0; + + return rv; + + /* fclose(*fp); close in CloseOutFile in writeMGCSFX */ + /* return 0; ok */ + /* return -1; error */ +} + +/***************************************************/ +void CreateMGCSFXW() +{ + int y; + int type_num; + mgcsfxtab *entry; + + if (mgcsfx_setup_flag == 0) init_mgcsfx (); + + if(desc_width < strlen(MSD_IC_TITLE)) desc_width = strlen(MSD_IC_TITLE); + nitem_mgcsfx ++; + + MSWIDE = desc_width * CWIDE + RBSIZE + 36; /* 36 is start of RB button */ + MSHIGH = nitem_mgcsfx * (RBSIZE + MARGIN); + + if(MSWIDE < strlen(MSD_TITLE) + 20) MSWIDE = strlen(MSD_TITLE) + 20; + if(MSWIDE < strlen(MSD_RBTITLE) + 16) MSWIDE = strlen(MSD_RBTITLE) + 16; + if(MSWIDE < MSNAMWIDE + 10) MSWIDE = MSNAMWIDE + 10; + if(MSWIDE < BUTTW * 2 + 10) MSWIDE = BUTTW * 2 + 10; + + MSHIGH += 55 + LINEHIGH + 10 + BUTTH + 10; + + MSWIDE += 20; /* right side margin */ + MSHIGH += 10; /* RB buttun down side margin */ + + + mgcsfxW = CreateWindow("xv mgcsfx", "XVmgcsfx", NULL, + MSWIDE, MSHIGH, infofg, infobg, 0); + if (!mgcsfxW) FatalError("can't create mgcsfx window!"); + + XSelectInput(theDisp, mgcsfxW, + ExposureMask | ButtonPressMask | KeyPressMask); + + mgcsfxNameW = XCreateSimpleWindow(theDisp, mgcsfxW, + 10, MSHIGH-LINEHIGH-10-BUTTH-10-1, + (u_int) MSNAMWIDE+6, (u_int) LINEHIGH+5, + 1, infofg, infobg); + if (!mgcsfxNameW) FatalError("can't create mgcsfx name window"); + XSelectInput(theDisp, mgcsfxNameW, ExposureMask); + + /* Ok $B%\%?%s(B */ + BTCreate(&msbut[MS_BOK], mgcsfxW, + MSWIDE-BUTTW-10-BUTTW-10-1, MSHIGH-BUTTH-10-1, + BUTTW, BUTTH, + "Ok", infofg, infobg, hicol, locol); + /* Cancel $B%\%?%s(B*/ + BTCreate(&msbut[MS_BCANC], mgcsfxW, + MSWIDE-BUTTW-10-1, MSHIGH-BUTTH-10-1, + BUTTW, BUTTH, + "Cancel", infofg, infobg, hicol, locol); + + y = 55; + /* User should input command to exec external command */ + typeRB = RBCreate(NULL, mgcsfxW, 36, y, MSD_IC_TITLE, + infofg, infobg,hicol,locol); + y += (RBSIZE + MARGIN); /* 18 */ + + type_num = 1; + for (entry = mgcsfx_table; entry; entry = entry->next){ + RBCreate(typeRB, mgcsfxW, 36, y, entry->description, + infofg, infobg,hicol,locol); + y += (RBSIZE + MARGIN); /* 18 */ + if(entry->output_command == NULL){ + RBSetActive(typeRB, type_num, 0); /* if no command, off */ + } + type_num++; + } + + XMapSubwindows(theDisp, mgcsfxW); +} + + +/***************************************************/ +void MGCSFXDialog(vis) + int vis; +{ + if (vis) { + CenterMapWindow(mgcsfxW, msbut[MS_BOK].x + msbut[MS_BOK].w/2, + msbut[MS_BOK].y + msbut[MS_BOK].h/2, MSWIDE, MSHIGH); + } + else XUnmapWindow(theDisp, mgcsfxW); + mgcsfxUp = vis; +} + + +/***************************************************/ +int MGCSFXCheckEvent(xev) + XEvent *xev; +{ + /* check event to see if it's for one of our subwindows. If it is, + deal accordingly, and return '1'. Otherwise, return '0' */ + + int rv; + rv = 1; + + if (!mgcsfxUp) return (0); + + if (xev->type == Expose) { + int x,y,w,h; + XExposeEvent *e = (XExposeEvent *) xev; + x = e->x; y = e->y; w = e->width; h = e->height; + + if (e->window == mgcsfxW) drawMSD(x, y, w, h); + else rv = 0; + } + + else if (xev->type == ButtonPress) { + XButtonEvent *e = (XButtonEvent *) xev; + int x,y; + x = e->x; y = e->y; + + if (e->button == Button1) { + if (e->window == mgcsfxW) clickMSD(x,y); + else rv = 0; + } /* button1 */ + else rv = 0; + } /* button press */ + + else if (xev->type == KeyPress) { + XKeyEvent *e = (XKeyEvent *) xev; + char buf[128]; KeySym ks; XComposeStatus status; + int stlen; + + stlen = XLookupString(e,buf,128,&ks,&status); + buf[stlen] = '\0'; + + if (e->window == mgcsfxW) { + if (stlen) { + keyinMSD(buf[0]); + } + } + else rv = 0; + } + else rv = 0; + + if (rv == 0 && (xev->type == ButtonPress || xev->type == KeyPress)) { + XBell(theDisp, 50); + rv = 1; /* eat it */ + } + + return (rv); +} + + +/***************************************************/ +int MGCSFXSaveParams(fname, col) + char *fname; + int col; +{ + colorType = col; + strcpy(DialogFileName, GetDirFName()); + return (0); +} + +/***************************************************/ +/* $B%@%$%"%m%0$rI=<($9$k$H$-$N=hM}(B */ +static void drawMSD(x,y,w,h) + int x,y,w,h; +{ + int i; + XRectangle xr; + + xr.x = x; xr.y = y; xr.width = w; xr.height = h; + XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted); + + XSetForeground(theDisp, theGC, infofg); + XSetBackground(theDisp, theGC, infobg); + + for (i = 0; i < MS_NBUTTS; i++) BTRedraw(&msbut[i]); + + ULineString(mgcsfxW, typeRB->x-16, typeRB->y-3-DESCENT, + MSD_RBTITLE); + RBRedraw(typeRB, -1); + + DrawString(mgcsfxW, 20, 29, MSD_TITLE); + + XSetClipMask(theDisp, theGC, None); + + showFNamMSD(); +} + +/***************************************************/ +/* $B%@%$%"%m%0$r%/%j%C%/$7$?$H$-$N=hM}(B */ +static void clickMSD(x,y) + int x,y; +{ + int i; + BUTT *bp; + + /* check BUTTs */ + + /* check the RBUTTS first, since they don't DO anything */ + if ((i = RBClick(typeRB, x,y)) >= 0) { /* $BA*Br(B(type)$B%\%?%s$N=hM}(B */ + (void) RBTrack(typeRB, i); /* $BA*Br(B(type)$B%\%?%s$r2!$7$?$H$-(B */ + changeSuffix(i); + return; + } + + for (i = 0; i < MS_NBUTTS; i++) { /* Ok,Cancel $B%\%?%s$N=hM}(B */ + bp = &msbut[i]; + if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) + break; + } + if (i < MS_NBUTTS) /* found one */ /* Ok,Cancel $B%\%?%s$r2!$7$?$H$-(B */ + if (BTTrack(bp)) doCmd(i); +} + +/***************************************************/ +/* $B%\%?%s(B(Ok, Cancel) $B$N=hM}(B */ +static void doCmd(cmd) + int cmd; +{ + int rv; + + switch (cmd) { + case MS_BOK: /* Ok button */ { + char *fullname; + + rv = writeMGCSFX(); /* Save with filter(MGCSFX) */ + MGCSFXDialog(0); + + fullname = GetDirFullName(); + if (!ISPIPE(fullname[0])) { + XVCreatedFile(fullname); + if(!rv) StickInCtrlList(0); + } + } + break; + case MS_BCANC: /* Cancel button */ + DialogFileName[0] = '\0'; + curPos = stPos = enPos = 0; + MGCSFXDialog(0); + break; + default: + break; + } +} + +/*******************************************/ +static int writeMGCSFX() +{ + int rv, type; + int ptype, w, h, pfree, nc; + byte *inpix, *rmap, *gmap, *bmap; + + FILE *fp = NULL; + int file; + char *fullname; + + rv = -1; + type = RBWhich(typeRB); + + SetDirFName(DialogFileName); /* change filename in dir dialog */ + fullname = GetDirFullName(); + + if(type == 0){ + if(getOutputCom() == 0) return rv; + } + + file = OpenOutFileDesc(fullname); + if(file < 0) return rv; + + WaitCursor(); + inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap); + + rv = WriteMGCSFX(&fp, inpix, ptype, w, h, + rmap, gmap, bmap, nc, colorType, fullname, + type, file, picComments); + + SetCursors(-1); + + if (CloseOutFile(fp, fullname, rv) == 0) DirBox(0); + + WaitCursor(); +#ifdef USE_SIGCHLD + if(w_p_fail == 0){ +#endif + while(wait(&w_pstatus) != w_pid); /* if( *((char *)&w_pstatus) != 0 ) ; */ +#ifdef USE_SIGCHLD + }else{ + w_p_fail = 0; + } +#endif + w_pid = 0; + w_pstatus = 0; + + if (pfree) free(inpix); + return rv; +} + + +/***************************************/ +static void changeSuffix(ms_type) + int ms_type; +{ + /* see if there's a common suffix at the end of the DialogFileName. + if there is, remember what case it was (all caps or all lower), lop + it off, and replace it with a new appropriate suffix, in the + same case */ + + int allcaps; + char *suffix, *sp, *dp, lowsuf[512]; + mgcsfxtab *magic; + + /* find the last '.' in the DialogFileName */ + suffix = (char *) rindex(DialogFileName, '.'); + if (!suffix) return; + suffix++; /* point to first letter of the suffix */ + + /* check for all-caposity */ + for (sp = suffix, allcaps=1; *sp; sp++) + if (islower(*sp)) allcaps = 0; + + /* copy the suffix into an all-lower-case buffer */ + for (sp=suffix, dp=lowsuf; *sp; sp++, dp++) { + *dp = (isupper(*sp)) ? tolower(*sp) : *sp; + } + *dp = '\0'; + + + magic = get_mgcsfx(ms_type); + if(magic != NULL && magic->suffix != NULL){ + strcpy(lowsuf,(magic->suffix)+1); + + if (allcaps) { /* upper-caseify lowsuf */ + for (sp=lowsuf; *sp; sp++) + *sp = (islower(*sp)) ? toupper(*sp) : *sp; + } + + /* one other case: if the original suffix started with a single + capital letter, make the new suffix start with a single cap */ + if (isupper(suffix[0])) lowsuf[0] = toupper(lowsuf[0]); + + strcpy(suffix, lowsuf); /* tack onto DialogFileName */ + showFNamMSD(); + } +} + +/***************************************************/ +/* $B%@%$%"%m%0Fb$K%U%!%$%k%M!<%`$rI=<($9$k$H$-$N=hM}(B ($B2<@A$1(B)*/ +static void redrawNamMSD() +{ + int cpos; + + /* draw substring DialogFileName[stPos:enPos] and cursor */ + + Draw3dRect(mgcsfxNameW, 0, 0, (u_int) MSNAMWIDE+5, (u_int) LINEHIGH+4, R3D_IN, 2, + hicol, locol, infobg); + + XSetForeground(theDisp, theGC, infofg); + + if (stPos>0) { /* draw a "there's more over here" doowah */ + XDrawLine(theDisp, mgcsfxNameW, theGC, 0,0,0,LINEHIGH+5); + XDrawLine(theDisp, mgcsfxNameW, theGC, 1,0,1,LINEHIGH+5); + XDrawLine(theDisp, mgcsfxNameW, theGC, 2,0,2,LINEHIGH+5); + } + + if ((size_t) enPos < strlen(DialogFileName)) { + /* draw a "there's more over here" doowah */ + XDrawLine(theDisp, mgcsfxNameW, theGC, MSNAMWIDE+5,0,MSNAMWIDE+5,LINEHIGH+5); + XDrawLine(theDisp, mgcsfxNameW, theGC, MSNAMWIDE+4,0,MSNAMWIDE+4,LINEHIGH+5); + XDrawLine(theDisp, mgcsfxNameW, theGC, MSNAMWIDE+3,0,MSNAMWIDE+3,LINEHIGH+5); + } + + XDrawString(theDisp, mgcsfxNameW, theGC,3,ASCENT+3,DialogFileName+stPos, enPos-stPos); + + cpos = XTextWidth(mfinfo, &DialogFileName[stPos], curPos-stPos); + XDrawLine(theDisp, mgcsfxNameW, theGC, 3+cpos, 2, 3+cpos, 2+CHIGH+1); + XDrawLine(theDisp, mgcsfxNameW, theGC, 3+cpos, 2+CHIGH+1, 5+cpos, 2+CHIGH+3); + XDrawLine(theDisp, mgcsfxNameW, theGC, 3+cpos, 2+CHIGH+1, 1+cpos, 2+CHIGH+3); +} + +/***************************************************/ +/* $B%@%$%"%m%0Fb$K%U%!%$%k%M!<%`$rI=<($9$k(B */ +static void showFNamMSD() +{ + int len; + + len = strlen(DialogFileName); + + if (curPosenPos) enPos = curPos; + + if (stPos>len) stPos = (len>0) ? len-1 : 0; + if (enPos>len) enPos = (len>0) ? len-1 : 0; + + /* while substring is shorter than window, inc enPos */ + + while (XTextWidth(mfinfo, &DialogFileName[stPos], enPos-stPos) < MSNAMWIDE + && enPos MSNAMWIDE) { + if (enPos != curPos) enPos--; + else stPos++; + } + + + if (ctrlColor) XClearArea(theDisp, mgcsfxNameW, 2,2, (u_int) MSNAMWIDE+5-3, + (u_int) LINEHIGH+4-3, False); + else XClearWindow(theDisp, mgcsfxNameW); + + redrawNamMSD(); + BTSetActive(&msbut[MS_BOK], strlen(DialogFileName)!=0); +} + +/***************************************************/ +/* $B%-!=' ' && c<'\177') { /* printable characters */ + /* note: only allow 'piped commands' in savemode... */ + + /* only allow spaces in 'piped commands', not filenames */ + if (c==' ' && (!ISPIPE(DialogFileName[0]) || curPos==0)) return (-1); + + /* only allow vertbars in 'piped commands', not filenames */ + if (c=='|' && curPos!=0 && !ISPIPE(DialogFileName[0])) return(-1); + + if (len >= MAXFNLEN-1) return(-1); /* max length of string */ + xvbcopy(&DialogFileName[curPos], &DialogFileName[curPos+1], (size_t) (len-curPos+1)); + DialogFileName[curPos]=c; curPos++; + } + + else if (c=='\010' || c=='\177') { /* BS or DEL */ + if (curPos==0) return(-1); /* at beginning of str */ + xvbcopy(&DialogFileName[curPos], &DialogFileName[curPos-1], (size_t) (len-curPos+1)); + curPos--; + } + + else if (c=='\025') { /* ^U: clear entire line */ + DialogFileName[0] = '\0'; + curPos = 0; + } + + else if (c=='\013') { /* ^K: clear to end of line */ + DialogFileName[curPos] = '\0'; + } + + else if (c=='\001') { /* ^A: move to beginning */ + curPos = 0; + } + + else if (c=='\005') { /* ^E: move to end */ + curPos = len; + } + + else if (c=='\004') { /* ^D: delete character at curPos */ + if (curPos==len) return(-1); + xvbcopy(&DialogFileName[curPos+1], &DialogFileName[curPos], (size_t) (len-curPos)); + } + + else if (c=='\002') { /* ^B: move backwards char */ + if (curPos==0) return(-1); + curPos--; + } + + else if (c=='\006') { /* ^F: move forwards char */ + if (curPos==len) return(-1); + curPos++; + } + + else if (c=='\012' || c=='\015') { /* CR(\r) or LF(\n) */ + FakeButtonPress(&msbut[MS_BOK]); + } + + else if (c=='\033') { /* ESC = Cancel */ + FakeButtonPress(&msbut[MS_BCANC]); + } + + else if (c=='\011') { /* tab = filename expansion */ + if (1 /* !autoComplete() */) XBell(theDisp, 0); + else { + curPos = strlen(DialogFileName); + } + } + + else return(-1); /* unhandled character */ + + showFNamMSD(); + + return(0); +} + + +/*******************************************/ +int getInputCom() +{ + static char *labels[] = { "\nOk", "\033Cancel" }; + int i; + + strcpy(input_command_ex, MGCSFX_DEFAULT_INPUT_COMMAND); + i = GetStrPopUp("Input External Command (Input is PNM):", labels, 2, + input_command_ex, 1024, "",0); + if (i == 0 && strlen(input_command_ex) != 0){ + input_command_ex_flag = 1; + return 1; + }else{ + input_command_ex_flag = 0; + return 0; + } +} + +int getOutputCom() +{ + static char *labels[] = { "\nOk", "\033Cancel" }; + int i; + + strcpy(output_command_ex, MGCSFX_DEFAULT_OUTPUT_COMMAND); + i = GetStrPopUp("Input External Command (Output is PNM_RAW):", labels, 2, + output_command_ex, 1024, "",0); + if (i == 0 && strlen(output_command_ex) != 0){ + output_command_ex_flag = 1; + return 1; + }else{ + output_command_ex_flag = 0; + return 0; + } +} + +#ifdef SVR4 +Sigfunc * +xv_signal(signo, func) + int signo; + Sigfunc *func; +{ + struct sigaction act, oact; + + act.sa_handler = func; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + act.sa_flags |= SA_RESTART; + + if (sigaction(signo, &act, &oact) < 0) + return SIG_ERR; + + return oact.sa_handler; +} +#endif + +#endif /* HAVE_MGCSFX */ diff -urN xv-3.10a/xvmisc.c xv-3.10a-jp-extension-current/xvmisc.c --- xv-3.10a/xvmisc.c Sat Jan 14 08:41:34 1995 +++ xv-3.10a-jp-extension-current/xvmisc.c Wed Oct 9 20:36:21 1996 @@ -497,6 +497,11 @@ as we have to keep the alloc'd colors around, but we don't want anything else to stay */ +#ifdef AUTO_EXPAND + chdir(initdir); + Vdsettle(); +#endif + if (!theDisp) exit(i); /* called before connection opened */ if (useroot && i==0) { /* save the root info */ @@ -520,6 +525,18 @@ if (tiffW) XDestroyWindow(theDisp, tiffW); #endif +#ifdef HAVE_PIC2 + if (pic2W) XDestroyWindow(theDisp, pic2W); +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (pcdW) XDestroyWindow(theDisp, pcdW); +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (mgcsfxW) XDestroyWindow(theDisp, mgcsfxW); +#endif /* HAVE_MGCSFX */ + /* if NOT using stdcmap for images, free stdcmap */ if (colorMapMode != CM_STDCMAP) { int j; @@ -716,6 +733,18 @@ #ifdef HAVE_TIFF if (tiffW) XDefineCursor(theDisp, tiffW, otherc); #endif + +#ifdef HAVE_PIC2 + if (pic2W) XDefineCursor(theDisp, pic2W, otherc); +#endif /* HAVE_PIC2 */ + +#ifdef HAVE_PCD + if (pcdW) XDefineCursor(theDisp, pcdW, otherc); +#endif /* HAVE_PCD */ + +#ifdef HAVE_MGCSFX + if (mgcsfxW) XDefineCursor(theDisp, mgcsfxW, otherc); +#endif /* HAVE_MGCSFX */ } @@ -1000,6 +1029,9 @@ ((rv=(char *) getenv("cwd"))==NULL)) rv = "./"; strcpy(buf, rv); } +#ifdef AUTO_EXPAND + Vdtodir(buf); +#endif } diff -urN xv-3.10a/xvml.c xv-3.10a-jp-extension-current/xvml.c --- xv-3.10a/xvml.c +++ xv-3.10a-jp-extension-current/xvml.c Tue Oct 22 18:17:25 1996 @@ -0,0 +1,992 @@ +/* + * xvml.c - makes text item structure for multi-lingual textviewer. + * + * Entry Points: + * struct ml_text *ml_draw_text() + * struct context *ml_create_context() + * int ml_set_charsets() + * void get_monofont_size() + */ + +#include "xv.h" +#include + +#ifdef TV_MULTILINGUAL /* whole this file. */ + +#include "xvml.h" +#define HAVE_STRDUP 1 +#define USE_MULE_EXTENSION + +#ifndef __STDC__ +#define CHAR char +#else +#define CHAR int +#endif + +#define CODE_SI 0x0e /* LS0 */ +#define CODE_SO 0x0f /* LS1 */ +#define CODE_SS2 ((unsigned char) 0x8e) +#define CODE_SS3 ((unsigned char) 0x8f) + +int ml_tab_width = 64; /* dots */ + +struct charset { + int bpc; /* bytes per char */ + int noc; /* number of chars */ + char designator; + char *registry; + int bit7; + + int loaded; + char *fontname; + + XFontStruct *fs; +} charset[] = { + { 1, 94, 'B', "iso8859-1", 0, 0, NULL, NULL}, + { 1, 96, 'A', "iso8859-1", 1, 0, NULL, NULL}, + { 1, 94, '0', "omron_udc_zh-0", 0, 0, NULL, NULL}, + { 1, 94, '2', "mulearabic-0", 0, 0, NULL, NULL}, + { 1, 94, '3', "mulearabic-1", 0, 0, NULL, NULL}, + { 1, 94, '4', "mulearabic-2", 0, 0, NULL, NULL}, + { 1, 94, 'J', "jisx0201.1976-0", 0, 0, NULL, NULL}, + { 1, 96, '0', "muleipa-1", 1, 0, NULL, NULL}, + { 1, 96, '1', "viscii1.1-1", 1, 0, NULL, NULL}, + { 1, 96, '2', "viscii1.1-1", 1, 0, NULL, NULL}, + { 1, 96, 'B', "iso8859-2", 1, 0, NULL, NULL}, + { 1, 96, 'C', "iso8859-3", 1, 0, NULL, NULL}, + { 1, 96, 'D', "iso8859-4", 1, 0, NULL, NULL}, + { 1, 96, 'T', "tis620.1986-0", 1, 0, NULL, NULL}, + { 1, 96, 'F', "iso8859-7", 1, 0, NULL, NULL}, + { 1, 96, 'G', "iso8859-6", 1, 0, NULL, NULL}, + { 1, 96, 'H', "iso8859-8", 1, 0, NULL, NULL}, + { 1, 94, 'I', "jisx0201.1976-0", 1, 0, NULL, NULL}, + { 1, 96, 'L', "iso8859-5", 1, 0, NULL, NULL}, + { 1, 96, 'M', "iso8859-9", 1, 0, NULL, NULL}, + { 2, 94, '2', "ethio-0", 0, 0, NULL, NULL}, + { 2, 94, '@', "jisx0208.1978", 0, 0, NULL, NULL}, + { 2, 94, 'A', "gb2312.1980-0", 0, 0, NULL, NULL}, + { 2, 94, 'B', "jisx0208.1983-0", 0, 0, NULL, NULL}, + { 2, 94, 'C', "ksc5601.1987-0", 0, 0, NULL, NULL}, + { 2, 94, 'D', "jisx0212.1990-0", 0, 0, NULL, NULL}, + { 2, 94, '0', "big5.eten-0", 0, 0, NULL, NULL}, + { 2, 94, '1', "big5.hku-0", 0, 0, NULL, NULL}, + /* End Mark */ + { 0, 0, 0, NULL, 0, 0, NULL, NULL}, +}; +#define NR_CHARSETS ((int) (sizeof charset / sizeof charset[0])) + +static struct charset *ascii = NULL; + +struct context { + struct charset *g[4]; + struct charset **gl, **gr; + struct charset **ss; + int eol; /* 0: \n, 1: \r\n, 2: \r, 3: any */ + int valid[4]; /* g[i] is valid? */ + int short_form; /* allow shortened designator sequence? */ + int lock_shift; /* allow locking shift? */ + + unsigned char *cbuf, *cbp; + struct ml_text text; + int line; + int delta; + int toolong; + + Display *dpy; + Screen *scr; + Window root_win; +}; +#define DPY (context->dpy) +#define SCR (context->scr) +#define ROOT_WIN (context->root_win) + +static unsigned char *escape_sequence PARM((unsigned char *)); +static unsigned char *designator_sequence PARM((unsigned char *)); +static void locking_shift PARM((unsigned CHAR)); +static void single_shift PARM((unsigned CHAR)); +static void put_unknown_char PARM((unsigned CHAR)); +static struct charset *search_charset PARM((int, int, int)); +static void pack_string PARM((struct charset *, + unsigned char *, int)); +static void init_xrm PARM((void)); +static void init_xrm_fonts PARM((void)); +static void init_xrm_tab PARM((void)); +#ifndef HAVE_STRDUP +static char *strdup PARM((char *)); +#endif + +static char *default_fonts[] = { /* default for xrm_fonts */ + "-sony-fixed-medium-r-normal--16-*-*-*-*-*-iso8859-1", + "-jis-fixed-medium-r-normal--16-*-*-*-*-*-jisx0208.1983-0", +}; +static int xrm_nfonts; +static char **xrm_fonts; + +static struct context *context; /* current context */ + +struct ml_text *ml_draw_text(ctx, string, len) + struct context *ctx; + char *string; + int len; +{ + unsigned char *str = (unsigned char *) string; + unsigned char *estr = str + len; + + context = ctx; + + if(ascii == NULL){ + fputs("ml_draw_text: call ml_set_charsets, first.\n", stderr); + return NULL; + } + + if(!str) + return &context->text; + + WaitCursor(); + + if (context->text.maxlines != 0) { + struct ml_text *tp = &context->text; + struct ml_line *lp; + int i; + for (i = tp->nlines, lp = tp->lines; i > 0; i--, lp++) { + XTextItem16 *ip; + int j; + if (lp->maxitems != 0) + free((char *) lp->items); + } + free((char *) tp->lines); + tp->maxlines = tp->nlines = 0; + } + if (context->cbuf != NULL) + free((char *) context->cbuf); + context->cbp = (unsigned char *) malloc((size_t) len * 8);/* all \xxx */ + context->cbuf = context->cbp; + context->line = 0; + context->delta = 0; + context->ss = NULL; + + while(str < estr){ + if((*str & 0x80) == 0){ /* left half */ + struct charset *cs = context->ss ? *context->ss : *context->gl; + unsigned char min_char, max_char; + if (cs != NULL) { + if(cs->noc == 94){ + min_char = 0x21; + max_char = 0x7e; + }else{ + min_char = 0x20; + max_char = 0x7f; + } + } + + if (cs == NULL) + put_unknown_char(*str++); + else if(*str < min_char || *str > max_char){ /* C1 */ + switch(*str){ + case ' ': + { + unsigned char *p = str + 1; + while (*p == ' ' && p < estr) + p++; + pack_string(ascii, str, (int) (p - str)); + str = p; + } + break; + + case '\t': + pack_string(ascii, str++, 0); + break; + + case '\n': + switch (context->eol) { + case 0: /* unix type eol */ + pack_string(ascii, str, 0); + WaitCursor(); + str++; + break; + case 1: /* dos type eol */ + case 2: /* mac type eol */ + put_unknown_char('\n'); + str++; + break; + case 3: /* any type eol */ + pack_string(ascii, str++, 0); + while (*str == '\n' || *str == '\r') + str++; + WaitCursor(); + break; + } + break; + + case '\r': + switch (context->eol) { + case 0: + put_unknown_char('\r'); + str++; + break; + case 1: + str++; + if (*str == '\n') + pack_string(ascii, str++, 0); + else + put_unknown_char('\r'); + break; + case 2: + pack_string(ascii, str, 0); + WaitCursor(); + str++; + break; + case 3: + pack_string(ascii, str++, 0); + while (*str == '\n' || *str == '\r') + str++; + WaitCursor(); + break; + } + break; + + case '\033': + { + unsigned char *p; + str++; + if((p = escape_sequence(str)) == str) + put_unknown_char('\033'); + else + str = p; + } + break; + + case CODE_SI: + case CODE_SO: + if (!context->lock_shift) + put_unknown_char((unsigned int) *str++); + else + locking_shift((unsigned int) *str++); + break; + + default: + put_unknown_char((unsigned int) *str++); + } + }else{ /* GL */ + if (context->ss != NULL) { + pack_string(cs, str, 1); + str += cs->bpc; + context->ss = NULL; + } else { + int n; + + if (cs->bpc == 1) { + unsigned char *p = str; + for (n = 0; p < estr; n++) { + if (*p < min_char || *p > max_char) + break; + p++; + } + pack_string(cs, str, n); + str = p; + } else { + unsigned char *p = str; + for (n = 0; p < estr - 1; n++) { + if (*p < min_char || *p > max_char || + *(p + 1) < min_char || *(p + 1) > max_char) + break; + p += 2; + } + if (n > 0) + pack_string(cs, str, n); + else + put_unknown_char(*p++); + str = p; + } + } + } + }else{ /* right half */ + struct charset *cs = context->ss ? *context->ss : *context->gr; + unsigned char min_char, max_char; + if (cs != NULL) { + if(cs->noc == 94){ + min_char = 0xa1; + max_char = 0xfe; + }else{ + min_char = 0xa0; + max_char = 0xff; + } + } + + if (cs == NULL) + put_unknown_char(*str++); + else if(*str < min_char || *str > max_char){ /* C2 */ + unsigned char c = *str++; + switch(c){ + case CODE_SS2: + case CODE_SS3: + single_shift((unsigned CHAR) c); + break; + default: + put_unknown_char(c); + } + }else{ /* GR */ + if (context->ss != NULL) { + pack_string(cs, str, 1); + str += cs->bpc; + context->ss = NULL; + } else { + int n; + + if (cs->bpc == 1) { + unsigned char *p = str; + for (n = 0; p < estr; n++) { + if (*p < min_char || *p > max_char) + break; + p++; + } + pack_string(cs, str, n); + str = p; + } else { + unsigned char *p = str; + for (n = 0; p < estr - 1; n++) { + if (*p < min_char || *p > max_char || + *(p + 1) < min_char || *(p + 1) > max_char) + break; + p += 2; + } + if (n > 0) + pack_string(cs, str, n); + else + put_unknown_char(*p++); + str = p; + } + } + } + } + } + + { + struct ml_text *tp = &context->text; + struct ml_line *lp; + int i; + + tp->width = 0; + tp->height = 0; + for (lp = tp->lines, i = tp->nlines; i > 0; lp++, i--) { + if (lp->nitems == 0) { + lp->ascent = ascii->fs->ascent; + lp->descent = ascii->fs->descent; + } + if (tp->width < lp->width) + tp->width = lp->width; + tp->height += lp->ascent + lp->descent; + } + } + + SetCursors(-1); + return &context->text; +} + +static unsigned char *escape_sequence(str) + unsigned char *str; +{ + unsigned char *p; + switch(*str){ + case '$': + case '(': case ')': case '*': case '+': + case '-': case '.': case '/': case ',': + if((p = designator_sequence(str)) == NULL) + return str; + return p; + case 'n': case 'o': case '~': case '}': case '|': + if (!context->lock_shift) + return str; + locking_shift(*str); + return str + 1; + case 'N': case 'O': + single_shift(*str); + return str + 1; + } + return str; + +} + +static unsigned char *designator_sequence(str) + unsigned char *str; +{ + unsigned char *p = str; + int noc, bpc, n_g, shortened; + unsigned char des; + struct charset *cs; + + if(*p == '$'){ + bpc = 2; + p++; + }else + bpc = 1; + + switch(*p++){ + case '(': noc = 94; n_g = 0; des = *p++; shortened = 0; break; + case ')': noc = 94; n_g = 1; des = *p++; shortened = 0; break; + case '*': noc = 94; n_g = 2; des = *p++; shortened = 0; break; + case '+': noc = 94; n_g = 3; des = *p++; shortened = 0; break; +#ifdef USE_MULE_EXTENSION + case ',': noc = 96; n_g = 0; des = *p++; shortened = 0; break; +#endif + case '-': noc = 96; n_g = 1; des = *p++; shortened = 0; break; + case '.': noc = 96; n_g = 2; des = *p++; shortened = 0; break; + case '/': noc = 96; n_g = 3; des = *p++; shortened = 0; break; + case '@': noc = 94; n_g = 0; des = 'B'; shortened = 0; break; + case 'A': noc = 94; n_g = 0; des = 'A'; shortened = 1; break; + case 'B': noc = 94; n_g = 0; des = 'B'; shortened = 1; break; + default: return NULL; + } + if (!context->short_form && shortened) + return NULL; + + if((cs = search_charset(bpc, noc, des)) == NULL){ + if(DEBUG){ + fprintf(stderr, "designator_sequence: (%d,%d,%c) not found.\n", + bpc, noc, des); + } + return NULL; + } + if (!context->valid[n_g]) + return NULL; + context->g[n_g] = cs; + if(DEBUG){ + fprintf(stderr, + "designator_sequence: G%d is `%s'.\n", n_g, cs->registry); + } + return p; +} + +static void locking_shift(c) + unsigned CHAR c; +{ + switch((unsigned char) c){ + case CODE_SI: context->gl = &context->g[0]; break; + case CODE_SO: context->gl = &context->g[1]; break; + case 'n': context->gl = &context->g[2]; break; + case 'o': context->gl = &context->g[3]; break; + case '~': context->gr = &context->g[1]; break; + case '}': context->gr = &context->g[2]; break; + case '|': context->gr = &context->g[3]; break; + } + if(DEBUG){ + fprintf(stderr, "locking_shift: (%d,%d).\n", + (int)(context->gl - context->g), + (int)(context->gr - context->g)); + } +} + +static void single_shift(c) + unsigned CHAR c; +{ + switch((unsigned char) c){ + case CODE_SS2: context->ss = &context->g[2]; break; + case CODE_SS3: context->ss = &context->g[3]; break; + } +} + + +static void put_unknown_char(chr) + unsigned CHAR chr; +{ + unsigned char c = chr; + + if(c < 0x20){ + unsigned char buf[2]; + buf[0] = '^'; + buf[1] = c + 0x40; + pack_string(ascii, buf, 2); + }else{ + unsigned char buf[4]; + buf[0] = '\\'; + buf[1] = ((c >> 6) & 07) + '0'; + buf[2] = ((c >> 3) & 07) + '0'; + buf[3] = ((c ) & 07) + '0'; + pack_string(ascii, buf, 4); + } +} + +struct context *ml_create_context(s) + Screen *s; +{ + context = (struct context *) malloc(sizeof *context); + + context->g[0] = NULL; + context->g[1] = NULL; + context->g[2] = NULL; + context->g[3] = NULL; + context->gl = NULL; + context->gr = NULL; + context->ss = NULL; + + context->cbuf = NULL; + context->text.maxlines = context->text.nlines = 0; + context->line = 0; + context->delta = 0; + context->toolong = 0; + + DPY = DisplayOfScreen(s); + SCR = s; + ROOT_WIN = RootWindowOfScreen(s); + + return context; +} + + +int ml_set_charsets(ctx, sys) + struct context *ctx; + struct coding_system *sys; +{ + int retval = 0; + int i; + + context = ctx; + + if(ascii == NULL){ + init_xrm(); + if((ascii = search_charset(1, 94, 'B')) == NULL){ + fputs("ml_set_charsets: ascii charset not found.\n", stderr); + Quit(1); + } + if (ascii->fs == NULL) { + fputs("ml_set_charsets: iso8859-1 font not found.\n", stderr); + Quit(1); + } + } + for(i = 0; i < 4; i++){ + struct charset *spec; + switch(sys->design[i].bpc){ + case -1: /* make G[i] invalid */ + context->valid[i] = 0; + break; + + case 0: /* don't change */ + break; + + case 1: case 2: /* change it */ + if((context->g[i] = search_charset(sys->design[i].bpc, + sys->design[i].noc, + sys->design[i].des)) == NULL){ + fputs("ml_set_charsets: ", stderr); + fprintf(stderr, "(%d,%d,%c) is specified as G%d, ", + sys->design[i].bpc, sys->design[i].noc, + sys->design[i].des, i); + fputs("but not found. using `iso8859-1'.\n", stderr); + context->g[i] = ascii; + retval++; + } + context->valid[i] = 1; + break; + + default: /* error */ + fprintf(stderr,"ml_set_charsets: bad arguments of G%d. ", i); + fputs("using `iso8859-1'.\n", stderr); + context->g[i] = ascii; + retval++; + } + } + if((unsigned int) sys->gl < 4) + context->gl = &context->g[sys->gl]; + else{ + fprintf(stderr, "ml_set_charsets: bad number as GL. using G0.\n"); + context->gl = &context->g[0]; + } + if((unsigned int) sys->gr < 4) + context->gr = &context->g[sys->gr]; + else{ + fprintf(stderr, "ml_set_charsets: bad number as GR. using G0.\n"); + context->gr = &context->g[0]; + } + context->eol = sys->eol; + context->short_form = sys->short_form; + context->lock_shift = sys->lock_shift; + return retval; +} + +static struct charset *search_charset(bpc, noc, des) + int bpc, noc; + int des; +{ + struct charset *cset; + for(cset = charset; cset->bpc != 0; cset++){ + if(cset->bpc == bpc && + cset->noc == noc && + cset->designator == (char) des){ + if(!cset->loaded){ +#if 0 + int i, l; + l = strlen(cset->registry); + for (i = 0; i < xrm_nfonts; i++) { + int li = strlen(xrm_fonts[i]); + if (li > l) { + if (xrm_fonts[i][li - l - 1] == '-' && + strcmp(xrm_fonts[i] + li - l, + cset->registry) == 0) { + if ((cset->fs = XLoadQueryFont(DPY, xrm_fonts[i])) + != NULL) { + if (DEBUG) { + fprintf(stderr, "%s for %s\n", + xrm_fonts[i], cset->registry); + } + cset->fontname = xrm_fonts[i]; + break; + } else + SetISTR(ISTR_WARNING, + "%s: font not found.", xrm_fonts[i]); + } + } + } +#else + int i, l; + l = strlen(cset->registry); + for (i = 0; i < xrm_nfonts && cset->fs == NULL; i++) { + int j, nfnts = 0; + char **fnts = XListFonts(DPY, xrm_fonts[i], + 65535, &nfnts); + for (j = 0 ; j < nfnts; j++) { + int ll = strlen(fnts[j]); + if (*(fnts[j] + ll - l - 1) == '-' && + strcmp(fnts[j] + ll - l, cset->registry)== 0) { + if ((cset->fs = XLoadQueryFont(DPY, fnts[j])) + != NULL) { + if (DEBUG) { + fprintf(stderr, "%s for %s\n", + fnts[j], cset->registry); + } + cset->fontname = strdup(fnts[j]); + break; + } else + SetISTR(ISTR_WARNING, + "%s: font not found", fnts[j]); + } + } + if (fnts != NULL) + XFreeFontNames(fnts); + } +#endif + if(cset->fs == NULL){ + SetISTR(ISTR_WARNING, + "font for %s not found.\nusing ascii font.", + cset->registry); + if (ascii != NULL) + cset->fs = ascii->fs; + } + + cset->loaded = 1; + } + return cset; + } + } + return NULL; +} + +static void pack_string(cs, str, len) + struct charset *cs; + unsigned char *str; + int len; /* number of chars(not bytes) */ +{ + struct ml_text *mt = &context->text; + struct ml_line *lp; + XTextItem16 *ip; + + if (context->line == mt->maxlines) { + int oldmax = mt->maxlines; + if (mt->maxlines < 1) + mt->maxlines = 1; + else + mt->maxlines = 2 * mt->maxlines; + if (oldmax == 0) + mt->lines = (struct ml_line *) + malloc(sizeof(struct ml_line) * mt->maxlines); + else { + mt->lines = (struct ml_line *) + realloc(mt->lines, + sizeof(struct ml_line) * mt->maxlines); + } + } + lp = &mt->lines[context->line]; + if (mt->nlines == context->line) { + mt->nlines++; + lp->maxitems = 0; + lp->nitems = 0; + lp->width = 0; + lp->ascent = lp->descent = 0; + } + + if (len == 0) { + switch (*str) { + case '\n': + context->line++; + context->delta = 0; + context->toolong = 0; + break; + case '\t': + { + int nx, x = lp->width + context->delta; + nx = (x + ml_tab_width) / ml_tab_width * ml_tab_width; + context->delta += nx - x; + } + break; + } + return; + } + + if (context->toolong) + return; + if (lp->width > 30000) { + context->toolong = 1; + cs = ascii; + str = (unsigned char *) "..."; + len = 3; + } + + if (lp->nitems == lp->maxitems) { + int oldmax = lp->maxitems; + if (lp->maxitems < 1) + lp->maxitems = 1; + else + lp->maxitems = 2 * lp->maxitems; + if (oldmax == 0) + lp->items = (XTextItem16 *) + malloc(sizeof(XTextItem16) * lp->maxitems); + else + lp->items = (XTextItem16 *) + realloc(lp->items, + sizeof(XTextItem16) * lp->maxitems); + } + ip = &lp->items[lp->nitems++]; + ip->chars = (XChar2b *) context->cbp; + ip->nchars = len; + ip->delta = context->delta; + ip->font = cs->fs->fid; + context->cbp += 2 * len; + context->delta = 0; + + if (cs->bpc == 1) { + XChar2b *p; + unsigned char b7 = cs->bit7 ? 0x80 : 0; + int i; + for (i = len, p = ip->chars; i > 0; i--, p++) { + p->byte1 = '\0'; + p->byte2 = (*str++ & 0x7f) | b7; + } + } else { + XChar2b *p; + unsigned char b7 = cs->bit7 ? 0x80 : 0; + int i; + for (i = len, p = ip->chars; i > 0; i--, p++) { + p->byte1 = (*str++ & 0x7f) | b7; + p->byte2 = (*str++ & 0x7f) | b7; + } + } + + lp->width += XTextWidth16(cs->fs, ip->chars, ip->nchars); + if (lp->ascent < cs->fs->ascent) + lp->ascent = cs->fs->ascent; + if (lp->descent < cs->fs->descent) + lp->descent = cs->fs->descent; +} + +void get_monofont_size(wide, high) + int *wide, *high; +{ + if (ascii == NULL) { + fputs("ml_draw_text: call ml_set_charsets, first.\n", stderr); + return; + } + *wide = ascii->fs->max_bounds.width; + *high = ascii->fs->ascent + ascii->fs->descent; +} + +static void init_xrm() +{ + init_xrm_fonts(); + init_xrm_tab(); +} + +static void init_xrm_fonts() +{ + char *p, *fns = XGetDefault(theDisp, "xv", "fontSet"); + int n; + if (fns == NULL) { + xrm_fonts = default_fonts; + xrm_nfonts = sizeof default_fonts / sizeof *default_fonts; + return; + } + while(*fns == ' ' || *fns == '\t') + fns++; + if (*fns == '\0') { + xrm_fonts = default_fonts; + xrm_nfonts = sizeof default_fonts / sizeof *default_fonts; + return; + } + fns = strdup(fns); + + n = 1; + for (p = fns; *p != '\0'; p++) { + if (*p == ',') + n++; + } + xrm_nfonts = n; + xrm_fonts = (char **) malloc(sizeof (char *) * xrm_nfonts); + for (n = 0, p = fns; n < xrm_nfonts && *p != '\0'; ) { + while (*p == ' ' || *p == '\t') + p++; + xrm_fonts[n++] = p; + while (1) { + char *q; + while (*p != ' ' && *p != '\t' && *p != ',' && *p != '\0') + p++; + q = p; + while (*q == ' ' || *q == '\t') + q++; + if (*q == ',' || *q == '\0') { + *p = '\0'; + p = q + 1; + break; + } else + p = q; + } + } + for ( ; n < xrm_nfonts; n++) + xrm_fonts[n] = ""; +} + +static void init_xrm_tab() +{ + char *ts = XGetDefault(theDisp, "xv", "tabWidth"); + unsigned short tab; + if (ts == NULL) + tab = 64; + else { + char *ep; + long t; + int bad = 0; + t = strtol(ts, &ep, 0); + tab = (unsigned short) t; + if (ep != NULL) { + while (*ep == ' ' && *ep == '\t') + ep++; + if (*ep != '\0') + bad = 1; + } + if (tab != (long) (unsigned long) t) + bad = 1; + if (bad) { + SetISTR(ISTR_WARNING, "bad tab width."); + tab = 64; + } + } + ml_tab_width = tab; +} + + +#ifndef HAVE_STRDUP +static char *strdup(str) + char *str; +{ + return strcpy(malloc(strlen(str) + 1), str); +} +#endif + +char *lookup_registry(d, b7) + struct design d; + int *b7; +{ + int i; + for (i = 0; i < NR_CHARSETS; i++) { + if (charset[i].bpc == d.bpc && charset[i].noc == d.noc && + charset[i].designator == d.des) { + *b7 = charset[i].bit7; + return charset[i].registry; + } + } + return NULL; +} + +struct design lookup_design(registry, b7) + char *registry; + int b7; +{ + struct design d; + int i; + d.bpc = 0; + d.noc = 0; + d.des = '\0'; + for (i = 0; i < NR_CHARSETS; i++) { + if (strcmp(charset[i].registry, registry) == 0 && + charset[i].bit7 == b7) { + d.bpc = charset[i].bpc; + d.noc = charset[i].noc; + d.des = charset[i].designator; + break; + } + } + return d; +} + +char *sjis_to_jis(orig, len, newlen) + char *orig; + int len, *newlen; +{ + unsigned char *new; + unsigned char *p, *q, *endp; + if (len == 0) { + *newlen = 0; + return (char *) malloc((size_t) 1); + } + new = (unsigned char *) malloc((size_t) len * 4); /* enough big */ + for (p = (unsigned char *) orig, endp = p + len, q = new; p < endp; ) { + if ((*p & 0x80) == 0) /* 1 byte char */ + *q++ = *p++; + else if (*p >= 0x81 && *p <= 0x9f) { /* kanji 1st byte */ + unsigned char c1 = *p++; + unsigned char c2 = *p++; + if (c2 < 0x40 || c2 > 0xfc) { /* bad 2nd byte */ + *q++ = CODE_SS2; + *q++ = c1; + *q++ = CODE_SS2; + *q++ = c2; + } else { /* right 2nd byte */ + if (c2 <= 0x9e) { + if (c2 > 0x7f) + c2--; + c1 = (c1 - 0x81) * 2 + 1 + 0xa0; + c2 = (c2 - 0x40) + 1 + 0xa0; + } else { + c1 = (c1 - 0x81) * 2 + 2 + 0xa0; + c2 = (c2 - 0x9f) + 1 + 0xa0; + } + *q++ = c1; + *q++ = c2; + } + } else if (*p >= 0xe0 && *p <= 0xef) { /* kanji 1st byte */ + unsigned char c1 = *p++; + unsigned char c2 = *p++; + if (c2 < 0x40 || c2 > 0xfc) { /* bad 2nd byte */ + *q++ = CODE_SS2; + *q++ = c1; + *q++ = CODE_SS2; + *q++ = c2; + } else { /* right 2nd byte */ + if (c2 <= 0x9e) { + c1 = (c1 - 0xe0) * 2 + 63 + 0xa0; + c2 = (c2 - 0x40) + 1 + 0xa0; + } else { + c1 = (c1 - 0xe0) * 2 + 64 + 0xa0; + c2 = (c2 - 0x9f) + 1 + 0xa0; + } + *q++ = c1; + *q++ = c2; + } + } else { /* katakana or something */ + *q++ = CODE_SS2; + *q++ = *p++; + } + } + *newlen = q - new; + + return (char *) realloc(new, (size_t) *newlen); +} + +#endif /* TV_MULTILINGUAL */ diff -urN xv-3.10a/xvml.h xv-3.10a-jp-extension-current/xvml.h --- xv-3.10a/xvml.h +++ xv-3.10a-jp-extension-current/xvml.h Mon Oct 14 15:01:47 1996 @@ -0,0 +1,96 @@ +#ifndef MLVIEW_H +#define MLVIEW_H + +/* + * What is this? + * + * It is a package to show multi-lingual text. + * + * How to use? + * + * 1. Call ml_set_screen(Screen *scr); + * Tell this package the screen you use. + * + * 2. Call ml_set_charsets(struct char_spec spec[4], int gl, int gr); + * Tell this package the initial charsets. + * Gn is set to the charset specified by spec[n], respectively. + * GL and GR are set to G[gl] and G[gr], respectively. + * If first call, iso8859-1 font is loaded. + * + * 3. Call ml_draw_text(char *string); + * It Creates a bitmap, and returns it to you. + * If something goes wrong, it returns None. + * DON'T free the returned pixmaps!! + * + * BUGS: + * - Amharic and Tigrigna characters are strange. + * - Big5 is not supported. + * - Reverse direction is not supported. + * - Composing is not supported. + * - Cantonese can't be shown. + * - Texts which have many lines are buggy. + * + * NOTE: + * - Shifted JIS and Shifted GB must be converted to iso2022 in advance. + * + * Example of parameters to ml_set_charsets: + * - EUC-Japan + * spec = { {1, 94, 'B'}, G0 is US-ASCII + * {2, 94, 'B'}, G1 is JIS X0208 + * {1, 94, 'J'}, G2 is (right-half of)JIS X0201 + * {2, 94, 'D'} }; G3 is JIS X0212 + * gl = 0; GL is G0 + * gr = 1; GR is G1 + * + * - Compound Text + * spec = { {1, 94, 'B'}, G0 is US-ASCII + * {1, 96, 'A'}, G1 is Latin-1 + * {1, 94, 'B'}, G2 is US-ASCII (maybe unused) + * {1, 94, 'B'} }; G3 is US-ASCII (maybe unused) + * gl = 0; GL is G0 + * gr = 1; GR is G1 + * + * - Korean Mail + * spec = { {1, 94, 'B'}, G0 is US-ASCII + * {2, 94, 'C'}, G1 is KSC5601 + * {1, 94, 'B'}, G2 is US-ASCII (maybe unused) + * {1, 94, 'B'} }; G3 is US-ASCII (maybe unused) + * gl = 0; GL is G0 + * gl = 1; GR is G1 + */ + +struct coding_system { + struct design { + int bpc; /* byte per char if 1 or 2, + don't touch if 0, or + don't use if -1.*/ + int noc; /* number of chars (94 or 96) */ + char des; /* designator ('A', 'B', ...) */ + } design[4]; + int gl, gr; + int eol; + int short_form; + int lock_shift; +}; + +struct ml_text { + int maxlines, nlines; + struct ml_line { + int maxitems, nitems; + int width, ascent, descent; + XTextItem16 *items; + } *lines; + int width, height; +}; + +struct context; +struct ml_text *ml_draw_text PARM((struct context *, char *, int)); +struct context *ml_create_context PARM((Screen *)); +int ml_set_charsets PARM((struct context *, + struct coding_system *)); +void get_monofont_size PARM((int *, int *)); +char *sjis_to_jis PARM((char *, int, int *)); +char *lookup_registry PARM((struct design, int *)); +struct design lookup_design PARM((char *, int)); + +#endif diff -urN xv-3.10a/xvpbm.c xv-3.10a-jp-extension-current/xvpbm.c --- xv-3.10a/xvpbm.c Wed Jan 4 06:23:44 1995 +++ xv-3.10a-jp-extension-current/xvpbm.c Wed Oct 9 20:36:24 1996 @@ -38,10 +38,83 @@ static char *bname; + +#ifdef HAVE_MGCSFX +/* + * When file read or file write is fail, probably it's caused by + * reading from pipe which has no data yet, or writing to pipe + * which is not ready yet. + * Then, we can use systemcall select to descriptor of pipe and wait. + * if you want, change 'undef' to 'define' in the following line. + * This feature is performance killer. + */ +#undef FIX_PIPE_ERROR + +#ifdef __osf__ +#ifdef __alpha +#define FIX_PIPE_ERROR +#endif /* __alpha */ +#endif /* __osf__ */ + +#endif /* HAVE_MGCSFX */ + + +#ifdef FIX_PIPE_ERROR + +int pipefdr; + +struct timeval timeout; +int width; +fd_set fds; + +static void ready_read() +{ + if(pipefdr < 0) return; /* if file descriptor is not pipe, OK */ + WaitCursor(); + +reselect: + /* setting of timeout */ + timeout.tv_sec = 1; /* 1 sec */ + timeout.tv_usec = 0; /* 0 usec */ + + FD_ZERO(&fds); /* clear bits */ + FD_SET(pipefdr, &fds); /* set bit of fd in fds */ + + /* number of file descriptor to want check (0 $B!A(B width-1) */ + width = pipefdr + 1; + + /* select returns number of file descriptors */ + if (select(width, &fds, NULL, NULL, &timeout) < 0){ + if(DEBUG){ + fprintf(stderr, "No file descriptors can't selected, waiting...\n"); + } + goto reselect; + } + + if (FD_ISSET(pipefdr, &fds)){ + /* Now, descriptor of pipe is ready to read */ + return; + }else{ + if(DEBUG){ + fprintf(stderr, "Can't read from pipe yet, waiting...\n"); + } + goto reselect; + } + +} +#endif /* FIX_PIPE_ERROR */ + /*******************************************/ +#ifdef HAVE_MGCSFX +int LoadPBM(fname, pinfo, fd) + char *fname; + PICINFO *pinfo; + int fd; +#else int LoadPBM(fname, pinfo) char *fname; PICINFO *pinfo; +#endif /* HAVE_MGCSFX */ /*******************************************/ { /* returns '1' on success */ @@ -50,6 +123,10 @@ int c, c1; int maxv, rv; +#ifdef FIX_PIPE_ERROR + pipefdr = fd; +#endif /* FIX_PIPE_ERROR */ + garbage = maxv = rv = 0; bname = BaseName(fname); @@ -57,6 +134,22 @@ pinfo->comment = (char *) NULL; +#ifdef HAVE_MGCSFX + if(fd < 0){ + /* open the file */ + fp = xv_fopen(fname,"r"); + if (!fp) return (pbmError(bname, "can't open file")); + + /* compute file length */ + fseek(fp, 0L, 2); + filesize = ftell(fp); + fseek(fp, 0L, 0); + }else{ + fp = fdopen(fd, "r"); + if (!fp) return (pbmError(bname, "can't open file")); + filesize = 0; /* dummy */ + } +#else /* open the file */ fp = xv_fopen(fname,"r"); if (!fp) return (pbmError(bname, "can't open file")); @@ -65,6 +158,7 @@ fseek(fp, 0L, 2); filesize = ftell(fp); fseek(fp, 0L, 0); +#endif /* HAVE_MGCSFX */ /* read the first two bytes of the file to determine which format @@ -236,7 +330,20 @@ } } else { +#ifdef FIX_PIPE_ERROR + reread: + numgot += fread(pic8 + numgot, (size_t) 1, (size_t) w*h - numgot, fp); /* read raw data */ + if(errno == EINTR){ + if(DEBUG){ + fprintf(stderr, + "Can't read all data from pipe, call select and waiting...\n"); + } + ready_read(); + goto reread; + } +#else numgot = fread(pic8, (size_t) 1, (size_t) w*h, fp); /* read raw data */ +#endif /* FIX_PIPE_ERROR */ } } @@ -297,7 +404,20 @@ } } else { +#ifdef FIX_PIPE_ERROR + reread: + numgot += fread(pic24 + numgot, (size_t) 1, (size_t) w*h*3 - numgot, fp); /* read data */ + if(errno == EINTR){ + if(DEBUG){ + fprintf(stderr, + "Can't read all data from pipe, call select and waiting...\n"); + } + ready_read(); + goto reread; + } +#else numgot = fread(pic24, (size_t) 1, (size_t) w*h*3, fp); /* read data */ +#endif /* FIX_PIPE_ERROR */ } } diff -urN xv-3.10a/xvpcd.c xv-3.10a-jp-extension-current/xvpcd.c --- xv-3.10a/xvpcd.c +++ xv-3.10a-jp-extension-current/xvpcd.c Wed Oct 9 20:37:20 1996 @@ -0,0 +1,1029 @@ +/* + * xvpcd.c - load routine for 'PhotoCD' format pictures + * + * LoadPCD(fname, pinfo, size) - loads a PhotoCD file + * + * This routine will popup a choice of which of the 5 available resolutions + * the user wants to choose, then load it as a 24 bit image. + * + * Copyright 1993 David Clunie, Melbourne, Australia. + * + * The outline of this is shamelessly derived from xvpbm.c to read the + * file, and xvtiffwr.c to handle the popup window and X stuff (X never + * has been my forte !), and the PhotoCD format information (though not + * the code) was found in Hadmut Danisch's (danisch@ira.uka.de) hpcdtoppm + * program in which he has reverse engineered the format by studying + * hex dumps of PhotoCDs ! After all who can afford the Kodak developer's + * kit, which none of us have seen yet ? Am I even allowed to mention these + * words (Kodak, PhotoCD) ? I presume they are registered trade marks. + * + * PS. I have no idea how Halmut worked out the YCC <-> RGB conversion + * factors, but I have calculated them from his tables and the results + * look good enough to me. + * + * Added size parameter to allow the schnautzer to create thumnails + * without requesting the size every time. + */ + +#define trace (void) +#define HAVE_PCD_DIALOG + +#include "xv.h" +#include + +#ifdef HAVE_PCD + +/* comments on error handling: + a truncated file is not considered a Major Error. The file is loaded, the + rest of the pic is filled with 0's. + + not being able to malloc is a Fatal Error. The program is aborted. */ + + +static void magnify PARM((int,int,int,int,int,byte*)); +static int pcdError PARM((char*,char*)); +static int gethuffdata PARM((byte*,byte*,byte*,int,int)); + +#define wcurfactor 16 /* Call WaitCursor() every n rows */ + +static char *bname; + +static int size; /* Set by window routines */ + +static int leaveitup; /* Cleared by docmd() when OK or CANCEL pressed */ +static int goforit; /* Set to 1 if OK or 0 if CANCEL */ + +static FILE *fp; + + +/*******************************************/ +int LoadPCD(fname, pinfo,theSize) + char *fname; + PICINFO *pinfo; + int theSize; +/* The size should be -1 for the popup to ask otherwise fast is assumed */ +/*******************************************/ +{ + /* returns '1' on success */ + + int rv; + long offset; + int mag; + + byte *pic24, *luma, *chroma1, *chroma2, *ptr, *lptr, *c1ptr, *c2ptr; + int w, h; + int row, col; + + int huffplanes; + + bname = BaseName(fname); + + pinfo->pic = (byte *) NULL; + pinfo->comment = (char *) NULL; + + + /* open the file */ + fp=fopen(fname,"r"); + if (!fp) return (pcdError(bname, "can't open file")); + +/* base/16 + - plain data starts at sector 1+2+1=4 + (numbered from 0, ie. the 5th sector) + - luma 192*128 = 24576 bytes (12 sectors) + + chroma1 96*64 = 6144 bytes (3 sectors) + + chroma2 96*64 = 6144 bytes (3 sectors) + = total 18 sectors + + - NB. "Plain" data is interleaved - 2 luma rows 192 wide, + then 1 of each of the chroma rows 96 wide ! + + base/4 + - plain data starts at sector 1+2+1+18+1=23 + - luma 384*256 = 98304 bytes (48 sectors) + + chroma1 192*128 = 24576 bytes (12 sectors) + + chroma2 192*128 = 24576 bytes (12 sectors) + = total 72 sectors + + - NB. "Plain" data is interleaved - 2 luma rows 384 wide, + then 1 of each of the chroma rows 192 wide ! + + base + - plain data starts at sector 1+2+1+18+1+72+1=96 + + - luma 768*512 = 393216 bytes (192 sectors) + + chroma1 384*256 = 98304 bytes (48 sectors) + + chroma2 384*256 = 98304 bytes (48 sectors) + = total 288 sectors + + - NB. "Plain" data is interleaved - 2 luma rows 768 wide, + then 1 of each of the chroma rows 384 wide ! + + 4base + - plain data for base is read + - luma data interpolated *2 + - chroma data interpolated *4 + + - cd_offset is 1+2+1+18+1+72+1+288=384 + - at cd_offset+4 (388) is huffman table + - at cd_offset+5 (389) is 4base luma plane + + (the sector at cd_offset+3 seems to contain 256 words each of + which is an offset presumably to the sector containing certain + rows ? rows/4 given 1024 possible rows. The rest of this sector + is filled with zeroes) + + + 16base + - plain data for base is read + - luma data interpolated *2 + - chroma data interpolated *4 + + - cd_offset is 1+2+1+18+1+72+1+288=384 + - at cd_offset+4 (388) is huffman table for 4 base + - at cd_offset+5 (389) is 4base luma plane + - luma plane interpolated *2 + + - cd_offset is set to current position (should be start of sector) + - at cd_offset+12 is huffman table for 16 base + - at cd_offset+14 is 16 base luma & 2 chroma planes which are read + (note that the luma plane comes first, with a sync pattern + announcing each row from 0 to 2047, then the two chroma planes + are interleaved by row, the row # being even from 0 to 2046, with + each row containing 1536 values, the chroma1 row coming first, + finally followed by a sync pattern with a row of 2048 announcing + the end (its plane seems to be set to 3, ie. chroma2) + - chroma planes interpolated *2 + + (the sector at cd_offset+10 & 11 seem to contain 1024 pairs of words + the first for luma and the second for chroma, each of + which is an offset presumably to the sector containing certain + rows ? rows/2 given 2048 possible rows) + +Not yet implemented: + +In order to do overskip for base and 4base, one has to reach the chroma +data for 16 base: + + - for 4base, after reading the 4base luma plane (and presumably + skipping the chroma planes) one sets cd_offset to the start of + the "current" sector + + - for base, one has to skip the 4base data first: + - cd_offset is set to 384 + - at (cd_offset+3 sectors)[510] is a 16 bit word high byte 1st + containing an offset to the beginning of the 16base stuff + though there is then a loop until >30 0xff's start a sector ! + + - being now positioned after the end of the 4base stuff, + - at (cd_offset+10 sectors)[2] is a 16 bit word high byte 1st + containing an offset to the chroma planes. + - at cd_offset+12 is the set of huffman tables + + - for base, the 16base chroma planes are then halved +*/ + +#ifdef HAVE_PCD_DIALOG + PCDSetParamOptions(bname); + if (theSize == -1) + { + PCDDialog(1); /* Open PCD Dialog box */ + SetCursors(-1); /* Somebody has already set it to wait :( */ + leaveitup=1; + goforit=0; + /* block until the popup window gets closed */ + while (leaveitup) { + int i; + XEvent event; + XNextEvent(theDisp, &event); + HandleEvent(&event, &i); + } + /* At this point goforit and size will have been set */ + if (!goforit) { + /* nothing allocated so nothing needs freeing */ + return 0; + } + WaitCursor(); + } + else + { + size = theSize; + goforit = 1; + } +#else /* HAVE_PCD_DIALOG */ + { + static char *sizeoptions[3] = { "0192*128", "1384*256","2768*512" }; + size=PopUp("Which of the stored resolutions would you like ?",sizeoptions,3); + } +#endif /* HAVE_PCD_DIALOG */ + + switch (size) { + case 0: + pinfo->w=192; + pinfo->h=128; + offset=4*0x800; + mag=1; + huffplanes=0; + sprintf(pinfo->fullInfo, "PhotoCD, base/16 resolution"); + break; + case 1: + pinfo->w=384; + pinfo->h=256; + offset=23*0x800; + mag=1; + huffplanes=0; + sprintf(pinfo->fullInfo, "PhotoCD, base/4 resolution"); + break; + case 2: + default: + pinfo->w=768; + pinfo->h=512; + offset=96*0x800; + mag=1; + huffplanes=0; + sprintf(pinfo->fullInfo, "PhotoCD, base resolution"); + break; + case 3: + pinfo->w=1536; + pinfo->h=1024; + offset=96*0x800; + mag=2; + huffplanes=1; + sprintf(pinfo->fullInfo, "PhotoCD, 4base resolution"); + break; + case 4: + pinfo->w=3072; + pinfo->h=2048; + offset=96*0x800; + mag=4; + huffplanes=2; + sprintf(pinfo->fullInfo, "PhotoCD, 16base resolution"); + break; + } + + /* allocate 24-bit image */ + pinfo->pic = (byte *) calloc(pinfo->w*pinfo->h*3,1); + if (!pinfo->pic) FatalError("couldn't malloc '24 bit rgb plane'"); + + pinfo->type = PIC24; + sprintf(pinfo->shrtInfo, "%dx%d PhotoCD.", pinfo->w, pinfo->h); + pinfo->colType = F_FULLCOLOR; + pinfo->frmType = -1; + + if (fseek(fp,offset,0) == -1) + return pcdError(bname,"Can't find start of data."); + + w = pinfo->w; h = pinfo->h; + pic24 = pinfo->pic; + + luma=(byte *) calloc(w*h,1); + if (!luma) FatalError("couldn't malloc 'luma plane'"); + chroma1=(byte *) calloc(w*h/4,1); + if (!chroma1) FatalError("couldn't malloc 'chroma1 plane'"); + chroma2=(byte *) calloc(w*h/4,1); + if (!chroma2) FatalError("couldn't malloc 'chroma2 plane'"); + + /* Read 2 luma rows length w, then one of each chroma rows w/2 */ + /* If a mag factor is active, the small image is read into the */ + /* top right hand corner of the larger allocated image */ + + for (row=0,lptr=luma,c1ptr=chroma1,c2ptr=chroma2; row 255) r=255; + if (r < 0 ) r=0; + if (g > 255) g=255; + if (g < 0 ) g=0; + if (b > 255) b=255; + if (b < 0 ) b=0; + + *ptr++=r; + *ptr++=g; + *ptr++=b; + if (col%2) { ++c1ptr; ++c2ptr; } + } + if (row%2 == 0) { c1ptr=rowc1ptr; c2ptr=rowc2ptr; } + if (row%wcurfactor == 0) WaitCursor(); + } + + free(luma); free(chroma1); free(chroma2); + + rv = 1; + + fclose(fp); + + if (!rv) { + if (pinfo->pic) free(pinfo->comment); + if (pinfo->comment) free(pinfo->comment); + pinfo->pic = (byte *) NULL; + pinfo->comment = (char *) NULL; + } + + return rv; +} + + +/*******************************************/ + +/* derived from Hadmut Danisch's interpolate() */ + +static void +magnify(mag,h,w,mh,mw,p) +int mag; /* power of 2 by which to magnify in place */ +int h,w; /* the "start" unmag'd dimensions of the data in the array */ +int mh,mw; /* the real (maximum) dimensions of the array */ +unsigned char *p; /* pointer to the data */ +{ + int x,y,yi; + unsigned char *optr,*nptr,*uptr; /* MUST be unsigned, else averaging fails */ + + while (mag > 1) { + + /* create every 2nd new row from 0 */ + /* even pixels being equal to the old, odd ones averaged with successor */ + /* special case being the last column which is just set equal to the */ + /* second last) ... */ + + for(y=0;y>1; /* odd averaged */ + } + } + + /* Fill in odd rows, as average of prior & succeeding rows, with */ + /* even pixels average of one column, odd pixels average of two */ + + for(y=0;y>1; /* even pixels */ + nptr[1]=(((int)optr[0])+ + ((int)optr[2])+ + ((int)uptr[0])+ + ((int)uptr[2])+2)>>2; /* odd pixels */ + nptr+=2; optr+=2; uptr+=2; + } + *(nptr++)=(((int)*(optr++))+ + ((int)*(uptr++))+1)>>1; /* 2nd last pixel */ + *(nptr++)=(((int)*(optr++))+ + ((int)*(uptr++))+1)>>1; /* last pixel */ + } + + xvbcopy((char *) (p + (2*h-2)*mw), /* 2nd last row */ + (char *) (p + (2*h-1)*mw), /* the last row */ + (size_t) (2*w)); /* length of a new row */ + + h*=2; w*=2; + mag>>=1; /* Obviously mag must be a power of 2 ! */ + } +} + + +/*******************************************/ +static int pcdError(fname, st) + char *fname, *st; +{ + SetISTR(ISTR_WARNING, "%s: %s", fname, st); + return 0; +} + + +/**** Stuff for PCDDialog box ****/ + +#define TWIDE 380 +#define THIGH 160 +#define T_NBUTTS 2 +#define T_BOK 0 +#define T_BCANC 1 +#define BUTTH 24 + +static void drawTD PARM((int,int,int,int)); +static void clickTD PARM((int,int)); +static void doCmd PARM((int)); +static void PCDSetParams PARM((void)); + + +/* local variables */ +static BUTT tbut[T_NBUTTS]; +static RBUTT *resnRB; + + + +/***************************************************/ +void CreatePCDW() +{ + int y; + + pcdW = CreateWindow("xv pcd", "XVpcd", NULL, + TWIDE, THIGH, infofg, infobg, 0); + if (!pcdW) FatalError("can't create pcd window!"); + + XSelectInput(theDisp, pcdW, ExposureMask | ButtonPressMask | KeyPressMask); + + BTCreate(&tbut[T_BOK], pcdW, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH, + "Ok", infofg, infobg, hicol, locol); + + BTCreate(&tbut[T_BCANC], pcdW, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH, + "Cancel", infofg, infobg, hicol, locol); + + y = 55; + resnRB = RBCreate(NULL, pcdW, 36, y, "192*128 Base/16", + infofg, infobg,hicol,locol); + RBCreate(resnRB, pcdW, 36, y+18, "384*256 Base/4", + infofg, infobg,hicol,locol); + RBCreate(resnRB, pcdW, 36, y+36, "768*512 Base", + infofg, infobg, hicol, locol); + RBCreate(resnRB, pcdW, TWIDE/2, y, "1536*1024 4Base", + infofg, infobg, hicol, locol); + RBCreate(resnRB, pcdW, TWIDE/2, y+18, "3072*2048 16Base", + infofg, infobg, hicol, locol); +#ifdef CRAP + RBCreate(resnRB, pcdW, TWIDE/2, y+36, "Other", + infofg, infobg, hicol, locol); +#endif + + XMapSubwindows(theDisp, pcdW); +} + + +/***************************************************/ +void PCDDialog(vis) +int vis; +{ + if (vis) { + CenterMapWindow(pcdW, tbut[T_BOK].x + tbut[T_BOK].w/2, + tbut[T_BOK].y + tbut[T_BOK].h/2, TWIDE, THIGH); + } + else XUnmapWindow(theDisp, pcdW); + pcdUp = vis; +} + + +/***************************************************/ +int PCDCheckEvent(xev) +XEvent *xev; +{ + /* check event to see if it's for one of our subwindows. If it is, + deal accordingly, and return '1'. Otherwise, return '0' */ + + int rv; + rv = 1; + + if (!pcdUp) return 0; + + if (xev->type == Expose) { + int x,y,w,h; + XExposeEvent *e = (XExposeEvent *) xev; + x = e->x; y = e->y; w = e->width; h = e->height; + + if (e->window == pcdW) drawTD(x, y, w, h); + else rv = 0; + } + + else if (xev->type == ButtonPress) { + XButtonEvent *e = (XButtonEvent *) xev; + int x,y; + x = e->x; y = e->y; + + if (e->button == Button1) { + if (e->window == pcdW) clickTD(x,y); + else rv = 0; + } /* button1 */ + else rv = 0; + } /* button press */ + + + else if (xev->type == KeyPress) { + XKeyEvent *e = (XKeyEvent *) xev; + char buf[128]; KeySym ks; XComposeStatus status; + int stlen; + + stlen = XLookupString(e,buf,128,&ks,&status); + buf[stlen] = '\0'; + + if (e->window == pcdW) { + if (stlen) { + if (buf[0] == '\r' || buf[0] == '\n') { /* enter */ + FakeButtonPress(&tbut[T_BOK]); + } + else if (buf[0] == '\033') { /* ESC */ + FakeButtonPress(&tbut[T_BCANC]); + } + } + } + else rv = 0; + } + else rv = 0; + + if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) { + XBell(theDisp, 50); + rv = 1; /* eat it */ + } + + return rv; +} + + +/***************************************************/ +void PCDSetParamOptions(fname) +char *fname; +{ + int cur; + cur = RBWhich(resnRB); + + RBSetActive(resnRB,0,1); + RBSetActive(resnRB,1,1); + RBSetActive(resnRB,2,1); + RBSetActive(resnRB,3,1); + RBSetActive(resnRB,4,1); + RBSetActive(resnRB,5,0); +} + + +/***************************************************/ +static void drawTD(x,y,w,h) +int x,y,w,h; +{ + char *title = "Load PhotoCD file..."; + int i; + XRectangle xr; + + xr.x = x; xr.y = y; xr.width = w; xr.height = h; + XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted); + + XSetForeground(theDisp, theGC, infofg); + XSetBackground(theDisp, theGC, infobg); + + for (i=0; ix-16, resnRB->y-10-DESCENT, "Resolution"); + RBRedraw(resnRB, -1); + + DrawString(pcdW, 20, 19, title); + + XSetClipMask(theDisp, theGC, None); +} + + +/***************************************************/ +static void clickTD(x,y) +int x,y; +{ + int i; + BUTT *bp; + + /* check BUTTs */ + + /* check the RBUTTS first, since they don't DO anything */ + if ( (i=RBClick(resnRB, x,y)) >= 0) { + (void) RBTrack(resnRB, i); + return; + } + + + for (i=0; ix, bp->y, bp->w, bp->h)) break; + } + + if (i= 0) { + hufftop+=2; + if (hufftop-hufftab >2*num) { + fprintf(stderr,"Table overflow\n"); + exit(1); + } + *huffptr=-(hufftop-huffptr); + } + huffptr-=*huffptr; + } + } + } + } + } + + *alength=num; + return hufftab; +} + +/* WORDTYPE & char buffer must be unsigned else */ +/* fills with sign bit not 0 on right shifts */ +typedef unsigned int WORDTYPE; +typedef int SWORDTYPE; +#define WORDSIZE sizeof(WORDTYPE) +#define NBYTESINBUF 0x800 + +static unsigned char buffer[NBYTESINBUF]; +static int bitsleft=0; +static int bytesleft=0; +static unsigned char *bufptr; +static WORDTYPE word; + +/* assume WORDTYPE is 32 bit word */ +#define issync() ((word & 0xffffff00) == 0xfffffe00) +#define skiptosync() { while (!issync()) (void)getbit(); } + +static void +dumpbuffer() +{ + int i,left; + unsigned char *ptr=buffer; + + fprintf(stderr,"dumpbuffer: bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + for (left=NBYTESINBUF; left>0; left-=16) { + fprintf(stderr,"%05d ",left); + for (i=0; i<8; i++) { + fprintf(stderr,"%02x",*ptr++); + fprintf(stderr,"%02x ",*ptr++); + } + fprintf(stderr,"\n"); + } +} + +static void +loadbuffer() +{ + trace(stderr,"loadbuffer: start at sector %ld\n",(long)ftell(fp)/0x800 +); + if ((bytesleft=fread(buffer,1,NBYTESINBUF,fp)) == 0) { + fprintf(stderr,"Truncation error\n"); + exit(1); + } + bufptr=buffer; + trace(stderr,"loadbuffer: Loaded buffer with %d bytes\n",bytesleft); + /* dumpbuffer(); */ +} + +static void +loadbyte() +{ + trace(stderr,"loadbyte: start bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + if (bytesleft <= 0) loadbuffer(); + --bytesleft; + word|=(WORDTYPE)(*bufptr++)<<(sizeof(WORDTYPE)*8-8-bitsleft); + bitsleft+=8; + trace(stderr,"loadbyte: done bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); +} + +static int +getbit() +{ + int bit; + + trace(stderr,"getbit: start bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + + while (bitsleft <= 0) loadbyte(); + --bitsleft; + bit=(SWORDTYPE)(word)<0; /* assumes word is signed */ + /* bit=word>>(sizeof(WORDTYPE)*8-1); */ + word<<=1; + + trace(stderr,"getbit: done bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + trace(stderr,"getbit: done bit=%d\n",bit); + + return bit; +} + +static WORDTYPE +getnn(nn) +int nn; +{ + WORDTYPE value; + + trace(stderr,"getnn: start nn=%d\n",nn); + trace(stderr,"getnn: start bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + + while (bitsleft <= nn) loadbyte(); + bitsleft-=nn; + value=word>>(sizeof(WORDTYPE)*8-nn); + word<<=nn; + + trace(stderr,"getnn: done bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + trace(stderr,"getnn: done value=0x%08lx\n",(unsigned long)value); + + return value; +} + +static WORDTYPE +isnn(nn) +int nn; +{ + WORDTYPE value; + + trace(stderr,"isnn: start nn=%d\n",nn); + trace(stderr,"isnn: start bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + + while (bitsleft <= nn) loadbyte(); + value=word>>(sizeof(WORDTYPE)*8-nn); + + trace(stderr,"isnn: done bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + trace(stderr,"isnn: done value=0x%08lx\n",(unsigned long)value); + + return value; +} + +static void +skipnn(nn) +int nn; +{ + trace(stderr,"skipnn: start nn=%d\n",nn); + trace(stderr,"skipnn: start bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); + + while (bitsleft <= nn) loadbyte(); + bitsleft-=nn; + word<<=nn; + + trace(stderr,"skipnn: done bytesleft=%d bitsleft= %d word=0x%08lx\n", + bytesleft,bitsleft,(unsigned long)word); +} + +#define get1() (getbit()) +#define get2() (getnn(2)) +#define get8() (getnn(8)) +#define get13() (getnn(13)) +#define get16() (getnn(16)) +#define get24() (getnn(24)) + +#define is8() (isnn(8)) +#define is16() (isnn(16)) +#define is24() (isnn(24)) + +#define skip1() (skipnn(1)) +#define skip8() (skipnn(8)) +#define skip16() (skipnn(16)) +#define skip24() (skipnn(24)) + +static int +gethuffdata(luma,chroma1,chroma2,realrowwidth,maxrownumber) +byte *luma, *chroma1, *chroma2; +int realrowwidth; +int maxrownumber; +{ + int row,plane,charcount; + int i; + + trace(stderr,"gethuffdata: start\n"); + + /* should really only look for luma plane for 4base, but the */ + /* there are zeroes in the rest of the sector that give both */ + /* chroma tables 0 length */ + + for (i=0; i<3; i++) hufftable[i]=gethufftable(&hufflength[i]); + + while (is24() != 0xfffffe) { + (void)get24(); + trace(stderr,"Skipping for sync\n"); + } + for (;;) { + ihufftab *huffstart; + schar *pixelptr; + + if (is24() == 0xfffffe) { + skip24(); + trace(stderr,"Charcount=%d\n",charcount); + charcount=0; + plane=get2(); + row=get13(); + skip1(); + trace(stderr,"Plane %d Row %d\n",plane,row); + if (row>=maxrownumber) { + trace(stderr,"Stopping at row %d\n",row); + break; + } + switch (plane) { + case 0: huffstart=hufftable[0]; + pixelptr=(schar *) (luma+row*realrowwidth); + trace(stderr,"Setting luma plane\n"); + break; + case 2: huffstart=hufftable[1]; + pixelptr=(schar *) (chroma1+row/2*realrowwidth/2); + trace(stderr,"Setting chroma1 plane\n"); + break; + case 3: huffstart=hufftable[2]; + pixelptr=(schar *) (chroma2+row/2*realrowwidth/2); + trace(stderr,"Setting chroma2 plane\n"); + break; + default: fprintf(stderr,"Bad plane %d\n",plane); + exit(1); + } + WaitCursor(); + } + else { + ihufftab *huffptr=huffstart; + for (;;) { + int bit; + bit=get1(); /* never fails :) */ + huffptr+=bit; /* select entry 0 or entry 1 */ + if (*huffptr < 0) { /* flag to choose next entry */ + huffptr-=*huffptr; + } + else { /* found the value for the code */ + schar value = *huffptr; + (*(pixelptr+charcount))+=value; /* in lower 8 bits */ + /* probably don't need to mask with 0xff */ + ++charcount; + trace(stderr,"[%d]=%d\n",charcount,(int)value); + break; + } + } + } + } + trace(stderr,"Out ... \n"); + + for (i=0; i<3; i++) if (hufftable[i]) free(hufftable[i]); + + return 1; +} +#endif /* HAVE_PCD */ diff -urN xv-3.10a/xvpi.c xv-3.10a-jp-extension-current/xvpi.c --- xv-3.10a/xvpi.c +++ xv-3.10a-jp-extension-current/xvpi.c Wed Oct 9 20:37:20 1996 @@ -0,0 +1,1060 @@ +/* + * xvpi.c - load routine for `Pi' format pictures. + * + * The `Pi' format is made by Yanagisawa. + * It is common among many Japanese personal computer users. + * + */ + +#include "xv.h" +#include + +#ifdef HAVE_PI + +typedef unsigned short data16; +typedef unsigned int data32; + +struct pi_info { + jmp_buf jmp; + FILE *fp; + struct { + int rest; + byte cur; + }bs; + long fsize; + byte mode; + int width, height; + float aspect; + int cbits; + int numcols; + byte *cmap; + struct ct_t{ + struct elt_t *top; + struct elt_t{ + struct elt_t *old, *recent; + byte val; + } *elt; + }*ct; + int defcmap; + int writing_grey; +}; + +static void pi_open_file PARM((struct pi_info*, char*)); +static void pi_read_header PARM((struct pi_info*, char**)); +static void pi_check_id PARM((struct pi_info*)); +static void pi_read_comment PARM((struct pi_info*, char**)); +static void pi_read_palette PARM((struct pi_info*)); +static void pi_expand PARM((struct pi_info*, byte**)); +static byte pi_read_color PARM((struct pi_info*, int)); +static int pi_read_position PARM((struct pi_info*)); +static data32 pi_read_length PARM((struct pi_info*)); +static int pi_copy_pixels PARM((struct pi_info*, + byte*, int, int, data32)); + +static void pi_write_header PARM((struct pi_info*, + char*, byte*, byte*, byte*)); +static void pi_write_id PARM((struct pi_info*)); +static void pi_write_comment PARM((struct pi_info*, char*)); +static void pi_write_palette PARM((struct pi_info*, byte*, byte*, byte*)); +static void pi_compress PARM((struct pi_info*, byte*)); +static void pi_write_gabage PARM((struct pi_info*)); +static void pi_write_color PARM((struct pi_info*, int, int)); +static int pi_test_matching PARM((struct pi_info*, + byte*, int, int, data32*)); +static void pi_write_position PARM((struct pi_info*, int)); +static void pi_write_length PARM((struct pi_info*, data32)); + +static void pi_table_create PARM((struct pi_info*)); +static byte pi_table_get_value PARM((struct pi_info*, int, int)); +static int pi_table_lookup_value PARM((struct pi_info*, int, int)); +static data32 pi_read_bits PARM((struct pi_info*, int)); +static void pi_write_bits PARM((struct pi_info*, data32, int)); +static void pi_init_pi_info PARM((struct pi_info*)); +static void pi_cleanup_pi_info PARM((struct pi_info*, int)); +static void pi_cleanup_pinfo PARM((PICINFO*)); +static void pi_memory_error PARM((char*, char*)); +static void pi_error PARM((struct pi_info*, int)); +static void pi_file_error PARM((struct pi_info*, int)); +static void pi_file_warning PARM((struct pi_info*, int)); +static void pi_show_pi_info PARM((struct pi_info*)); +static void *pi_malloc PARM((size_t, char*)); +static void *pi_realloc PARM((void*, size_t, char*)); + + +static char *pi_id = "Pi"; +static char *pi_msgs[] = { + NULL, +#define PI_OPEN 1 + "couldn't open.", +#define PI_CORRUPT 2 + "file corrupted.", +#define PI_FORMAT 3 + "not PI format.", +#define PI_PLANES 4 + "bad number of planes.", +#define PI_WRITE 5 + "write failed.", +}; + + +/* The main routine of `Pi' loader. */ +int LoadPi(fname, pinfo) + char *fname; + PICINFO *pinfo; +{ + struct pi_info pi; + int e; + int i; + if(DEBUG) fputs("LoadPi:\n", stderr); + + pinfo->comment = NULL; + pi_init_pi_info(&pi); + if((e = setjmp(pi.jmp)) != 0){ + /* When an error occurs, comes here. */ + pi_cleanup_pi_info(&pi, 0); + pi_cleanup_pinfo(pinfo); + if(DEBUG) fputs("\n", stderr); + return 0; + } + + pi_open_file(&pi, fname); + pi_read_header(&pi, &pinfo->comment); + pi_expand(&pi, &pinfo->pic); + + pinfo->normw = pinfo->w = pi.width; + pinfo->normh = pinfo->h = pi.height; + pinfo->type = PIC8; + if(pi.numcols > 256) /* shouldn't happen. */ + pi.numcols = 256; + for(i = 0; i < pi.numcols; i++){ + pinfo->r[i] = pi.cmap[i * 3 ]; + pinfo->g[i] = pi.cmap[i * 3 + 1]; + pinfo->b[i] = pi.cmap[i * 3 + 2]; + } + pinfo->frmType = F_PI; + pinfo->colType = F_FULLCOLOR; + sprintf(pinfo->fullInfo, "Pi, %d colors (%ld bytes)", + pi.numcols, pi.fsize); + sprintf(pinfo->shrtInfo, "%dx%d Pi.", pi.width, pi.height); + normaspect = pi.aspect; + + pi_cleanup_pi_info(&pi, 0); + if(DEBUG) fputs("\n", stderr); + return 1; +} + +static void pi_open_file(pi, fname) + struct pi_info *pi; + char *fname; +{ + if((pi->fp = fopen(fname, "rb")) == NULL) + pi_file_error(pi, PI_OPEN); + fseek(pi->fp, (size_t) 0, SEEK_END); + pi->fsize = ftell(pi->fp); + fseek(pi->fp, (size_t) 0, SEEK_SET); +} + +static void pi_read_header(pi, comm) + struct pi_info *pi; + char **comm; +{ + byte buf[10]; + int mda; + int i; + + pi_check_id(pi); + pi_read_comment(pi, comm); + + if(fread(buf, (size_t) 10, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_CORRUPT); + + pi->mode = buf[0]; + pi->defcmap = pi->mode & 0x80; + if(buf[1] != 0 && buf[2] != 0) + pi->aspect = (float) buf[2] / (int) buf[1]; + pi->cbits = buf[3]; + pi->numcols = 1 << pi->cbits; + + if(pi->cbits != 4 && pi->cbits != 8) + pi_error(pi, PI_PLANES); + + mda = (int) buf[8] << 8 | (int) buf[9]; + for(i = 0; i < mda; i++){ + if(fgetc(pi->fp) == EOF) + pi_file_error(pi, PI_CORRUPT); + } + + if(fread(buf, (size_t) 4, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_CORRUPT); + pi->width = (int) buf[0] << 8 | (int) buf[1]; + pi->height = (int) buf[2] << 8 | (int) buf[3]; + + pi_read_palette(pi); + + if(DEBUG) pi_show_pi_info(pi); +} + +static void pi_check_id(pi) + struct pi_info *pi; +{ + char buf[2]; + + if(fread(buf, (size_t) 2, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_CORRUPT); + if(strncmp(buf, pi_id, (size_t) 2) != 0) + pi_error(pi, PI_FORMAT); +} + +static void pi_read_comment(pi, comm) + struct pi_info *pi; + char **comm; +{ +/* + * The comment format is like: + * comment string `^Z' dummy string `\0' + */ + int max = -1, i = 0; + int c; + + while(1){ + if((c = fgetc(pi->fp)) == EOF) + pi_file_error(pi, PI_CORRUPT); + if(c == '\032') /* 0x1a, '^Z' */ + break; + if(max < i){ + max += 32; + *comm = pi_realloc(*comm, (size_t) max + 1, "pi_read_comment(1)"); + } + (*comm)[i++] = c; + } + if(max < i){ + max++; + *comm = pi_realloc(*comm, (size_t) max + 1, "pi_read_comment(2)"); + } + (*comm)[i] = '\0'; + + while((c = fgetc(pi->fp)) != '\0'){ /* skip the dummy area */ + if(c == EOF) + pi_file_error(pi, PI_CORRUPT); + } +} + +static void pi_read_palette(pi) + struct pi_info *pi; +{ + pi->cmap = pi_malloc((size_t) pi->numcols * 3, "pi_read_palette"); + if(pi->mode & 0x80){ + if(pi->numcols == 16){ + int i; + byte on; + + on = 0x77; + for(i = 0; i < 8; i++){ + pi->cmap[i * 3 ] = i & 2 ? on : 0; + pi->cmap[i * 3 + 1] = i & 4 ? on : 0; + pi->cmap[i * 3 + 2] = i & 1 ? on : 0; + } + on = 0xff; + for(; i < 16; i++){ + pi->cmap[i * 3 ] = i & 2 ? on : 0; + pi->cmap[i * 3 + 1] = i & 4 ? on : 0; + pi->cmap[i * 3 + 2] = i & 1 ? on : 0; + } + }else{ /* pi->numcols == 256 */ + int i; + byte r, g, b; + r = g = b = 0; + for(i = 0; i < 256; i++){ + pi->cmap[i * 3 ] = r; + pi->cmap[i * 3 + 1] = g; + pi->cmap[i * 3 + 2] = b; + if((b += 0x40) == 0){ + if((r += 0x20) == 0) + g += 0x20; + } + } + } + }else{ + if(fread(pi->cmap, (size_t) pi->numcols * 3, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_CORRUPT); + } +} + +/* The main routine to expand `Pi' file. */ +static void pi_expand(pi, pic) + struct pi_info *pi; + byte **pic; +{ + byte prev_col = 0; + int prev_pos = -1; + int cnt = 0, max_cnt = pi->width * pi->height; + + *pic = pi_malloc((size_t) max_cnt, "pi_expand"); + + pi_table_create(pi); + + if(pi->width > 2){ + (*pic)[0] = pi_read_color(pi, 0); + (*pic)[1] = pi_read_color(pi, (*pic)[0]); + + while(cnt < max_cnt){ + int pos = pi_read_position(pi); + if(pos != prev_pos){ + data32 len = pi_read_length(pi); + cnt = pi_copy_pixels(pi, *pic, cnt, pos, len); + prev_col = (*pic)[cnt - 1]; + prev_pos = pos; + }else{ + do{ + prev_col = pi_read_color(pi, (int) prev_col); + (*pic)[cnt++] = prev_col; + prev_col = pi_read_color(pi, (int) prev_col); + (*pic)[cnt++] = prev_col; + }while(pi_read_bits(pi, 1) == 1); + + prev_pos = -1; + } + } + }else{ + while(cnt < max_cnt){ + prev_col = pi_read_color(pi, (int) prev_col); + (*pic)[cnt++] = prev_col; + } + } +} + +static byte pi_read_color(pi, prev) + struct pi_info *pi; + int prev; +{ + byte n; + if(pi->cbits == 4){ + if(pi_read_bits(pi, 1) == 1) + n = pi_read_bits(pi, 1); /* 1x */ + else{ + if(pi_read_bits(pi, 1) == 0) + n = pi_read_bits(pi, 1) + 2; /* 00x */ + else{ + if(pi_read_bits(pi, 1) == 0) + n = pi_read_bits(pi, 2) + 4; /* 010xx */ + else + n = pi_read_bits(pi, 3) + 8; /* 011xxx */ + } + } + }else{ /* cbits == 8 */ + if(pi_read_bits(pi, 1) == 1) + n = pi_read_bits(pi, 1); + else{ + int bits = 0; + byte base = 2; + while(bits < 6){ + if(pi_read_bits(pi, 1) == 0) + break; + bits++; + base <<= 1; + } + n = pi_read_bits(pi, bits + 1) + base; + } + } + + return pi_table_get_value(pi, prev, (int) n); +} + +static int pi_read_position(pi) + struct pi_info *pi; +{ + byte r; + if((r = pi_read_bits(pi, 2)) != 3) + return (int) r; + else + return (int) pi_read_bits(pi, 1) + 3; +} + +static data32 pi_read_length(pi) + struct pi_info *pi; +{ + data32 r = 1; + int bits = 0; + while(pi_read_bits(pi, 1) == 1){ + r <<= 1; + bits++; + } + if(bits > 0) + return r + pi_read_bits(pi, bits); + return 1; +} + +static int pi_copy_pixels(pi, pic, cnt, pos, len) + struct pi_info *pi; + byte *pic; + int cnt, pos; + data32 len; +{ + int s = 0, d = cnt; + int max = pi->width * pi->height; + switch(pos){ + case 0: + if(cnt < 2){ + if(pic[0] == pic[1]) + s = cnt - 2; + else + s = cnt - 4; + }else{ + if(pic[cnt - 2] == pic[cnt - 1]) + s = cnt - 2; + else + s = cnt - 4; + } + break; + case 1: + s = cnt - pi->width; + break; + case 2: + s = cnt - pi->width * 2; + break; + case 3: + s = cnt - pi->width + 1; + break; + case 4: + s = cnt - pi->width - 1; + } + + len *= 2; + while(s < 0 && len != 0 && d < max){ + pic[d++] = pic[-(s++) % 2]; + len--; + } + while(len != 0 && d < max){ + pic[d++] = pic[s++]; + len--; + } + return d; +} + +/* The main routine of `Pi' saver. */ +int WritePi(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle, + comment) + FILE *fp; + byte *pic; + int ptype, w, h; + byte *rmap, *gmap, *bmap; + int numcols, colorstyle; + char *comment; +{ + byte rtemp[256], gtemp[256], btemp[256]; + struct pi_info pi; + int e; + + if(DEBUG) fputs("WritePi\n", stderr); + pi_init_pi_info(&pi); + pi.fp = fp; + pi.width = w; + pi.height = h; + pi.writing_grey = (colorstyle == F_GREYSCALE); + if(ptype == PIC24){ + if(!(pic = Conv24to8(pic, w, h, 256, rtemp, gtemp, btemp))) + pi_memory_error("Conv24to8", "WritePi"); + rmap = rtemp; + gmap = gtemp; + bmap = btemp; + numcols = 256; + } + + if((e = setjmp(pi.jmp)) != 0){ + /* When an error occurs, comes here. */ + pi_cleanup_pi_info(&pi, 1); + if(DEBUG) fputs("\n", stderr); + return -1; + } + + pi.numcols = numcols; + pi_write_header(&pi, comment, rmap, gmap, bmap); + pi_compress(&pi, pic); + pi_write_gabage(&pi); + + pi_cleanup_pi_info(&pi, 1); + if(DEBUG) fputs("\n", stderr); + return 0; +} + +static void pi_write_header(pi, comm, r, g, b) + struct pi_info *pi; + char *comm; + byte *r, *g, *b; +{ + byte buf[14]; + + if(DEBUG) pi_show_pi_info(pi); + + pi_write_id(pi); + pi_write_comment(pi, comm); + + buf[0] = buf[1] = buf[2] = 0; + buf[3] = pi->cbits = pi->numcols > 16 ? 8 : 4; + buf[4] = 'X'; + buf[5] = 'V'; + buf[6] = ' '; + buf[7] = ' '; + buf[8] = buf[9] = 0; + buf[10] = pi->width >> 8; + buf[11] = pi->width; + buf[12] = pi->height >> 8; + buf[13] = pi->height; + if(fwrite(buf, (size_t) 14, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_WRITE); + + pi_write_palette(pi, r, g, b); +} + +static void pi_write_id(pi) + struct pi_info *pi; +{ + if(fwrite(pi_id, (size_t) 2, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_WRITE); +} + +static void pi_write_comment(pi, comm) + struct pi_info *pi; + char *comm; +{ + if(comm){ + int i; + for(i = 0; comm[i]; i++){ + if(comm[i] == '\032') /* 0x1a, '^Z' */ + comm[i] = ' '; + } + if(i > 0){ + if(fwrite(comm, (size_t) i, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_WRITE); + } + } + + if(fwrite("\032\0", (size_t) 2, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_WRITE); +} + +static void pi_write_palette(pi, r, g, b) + struct pi_info *pi; + byte *r, *g, *b; +{ + int i; + int pinum = 1 << pi->cbits; + char buf[3]; + + for(i = 0; i < pi->numcols; i++){ + buf[0] = *r++; + buf[1] = *g++; + buf[2] = *b++; + if(pi->writing_grey) + buf[0] = buf[1] = buf[2] = MONO(buf[0], buf[1], buf[2]); + if(fwrite(buf, (size_t) 3, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_WRITE); + } + for( ; i < pinum; i++){ + if(fwrite(buf, (size_t) 3, (size_t) 1, pi->fp) != 1) + pi_file_error(pi, PI_WRITE); + } + pi->numcols = pinum; +} + +/* The main routine to compress `Pi' format. */ +static void pi_compress(pi, pic) + struct pi_info *pi; + byte *pic; +{ + byte prev_col = 0; + int prev_pos = -1; + int cnt = 0, max_cnt = pi->width * pi->height; + pi_table_create(pi); + + if(pi->width > 2){ + int pos; + data32 len; + + pi_write_color(pi, 0, pic[0]); + pi_write_color(pi, pic[0], pic[1]); + pos = pi_test_matching(pi, pic, prev_pos, cnt, &len); + while(cnt < max_cnt){ + if(pos >= 0){ + pi_write_position(pi, pos); + pi_write_length(pi, len); + if((cnt += len * 2) >= max_cnt) + break; + prev_col = pic[cnt - 1]; + prev_pos = pos; + pos = pi_test_matching(pi, pic, prev_pos, cnt, &len); + }else{ + pi_write_position(pi, prev_pos); + prev_pos = -1; + while(pos < 0){ + pi_write_color(pi, (int) prev_col, pic[cnt]); + prev_col = pic[cnt]; + if(++cnt >= max_cnt) + break; + pi_write_color(pi, (int) prev_col, pic[cnt]); + prev_col = pic[cnt]; + if(++cnt >= max_cnt) + break; + pos = pi_test_matching(pi, pic, -1, cnt, &len); + if(pos < 0) + pi_write_bits(pi, 1, 1); + else + pi_write_bits(pi, 0, 1); + } + } + } + }else{ + while(cnt < max_cnt){ + pi_write_color(pi, (int) prev_col, pic[cnt]); + prev_col = pic[cnt++]; + } + } +} + +static void pi_write_gabage(pi) + struct pi_info *pi; +{ + pi_write_bits(pi, 0, 32); +} + +static void pi_write_color(pi, prev, col) + struct pi_info *pi; + int prev, col; +{ + int n = pi_table_lookup_value(pi, prev, col); + + if(pi->cbits == 4){ + if(n < 2) + pi_write_bits(pi, (data32) n | 2, 2); + else if(n < 4) + pi_write_bits(pi, (data32) n - 2, 3); + else if(n < 8) + pi_write_bits(pi, (data32) (n - 4) | 8, 5); + else + pi_write_bits(pi, (data32) (n - 8) | 24, 6); + }else{ /* cbits == 8 */ + if(n < 2){ + pi_write_bits(pi, (data32) n | 2, 2); + }else{ + int bits = 0; + byte base = 2; + while(bits < 6){ + if(n < (int) base * 2) + break; + bits++; + base <<= 1; + } + pi_write_bits(pi, 0, 1); + if(bits > 0) + pi_write_bits(pi, 0xffffffff, bits); + if(bits < 6) + pi_write_bits(pi, 0, 1); + pi_write_bits(pi, (data32) n - base, bits + 1); + } + } +} + +static int pi_test_matching(pi, pic, prev, cnt, len) + struct pi_info *pi; + byte *pic; + int prev, cnt; + data32 *len; +{ + data32 lens[5]; + int pos, p; + int s, d = 0; + int max = pi->width * pi->height; + + for(pos = 0; pos < 5; pos++){ + switch(pos){ + case 0: + if(cnt < 2){ + if(pic[0] == pic[1]) + d = cnt - 2; + else + d = cnt - 4; + }else{ + if(pic[cnt - 2] == pic[cnt - 1]) + d = cnt - 2; + else + d = cnt - 4; + } + break; + case 1: + d = cnt - pi->width; + break; + case 2: + d = cnt - pi->width * 2; + break; + case 3: + d = cnt - pi->width + 1; + break; + case 4: + d = cnt - pi->width - 1; + } + s = cnt; + lens[pos] = 0; + + if(prev == 0 && pos == 0) + continue; + + while(d < max){ + if(pic[(d < 0) ? (-d) % 2 : d] != pic[s]) + break; + lens[pos]++; + d++; + s++; + } + + } + + for(pos = 0, p = 1; p < 5; p++){ + if(lens[p] >= lens[pos]) + pos = p; + } + + if(lens[pos] / 2 == 0) + return -1; + *len = lens[pos] / 2; + return pos; +} + +static void pi_write_position(pi, pos) + struct pi_info *pi; + int pos; +{ + switch(pos){ + case 0: + pi_write_bits(pi, 0, 2); + break; + case 1: + pi_write_bits(pi, 1, 2); + break; + case 2: + pi_write_bits(pi, 2, 2); + break; + case 3: + pi_write_bits(pi, 6, 3); + break; + case 4: + pi_write_bits(pi, 7, 3); + break; + } +} + +static void pi_write_length(pi, len) + struct pi_info *pi; + data32 len; +{ + int bits = 0; + data32 base = 1; + + while(len >= base * 2){ + bits++; + base <<= 1; + } + if(bits > 0){ + pi_write_bits(pi, 0xffffffff, bits); + pi_write_bits(pi, 0, 1); + pi_write_bits(pi, len - base, bits); + }else + pi_write_bits(pi, 0, 1); +} + +/* + * These pi_table_* functions manipulate the color table. + * pi_table_create: + * allocates and initializes a color table. + * pi_table_get_value: + * get the specified value, and move it to the top of the list. + * pi_table_lookup_value: + * look up the specified value, and move it to the top of the list. + */ +static void pi_table_create(pi) + struct pi_info *pi; +{ + struct ct_t *t; + int i; + byte mask = pi->numcols - 1; + pi->ct = pi_malloc(sizeof *pi->ct * pi->numcols, "pi_table_create(1)"); + for(i = 0, t = pi->ct; i < pi->numcols; i++, t++){ + int j; + byte v = i; + t->elt = pi_malloc(sizeof *t->elt * pi->numcols, "pi_table_create(2)"); + t->top = &t->elt[pi->numcols - 1]; + for(j = 0; j < pi->numcols; j++){ + v = (v + 1) & mask; + if(j > 0) + t->elt[j].old = &t->elt[j - 1]; + else + t->elt[0].old = t->top; + if(j < pi->numcols - 1) + t->elt[j].recent = &t->elt[j + 1]; + else + t->elt[j].recent = &t->elt[0]; + t->elt[j].val = v; + } + t->elt[0].old = t->top; + t->top->recent = &t->elt[0]; + } +} + +static byte pi_table_get_value(pi, left, num) + struct pi_info *pi; + int left, num; +{ + struct ct_t *t = &pi->ct[left]; + struct elt_t *e = t->top; + if(left >= pi->numcols || num >= pi->numcols) + abort(); + if(num != 0){ + do { + e = e->old; + }while(--num != 0); + + e->old->recent = e->recent; + e->recent->old = e->old; + + e->recent = t->top->recent; + e->recent->old = e; + e->old = t->top; + t->top->recent = e; + + t->top = e; + } + return e->val; +} + +static int pi_table_lookup_value(pi, left, v) + struct pi_info *pi; + int left, v; +{ + struct ct_t *t = &pi->ct[left]; + struct elt_t *e = t->top; + int num = 0; + + if(left >= pi->numcols || v >= pi->numcols) + abort(); + + while(e->val != v){ + e = e->old; + num++; + } + + if(num != 0){ + e->old->recent = e->recent; + e->recent->old = e->old; + + e->recent = t->top->recent; + e->recent->old = e; + e->old = t->top; + t->top->recent = e; + + t->top = e; + } + + return num; +} + +/* + * These 2 functions read or write to a bit stream. + * pi_read_bits: + * reads a specified-bit data from the bit stream. + * pi_write_bits: + * writes a specified-bit data to the bit stream. + */ +static data32 pi_read_bits(pi, numbits) + struct pi_info *pi; + int numbits; +{ + data32 r = 0; + + while(numbits > 0){ + while(pi->bs.rest > 0 && numbits > 0){ + r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0); + pi->bs.cur <<= 1; + pi->bs.rest--; + numbits--; + } + if(numbits > 0){ + int c; + if((c = fgetc(pi->fp)) == EOF) + pi_file_warning(pi, PI_CORRUPT); + pi->bs.cur = c; + pi->bs.rest = 8; + } + } + + return r; +} + +static void pi_write_bits(pi, dat, bits) + struct pi_info *pi; + data32 dat; + int bits; +{ + data32 dat_mask = 1 << (bits - 1); + while(bits > 0){ + while(pi->bs.rest < 8 && bits > 0){ + pi->bs.cur <<= 1; + if(dat & dat_mask) + pi->bs.cur |= 1; + pi->bs.rest++; + bits--; + dat_mask >>= 1; + } + if(pi->bs.rest >= 8){ + if(fputc((int)pi->bs.cur, pi->fp) == EOF) + pi_file_error(pi, PI_WRITE); + pi->bs.cur = 0; + pi->bs.rest = 0; + } + } +} + +/* + * The routines to initialize or clean up. + * pi_inif_pi_info: + * initializes a pi_info structure. + * pi_cleanup_pi_info: + * cleanup pi_info structure. It frees allocated memories. + * pi_cleanup_pinfo: + * cleanup PICINFO structure when an error occurs. + */ +static void pi_init_pi_info(pi) + struct pi_info *pi; +{ + pi->fp = NULL; + pi->bs.rest = 0; + pi->bs.cur = 0; + pi->fsize = 0; + pi->mode = 0; + pi->width = pi->mode = 0; + pi->aspect = 1.0; + pi->cbits = 0; + pi->numcols = 0; + pi->cmap = NULL; + pi->ct = NULL; + pi->defcmap = 0; + pi->writing_grey = 0; +} + +static void pi_cleanup_pi_info(pi, writing) + struct pi_info *pi; + int writing; +{ + if(pi->fp && !writing){ + fclose(pi->fp); + pi->fp = NULL; + } + if(pi->cmap){ + free(pi->cmap); + pi->cmap = NULL; + } + if(pi->ct){ + int i; + for(i = 0; i < pi->numcols; i++) + free(pi->ct[i].elt); + free(pi->ct); + pi->ct = NULL; + } +} + +static void pi_cleanup_pinfo(pinfo) + PICINFO *pinfo; +{ + if(pinfo->pic){ + free(pinfo->pic); + pinfo->pic = NULL; + } + if(pinfo->comment){ + free(pinfo->comment); + pinfo->comment = NULL; + } +} + +/* + * Error handling routins. + * pi_memory_error: + * shows a error message, and terminates. + * pi_error: + * shows a non-file error message. + * pi_file_error: + * shows a file error message. + */ +static void pi_memory_error(scm, fn) + char *scm, *fn; +{ + char buf[128]; + sprintf(buf, "%s: couldn't allocate memory. (%s)", scm ,fn); + FatalError(buf); +} + +static void pi_error(pi, mn) + struct pi_info *pi; + int mn; +{ + SetISTR(ISTR_WARNING, "%s", pi_msgs[mn]); + longjmp(pi->jmp, 1); +} + +static void pi_file_error(pi, mn) + struct pi_info *pi; + int mn; +{ + if(feof(pi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", pi_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", pi_msgs[mn], ERRSTR(errno)); + longjmp(pi->jmp, 1); +} + +static void pi_file_warning(pi, mn) + struct pi_info *pi; + int mn; +{ + if(feof(pi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", pi_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", pi_msgs[mn], ERRSTR(errno)); +} + +static void pi_show_pi_info(pi) + struct pi_info *pi; +{ + fprintf(stderr, " file size: %ld.\n", pi->fsize); + fprintf(stderr, " mode: 0x%02x.\n", pi->mode); + fprintf(stderr, " image size: %dx%d.\n", pi->width, pi->height); + fprintf(stderr, " aspect: %f.\n", pi->aspect); + fprintf(stderr, " number of color bits: %d.\n", pi->cbits); + fprintf(stderr, " number of colors: %d.\n", pi->numcols); + fprintf(stderr, " using default colormap: %s.\n", + pi->defcmap ? "true" : "false"); + fprintf(stderr, " writing greyscale image: %s.\n", + pi->writing_grey ? "true" : "false"); +} + +/* + * Memory related routines. If failed, they calls pi_memory_error. + */ +static void *pi_malloc(n, fn) + size_t n; + char *fn; +{ + void *r = (void *) malloc(n); + if(r == NULL) + pi_memory_error("malloc", fn); + return r; +} + +static void *pi_realloc(p, n, fn) + void *p; + size_t n; + char *fn; +{ + void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n); + if(r == NULL) + pi_memory_error("realloc", fn); + return r; +} +#endif /* HAVE_PI */ diff -urN xv-3.10a/xvpic.c xv-3.10a-jp-extension-current/xvpic.c --- xv-3.10a/xvpic.c +++ xv-3.10a-jp-extension-current/xvpic.c Wed Oct 9 20:37:21 1996 @@ -0,0 +1,1285 @@ +/* + * xvpic.c - load routine for `PIC' format pictures. + * + * The `PIC' format is used by many Japanese personal computer users. + */ + +#include "xv.h" +#include + +#ifdef HAVE_PIC + +typedef unsigned short data16; +typedef unsigned int data32; + +struct pic_info { + jmp_buf jmp; + FILE *fp; + struct { + int rest; + byte cur; + }bs; + long fsize; + int type, mode; + int width, height; + float aspect; + int cbits; + int cmapped; + byte *cmap; + int cached; + struct cache_t { + int newest; + struct cachenode_t { + data32 dat; + int newer, older; + } *node; + } cache; + int g_bits, r_bits, b_bits, i_bits; + int inv_gr; + int tiled256; + int numcols; + int writing_grey; + data32 *data; +}; + +static void pic_open_file PARM((struct pic_info*,char*)); +static void pic_check_id PARM((struct pic_info*)); +static void pic_read_comment PARM((struct pic_info*, char**)); +static void pic_read_header PARM((struct pic_info*)); +static void pic_expand_data PARM((struct pic_info*)); +static int pic_expanding_read_len PARM((struct pic_info*)); +static data32 pic_expanding_read_color PARM((struct pic_info*)); +static void pic_expanding_read_chain + PARM((struct pic_info*, int, int, data32)); +static void pic_make_xvpic + PARM((struct pic_info*, byte**, byte*, byte*, byte*)); + +static void pic_write_id PARM((struct pic_info*)); +static void pic_write_comment PARM((struct pic_info*, char*)); +static void pic_write_header PARM((struct pic_info*)); +static void pic_write_palette + PARM((struct pic_info*, byte*, byte*, byte*)); +static void pic_make_sparse_data PARM((struct pic_info*, byte*)); +static void pic_write_data PARM((struct pic_info*)); +static void pic_write_length PARM((struct pic_info*, data32)); +static void pic_write_color PARM((struct pic_info*, data32)); +static void pic_write_chain + PARM((struct pic_info*, int, int, data32)); + +static data32 pic_read_rgb PARM((struct pic_info*)); +static data32 pic_read_color_code PARM((struct pic_info*)); +static void pic_write_rgb PARM((struct pic_info*, data32)); +static void pic_write_color_code PARM((struct pic_info*, data32)); + +static void pic_cache_init PARM((struct pic_info*)); +static data32 pic_cache_get_value PARM((struct pic_info*, int)); +static void pic_cache_add_value PARM((struct pic_info*, data32)); +static int pic_cache_lookup PARM((struct pic_info*, data32)); + +static data32 pic_read_bits PARM((struct pic_info*, int)); +static void pic_write_bits PARM((struct pic_info*, data32, int)); +static byte pic_pad_bit PARM((int, data32)); + +static void pic_init_info PARM((struct pic_info*)); +static void pic_cleanup_pic_info PARM((struct pic_info*, int)); +static void pic_cleanup_pinfo PARM((PICINFO*)); +static void pic_memory_error PARM((char*, char*)); +static void pic_error PARM((struct pic_info*, int)); +static void pic_file_error PARM((struct pic_info*, int)); +static void pic_file_warning PARM((struct pic_info*, int)); +static void pic_show_pic_info PARM((struct pic_info*)); +static void *pic_malloc PARM((size_t, char*)); +static void *pic_realloc PARM((void*, size_t, char*)); + + +static char *pic_id = "PIC"; + +/* Error Messages */ +static char *pic_msgs[] = { + NULL, +#define PIC_OPEN 1 + "can't open file.", +#define PIC_CORRUPT 2 + "file corrupted.", +#define PIC_FORMAT 3 + "not PIC format.", +#define PIC_SUPPORT 4 + "unsupported type.", +#define PIC_COMMENT 5 + "can't read comment.", +#define PIC_TYPE 6 + "bad machine type.", +#define PIC_MODE 7 + "bad machine-dependent mode.", +#define PIC_NUM_COLORS 8 + "bad number of colors.", +#define PIC_SIZE 9 + "bad size.", +#define PIC_ASPECT 10 + "bad aspect.", +#define PIC_WRITE 11 + "write failed.", +}; + +#define H4(b) (((b) >> 4) & 0x0f) +#define L4(b) ( (b) & 0x0f) + + +/* The main routine to load a PIC file. */ +int LoadPIC(fname, pinfo) + char *fname; + PICINFO *pinfo; +{ + int e; + struct pic_info pic; + char buf[128]; + + if(DEBUG) fputs("LoadPIC:\n", stderr); + + pic_init_info(&pic); + + pinfo->comment = NULL; + if((e = setjmp(pic.jmp)) != 0){ + /* When an error occurs, comes here. */ + pic_cleanup_pic_info(&pic, 0); + pic_cleanup_pinfo(pinfo); + if(DEBUG) fputs("\n", stderr); + return 0; + } + + pic_open_file(&pic, fname); + pic_check_id(&pic); + pic_read_comment(&pic, &pinfo->comment); + pic_read_header(&pic); + pic_expand_data(&pic); + pic_make_xvpic(&pic, &pinfo->pic, pinfo->r, pinfo->g, pinfo->b); + + pinfo->w = pic.width; + if(pic.tiled256) + pinfo->h = pic.height * 2; + else + pinfo->h = pic.height; + pinfo->normw = pinfo->w; + pinfo->normh = pinfo->h; + pinfo->type = pic.cmapped ? PIC8 : PIC24; + pinfo->frmType = F_PIC; + pinfo->colType = F_FULLCOLOR; + strcpy(pinfo->fullInfo, "PIC"); + switch(pic.type){ + case 0x0: + strcat(pinfo->fullInfo, ", X68k"); + break; + case 0x1: + strcat(pinfo->fullInfo, ", PC-88VA"); + if(pic.mode & 1) + strcat(pinfo->fullInfo, ", HR"); + if(pic.mode & 2) + strcat(pinfo->fullInfo, ", tiled 256"); + break; + case 0x2: + strcat(pinfo->fullInfo, ", FM-TOWNS"); + if(pic.mode == 0x5){ + strcat(pinfo->fullInfo, ", low-resolution"); + }else{ + strcat(pinfo->fullInfo, ", high-resolution"); + } + break; + case 0x3: + strcat(pinfo->fullInfo, ", Machintosh"); + break; + case 0xf: + ; + } + sprintf(buf, " (%ld bytes)", pic.fsize); + strcat(pinfo->fullInfo, buf); + sprintf(pinfo->shrtInfo, "%dx%d(aspect %4.2f) PIC.", + pinfo->w, pinfo->h, pic.aspect); + if (!nopicadjust) + normaspect = pic.aspect; + + pic_cleanup_pic_info(&pic, 0); + if(DEBUG) fputs("\n", stderr); + return 1; +} + +static void pic_open_file(pi, fname) + struct pic_info *pi; + char *fname; +{ + if((pi->fp = fopen(fname, "rb")) == NULL) + pic_file_error(pi, PIC_OPEN); + fseek(pi->fp, (size_t) 0, SEEK_END); + pi->fsize = ftell(pi->fp); + fseek(pi->fp, (size_t) 0, SEEK_SET); +} + +static void pic_check_id(pi) + struct pic_info *pi; +{ + char buf[3]; + if(fread(buf, (size_t) 3, (size_t) 1, pi->fp) != 1) + pic_file_error(pi, PIC_CORRUPT); + if(strncmp(buf, pic_id, (size_t) 3) != 0) + pic_error(pi, PIC_FORMAT); +} + +static void pic_read_comment(pi, comm) + struct pic_info *pi; + char **comm; +{ + /* The comment field is like: + * comment-string ^Z dummy \0 \0 + */ + int max = -1, i = 0; + int c; + + while(1){ + if((c = fgetc(pi->fp)) == EOF) + pic_file_error(pi, PIC_CORRUPT); + if(c == '\032') /* 0x1a, '^Z' */ + break; + if(max < i){ + max += 32; + *comm = pic_realloc(*comm, (size_t) max + 1, "pic_read_comment#1"); + } + (*comm)[i++] = c; + } + + if(max < i){ + max++; + *comm = pic_realloc(*comm, (size_t) max + 1, "pic_read_comment#2"); + } + (*comm)[i] = '\0'; + + while((c = fgetc(pi->fp)) != '\0'){ /* skip the dummy area */ + if(c == EOF) + pic_file_error(pi, PIC_CORRUPT); + } + + if(fgetc(pi->fp) != '\0') /* check the reserved byte */ + pic_error(pi, PIC_SUPPORT); +} + +static void pic_read_header(pi) + struct pic_info *pi; +{ + pi->mode = pic_read_bits(pi, 4); + pi->type = pic_read_bits(pi, 4); + pi->cbits = pic_read_bits(pi, 16); + pi->width = pic_read_bits(pi, 16); + pi->height = pic_read_bits(pi, 16); + + /* machine dependent setups. */ + switch(pi->type){ + case 0x0: /* X68K */ + if(pi->mode != 0) + pic_error(pi, PIC_MODE); + switch(pi->cbits){ + case 4: + pi->aspect = 1.0; + pi->g_bits = pi->r_bits = pi->b_bits = 5; + pi->i_bits = 1; + pi->cmapped = 1; + break; + + case 8: + pi->aspect = 4.0 / 3.0; + pi->g_bits = pi->r_bits = pi->b_bits = 5; + pi->i_bits = 1; + pi->cmapped = 1; + break; + + case 15: + pi->aspect = 4.0 / 3.0; + pi->g_bits = pi->r_bits = pi->b_bits = 5; + pi->cached = 1; + break; + + case 16: + pi->aspect = 4.0 / 3.0; + pi->g_bits = pi->r_bits = pi->b_bits = 5; + pi->i_bits = 1; + pi->cached = 1; + break; + + default: + pic_error(pi, PIC_NUM_COLORS); + } + break; + + case 0x1: /* PC-88VA */ + if(pi->height > 1000) + pic_error(pi, PIC_SIZE); + switch(pi->width * 1000 + pi->height){ + case 640400: + case 640204: + case 640200: + case 320408: + case 320400: + case 320200: + break; + default: + pic_error(pi, PIC_SIZE); + } + pi->aspect = 400.0 / pi->height; + pi->aspect *= pi->width / 640.0; + if(pi->mode & 0x1) /* HR mode */ + pi->aspect *= 2.0; + if(pi->mode & 0x2){ /* tiled 256 format */ + if(pi->cbits != 16) + pic_error(pi, PIC_NUM_COLORS); + pi->tiled256 = 1; + } + switch(pi->cbits){ + case 8: + pi->g_bits = pi->r_bits = 3; + pi->b_bits = 2; + break; + + case 12: + pi->g_bits = pi->r_bits = pi->b_bits = 4; + pi->cached = 1; + break; + + case 16: + pi->g_bits = 6; + pi->r_bits = pi->b_bits = 5; + pi->cached = 1; + break; + + default: + pic_error(pi, PIC_NUM_COLORS); + } + break; + + case 0x2: /* FM-TOWNS */ + if(pi->cbits != 15) + pic_error(pi, PIC_NUM_COLORS); + switch(pi->mode){ + case 0x5: + case 0xc: + break; + default: + pic_error(pi, PIC_MODE); + } + pi->g_bits = pi->r_bits = pi->b_bits = 5; + pi->cached = 1; + break; + + case 0x3: /* MAC */ + if(pi->cbits != 15) + pic_error(pi, PIC_NUM_COLORS); + pi->r_bits = pi->g_bits = pi->b_bits = 5; + pi->inv_gr = 1; + break; + + case 0xf: /* misc */ + { + byte ah, al; + + switch(pi->mode){ + case 0x0: + break; + case 0x1: + pi->aspect = 4.0 / 3.0; + break; + case 0xf: + break; + default: + pic_error(pi, PIC_MODE); + } + pic_read_bits(pi, 16); /* x */ + pic_read_bits(pi, 16); /* y */ + ah = pic_read_bits(pi, 8); + al = pic_read_bits(pi, 8); + if(ah > 0 && al > 0) + pi->aspect = (float) al / (int) ah; + else if(pi->mode == 0xf) + pic_error(pi, PIC_ASPECT); + switch(pi->cbits){ + case 4: + case 8: + pi->g_bits = pi->r_bits = pi->b_bits = pic_read_bits(pi, 8); + pi->cmapped = 1; + break; + + case 12: + pi->g_bits = pi->r_bits = pi->b_bits = 4; + pi->cached = 1; + break; + + case 15: + pi->g_bits = pi->r_bits = pi->b_bits = 5; + pi->cached = 1; + break; + + case 16: + pi->g_bits = pi->r_bits = pi->b_bits = 5; + pi->i_bits = 1; + pi->cached = 1; + break; + + case 24: + pi->g_bits = pi->r_bits = pi->b_bits = 8; + pi->cached = 1; + break; + + case 32: + pic_error(pi, PIC_SUPPORT); + break; + + default: + pic_error(pi, PIC_NUM_COLORS); + } + } + break; + + default: + pic_error(pi, PIC_TYPE); + } + + pi->numcols = 1 << pi->cbits; + + /* read palette data */ + if(pi->cmapped){ + int i; + pi->cmap = pic_malloc((size_t) 3 * pi->numcols, "pic_read_header#1"); + for(i = 0; i < pi->numcols; i++){ + data32 c = pic_read_rgb(pi); + pi->cmap[i * 3 ] = c >> 16 & 0xff; + pi->cmap[i * 3 + 1] = c >> 8 & 0xff; + pi->cmap[i * 3 + 2] = c & 0xff; + } + } + + /* setup color code cache */ + if(pi->cached) + pic_cache_init(pi); + + + pi->data = pic_malloc(sizeof(data32) * pi->width * pi->height, + "pic_read_header#2"); + { + int i; + for(i = 0; i < pi->width * pi->height; i++) + pi->data[i] = 0xffffffff; + } + + if(DEBUG) + pic_show_pic_info(pi); +} + +/* The main routine to expand a PIC file. */ +static void pic_expand_data(pi) + struct pic_info *pi; +{ + int cnt; + data32 c; + pi->data[0] = c = 0; + for(cnt = -1; cnt < pi->width * pi->height; ){ + int len = pic_expanding_read_len(pi); + cnt += len; + if(cnt < pi->width * pi->height){ + int x = cnt % pi->width; + int y = cnt / pi->width; + data32 c = pic_expanding_read_color(pi); + pic_expanding_read_chain(pi, x, y, c); + } + } +} + +static int pic_expanding_read_len(pi) + struct pic_info *pi; +{ + int len; + byte bits; + for(len = 2, bits = 1; pic_read_bits(pi, 1) == 1; bits++) + len <<= 1; + return len - 1 + pic_read_bits(pi, bits); +} + +static data32 pic_expanding_read_color(pi) + struct pic_info *pi; +{ + if(pi->cached){ + byte b = pic_read_bits(pi, 1); + if(b){ + return pic_cache_get_value(pi, (int) pic_read_bits(pi, 7)); + }else{ + data32 c = pic_read_color_code(pi); + pic_cache_add_value(pi, c); + return c; + } + } + return pic_read_color_code(pi); +} + +static void pic_expanding_read_chain(pi, x, y, c) + struct pic_info *pi; + int x, y; + data32 c; +{ + pi->data[y * pi->width + x] = c; + if(pic_read_bits(pi, 1) == 1){ + int fin = 0; + while(!fin){ + switch(pic_read_bits(pi, 2)){ + case 1: /* left */ + pi->data[(++y) * pi->width + (--x)] = c; + break; + case 2: /* middle */ + pi->data[(++y) * pi->width + x ] = c; + break; + case 3: /* right */ + pi->data[(++y) * pi->width + (++x)] = c; + break; + case 0: /* far or nothing */ + if(pic_read_bits(pi, 1) == 0) + fin = 1; + else{ + if(pic_read_bits(pi, 1) == 0) + pi->data[(++y) * pi->width + (x -= 2)] = c; + else + pi->data[(++y) * pi->width + (x += 2)] = c; + } + } + } + } +} + +/* + * Make a picture from the expanded data. + */ +static void pic_make_xvpic(pi, xp, rp, gp, bp) + struct pic_info *pi; + byte **xp, *rp, *gp, *bp; +{ + if(pi->cmapped){ + if(pi->tiled256) + *xp = pic_malloc((size_t) pi->width * pi->height * 2, + "pic_make_xvpic#1"); + else + *xp = pic_malloc((size_t) pi->width * pi->height, + "pic_make_xvpic#2"); + }else + *xp = pic_malloc((size_t) pi->width * pi->height * 3, + "pic_make_xvpic#3"); + + if(pi->cmapped){ + int i; + + for(i = 0; i < pi->numcols; i++){ + rp[i] = pi->cmap[i * 3 ]; + gp[i] = pi->cmap[i * 3 + 1]; + bp[i] = pi->cmap[i * 3 + 2]; + } + + if(pi->tiled256){ + int pic_idx = 0, dat_idx; + data16 col = 0; + for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){ + if(pi->data[dat_idx] != 0xffffffff) + col = pi->data[dat_idx]; + (*xp)[pic_idx++] = col & 0xff; + (*xp)[pic_idx++] = col >> 8 & 0xff; + dat_idx++; + } + }else{ + int pic_idx = 0, dat_idx; + byte col = 0; + for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){ + if(pi->data[dat_idx] != 0xffffffff) + col = pi->data[dat_idx]; + (*xp)[pic_idx++] = col; + } + } + }else{ + int pic_idx = 0, dat_idx; + byte r, g, b; + for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){ + if(pi->data[dat_idx] != 0xffffffff){ + data32 col = pi->data[dat_idx]; + r = col >> 16 & 0xff; + g = col >> 8 & 0xff; + b = col & 0xff; + } + (*xp)[pic_idx++] = r; + (*xp)[pic_idx++] = g; + (*xp)[pic_idx++] = b; + } + } +} + + +/* The main routine to write PIC file. */ +int WritePIC(fp, pic0, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle, + comment) + FILE *fp; + byte *pic0; + int ptype, w, h; + byte *rmap, *gmap, *bmap; + int numcols, colorstyle; + char *comment; +{ + struct pic_info pic; + int e; + + if(DEBUG) fputs("WritePIC:\n", stderr); + + pic_init_info(&pic); + pic.fp = fp; + pic.width = w; + pic.height = h; + pic.writing_grey = (colorstyle == F_GREYSCALE); + if(ptype != PIC24){ /* PIC8 */ + pic.cmapped = 1; + pic.cached = 0; + pic.cbits = 8; + pic.g_bits = + pic.r_bits = + pic.b_bits = 8; + pic.i_bits = 0; + pic.numcols = numcols; + }else{ /* PIC24 */ + pic.cmapped = 0; + pic.cached = 1; + pic.cbits = 24; + pic.g_bits = + pic.r_bits = + pic.b_bits = 8; + pic.i_bits = 0; + pic.numcols = 1 << 24; + pic_cache_init(&pic); + } + + if((e = setjmp(pic.jmp)) != 0){ + /* When an error occurs while writing, comes here. */ + pic_cleanup_pic_info(&pic, 1); + if(DEBUG) fputs("\n", stderr); + return -1; + } + + pic_write_id(&pic); + pic_write_comment(&pic, comment); + pic_write_header(&pic); + if(pic.cmapped) + pic_write_palette(&pic, rmap, gmap, bmap); + pic_make_sparse_data(&pic, pic0); + pic_write_data(&pic); + pic_write_bits(&pic, 0, 8); + + pic_cleanup_pic_info(&pic, 1); + if(DEBUG) fputs("\n", stderr); + return 0; +} + +static void pic_write_id(pi) + struct pic_info *pi; +{ + if(fwrite("PIC", (size_t) 3, (size_t) 1, pi->fp) != 1) + pic_file_error(pi, PIC_WRITE); +} + +static void pic_write_comment(pi, comm) + struct pic_info *pi; + char *comm; +{ + if(comm){ + while(*comm){ + int c = *comm; + if(c == '\032') + c = ' '; + if(fputc(*comm, pi->fp) == EOF) + pic_file_error(pi, PIC_WRITE); + comm++; + } + } + /* write ^Z, 0, and reserved. */ + if(fwrite("\032\0\0", (size_t)3, (size_t) 1, pi->fp) != 1) + pic_file_error(pi, PIC_WRITE); +} + +static void pic_write_header(pi) + struct pic_info *pi; +{ + if(DEBUG) pic_show_pic_info(pi); + pic_write_bits(pi, (data32) 0, 4); /* mode: 1:1 */ + pic_write_bits(pi, (data32) 0xf, 4); /* type: misc */ + pic_write_bits(pi, (data32) pi->cbits, 16); /* bits */ + pic_write_bits(pi, (data32) pi->width, 16); /* width */ + pic_write_bits(pi, (data32) pi->height, 16); /* height */ + pic_write_bits(pi, (data32) 0xffff, 16); /* x: unused */ + pic_write_bits(pi, (data32) 0xffff, 16); /* y: unused */ + pic_write_bits(pi, (data32) 0x0101, 16); /* real aspect */ +} + +static void pic_write_palette(pi, r, g, b) + struct pic_info *pi; + byte *r, *g, *b; +{ + int i; + data32 rgb = 0; + pic_write_bits(pi, (data32) pi->g_bits, 8); + for(i = 0; i < pi->numcols; i++){ + rgb = (data32) *r++ << 16 | (data32) *g++ << 8 | (data32) *b++; + pic_write_rgb(pi, rgb); + } + for( ; i < 256; i++) + pic_write_rgb(pi, rgb); +} + +static void pic_make_sparse_data(pi, dat) + struct pic_info *pi; + byte *dat; +{ + int i; + data32 c; + + pi->data = pic_malloc(sizeof(data32) * pi->width * pi->height, + "pic_make_sparse_data"); + + if(pi->cmapped){ + c = 0; + for(i = 0; i < pi->width * pi->height; i++){ + if(c != dat[i]) + c = pi->data[i] = dat[i]; + else + pi->data[i] = 0xffffffff; + } + }else{ + int j = 0; + c = 0; + for(i = 0; i < pi->width * pi->height; i++){ + data32 r, g, b, t; + r = dat[j++]; + g = dat[j++]; + b = dat[j++]; + t = r << 16 | g << 8 | b; + if(c != t) + c = pi->data[i] = t; + else + pi->data[i] = 0xffffffff; + } + } +} + +static void pic_write_data(pi) + struct pic_info *pi; +{ + int i; + int max = pi->width * pi->height; + data32 c = 0; + + i = -1; + while(i < max){ + int j; + for(j = i + 1; j < max; j++){ + if(pi->data[j] != 0xffffffff) + break; + } + pic_write_length(pi, (data32) j - i); + i = j; + if(i < max){ + pic_write_color(pi, c = pi->data[i]); + pic_write_chain(pi, i % pi->width, i / pi->width, c); + } + } +} + +static void pic_write_length(pi, len) + struct pic_info *pi; + data32 len; +{ + int bits = 0; /* leading 1's */ + int max = 2; + + while(len > max){ + max = (max + 1) * 2; + bits++; + } + pic_write_bits(pi, 0xffffffff, bits); + pic_write_bits(pi, 0, 1); + pic_write_bits(pi, len - max / 2, bits + 1); +} + +static void pic_write_color(pi, c) + struct pic_info *pi; + data32 c; +{ + if(pi->cached){ + int idx = pic_cache_lookup(pi, c); + if(idx < 0){ /* not found */ + pic_write_bits(pi, 0, 1); + pic_write_color_code(pi, c); + pic_cache_add_value(pi, c); + }else{ /* found */ + pic_write_bits(pi, (data32) 0xffffffff, 1); + pic_write_bits(pi, (data32) idx, 7); + } + }else + pic_write_color_code(pi, c); +} + +static void pic_write_chain(pi, x, y, c) + struct pic_info *pi; + int x, y; + data32 c; +{ + int ctr = (y + 1) * pi->width + x; + + if(y < pi->height - 1 && + ( pi->data[ctr ] == c || + (x > 0 && pi->data[ctr - 1] == c) || + (x < pi->width - 1 && pi->data[ctr + 1] == c) || + (x > 1 && pi->data[ctr - 2] == c) || + (x < pi->width - 2 && pi->data[ctr + 2] == c))){ + pic_write_bits(pi, 1, 1); + while(++y < pi->height){ + if(pi->data[ctr] == c){ /* center */ + pic_write_bits(pi, 2, 2); + pi->data[ctr] = 0xffffffff; + ctr += pi->width; + }else if(x > 0 && pi->data[ctr - 1] == c){ /* left */ + pic_write_bits(pi, 1, 2); + pi->data[ctr - 1] = 0xffffffff; + ctr += pi->width - 1; + }else if(x < pi->width - 1 && pi->data[ctr + 1] == c){/* right */ + pic_write_bits(pi, 3, 2); + pi->data[ctr + 1] = 0xffffffff; + ctr += pi->width + 1; + }else if(x > 1 && pi->data[ctr - 2] == c){ /* 2-left */ + pic_write_bits(pi, 2, 4); + pi->data[ctr - 2] = 0xffffffff; + ctr += pi->width - 2; + }else if(x < pi->width - 2 && pi->data[ctr + 2] == c){/* 2-right */ + pic_write_bits(pi, 3, 4); + pi->data[ctr + 2] = 0xffffffff; + ctr += pi->width + 2; + }else /* nothing */ + break; + } + pic_write_bits(pi, 0, 3); + }else + pic_write_bits(pi, 0, 1); +} + + +/* + * These 4 functions reads or writes a color. + * + * pic_read_rgb: + * reads an RGB. Each bit length is [rgb]_bits, but + * it is expanded to 8bits when returned. + * + * pic_read_color_code: + * reads a color code, whose length is cbits. + * It is the index to the colormap or RGB itself. + * + * pic_write_rgb: + * writes an RGB value. + * + * pic_write_color_code: + * writes a color code. + */ +static data32 pic_read_rgb(pi) + struct pic_info *pi; +{ + int rb = pi->r_bits, gb = pi->g_bits, bb = pi->b_bits; + byte r, g, b; + if(pi->inv_gr){ + r = pic_read_bits(pi, rb); + g = pic_read_bits(pi, gb); + }else{ + g = pic_read_bits(pi, gb); + r = pic_read_bits(pi, rb); + } + b = pic_read_bits(pi, bb); + if(pi->i_bits){ + byte i; + i = pic_read_bits(pi, pi->i_bits); + r = r << pi->i_bits | i; + g = g << pi->i_bits | i; + b = b << pi->i_bits | i; + rb += pi->i_bits; + gb += pi->i_bits; + bb += pi->i_bits; + } + r = pic_pad_bit(rb, r); + g = pic_pad_bit(gb, g); + b = pic_pad_bit(bb, b); + + return (data32) r << 16 | (data32) g << 8 | (data32) b; +} + +static data32 pic_read_color_code(pi) + struct pic_info *pi; +{ + if(pi->cmapped) + return pic_read_bits(pi, pi->cbits); + return pic_read_rgb(pi); +} + +static void pic_write_rgb(pi, rgb) + struct pic_info *pi; + data32 rgb; +{ + byte r = rgb >> 16; + byte g = rgb >> 8; + byte b = rgb; + if(pi->writing_grey) + r = g = b = MONO(r, g, b); + pic_write_bits(pi, g, pi->g_bits); + pic_write_bits(pi, r, pi->r_bits); + pic_write_bits(pi, b, pi->b_bits); +} + +static void pic_write_color_code(pi, code) + struct pic_info *pi; + data32 code; +{ + if(pi->cmapped){ + pic_write_bits(pi, code, pi->cbits); + }else{ + pic_write_rgb(pi, code); + } +} + + +/* + * These pic_cache_* functions are an implementation of the color cache. + * + * pic_cache_init: + * initializes the cache. + * + * pic_cache_get_value: + * gets a color indexed by the argument `idx'. + * It updates the `most recently used' time. + * + * pic_cache_add_value: + * adds a color to the top of the cache list. + */ +static void pic_cache_init(pi) + struct pic_info *pi; +{ + int i; + pi->cache.node = pic_malloc(sizeof(struct cachenode_t) * 128, + "pic_cache_init"); + for(i = 0; i < 128; i++){ + pi->cache.node[i].newer = i + 1; + pi->cache.node[i].older = i - 1; + pi->cache.node[i].dat = 0; + } + pi->cache.node[ 0].older = 127; + pi->cache.node[127].newer = 0; + pi->cache.newest = 0; +} + +static data32 pic_cache_get_value(pi, idx) + struct pic_info *pi; + int idx; +{ + struct cachenode_t *p = pi->cache.node; + int n = pi->cache.newest; + if(n != idx){ + p[p[idx].newer].older = p[idx].older; + p[p[idx].older].newer = p[idx].newer; + + p[p[n].newer].older = idx; + p[idx].newer = p[n].newer; + p[n].newer = idx; + p[idx].older = n; + + pi->cache.newest = idx; + } + return pi->cache.node[idx].dat; +} + +static void pic_cache_add_value(pi, dat) + struct pic_info *pi; + data32 dat; +{ + pi->cache.newest = pi->cache.node[pi->cache.newest].newer; + pi->cache.node[pi->cache.newest].dat = dat; +} + +static int pic_cache_lookup(pi, dat) + struct pic_info *pi; + data32 dat; +{ + int i; + for(i = 0; i < 128; i++){ + if(pi->cache.node[i].dat == dat){ + pic_cache_get_value(pi, i); + return i; + } + } + return -1; +} + + +/* + * These pic_{read,write}_bits functions access the bit stream. + * pic_read_bits: + * reads the specified bits from the file. + * + * pic_write_bits: + * writes the specified bits to the file. + */ +static data32 pic_read_bits(pi, bits) + struct pic_info *pi; + int bits; +{ + data32 r = 0; + + while(bits > 0){ + while(pi->bs.rest > 0 && bits > 0){ + r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0); + pi->bs.cur <<= 1; + pi->bs.rest--; + bits--; + } + if(bits > 0){ + int c; + if((c = fgetc(pi->fp)) == EOF){ + pic_file_warning(pi, PIC_CORRUPT); + c = 0; + } + pi->bs.cur = c; + pi->bs.rest = 8; + } + } + + return r; +} + +static void pic_write_bits(pi, dat, bits) + struct pic_info *pi; + data32 dat; + int bits; +{ + data32 dat_mask = 1 << (bits - 1); + while(bits > 0){ + while(pi->bs.rest < 8 && bits > 0){ + pi->bs.cur <<= 1; + if(dat & dat_mask) + pi->bs.cur |= 1; + pi->bs.rest++; + bits--; + dat_mask >>= 1; + } + if(pi->bs.rest >= 8){ + if(fputc((int)pi->bs.cur, pi->fp) == EOF) + pic_error(pi, PIC_WRITE); + pi->bs.cur = 0; + pi->bs.rest = 0; + } + } +} + + +/* + * This function extends a some-bit data to the 8-bit data. + */ +static byte pic_pad_bit(bits, dat) + int bits; + data32 dat; +{ + switch(bits){ + case 1: + if(dat & 1) + dat = 0xff; + else + dat = 0; + break; + case 2: + dat = dat << 6 | dat << 4 | dat << 2 | dat; + break; + case 3: + dat = dat << 5 | dat << 2 | dat >> 1; + break; + case 4: + dat = dat << 4 | dat; + break; + case 5: + dat = dat << 3 | dat >> 2; + break; + case 6: + dat = dat << 2 | dat >> 4; + break; + case 7: + dat = dat << 1 | dat >> 6; + } + + return dat; +} + +/* + * These functions initialize or clean up structures. + * pic_init_info: + * initializes a pic_info structure. + * pic_cleanup_pic_info: + * cleans up a pic_info structure. + * pic_cleanup_pinfo: + * cleans up a PICINFO structure. + */ +static void pic_init_info(pi) + struct pic_info *pi; +{ + pi->fp = NULL; + pi->bs.rest = 0; + pi->bs.cur = '\0'; + pi->type = pi->mode = 0; + pi->width = pi->height = 0; + pi->aspect = 1.0; + pi->cbits = 0; + pi->cmapped = pi->cached = 0; + pi->cache.node = NULL; + pi->cmap = NULL; + pi->g_bits = pi->r_bits = pi->b_bits = pi->i_bits = 0; + pi->inv_gr = 0; + pi->tiled256 = 0; + pi->numcols = 0; + pi->writing_grey = 0; +} + +static void pic_cleanup_pic_info(pi, writing) + struct pic_info *pi; + int writing; +{ + if(!writing && pi->fp) + fclose(pi->fp); + if(pi->cmap) + free(pi->cmap); + if(pi->cache.node) + free(pi->cache.node); + if(pi->data) + free(pi->data); + pi->fp = NULL; + pi->cmap = NULL; + pi->cache.node = NULL; + pi->data = NULL; +} + +static void pic_cleanup_pinfo(pinfo) + PICINFO *pinfo; +{ + if(pinfo->pic){ + free(pinfo->pic); + pinfo->pic = NULL; + } + if(pinfo->comment){ + free(pinfo->comment); + pinfo->comment = NULL; + } +} + +/* + * Error Handlers. + * pic_memory_error: + * shows an error message, and terminates. + * pic_error: + * shows an non-file error message, and jumps to the entry for errors. + * pic_file_error: + * shows an file error message, and jumps to the entry for errors. + * pic_file_warning: + * shows an file warning message. + */ +static void pic_memory_error(scm, fn) + char *scm, *fn; +{ + char buf[128]; + sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn); + FatalError(buf); +} + +static void pic_error(pi, mn) + struct pic_info *pi; + int mn; +{ + SetISTR(ISTR_WARNING, "%s", pic_msgs[mn]); + longjmp(pi->jmp, 1); +} + +static void pic_file_error(pi, mn) + struct pic_info *pi; + int mn; +{ + if(feof(pi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", pic_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", pic_msgs[mn], ERRSTR(errno)); + longjmp(pi->jmp, 1); +} + +static void pic_file_warning(pi, mn) + struct pic_info *pi; + int mn; +{ + if(feof(pi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", pic_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", pic_msgs[mn], ERRSTR(errno)); +} + +static void pic_show_pic_info(pi) + struct pic_info *pi; +{ + fprintf(stderr, " file size: %ld.\n", pi->fsize); + + fputs(" machine: ", stderr); + switch(pi->type){ + case 0x0: + fputs("X68k", stderr); + break; + case 0x1: + fputs("PC-88VA", stderr); + if(pi->mode & 1) + fputs(",HR", stderr); + if(pi->mode & 2) + fputs(",tiled256", stderr); + break; + case 0x2: + fprintf(stderr, + "FM-TOWNS,%s-resolution", pi->mode == 5 ? "low" : "high"); + break; + case 0x3: + fputs("Machintosh", stderr); + break; + case 0xf: + fputs("misc", stderr); + } + fputs("\n", stderr); + + fprintf(stderr, " image size: %dx%d\n", pi->width, pi->height); + fprintf(stderr, " aspect: %f\n", pi->aspect); + fprintf(stderr, " cache: %s\n", pi->cached ? "on" : "off"); + fprintf(stderr, " colormap: %s\n", pi->cmapped ? "on" : "off"); + fprintf(stderr, " number of color bits: %d\n", pi->cbits); + fprintf(stderr, " number of RGB bits: R%d,G%d,B%d,I%d\n", + pi->r_bits, pi->g_bits, pi->b_bits, pi->i_bits); + fprintf(stderr, " inverted G&R: %s\n", pi->inv_gr ? "true" : "false"); + fprintf(stderr, " number of colors: %d\n", pi->numcols); +} + +/* Memory related routines. */ +static void *pic_malloc(n, fn) + size_t n; + char *fn; +{ + void *r = (void *) malloc(n); + if(r == NULL) + pic_memory_error("malloc", fn); + return r; +} + +static void *pic_realloc(p, n, fn) + void *p; + size_t n; + char *fn; +{ + void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n); + if(r == NULL) + pic_memory_error("realloc", fn); + return r; +} +#endif /* HAVE_PIC */ diff -urN xv-3.10a/xvpic2.c xv-3.10a-jp-extension-current/xvpic2.c --- xv-3.10a/xvpic2.c +++ xv-3.10a-jp-extension-current/xvpic2.c Wed Oct 9 20:37:21 1996 @@ -0,0 +1,3598 @@ +/* + * $Id: xvpic2.c,v 2.9.1.14 1995/04/24 15:34:15 ikeyan Exp $ + * xvpic2.c - load and save routines for `PIC2' format pictures. + * + * + * Outline + * ======= + * xvpic2.c supports the PIC2 format image file. It is used some + * Japanese personal computer users. + * + * The PIC2 format is designed by A.Yanagisawa. It is very excellent + * format except for it's encode/decode speed ;-) + * + * The features of the PIC2 format: + * - Powerful header information (included author, filename, title, + * saver, product number, created date and comment). + * - Reversible compression, and very high compression ratio (In a lot + * of case, keep higher compression ratio than the JPEG compression. + * Especially, because of it's compression method, PIC2 is good at + * pictures like cell animation). + * - Can handle full coloer(24 bits) image. + * - Can include multi image blocks into one PIC2 file. + * - Have four different block format (P2SS, P2SF, P2BM and + * P2BI). P2SS format uses arithmetric compression for storeing + * data. P2SF uses normal run length compression. P2BM and P2BI is + * raw image format. Select any one accoding to the situation. + * + * Explanation of the PIC2 compression: + + * - In the first place, try to record pixel color, uses color caches + * which keep some recent colors, and formed accding to color's + * frequency. PIC2 has some color cache spaces that are switched by + * upper pixel value of current pixel. If cache is hit, record + * that. + * - Unfortunately, in the case of color cache didn't hit, record the + * difference from the value estimated with the value of upper and + * left pixel of current pixel + * - And extract image's color chain if exist, and record that (It + * results in image's outline). + * - In all time of recording values, it is pressed with arithmetric + * compression method which produce the ideal compression ratio in + * theory(P2SS). + * + * Features + * ======== + * - Support 3,6,9,12,15,18,21,24bit PIC2 format (Load/Save). + * - Support all image block formats of PIC2 (Load/Save). + * - Support multi block PIC2 file (Load/Save). + * + * + * Bugs + * ==== + * - Unsupport 8bit PIC2 image file. + * + * If you find other bugs (surely exist :-)), send me bug-report. + * + * + * Author + * ====== + * IKEMOTO Masahiro + */ + +#define PIC2_IGNORE_UNUSED_FUNCTIONS +#define NEEDSDIR + +#include "xv.h" +#include + +#ifdef HAVE_PIC2 + +typedef unsigned long pixel; + +#define pic2_cextoshort(addr) ( \ + (((short) (((byte *) addr)[0])) << 8) | \ + ( (short) (((byte *) addr)[1])) \ +) +#define pic2_cextolong(addr) ( \ + (((long) (((byte *) addr)[0])) << 24) | \ + (((long) (((byte *) addr)[1])) << 16) | \ + (((long) (((byte *) addr)[2])) << 8) | \ + ( (long) (((byte *) addr)[3])) \ +) +#define pic2_shorttocex(addr, n) { \ + ((byte *) addr)[0] = (((unsigned short) (n) >> 8) & 0xff); \ + ((byte *) addr)[1] = ( (unsigned short) (n) & 0xff); \ +} +#define pic2_longtocex(addr, n) { \ + ((byte *) addr)[0] = (((unsigned long) (n) >> 24) & 0xff); \ + ((byte *) addr)[1] = (((unsigned long) (n) >> 16) & 0xff); \ + ((byte *) addr)[2] = (((unsigned long) (n) >> 8) & 0xff); \ + ((byte *) addr)[3] = ( (unsigned long) (n) & 0xff); \ +} +#define pic2_shift_bits(b, n) (((n) > 0) ? ((b) << (n)) : ((b) >> -(n))) + +#define PIC2_READ_MODE 0 +#define PIC2_WRITE_MODE 1 + +#define PIC2_ARITH_CACHE 32 +#define PIC2_ARITH_CONTEXT 128 +#define PIC2_FAST_CACHE 64 + +#define PIC2_HEADER_SIZE 124 +#define PIC2_BLOCK_HEADER_SIZE 26 + +struct pic2_header { + char magic[4]; + char name[18]; + char subtitle[8]; + char crlf0[2]; + char title[30]; + char crlf1[2]; + char saver[30]; + char crlf2[2]; + char eof[1]; + char reserve0[1]; + short flag; + short no; + long time; + long size; + short depth; + short x_aspect; + short y_aspect; + short x_max; + short y_max; + long reserve1; +}; + +struct pic2_block { + char id[4]; + long size; + short flag; + short x_wid; + short y_wid; + short x_offset; + short y_offset; + long opaque; + long reserve; +}; + +struct pic2_info { + jmp_buf jmp; + FILE *fp; + struct { + int rest; + byte cur; + int bits; + char zero; + }bs; + long fsize; + struct pic2_header *header; + struct pic2_block *block; + int n_pal; + int pal_bits; + byte pal[256][3]; + char *comment; + char mode; + long next_pos; + long block_pos; + short x_max; + short y_max; + int ynow; + byte *buf; + pixel *vram_prev; + pixel *vram_now; + pixel *vram_next; + short *flag_now; + short *flag_next; + short *flag2_now; + short *flag2_next; + short *flag2_next2; + pixel (*cache)[PIC2_ARITH_CACHE]; + unsigned short *cache_pos; + unsigned short *mulu_tab; + long aa; + long cc; + long dd; + char cache_hit_c; + int (*next_line) PARM((struct pic2_info *, pixel **)); + char writing_grey; + char pagebname[64]; + int pnum; +}; + +static void pic2_open_file PARM((struct pic2_info*,char*)); +static void pic2_read_header PARM((struct pic2_info*)); +static void pic2_read_block_header1 PARM((struct pic2_info*)); +static void pic2_read_block_header2 PARM((struct pic2_info*)); +static short pic2_arith_decode_bit PARM((struct pic2_info*,int)); +static short pic2_arith_decode_nn PARM((struct pic2_info*,int)); +static void pic2_arith_expand_chain PARM((struct pic2_info*,int,int,pixel)); +static short pic2_arith_get_number PARM((struct pic2_info*,int,int)); +static pixel pic2_arith_read_color PARM((struct pic2_info*,int)); +static int pic2_arith_expand_line PARM((struct pic2_info*,pixel**)); +static int pic2_arith_loader_init PARM((struct pic2_info*)); +static int pic2_fast_read_length PARM((struct pic2_info*)); +static void pic2_fast_expand_chain PARM((struct pic2_info*,int,pixel)); +static pixel pic2_fast_read_color PARM((struct pic2_info*,pixel)); +static int pic2_fast_expand_line PARM((struct pic2_info*,pixel**)); +static int pic2_fast_loader_init PARM((struct pic2_info*)); +static int pic2_beta_expand_line PARM((struct pic2_info*,pixel**)); +static int pic2_beta_loader_init PARM((struct pic2_info*)); +static void pic2_make_xvpic PARM((struct pic2_info*,byte**, + byte*,byte*,byte*)); +static void pic2_make_pagefile PARM((struct pic2_info*,char*,int)); +static void pic2_setup_pic2_info PARM((struct pic2_info*, + char*,char*,char*,char*, + int,int,int,int,int,int,char *)); +static void pic2_append PARM((struct pic2_info*)); +static void pic2_write_header1 PARM((struct pic2_info*)); +static void pic2_write_header2 PARM((struct pic2_info*)); +static void pic2_write_block_header PARM((struct pic2_info*)); +static void pic2_arith_write_zero_bit PARM((struct pic2_info*)); +static void pic2_arith_flush_bit_buf PARM((struct pic2_info*)); +static void pic2_arith_carry_bit PARM((struct pic2_info*)); +static void pic2_arith_encode_bit PARM((struct pic2_info*,int,int)); +static void pic2_arith_encode_nbyte PARM((struct pic2_info*,int,int,int)); +static void pic2_arith_encode_nn PARM((struct pic2_info*,int,int)); +static void pic2_arith_press_chain PARM((struct pic2_info*,int)); +static void pic2_arith_put_number PARM((struct pic2_info*,int,int,int)); +static void pic2_arith_write_color PARM((struct pic2_info*,int)); +static void pic2_arith_press_line2 PARM((struct pic2_info*)); +static int pic2_arith_press_line PARM((struct pic2_info*,pixel**)); +static int pic2_arith_saver_init PARM((struct pic2_info*,pixel**)); +static void pic2_fast_write_length PARM((struct pic2_info*,int)); +static void pic2_fast_press_chain PARM((struct pic2_info*,int)); +static void pic2_fast_press_chain2 PARM((struct pic2_info*,int)); +static void pic2_fast_flush_chain PARM((struct pic2_info*)); +static void pic2_fast_write_color PARM((struct pic2_info*,int)); +static void pic2_fast_press_line2 PARM((struct pic2_info*)); +static int pic2_fast_press_line PARM((struct pic2_info*,pixel**)); +static int pic2_fast_saver_init PARM((struct pic2_info*,pixel**)); +static int pic2_beta_press_line PARM((struct pic2_info*,pixel**)); +static int pic2_beta_saver_init PARM((struct pic2_info*,pixel**)); +static void pic2_write_data PARM((struct pic2_info*,byte*, + int,int,int,int,int, + byte*,byte*,byte*,int,int)); +static int pic2_next_line PARM((struct pic2_info*,pixel**)); +static int pic2_next_block PARM((struct pic2_info*)); +static int pic2_find_block PARM((struct pic2_info*)); +static int pic2_load_block PARM((struct pic2_info*)); +static int pic2_save_block PARM((struct pic2_info*,pixel**, + int,int,int,int,char*,pixel)); +#ifndef PIC2_IGNORE_UNUSED_FUNCTIONS +static void pic2_read_palette PARM((struct pic2_info*, + byte*,byte*,byte*)); +static void pic2_write_palette PARM((struct pic2_info*,int,int, + byte*,byte*,byte*)); +#endif /* !PIC2_IGNORE_UNUSED_FUNCTIONS */ +static byte pic2_convert_color_bits PARM((int,int,int)); +static byte pic2_pad_color_bits PARM((int,int,int)); +static byte pic2_reduce_color_bits PARM((int,int,int)); +static pixel pic2_exchange_rg PARM((pixel,int)); +static void pic2_handle_para PARM((struct pic2_info*,int)); +static int pic2_alloc_buffer PARM((struct pic2_info*)); +static void pic2_free_buffer PARM((struct pic2_info*)); +static long pic2_seek_file PARM((struct pic2_info*,long,int)); +static long pic2_tell_file PARM((struct pic2_info*)); +static int pic2_read_file PARM((struct pic2_info*,void*,size_t)); +static long pic2_read_long PARM((struct pic2_info*)); +static short pic2_read_short PARM((struct pic2_info*)); +static char pic2_read_char PARM((struct pic2_info*)); +static int pic2_write_file PARM((struct pic2_info*,void*,size_t)); +static int pic2_write_long PARM((struct pic2_info*,long)); +static int pic2_write_short PARM((struct pic2_info*,int)); +static int pic2_write_char PARM((struct pic2_info*,int)); +static unsigned long pic2_read_bits PARM((struct pic2_info*,int)); +static void pic2_write_bits PARM((struct pic2_info*, + unsigned long,int)); +static void pic2_flush_bits PARM((struct pic2_info*)); +static void pic2_memory_error PARM((char*,char*)); +static void pic2_error PARM((struct pic2_info*,int)); +static void pic2_file_error PARM((struct pic2_info*,int)); +static void pic2_init_info PARM((struct pic2_info*)); +static void pic2_cleanup_pic2_info PARM((struct pic2_info*,int)); +static void pic2_cleanup_pinfo PARM((PICINFO*)); +static void pic2_show_pic2_info PARM((struct pic2_info*)); +static char *pic2_strncpy PARM((char*,char*,size_t)); +static void *pic2_malloc PARM((size_t,char*)); +static void *pic2_new PARM((size_t,char*)); + +static int WritePIC2 PARM((FILE*,byte*,int,int,int, + byte*,byte*,byte*,int,int,char*, + int,int,int,int,int,char*)); + +static char *pic2_id = "P2DT"; + +/* Error Messages */ +static char *pic2_msgs[] = { + NULL, +#define PIC2_OPEN 1 + "can't open file.", +#define PIC2_CORRUPT 2 + "file corrupted.", +#define PIC2_FORMAT 3 + "not PIC2 format.", +#define PIC2_DEPTH 4 + "not support the depth which cannot be divided with 3.", +#define PIC2_TMPFILE 5 + "unable to create temporary filename???", +#define PIC2_PAGE 6 + "couldn't load the page.", +#define PIC2_APPEND 7 + "cannot append.", +#define PIC2_WRITE 8 + "write failed.", +}; + +struct _form_tab { + char *id; + int (*loader_init) PARM((struct pic2_info *)); + int (*saver_init) PARM((struct pic2_info *, pixel **)); +} form_tab[] = { + { "P2SS", pic2_arith_loader_init, pic2_arith_saver_init}, + { "P2SF", pic2_fast_loader_init, pic2_fast_saver_init}, + { "P2BM", pic2_beta_loader_init, pic2_beta_saver_init}, + { "P2BI", pic2_beta_loader_init, pic2_beta_saver_init}, +}; +#define n_form_tab (sizeof(form_tab) / sizeof(struct _form_tab)) +#define P2SS 0 +#define P2SF 1 +#define P2BM 2 +#define P2BI 3 + +/* The main routine to load a PIC2 file. */ +int LoadPIC2(fname, pinfo, quick) +char *fname; +PICINFO *pinfo; +int quick; +{ + int e, i, block; + struct pic2_info pic2; + + if (DEBUG) + fputs("LoadPIC2:\n", stderr); + + pic2_init_info(&pic2); + + if ((e = setjmp(pic2.jmp)) != 0){ + /* When an error occurs, comes here. */ + pic2_free_buffer(&pic2); + pic2_cleanup_pic2_info(&pic2, 0); + pic2_cleanup_pinfo(pinfo); + if (pic2split) + KillPageFiles(pic2.pagebname, pic2.pnum); + SetCursors(-1); + if (DEBUG) + fputs("\n", stderr); + return (0); + } + pic2_open_file(&pic2, fname); + pic2_read_header(&pic2); + + if ((i = pic2_find_block(&pic2)) == 0) + pic2_file_error(&pic2, PIC2_CORRUPT); + + block = 1; + while(i == 2) { + SetISTR(ISTR_WARNING, "unknown or invalid block #%d.", block); + i = pic2_next_block(&pic2); + block++; + } + + if (pic2split && !quick) { + char firstpage[512]; + struct stat st; + +#ifndef VMS + sprintf(pic2.pagebname, "%s/xvpic2XXXXXX", tmpdir); +#else + sprintf(pic2.pagebname, "Sys$Scratch:xvpic2XXXXXX"); +#endif /* VMS */ + mktemp(pic2.pagebname); + if (pic2.pagebname[0] == '\0') + pic2_error(&pic2, PIC2_TMPFILE); + strcat(pic2.pagebname, "."); + + sprintf(firstpage, "%s%d", pic2.pagebname, 1); + if (stat(firstpage, &st)) { + for (pic2.pnum = 1; i >= 1; pic2.pnum++) { + pic2_load_block(&pic2); + pic2_make_pagefile(&pic2, pic2.pagebname, pic2.pnum); + while(block++, (i = pic2_next_block(&pic2)) == 2) + SetISTR(ISTR_WARNING, + "unknown or invalid block #%d.", block); + } + pinfo->numpages = --pic2.pnum; + if (!LoadPIC2(firstpage, pinfo, 1)) + pic2_error(&pic2, PIC2_PAGE); + if (pic2.pnum == 1) + unlink(firstpage); + else + strcpy(pinfo->pagebname, pic2.pagebname); + } else + if (!LoadPIC2(fname, pinfo, 1)) + pic2_error(&pic2, PIC2_PAGE); + } else { + char buf[128], format[64]; + int j; + + pinfo->w = pic2.x_max; + pinfo->h = pic2.y_max; + pinfo->normw = pinfo->w; + pinfo->normh = pinfo->h; + pinfo->type = PIC24; + for (j = 0; j < n_form_tab; j++) { + if (xvbcmp(pic2.block->id, form_tab[j].id, (size_t) 4) == 0) + break; + } + pinfo->frmType = F_PIC2; + pinfo->colType = F_FULLCOLOR; + pinfo->comment = pic2.comment; + + if (pic2split) { + pic2_make_xvpic(&pic2, &pinfo->pic, pinfo->r, pinfo->g, pinfo->b); + strcpy(format, form_tab[j].id); + } else { + for (pic2.pnum = 1; i >= 1; pic2.pnum++) { + SetISTR(ISTR_INFO, "composing block #%d", block); + pic2_make_xvpic(&pic2, &pinfo->pic, + pinfo->r, pinfo->g, pinfo->b); + while(block++, (i = pic2_next_block(&pic2)) == 2) + SetISTR(ISTR_WARNING, + "unknown or invalid block #%d.", block); + } + if (--block > 1) + if (block != --pic2.pnum) + sprintf(format, "MultiBlock[%d/%d]", block, pic2.pnum); + else + sprintf(format, "MultiBlock[%d]", block); + else + strcpy(format, form_tab[j].id); + } + sprintf(buf, "PIC2(%s). %d colors (%ld bytes)", format, + (int) 1 << pic2.header->depth, pic2.fsize); + strcat(pinfo->fullInfo, buf); + sprintf(pinfo->shrtInfo, "%dx%d(aspect %4.2f) PIC2(%s).", + pinfo->w, pinfo->h, + (float) pic2.header->x_aspect / (float) pic2.header->y_aspect, + format); + if (!nopicadjust) + normaspect = (float) pic2.header->x_aspect + / (float) pic2.header->y_aspect; + } + pic2_cleanup_pic2_info(&pic2, 0); + SetCursors(-1); + if (DEBUG) + fputs("\n", stderr); + return (1); +} + +/* + * This function opens the file, and set its size. + */ +static void pic2_open_file(pi, fname) + struct pic2_info *pi; + char *fname; +{ + if ((pi->fp = fopen(fname, "rb")) == NULL) + pic2_file_error(pi, PIC2_OPEN); + fseek(pi->fp, (size_t) 0, SEEK_END); + pi->fsize = ftell(pi->fp); + fseek(pi->fp, (size_t) 0, SEEK_SET); +} + +/* + * These functions read the PIC2 header informations. + * pic2_read_header: + * reads the PIC2 header. + * pic2_read_block_header1: + * reads the id number of block header and the size of block. + * pic2_read_block_header2: + * reads the rest of block header. + */ +static void pic2_read_header(pi) +struct pic2_info *pi; +{ + long s_comment; + + pi->mode = PIC2_READ_MODE; + + /* read header image */ + pic2_read_file(pi, pi->header->magic, 4); + pic2_read_file(pi, pi->header->name, 18); + pic2_read_file(pi, pi->header->subtitle, 8); + pic2_read_file(pi, pi->header->crlf0, 2); + pic2_read_file(pi, pi->header->title, 30); + pic2_read_file(pi, pi->header->crlf1, 2); + pic2_read_file(pi, pi->header->saver, 30); + pic2_read_file(pi, pi->header->crlf2, 2); + pic2_read_file(pi, pi->header->eof, 1); + pic2_read_file(pi, pi->header->reserve0, 1); + pi->header->flag = pic2_read_short(pi); + pi->header->no = pic2_read_short(pi); + pi->header->time = pic2_read_long(pi); + pi->header->size = pic2_read_long(pi); + pi->header->depth = pic2_read_short(pi); + pi->header->x_aspect = pic2_read_short(pi); + pi->header->y_aspect = pic2_read_short(pi); + pi->header->x_max = pic2_read_short(pi); + pi->header->y_max = pic2_read_short(pi); + pi->header->reserve1 = pic2_read_long(pi); + + /* check magic number */ + if (strncmp(pi->header->magic, pic2_id, (size_t) 4) != 0) + pic2_error(pi, PIC2_FORMAT); + + /* read palette data, if exists */ + if (pi->header->flag & 1) { + pi->pal_bits = pic2_read_char(pi); + pi->n_pal = pic2_read_short(pi); + pic2_read_file(pi, pi->pal, (size_t) (pi->n_pal * 3)); + } + + /* read comments */ + s_comment = pi->header->size - pic2_tell_file(pi); + pi->comment = pic2_new(s_comment + 1, "pic2_read_header"); + pic2_read_file(pi, pi->comment, (size_t) s_comment); + pi->comment[s_comment] = '\0'; + + pi->x_max = pi->header->x_max; + pi->y_max = pi->header->y_max; + + /* set initial block point */ + pi->next_pos = pic2_tell_file(pi); +} + +static void pic2_read_block_header1(pi) +struct pic2_info *pi; +{ + pic2_read_file(pi, pi->block->id, 4); + pi->block->size = pic2_read_long(pi); +} + +static void pic2_read_block_header2(pi) +struct pic2_info *pi; +{ + pi->block->flag = pic2_read_short(pi); + pi->block->x_wid = pic2_read_short(pi); + pi->block->y_wid = pic2_read_short(pi); + pi->block->x_offset = pic2_read_short(pi); + pi->block->y_offset = pic2_read_short(pi); + pi->block->opaque = pic2_read_long(pi); + pi->block->reserve = pic2_read_long(pi); +} + +/* + * These functions are arithmetric pic2 format extractor. + */ +static short pic2_arith_decode_bit(pi, c) +struct pic2_info *pi; +int c; +{ + unsigned short pp; + + pp = pi->mulu_tab[(pi->aa & 0x7f00) / 2 + c]; + if (pi->dd >= (int) pp) { + pi->dd -= pp; + pi->aa -= pp; + + while ((short) pi->aa >= 0) { + pi->dd *= 2; + if (pic2_read_bits(pi, 1)) + pi->dd++; + pi->aa *= 2; + } + return (1); + } else { + pi->aa = pp; + + while ((short) pi->aa >= 0) { + pi->dd *= 2; + if (pic2_read_bits(pi, 1)) + pi->dd++; + pi->aa *= 2; + } + return (0); + } +} + +static short pic2_arith_decode_nn(pi, c) +struct pic2_info *pi; +int c; +{ + int n; + + if (pic2_arith_decode_bit(pi, c)) { + /* n < 1 */ + n = 0; + } else if (pic2_arith_decode_bit(pi, c + 1)) { + /* n < 1 + 2 */ + n = 1; + if (pic2_arith_decode_bit(pi, c + 8)) + n += 1; + } else if (pic2_arith_decode_bit(pi, c + 2)) { + /* n < 1 + 2 + 4 */ + n = 1 + 2; + if (pic2_arith_decode_bit(pi, c + 8)) + n += 1; + if (pic2_arith_decode_bit(pi, c + 9)) + n += 2; + } else if (pic2_arith_decode_bit(pi, c + 3)) { + /* n < 1 + 2 + 4 + 8 */ + n = 1 + 2 + 4; + if (pic2_arith_decode_bit(pi, c + 8)) + n += 1; + if (pic2_arith_decode_bit(pi, c + 9)) + n += 2; + if (pic2_arith_decode_bit(pi, c + 10)) + n += 4; + } else if (pic2_arith_decode_bit(pi, c + 4)) { + /* n < 1 + 2 + 4 + 8 + 16 */ + n = 1 + 2 + 4 + 8; + if (pic2_arith_decode_bit(pi, c + 8)) + n += 1; + if (pic2_arith_decode_bit(pi, c + 9)) + n += 2; + if (pic2_arith_decode_bit(pi, c + 10)) + n += 4; + if (pic2_arith_decode_bit(pi, c + 11)) + n += 8; + } else if (pic2_arith_decode_bit(pi, c + 5)) { + /* n < 1 + 2 + 4 + 8 + 16 + 32 */ + n = 1 + 2 + 4 + 8 + 16; + if (pic2_arith_decode_bit(pi, c + 8)) + n += 1; + if (pic2_arith_decode_bit(pi, c + 9)) + n += 2; + if (pic2_arith_decode_bit(pi, c + 10)) + n += 4; + if (pic2_arith_decode_bit(pi, c + 11)) + n += 8; + if (pic2_arith_decode_bit(pi, c + 12)) + n += 16; + + } else if (pic2_arith_decode_bit(pi, c + 6)) { + /* n < 1 + 2 + 4 + 8 + 16 + 32 + 64 */ + n = 1 + 2 + 4 + 8 + 16 + 32; + if (pic2_arith_decode_bit(pi, c + 8)) + n += 1; + if (pic2_arith_decode_bit(pi, c + 9)) + n += 2; + if (pic2_arith_decode_bit(pi, c + 10)) + n += 4; + if (pic2_arith_decode_bit(pi, c + 11)) + n += 8; + if (pic2_arith_decode_bit(pi, c + 12)) + n += 16; + if (pic2_arith_decode_bit(pi, c + 13)) + n += 32; + + } else if (pic2_arith_decode_bit(pi, c + 7)) { + /* n < 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 */ + n = 1 + 2 + 4 + 8 + 16 + 32 + 64; + if (pic2_arith_decode_bit(pi, c + 8)) + n += 1; + if (pic2_arith_decode_bit(pi, c + 9)) + n += 2; + if (pic2_arith_decode_bit(pi, c + 10)) + n += 4; + if (pic2_arith_decode_bit(pi, c + 11)) + n += 8; + if (pic2_arith_decode_bit(pi, c + 12)) + n += 16; + if (pic2_arith_decode_bit(pi, c + 13)) + n += 32; + if (pic2_arith_decode_bit(pi, c + 14)) + n += 64; + + } else { + n = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128; + } + return (n); +} + +static void pic2_arith_expand_chain(pi, x, y, cc) +struct pic2_info *pi; +int x, y; +pixel cc; +{ + static const unsigned short c_tab[] = { + 80 + 6 * 5, /* -5 */ + 80 + 6 * 4, + 80 + 6 * 3, + 80 + 6 * 2, + 80 + 6 * 1, + 80 + 6 * 0, /* 0 */ + 80 + 6 * 0, /* 1 */ + }; + unsigned short b; + + b = c_tab[pi->flag_now[x] + 5]; + if (!pic2_arith_decode_bit(pi, b++)) { + if (pic2_arith_decode_bit(pi, b++)) { /* down */ + pi->vram_next[x ] = cc; + pi->flag_next[x ] = -1; + } else if (pic2_arith_decode_bit(pi, b++)) { /* left */ + pi->vram_next[x - 1] = cc; + pi->flag_next[x - 1] = -2; + } else if (pic2_arith_decode_bit(pi, b++)) { /* right */ + pi->vram_next[x + 1] = cc; + pi->flag_next[x + 1] = -3; + } else if (pic2_arith_decode_bit(pi, b++)) { /* left2 */ + pi->vram_next[x - 2] = cc; + pi->flag_next[x - 2] = -4; + } else { /* right2 */ + pi->vram_next[x + 2] = cc; + pi->flag_next[x + 2] = -5; + } + } +} + +static short pic2_arith_get_number(pi, c, bef) +struct pic2_info *pi; +int c, bef; +{ + unsigned short n; + byte maxcol; + + maxcol = 0xff >> (8 - pi->header->depth / 3); + + n = pic2_arith_decode_nn(pi, c); + if (bef > ((int) maxcol >> 1)) { + if (n > ((int) maxcol - bef) * 2) + n = maxcol - n; + else if (n & 1) + n = n / 2 + bef + 1; + else + n = bef - n / 2; + } else { + if ((int) n > (bef * 2)) + n = n; + else if (n & 1) + n = n / 2 + bef + 1; + else + n = bef - n / 2; + } + return (n); +} + +static pixel pic2_arith_read_color(pi, x) +struct pic2_info *pi; +int x; +{ + pixel c1, c2, cc; + unsigned short i, j, k, m; + short r, g, b, r0, g0, b0; + short colbits; + pixel rmask, gmask, bmask; + byte maxcol; + + colbits = pi->header->depth / 3; + rmask = (0xff >> (8 - colbits)) << (colbits * 2); + gmask = (0xff >> (8 - colbits)) << colbits; + bmask = (0xff >> (8 - colbits)); + maxcol = (byte) bmask; + + c1 = pi->vram_prev[x]; + k = ((c1 >> ((colbits - 3) * 3)) & 0x1c0) + | ((c1 >> ((colbits - 3) * 2)) & 0x038) + | ((c1 >> (colbits - 3) ) & 0x007); + if (colbits == 5) + k = pic2_exchange_rg(k, 3); + + if (pic2_arith_decode_bit(pi, pi->cache_hit_c)) { /* ouch */ + pi->cache_hit_c = 16; + + c2 = pi->vram_now[x - 1]; + r = ((c1 & rmask) + (c2 & rmask)) >> (colbits * 2 + 1); + g = ((c1 & gmask) + (c2 & gmask)) >> (colbits + 1); + b = ((c1 & bmask) + (c2 & bmask)) >> ( 1); + + g0 = pic2_arith_get_number(pi, 32, g); + r = r + g0 - g; + if (r > (short) maxcol) + r = maxcol; + else if (r < 0) + r = 0; + + b = b + g0 - g; + if (b > (short) maxcol) + b = maxcol; + else if (b < 0) + b = 0; + + r0 = pic2_arith_get_number(pi, 48, r); + b0 = pic2_arith_get_number(pi, 64, b); + + pi->cache_pos[k] = j = (pi->cache_pos[k] - 1) & (PIC2_ARITH_CACHE - 1); + pi->cache[k][j] = cc = (r0 << (colbits * 2)) | (g0 << colbits) | b0; + } else { + pi->cache_hit_c = 15; + + j = pic2_arith_decode_nn(pi, 17); + m = pi->cache_pos[k]; + i = (m + j / 2) & (PIC2_ARITH_CACHE - 1); + j = (m + j) & (PIC2_ARITH_CACHE - 1); + + cc = pi->cache[k][j]; + pi->cache[k][j] = pi->cache[k][i]; + pi->cache[k][i] = pi->cache[k][m]; + pi->cache[k][m] = cc; + } + return (cc); +} + +static int pic2_arith_expand_line(pi, line) +struct pic2_info *pi; +pixel **line; +{ + int ymax; + int x, xw; + pixel cc; + + pic2_handle_para(pi, 0); + + xw = pi->block->x_wid; + ymax = pi->block->y_wid - 1; + + if (pi->ynow > ymax) + return (-2); /* end */ + + /* set right end of previous line before left end of current line. */ + if (pi->ynow == 0) { + cc = 0; + } else + cc = pi->vram_prev[xw - 1]; + pi->vram_now[-1] = cc; + + /* clear flag for change point */ + xvbzero((char *) pi->flag_next, xw * sizeof(pi->flag_next[0])); + + /* clear flag for position probability space */ + xvbzero((char *) pi->flag2_next2, xw * sizeof(pi->flag2_next2[0])); + + for (x = 0; x < xw; x++) { + if (pi->flag_now[x] < 0) { + cc = pi->vram_now[x]; + if (pi->ynow < ymax) + pic2_arith_expand_chain(pi, x, pi->ynow, cc); + } else if (pic2_arith_decode_bit(pi, pi->flag2_now[x])) { + /* ajust probability space around of change point */ + pi->flag2_now [x + 1]++; + pi->flag2_now [x + 2]++; + pi->flag2_next [x - 1]++; + pi->flag2_next [x ]++; + pi->flag2_next [x + 1]++; + pi->flag2_next2[x - 1]++; + pi->flag2_next2[x ]++; + pi->flag2_next2[x + 1]++; + + pi->vram_now[x] = cc = pic2_arith_read_color(pi, x); + if (pi->ynow < ymax) + pic2_arith_expand_chain(pi, x, pi->ynow, cc); + } else + pi->vram_now[x] = cc; + } + if (line != NULL) + *line = pi->vram_now; + pi->ynow++; + + pic2_handle_para(pi, 1); + + return (pi->ynow - 1); +} + +static int pic2_arith_loader_init(pi) +struct pic2_info *pi; +{ + unsigned short p2b[256]; + int i, xw; + + pi->ynow = 0; + + /* check the color depth */ + if (pi->header->depth % 3) + pic2_error(pi, PIC2_DEPTH); + + /* set function for extract next line */ + pi->next_line = pic2_arith_expand_line; + + /* clear cache and flags */ + xw = pi->block->x_wid; + xvbzero((char *) pi->cache, 8 * 8 * 8 * sizeof(pi->cache[0])); + xvbzero((char *) pi->cache_pos, 8 * 8 * 8 * sizeof(pi->cache_pos[0])); + + xvbzero((char *) pi->flag_now, xw * sizeof(pi->flag_now[0])); + xvbzero((char *) pi->flag2_now, 8 + xw * sizeof(pi->flag2_now[0])); + xvbzero((char *) pi->flag2_next, 8 + xw * sizeof(pi->flag2_next[0])); + + /* go to picture data field */ + pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET); + + /* clear bit field marker */ + pi->bs.rest = 0; + pi->bs.cur = 0; + + /* read probability table */ + for (i = 0; i < PIC2_ARITH_CONTEXT; i++) + p2b[i] = pic2_read_short(pi); + + /* make multiplication table */ + for (i = 0; i < 16384; i++) { + pi->mulu_tab[i] = (long) (i / 128 + 128) * (int) p2b[i & 127] / 256; + if (pi->mulu_tab[i] == 0) pi->mulu_tab[i] = 1; + } + /* initialize some valuables */ + pi->aa = 0xffff; + pi->dd = 0; + for (i = 0; i < 16; i++) { + pi->dd *= 2; + if (pic2_read_bits(pi, 1)) + pi->dd |= 1; + } + pi->cache_hit_c = 16; + + return (0); +} + +/* + * These functions are fast pic2 compression extractor. + */ +static int pic2_fast_read_length(pi) +struct pic2_info *pi; +{ + int a; + + a = 0; + while (pic2_read_bits(pi, 1)) { + a++; + } + if (a == 0) + return (0); + return (pic2_read_bits(pi, a) + (1 << a) - 1); +} + +static void pic2_fast_expand_chain(pi, x, cc) +struct pic2_info *pi; +int x; +pixel cc; +{ + if (pic2_read_bits(pi, 1) != 0) { + if (pic2_read_bits(pi, 1) != 0) { /* down */ + pi->vram_next[x] = cc; + pi->flag_next[x] = -1; + } else if (pic2_read_bits(pi, 1) != 0) { + if (pic2_read_bits(pi, 1) == 0) { /* left2down */ + pi->vram_next[x - 2] = cc; + pi->flag_next[x - 2] = -1; + } else { /* left1down */ + pi->vram_next[x - 1] = cc; + pi->flag_next[x - 1] = -1; + } + } else { + if (pic2_read_bits(pi, 1) == 0) { /* right2down */ + pi->vram_next[x + 2] = cc; + pi->flag_next[x + 2] = -1; + } else { /* left1down */ + pi->vram_next[x + 1] = cc; + pi->flag_next[x + 1] = -1; + } + } + } +} + +static pixel pic2_fast_read_color(pi, bc) +struct pic2_info *pi; +pixel bc; +{ + pixel cc; + unsigned short j, k, m; + short depth, colbits; + pixel (*cache)[PIC2_FAST_CACHE]; + + depth = pi->header->depth; + colbits = depth / 3; + cache = (pixel (*)[PIC2_FAST_CACHE]) pi->cache; + + bc = pic2_exchange_rg(bc, colbits); + k = pic2_shift_bits(bc, 8 - depth); + if (pic2_read_bits(pi, 1) == 0) { + pi->cache_pos[k] = m = (pi->cache_pos[k] - 1) & (PIC2_FAST_CACHE - 1); + cc = pic2_read_bits(pi, depth); + cc = pic2_exchange_rg(cc, colbits); + cache[k][m] = cc; + } else { + j = pic2_read_bits(pi, 6); /* 6= log2(PIC2_FAST_CACHE) */ + m = pi->cache_pos[k]; + cc = cache[k][(m + j) & (PIC2_FAST_CACHE - 1)]; + } + return (cc); +} + +static int pic2_fast_expand_line(pi, line) +struct pic2_info *pi; +pixel **line; +{ + int ymax; + int x, xw; + pixel cc; + + pic2_handle_para(pi, 0); + + xw = pi->block->x_wid; + ymax = pi->block->y_wid - 1; + + if (pi->ynow > ymax) + return (-2); + + if (pi->ynow == 0) { + pi->dd = 0; + pi->aa = pic2_fast_read_length(pi); + if (pi->aa == 1023) + pi->dd = 1023; + else if (pi->aa > 1023) + pi->aa--; + cc = 0; + } else + cc = pi->vram_prev[xw - 1]; + + xvbzero((char *) pi->flag_next, xw * sizeof(pi->flag_next[0])); + + for (x = 0; x < xw; x++) { + if (pi->dd > 0) { + if (pi->flag_now[x] < 0) { /* on chain ? */ + cc = pi->vram_now[x]; + pic2_fast_expand_chain(pi, x, cc); + if (--pi->dd == 0) { + pi->aa = pic2_fast_read_length(pi); + if (pi->aa == 1023) + pi->dd = 1023; + else if (pi->aa > 1023) + pi->aa--; + } + } else + pi->vram_now[x] = cc; + } else { + if (pi->flag_now[x] < 0) { /* on chain ? */ + cc = pi->vram_now[x]; + pic2_fast_expand_chain(pi, x, cc); + } else if (--pi->aa < 0) { + cc = pi->vram_now[x] = pic2_fast_read_color(pi, cc); + pic2_fast_expand_chain(pi, x, cc); + pi->aa = pic2_fast_read_length(pi); + if (pi->aa == 1023) + pi->dd = 1023; + else if (pi->aa > 1023) + pi->aa--; + } else + pi->vram_now[x] = cc; + } + } + if (line != NULL) + *line = pi->vram_now; + pi->ynow++; + + pic2_handle_para(pi, 1); + + return (pi->ynow - 1); +} + +static int pic2_fast_loader_init(pi) +struct pic2_info *pi; +{ + int xw; + + pi->ynow = 0; + + /* check the color depth */ + if (pi->header->depth % 3) + pic2_error(pi, PIC2_DEPTH); + + /* set function for extract next line */ + pi->next_line = pic2_fast_expand_line; + + /* clear cache and flags */ + xw = pi->block->x_wid; + xvbzero((char *) pi->cache, sizeof(pi->cache[0]) * 256); + xvbzero((char *) pi->cache_pos, sizeof(pi->cache_pos[0]) * 8 * 8 * 8); + xvbzero((char *) pi->flag_now, (xw + 8) * sizeof(pi->flag_now[0])); + xvbzero((char *) pi->flag_next, (xw + 8) * sizeof(pi->flag_next[0])); + + /* go to picture data field */ + pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET); + + /* clear bit field marker */ + pi->bs.rest = 0; + pi->bs.cur = 0; + + return (0); +} + +/* + * These functions are beta pic2 format extractor. + */ +static int pic2_beta_expand_line(pi, line) +struct pic2_info *pi; +pixel **line; +{ + int i, xw, ymax; + byte a, b, c, *p; + pixel *pc; + short depth, pixbyte, colbits; + + depth = pi->header->depth; + pixbyte = depth / 8 + ((depth % 8) > 0); + colbits = depth / 3; + + xw = pi->block->x_wid; + ymax = pi->block->y_wid - 1; + + if (pi->ynow > ymax) + return (-2); /* end */ + + pc = pi->vram_now; + p = (byte *) pi->vram_prev; + if (pixbyte == 3) { + pic2_read_file(pi, pi->vram_prev, (size_t) (xw * pixbyte)); + for (i = 0; i < xw; i++, pc++) { + a = *p++; + b = *p++; + c = *p++; + *pc = ((pixel) a << 16) | ((pixel) b << 8) | (pixel) c; + } + } else if (pixbyte == 2) { + pic2_read_file(pi, pi->vram_prev, (size_t) (xw * 2)); + if (strncmp(pi->block->id, "P2BM", 4) == 0) { + for (i = 0; i < xw; i++, pc++) { + a = *p++; + b = *p++; + *pc = ((pixel) a << 8) | (pixel) b; + if (colbits == 5) { + *pc >>= 1; + *pc = pic2_exchange_rg(*pc, colbits); + } + } + } else { + for (i = 0; i < xw; i++, pc++) { + a = *p++; + b = *p++; + *pc = ((pixel) b << 8) | (pixel) a; + if (colbits == 5) { + *pc >>= 1; + *pc = pic2_exchange_rg(*pc, colbits); + } + } + } + } else { + pic2_read_file(pi, pi->vram_prev, (size_t) xw); + for (i = 0; i < xw; i++) + *pc++ = *p++; + } + if (line != NULL) + *line = pi->vram_now; + + pc = pi->vram_prev; + pi->vram_prev = pi->vram_now; + pi->vram_now = pi->vram_next; + pi->vram_next = pc; + + pi->ynow++; + return (pi->ynow - 1); +} + +static int pic2_beta_loader_init(pi) +struct pic2_info *pi; +{ + pi->ynow = 0; + pi->next_line = pic2_beta_expand_line; + pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET); + return (0); +} + +/* + * Make a picture from the expanded data. + */ +static void pic2_make_xvpic(pi, xp, rp, gp, bp) +struct pic2_info *pi; +byte **xp, *rp, *gp, *bp; +{ + int line, i; + pixel *linep, opaque; + short colbits; + byte colmask; + + if (*xp == NULL) + *xp = pic2_new((size_t) pi->x_max * pi->y_max * 3, "pic2_make_xvpic"); + + if (pi->block->flag & 1) + opaque = pi->block->opaque; + else + opaque = 0xffffffff; + + colbits = pi->header->depth / 3; + colmask = 0xff >> (8 - colbits); + + line = pic2_load_block(pi); + for (;;) { + int pic_idx; + + line = pic2_next_line(pi, &linep); + if (line < 0) + break; + pic_idx = ((line + pi->block->y_offset) * pi->x_max + + pi->block->x_offset) * 3; + + for (i = 0; i < pi->block->x_wid; i++, linep++) { + byte r, g, b; + + if (*linep != opaque) { + r = ((*linep >> (colbits * 2)) & colmask); + r = pic2_convert_color_bits(r, colbits, 8); + g = ((*linep >> colbits ) & colmask); + g = pic2_convert_color_bits(g, colbits, 8); + b = ( *linep & colmask); + b = pic2_convert_color_bits(b, colbits, 8); + (*xp)[pic_idx++] = r; + (*xp)[pic_idx++] = g; + (*xp)[pic_idx++] = b; + } else + pic_idx += 3; + + WaitCursor(); + } + } +} + +/* + * This function splits multi block PIC2 file to several pages. + */ +static void pic2_make_pagefile(pi, pagebname, pnum) +struct pic2_info *pi; +char *pagebname; +int pnum; +{ + struct pic2_info pic2; + FILE *fp; + char pagefile[64], *buf; + size_t imagesize; + + sprintf(pagefile, "%s%d", pagebname, pnum); + if ((fp = fopen(pagefile, "wb")) == NULL) + pic2_error(pi, PIC2_WRITE); + + xvbcopy((char *) pi, (char *) &pic2, sizeof(struct pic2_info)); + pic2.fp = fp; + + pic2_write_header1(&pic2); + + pic2_write_block_header(&pic2); + + imagesize = pi->block->size - PIC2_BLOCK_HEADER_SIZE; + buf = (char *) pic2_malloc(imagesize, "pic2_make_pagefile"); + + pic2_seek_file(pi, pi->block_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET); + if (fread(buf, (size_t) 1, imagesize, pi->fp) < imagesize) { + free(buf); + pic2_file_error(pi, PIC2_CORRUPT); + } + if (fwrite(buf, (size_t) 1, imagesize, fp) < imagesize) { + free(buf); + pic2_error(pi, PIC2_WRITE); + } + free(buf); + + pic2.next_pos = pic2_tell_file(&pic2); + pic2_write_header2(&pic2); + + fclose(fp); +} + +/* The main routine to save a PIC2 file. */ +static int WritePIC2(fp, pic0, ptype, w, h, rmap, gmap, bmap, numcols, + colorstyle, fname, type, depth, x_offset, y_offset, + append, comment) +FILE *fp; +byte *pic0; +int ptype, w, h; +byte *rmap, *gmap, *bmap; +int numcols, colorstyle; +char *fname; +int type, depth; +int x_offset, y_offset; +int append; +char *comment; +{ + struct pic2_info pic2; + char creator[256], title[256], saver[256]; + int e; + + if (DEBUG) + fputs("WritePIC2:\n", stderr); + + pic2_init_info(&pic2); + pic2.fp = fp; + pic2.writing_grey = (colorstyle == F_GREYSCALE); + + if ((e = setjmp(pic2.jmp)) != 0){ + /* When an error occurs while writing, comes here. */ + pic2_free_buffer(&pic2); + pic2_cleanup_pic2_info(&pic2, 1); + SetCursors(-1); + if (DEBUG) + fputs("\n", stderr); + return (-1); + } + sprintf(creator, "XV Version %s", VERSTR); + pic2_strncpy(title, comment, 30); + sprintf(saver, "XV %s/UNIX/Bradley", VERSTR); + + if (!append) { + pic2_setup_pic2_info(&pic2, creator, fname, title, saver, + 0, depth, 1, 1, w, h, comment); + pic2_write_header1(&pic2); + } else { + pic2_read_header(&pic2); + pic2_append(&pic2); + free(pic2.comment); + pic2_setup_pic2_info(&pic2, creator, fname, title, saver, + 0, depth, 1, 1, w, h, comment); + } + + pic2_write_data(&pic2, pic0, ptype, x_offset, y_offset, w, h, + rmap, gmap, bmap, type, depth); + pic2_write_header2(&pic2); + + pic2_cleanup_pic2_info(&pic2, 1); + SetCursors(-1); + if (DEBUG) + fputs("\n", stderr); + return (0); +} + +/* + * This function initializes pic2_info. + */ +static void pic2_setup_pic2_info(pi, name, fname, title, saver, no, depth, + x_aspect, y_aspect, x_max, y_max, comment) +struct pic2_info *pi; +char *name, *fname, *title, *saver; +int no, depth; +int x_aspect, y_aspect; +int x_max, y_max; +char *comment; +{ + char basename[256], *suffix; + + pi->mode = PIC2_WRITE_MODE; + + /* set magic number */ + strncpy(pi->header->magic, pic2_id, 4); + + /* set creator's name */ + pic2_strncpy(pi->header->name, (char *) name, 18); + + /* set title and subtitle */ + pic2_strncpy(pi->header->title, (char *) title, 30); + strcpy(basename, BaseName(fname)); + suffix = (char *) rindex(basename, '.'); + if (suffix) { + suffix++; + if (!strcmp(suffix, "p2") || !strcmp(suffix, "P2")) + *(suffix - 1) = '\0'; + } + pic2_strncpy(pi->header->subtitle, basename, 8); + + /* set saver */ + pic2_strncpy(pi->header->saver, saver, 30); + + /* set picture number */ + pi->header->no = no; + + /* import comment */ + pi->comment = comment; + + /* set some picture's info */ + pi->header->depth = depth; + pi->header->x_aspect = x_aspect; + pi->header->y_aspect = y_aspect; + pi->header->x_max = x_max; + pi->header->y_max = y_max; + + /* set some gaps */ + pi->header->crlf0[0] = pi->header->crlf1[0] = pi->header->crlf2[0] = 0x0d; + pi->header->crlf0[1] = pi->header->crlf1[1] = pi->header->crlf2[1] = 0x0a; + + pi->header->eof[0] = 0x1a; + pi->header->reserve0[0] = 0; + pi->header->reserve1 = 0; + + /* set palettes */ + if (pi->n_pal > 0) + pi->header->flag = 1; + else + pi->header->flag = 0; +} + +/* + * This function appends to existing pic2 file. + */ +static void pic2_append(pi) +struct pic2_info *pi; +{ + int block; + + block = pic2_find_block(pi); + while (block > 0) + block = pic2_next_block(pi); + + if (block != 0) + pic2_error(pi, PIC2_APPEND); +} + +/* + * These functions write the PIC2 header. + * pic2_write_header1: + * write palette data and comment. + * pic2_write_header2: + * write the terminate block and rest header. + * pic2_write_block_header: + * write the block header. + */ +static void pic2_write_header1(pi) +struct pic2_info *pi; +{ + char *comment; + + /* seek to block start position */ + pic2_seek_file(pi, PIC2_HEADER_SIZE, SEEK_SET); + + /* write palette */ + if (pi->n_pal > 0) { + pic2_write_char(pi, pi->pal_bits); + pic2_write_short(pi, pi->n_pal); + pic2_write_file(pi, pi->pal, (size_t) (pi->n_pal * 3)); + } + /* save comment */ + comment = pi->comment; + if (pi->comment != NULL) { + for (comment = pi->comment; *comment; comment++) { + if (*comment == '\n') { + pic2_write_char(pi, '\r'); + pic2_write_char(pi, '\n'); + } else if (*comment != '\r') + pic2_write_char(pi, *comment); + } + pic2_write_char(pi, 0); + } + /* set the next block position */ + pi->next_pos = pic2_tell_file(pi); + pi->header->size = pi->next_pos; +} + +static void pic2_write_header2(pi) +struct pic2_info *pi; +{ + pic2_seek_file(pi, pi->next_pos, SEEK_SET); + + /* write terminate block */ + pic2_write_long(pi, 0); + pic2_write_long(pi, 0); + + /* set some header information */ + if (pi->header->x_max < pi->x_max) + pi->header->x_max = pi->x_max; + if (pi->header->y_max < pi->x_max) + pi->header->y_max = pi->y_max; + + pi->header->time = time(NULL); + pic2_seek_file(pi, 0, SEEK_SET); + + /* write header image */ + pic2_write_file(pi, pi->header->magic, 4); + pic2_write_file(pi, pi->header->name, 18); + pic2_write_file(pi, pi->header->subtitle, 8); + pic2_write_file(pi, pi->header->crlf0, 2); + pic2_write_file(pi, pi->header->title, 30); + pic2_write_file(pi, pi->header->crlf1, 2); + pic2_write_file(pi, pi->header->saver, 30); + pic2_write_file(pi, pi->header->crlf2, 2); + pic2_write_file(pi, pi->header->eof, 1); + pic2_write_file(pi, pi->header->reserve0, 1); + pic2_write_short(pi, pi->header->flag); + pic2_write_short(pi, pi->header->no); + pic2_write_long(pi, pi->header->time); + pic2_write_long(pi, pi->header->size); + pic2_write_short(pi, pi->header->depth); + pic2_write_short(pi, pi->header->x_aspect); + pic2_write_short(pi, pi->header->y_aspect); + pic2_write_short(pi, pi->header->x_max); + pic2_write_short(pi, pi->header->y_max); + pic2_write_long(pi, pi->header->reserve1); +} + +static void pic2_write_block_header(pi) +struct pic2_info *pi; +{ + pic2_write_file(pi, pi->block->id, 4); + pic2_write_long(pi, pi->block->size); + pic2_write_short(pi, pi->block->flag); + pic2_write_short(pi, pi->block->x_wid); + pic2_write_short(pi, pi->block->y_wid); + pic2_write_short(pi, pi->block->x_offset); + pic2_write_short(pi, pi->block->y_offset); + pic2_write_long(pi, pi->block->opaque); + pic2_write_long(pi, pi->block->reserve); +} + +/* + * These functions are arithmetric format compressor. + */ +#define pic2_arith_write_one_bit(pi) (pi->bs.bits++) + +static void pic2_arith_write_zero_bit(pi) +struct pic2_info *pi; +{ + if (pi->bs.zero) + pic2_write_bits(pi, 0, 1); + + while (pi->bs.bits--) + pic2_write_bits(pi, 1, 1); + + pi->bs.bits = 0; + pi->bs.zero = 1; +} + +static void pic2_arith_flush_bit_buf(pi) +struct pic2_info *pi; +{ + int i; + + for (i = 0; i < 16; i++) { + if (pi->cc & 0x8000) + pic2_arith_write_one_bit(pi); + else + pic2_arith_write_zero_bit(pi); + pi->cc <<= 1; + } + pic2_arith_write_zero_bit(pi); + pic2_flush_bits(pi); +} + +static void pic2_arith_carry_bit(pi) +struct pic2_info *pi; +{ + pic2_write_bits(pi, 1, 1); + + if (pi->bs.bits == 0) { + pi->bs.zero = 0; + } else { + while (--pi->bs.bits) + pic2_write_bits(pi, 0, 1); + pi->bs.zero = 1; + } +} + +static void pic2_arith_encode_bit(pi, n, c) +struct pic2_info *pi; +int n, c; +{ + int pp; + long *c_sum, *c_0_sum; + + c_sum = (long *) pi->mulu_tab; + c_0_sum = c_sum + PIC2_ARITH_CONTEXT + 1; + + if (pi->dd == 0) { + c_sum[c]++; + if (n == 0) + c_0_sum[c]++; + return; + } + pp = pi->mulu_tab[(pi->aa & 0x7f00) / 2 + c]; + if (n != 0) { + pi->cc = pi->cc + pp; + if (pi->cc > 0xffff) { + pic2_arith_carry_bit(pi); + pi->cc = pi->cc & 0xffff; + } + pi->aa = pi->aa - pp; + while (pi->aa < 0x8000) { + if (pi->cc & 0x8000) + pic2_arith_write_one_bit(pi); + else + pic2_arith_write_zero_bit(pi); + pi->cc = (pi->cc * 2) & 0xffff; + pi->aa = pi->aa * 2; + } + } else { + pi->aa = pp; + + while (pi->aa < 0x8000) { + if (pi->cc & 0x8000) + pic2_arith_write_one_bit(pi); + else + pic2_arith_write_zero_bit(pi); + pi->cc = (pi->cc * 2) & 0xffff; + pi->aa = pi->aa * 2; + } + } +} + +static void pic2_arith_encode_nbyte(pi, n, c, max) +struct pic2_info *pi; +int n, c, max; +{ + short i; + + for (i = 0; i < n; i++) { + pic2_arith_encode_bit(pi, 0, c + i); + } + if (n < max) + pic2_arith_encode_bit(pi, 1, c + n); +} + +static void pic2_arith_encode_nn(pi, n, c) +struct pic2_info *pi; +int n, c; +{ + if (n < 1) { + pic2_arith_encode_bit(pi, 1, c); + } else if (n < 1 + 2) { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 1, c + 1); + n -= 1; + pic2_arith_encode_bit(pi, n & 1, c + 8); + } else if (n < 1 + 2 + 4) { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 0, c + 1); + pic2_arith_encode_bit(pi, 1, c + 2); + n -= 1 + 2; + pic2_arith_encode_bit(pi, n & 1, c + 8); + pic2_arith_encode_bit(pi, n & 2, c + 9); + } else if (n < 1 + 2 + 4 + 8) { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 0, c + 1); + pic2_arith_encode_bit(pi, 0, c + 2); + pic2_arith_encode_bit(pi, 1, c + 3); + n -= 1 + 2 + 4; + pic2_arith_encode_bit(pi, n & 1, c + 8); + pic2_arith_encode_bit(pi, n & 2, c + 9); + pic2_arith_encode_bit(pi, n & 4, c + 10); + } else if (n < 1 + 2 + 4 + 8 + 16) { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 0, c + 1); + pic2_arith_encode_bit(pi, 0, c + 2); + pic2_arith_encode_bit(pi, 0, c + 3); + pic2_arith_encode_bit(pi, 1, c + 4); + n -= 1 + 2 + 4 + 8; + pic2_arith_encode_bit(pi, n & 1, c + 8); + pic2_arith_encode_bit(pi, n & 2, c + 9); + pic2_arith_encode_bit(pi, n & 4, c + 10); + pic2_arith_encode_bit(pi, n & 8, c + 11); + } else if (n < 1 + 2 + 4 + 8 + 16 + 32) { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 0, c + 1); + pic2_arith_encode_bit(pi, 0, c + 2); + pic2_arith_encode_bit(pi, 0, c + 3); + pic2_arith_encode_bit(pi, 0, c + 4); + pic2_arith_encode_bit(pi, 1, c + 5); + n -= 1 + 2 + 4 + 8 + 16; + pic2_arith_encode_bit(pi, n & 1, c + 8); + pic2_arith_encode_bit(pi, n & 2, c + 9); + pic2_arith_encode_bit(pi, n & 4, c + 10); + pic2_arith_encode_bit(pi, n & 8, c + 11); + pic2_arith_encode_bit(pi, n & 16, c + 12); + } else if (n < 1 + 2 + 4 + 8 + 16 + 32 + 64) { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 0, c + 1); + pic2_arith_encode_bit(pi, 0, c + 2); + pic2_arith_encode_bit(pi, 0, c + 3); + pic2_arith_encode_bit(pi, 0, c + 4); + pic2_arith_encode_bit(pi, 0, c + 5); + pic2_arith_encode_bit(pi, 1, c + 6); + n -= 1 + 2 + 4 + 8 + 16 + 32; + pic2_arith_encode_bit(pi, n & 1, c + 8); + pic2_arith_encode_bit(pi, n & 2, c + 9); + pic2_arith_encode_bit(pi, n & 4, c + 10); + pic2_arith_encode_bit(pi, n & 8, c + 11); + pic2_arith_encode_bit(pi, n & 16, c + 12); + pic2_arith_encode_bit(pi, n & 32, c + 13); + } else if (n < 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128) { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 0, c + 1); + pic2_arith_encode_bit(pi, 0, c + 2); + pic2_arith_encode_bit(pi, 0, c + 3); + pic2_arith_encode_bit(pi, 0, c + 4); + pic2_arith_encode_bit(pi, 0, c + 5); + pic2_arith_encode_bit(pi, 0, c + 6); + pic2_arith_encode_bit(pi, 1, c + 7); + n -= 1 + 2 + 4 + 8 + 16 + 32 + 64; + pic2_arith_encode_bit(pi, n & 1, c + 8); + pic2_arith_encode_bit(pi, n & 2, c + 9); + pic2_arith_encode_bit(pi, n & 4, c + 10); + pic2_arith_encode_bit(pi, n & 8, c + 11); + pic2_arith_encode_bit(pi, n & 16, c + 12); + pic2_arith_encode_bit(pi, n & 32, c + 13); + pic2_arith_encode_bit(pi, n & 64, c + 14); + } else { + pic2_arith_encode_bit(pi, 0, c); + pic2_arith_encode_bit(pi, 0, c + 1); + pic2_arith_encode_bit(pi, 0, c + 2); + pic2_arith_encode_bit(pi, 0, c + 3); + pic2_arith_encode_bit(pi, 0, c + 4); + pic2_arith_encode_bit(pi, 0, c + 5); + pic2_arith_encode_bit(pi, 0, c + 6); + pic2_arith_encode_bit(pi, 0, c + 7); + } +} + +static void pic2_arith_press_chain(pi, x) +struct pic2_info *pi; +int x; +{ + int b, d; + pixel c; + + b = -(pi->flag_now[x]); + c = pi->vram_now[x]; + d = 0; + + if (b < 0) + b = 0; + + if (pi->flag_next[x] == 1 && pi->vram_next[x] == c) { + d = 1; + pi->flag_next[x] = -1; + } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == c) { + d = 2; + pi->flag_next[x - 1] = -2; + } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == c) { + d = 3; + pi->flag_next[x + 1] = -3; + } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == c) { + d = 4; + pi->flag_next[x - 2] = -4; + } else if (pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == c) { + if ((pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == c) + || (pi->flag_now[x + 1] != 0 && pi->vram_now[x + 1] == c) + || (pi->flag_now[x + 3] != 0 && pi->vram_now[x + 3] == c)) { + pic2_arith_encode_nbyte(pi, 0, 80 + 6 * b, 5); + return; + } + d = 5; + pi->flag_next[x + 2] = -5; + } + pic2_arith_encode_nbyte(pi, d, 80 + 6 * b, 5); +} + +static void pic2_arith_put_number(pi, xn, xa, xb) +struct pic2_info *pi; +int xn, xa, xb; +{ + short n; + byte maxcol; + + maxcol = 0xff >> (8 - pi->header->depth / 3); + + if (xa > ((int) maxcol >> 1)) { + if (xb > xa) + n = (xb - xa) * 2 - 1; + else if (xa - ((int) maxcol - xa) > xb) + n = maxcol - xb; + else + n = (xa - xb) * 2; + } else { + if (xb <= xa) + n = (xa - xb) * 2; + else if (2 * xa < xb) + n = xb; + else + n = (xb - xa) * 2 - 1; + } + pic2_arith_encode_nn(pi, n, xn); +} + +static void pic2_arith_write_color(pi, x) +struct pic2_info *pi; +int x; +{ + pixel c1, c2, cc; + short g0, r0, b0, r, g, b; + int i, j; + unsigned short k; + pixel *p, *pp; + short colbits; + pixel rmask, gmask, bmask; + byte maxcol; + + colbits = pi->header->depth / 3; + rmask = (0xff >> (8 - colbits)) << (colbits * 2); + gmask = (0xff >> (8 - colbits)) << colbits; + bmask = (0xff >> (8 - colbits)); + maxcol = (byte) bmask; + + cc = pi->vram_now[x]; + c1 = pi->vram_prev[x]; + k = ((c1 >> ((colbits - 3) * 3)) & 0x1c0) + | ((c1 >> ((colbits - 3) * 2)) & 0x038) + | ((c1 >> (colbits - 3) ) & 0x007); + if (colbits == 5) + k = pic2_exchange_rg(k, 3); + + p = pi->cache[k]; + for (i = 0; i < (PIC2_ARITH_CACHE - 1); i++) { + if (cc == *p++) + break; + } + if (i == (PIC2_ARITH_CACHE - 1)) { + pp = p - 1; + for (j = i; j > 0; j--) { + *--p = *--pp; + } + pi->cache[k][0] = cc; + pic2_arith_encode_bit(pi, 1, pi->cache_hit_c); + pi->cache_hit_c = 16; + + c2 = pi->vram_now[x - 1]; + r = ((c1 & rmask) + (c2 & rmask)) >> (colbits * 2 + 1); + g = ((c1 & gmask) + (c2 & gmask)) >> (colbits + 1); + b = ((c1 & bmask) + (c2 & bmask)) >> ( 1); + + r0 = (cc >> (colbits * 2)) & maxcol; + g0 = (cc >> colbits ) & maxcol; + b0 = cc & maxcol; + + r = r + g0 - g; + if (r < 0) + r = 0; + else if (r > (short) maxcol) + r = maxcol; + + b = b + g0 - g; + if (b < 0) + b = 0; + else if (b > (short) maxcol) + b = maxcol; + + pic2_arith_put_number(pi, 32, g, g0); + pic2_arith_put_number(pi, 48, r, r0); + pic2_arith_put_number(pi, 64, b, b0); + } else { + *--p = pi->cache[k][i / 2]; + pi->cache[k][i / 2] = pi->cache[k][0]; + pi->cache[k][0] = cc; + + pic2_arith_encode_bit(pi, 0, pi->cache_hit_c); + pi->cache_hit_c = 15; + pic2_arith_encode_nn(pi, i, 17); + } +} + +static void pic2_arith_press_line2(pi) +struct pic2_info *pi; +{ + int x, xw, ymax; + pixel cc; + + xw = pi->block->x_wid; + ymax = pi->block->y_wid -1; + cc = pi->vram_now[xw - 1]; /* last color */ + pi->vram_next[-1] = cc; + + /* mark change point */ + for (x = 0; x < xw; x++) + if (cc != pi->vram_next[x]) { + pi->flag_next[x] = 1; + cc = pi->vram_next[x]; + } else + pi->flag_next[x] = 0; + + for (x = 0; x < xw; x++) { + if (pi->flag_now[x] == 1) { /* change point */ + pi->flag2_now [x + 1]++; + pi->flag2_now [x + 2]++; + pi->flag2_next [x - 1]++; + pi->flag2_next [x ]++; + pi->flag2_next [x + 1]++; + pi->flag2_next2[x - 1]++; + pi->flag2_next2[x ]++; + pi->flag2_next2[x + 1]++; + + /* write change point */ + pic2_arith_encode_bit(pi, 1, pi->flag2_now[x]); + + /* write color */ + pic2_arith_write_color(pi, x); + + /* if not last line, write chain */ + if (pi->ynow - 1 < ymax) + pic2_arith_press_chain(pi, x); + } else if (pi->flag_now[x] == 0) /* not on chain */ + /* write change point */ + pic2_arith_encode_bit(pi, 0, pi->flag2_now[x]); + else /* on chain */ + /* if not on last line, write next chain */ + if (pi->ynow - 1 < ymax) + pic2_arith_press_chain(pi, x); + } +} + +static int pic2_arith_press_line(pi, line) +struct pic2_info *pi; +pixel **line; +{ + int i, xw, ymax; + long *c_sum, *c_0_sum; + + xw = pi->block->x_wid; + ymax = pi->block->y_wid -1; + c_sum = (long *) pi->mulu_tab; + c_0_sum = c_sum + PIC2_ARITH_CONTEXT +1; + + pic2_handle_para(pi, 0); + + xvbzero((char *) pi->flag2_next2 - 4, + (8 + xw) * sizeof(pi->flag2_next2[0])); + + if (pi->ynow == 0) { /* first line */ + int x; + pixel cc = 0; + + if (pi->dd != 0) { /* compress pass */ + unsigned short c_tab[PIC2_ARITH_CONTEXT]; + + for (i = 0; i < PIC2_ARITH_CONTEXT; i++) { + unsigned long a, b; + a = c_0_sum[i]; + b = c_sum[i]; + while (a > 32767) { + a /= 2; + b /= 2; + } + if (a == b) + c_tab[i] = 0xffff; /* b==0 here, too */ + else + c_tab[i] = (65536 * a) / b; /* a < b, so less 65536 */ + } + for (i = 0; i < 16384; i++) { + pi->mulu_tab[i] = (long) (i / 128 + 128) * (int) c_tab[i & 127] / 256; + if (pi->mulu_tab[i] == 0) + pi->mulu_tab[i] = 1; /* 0 is wrong */ + } + for (i = 0; i < PIC2_ARITH_CONTEXT; i++) + pic2_write_short(pi, c_tab[i]); + + xvbzero((char *) pi->vram_now, xw * sizeof(pi->vram_now[0])); + } else { /* statistical pass */ + xvbzero((char *) c_0_sum, PIC2_ARITH_CONTEXT * sizeof(c_0_sum[0])); + xvbzero((char *) c_sum, PIC2_ARITH_CONTEXT * sizeof(c_sum[0])); + } + + /* initialize flags */ + xvbzero((char *) pi->cache, 8 * 8 * 8 * sizeof(pi->cache[0])); + xvbzero((char *) pi->cache_pos, 8 * 8 * 8 * sizeof(pi->cache_pos[0])); + + xvbzero((char *) pi->flag2_next - 4, + (8 + xw) * sizeof(pi->flag2_next[0])); + xvbzero((char *) pi->flag2_next2 - 4, + (8 + xw) * sizeof(pi->flag2_next2[0])); + + pi->vram_next[-1] = cc; + for (x = 0; x < xw; x++) + if (cc != pi->vram_next[x]) { + pi->flag_next[x] = 1; + cc = pi->vram_next[x]; + } else + pi->flag_next[x] = 0; + + pi->aa = 0xffff; + cc = 0; + pi->cache_hit_c = 16; + } else /* after second line */ + pic2_arith_press_line2(pi); + + if (pi->ynow == ymax) { + pi->ynow++; + pic2_handle_para(pi, 1); + pic2_handle_para(pi, 0); + pic2_arith_press_line2(pi); + } + /* line buffer for next data */ + if (line != NULL) + *line = pi->vram_prev; + + pi->ynow++; + + if (pi->ynow - 1 < ymax) { + pic2_handle_para(pi, 1); + return (pi->ynow); + } else { /* end */ + if (pi->dd == 0) { /* statistical pass */ + pi->dd = 1; + pi->ynow = 0; + pic2_handle_para(pi, 1); + return (0); + } else { + pic2_handle_para(pi, 1); + pic2_arith_flush_bit_buf(pi); + return (-2); /* end */ + } + } +} + +static int pic2_arith_saver_init(pi, line) +struct pic2_info *pi; +pixel **line; +{ + pi->ynow = 0; + + /* check the color depth */ + if (pi->header->depth % 3) + pic2_error(pi, PIC2_DEPTH); + + /* set next line function */ + pi->next_line = pic2_arith_press_line; + + if (line != NULL) + *line = pi->vram_next + 4; + + pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET); + + /* clear bit field marker */ + pi->bs.rest = 0; + pi->bs.cur = 0; + pi->bs.zero = 0; + pi->bs.bits = 0; + + return (0); +} + +/* + * These functions are fast pic2 format compressor. + */ +static void pic2_fast_write_length(pi, n) +struct pic2_info *pi; +int n; +{ + int a, b; + static const unsigned short len_data[8][2] = { + {1, 0}, + {1, 0}, + {3, 4}, + {3, 5}, + {5, 24}, + {5, 25}, + {5, 26}, + {5, 27}, + }; + + n++; + if (n < 8) + pic2_write_bits(pi, len_data[n][1], len_data[n][0]); + else { + a = 0; + b = 2; + while (n > b - 1) { + a = a + 1; + b = b * 2; + } + pic2_write_bits(pi, 0xfffffffe, a + 1); + if (a > 0) + pic2_write_bits(pi, n - b / 2, a); + } +} + +static void pic2_fast_press_chain(pi, x) +struct pic2_info *pi; +int x; +{ + int ymax; + pixel cc; + + ymax = pi->block->y_wid -1; + cc = pi->vram_now[x]; + + if (pi->ynow - 1 == ymax) { + pic2_write_bits(pi, 0, 1); + return; + } + if (pi->flag_next[x] == 1 && pi->vram_next[x] == cc) { + pi->flag_next[x] = -1; + pic2_write_bits(pi, 3, 2); + } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == cc) { + pi->flag_next[x - 1] = -1; + pic2_write_bits(pi, 11, 4); + } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == cc) { + pi->flag_next[x + 1] = -1; + pic2_write_bits(pi, 9, 4); + } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == cc) { + pi->flag_next[x - 2] = -1; + pic2_write_bits(pi, 10, 4); + } else if ((pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == cc) + && !(pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == cc)) { + pi->flag_next[x + 2] = -1; + pic2_write_bits(pi, 8, 4); + } else + pic2_write_bits(pi, 0, 1); +} + +static void pic2_fast_press_chain2(pi, x) +struct pic2_info *pi; +int x; +{ + int ymax; + pixel cc; + char *chain_buff; + + ymax = pi->block->y_wid -1; + chain_buff = (char *) pi->mulu_tab; + cc = pi->vram_now[x]; + + if (pi->ynow - 1 == ymax) { + chain_buff[pi->cc++] = 0; + return; + } + if (pi->flag_next[x] == 1 && pi->vram_next[x] == cc) { + pi->flag_next[x] = -1; + chain_buff[pi->cc++] = 1; + } else if (pi->flag_next[x - 1] == 1 && pi->vram_next[x - 1] == cc) { + pi->flag_next[x - 1] = -1; + chain_buff[pi->cc++] = 2; + } else if (pi->flag_next[x + 1] == 1 && pi->vram_next[x + 1] == cc) { + pi->flag_next[x + 1] = -1; + chain_buff[pi->cc++] = 3; + } else if (pi->flag_next[x - 2] == 1 && pi->vram_next[x - 2] == cc) { + pi->flag_next[x - 2] = -1; + chain_buff[pi->cc++] = 4; + } else if ((pi->flag_next[x + 2] == 1 && pi->vram_next[x + 2] == cc) + && !(pi->flag_now[x + 2] != 0 && pi->vram_now[x + 2] == cc)) { + pi->flag_next[x + 2] = -1; + chain_buff[pi->cc++] = 5; + } else + chain_buff[pi->cc++] = 0; +} + +static void pic2_fast_flush_chain(pi) +struct pic2_info *pi; +{ + int i; + char *chain_buf; + + chain_buf = (char *) pi->mulu_tab; + for (i = 0; i < pi->cc; i++){ + switch (chain_buf[i]) { + case 0: + pic2_write_bits(pi, 0, 1); + break; + case 1: + pic2_write_bits(pi, 3, 2); + break; + case 2: + pic2_write_bits(pi, 11, 4); + break; + case 3: + pic2_write_bits(pi, 9, 4); + break; + case 4: + pic2_write_bits(pi, 10, 4); + break; + case 5: + pic2_write_bits(pi, 8, 4); + break; + } + } + pi->cc = 0; +} + +static void pic2_fast_write_color(pi, x) +struct pic2_info *pi; +int x; +{ + pixel cc, bc; + unsigned short j, k, m; + short depth, colbits; + pixel (*cache)[PIC2_FAST_CACHE]; + + depth = pi->header->depth; + colbits = depth / 3; + cache = (pixel (*)[PIC2_FAST_CACHE]) pi->cache; + + bc = pi->vram_now[x - 1]; + bc = pic2_exchange_rg(bc, colbits); + k = pic2_shift_bits(bc, 8 - depth); + cc = pi->vram_now[x]; + m = pi->cache_pos[k]; + + for (j = 0; j < PIC2_FAST_CACHE; j++) + if (cache[k][(m + j) & (PIC2_FAST_CACHE - 1)] == cc) + break; + + if (j == PIC2_FAST_CACHE) { + m = (m - 1) & (PIC2_FAST_CACHE - 1); + pi->cache_pos[k] = m; + cache[k][m] = cc; + + cc = pic2_exchange_rg(cc, colbits); + pic2_write_bits(pi, 0, 1); + pic2_write_bits(pi, cc, depth); + } else { + pic2_write_bits(pi, 1, 1); + pic2_write_bits(pi, j, 6); + } +} + +static void pic2_fast_press_line2(pi) +struct pic2_info *pi; +{ + int x, xw; + pixel cc; + + xw = pi->block->x_wid; + cc = pi->vram_now[xw - 1]; /* last color */ + pi->vram_next[-1] = cc; + + /* mark change point */ + for (x = 0; x < xw; x++) + if (cc != pi->vram_next[x]) { + pi->flag_next[x] = 1; + cc = pi->vram_next[x]; + } else + pi->flag_next[x] = 0; + + for (x = 0; x < xw; x++) + if (pi->flag_now[x] == 1) { /* change point */ + if (pi->aa >= 1023) + pi->aa++; + pic2_fast_write_length(pi, pi->aa); + pic2_fast_flush_chain(pi); + pi->aa = 0; + pic2_fast_write_color(pi, x); + pic2_fast_press_chain(pi, x); + } else if (pi->flag_now[x] == 0) { + pi->aa++; + } else { + pic2_fast_press_chain2(pi, x); + if (pi->cc == 1023) { + pic2_fast_write_length(pi, 1023); + pic2_fast_flush_chain(pi); + pi->aa = 0; + } + } +} + +static int pic2_fast_press_line(pi, line) +struct pic2_info *pi; +pixel **line; +{ + int xw, ymax; + + xw = pi->block->x_wid; + ymax = pi->block->y_wid -1; + + pic2_handle_para(pi, 0); + + if (pi->ynow == 0) { /* first line */ + int x; + pixel cc = 0; + + /* initialize flags */ + xvbzero((char *) pi->cache, 256 * sizeof(pi->cache[0])); + xvbzero((char *) pi->cache_pos, + PIC2_FAST_CACHE * sizeof(pi->cache_pos[0])); + + /* mark change point */ + pi->vram_next[-1] = cc; + for (x = 0; x < xw; x++) + if (cc != pi->vram_next[x]) { + pi->flag_next[x] = 1; + cc = pi->vram_next[x]; + } else + pi->flag_next[x] = 0; + + pi->cc = 0; + pi->aa = 0; + } else /* after second line */ + pic2_fast_press_line2(pi); + + if (pi->ynow == ymax) { + pi->ynow++; + pic2_handle_para(pi, 1); + pic2_handle_para(pi, 0); + pic2_fast_press_line2(pi); + } + /* line buffer for next data */ + if (line != NULL) + *line = pi->vram_prev; + + pi->ynow++; + + if (pi->ynow - 1 < ymax) { + pic2_handle_para(pi, 1); + return (pi->ynow); + } else { /* end */ + pic2_handle_para(pi, 1); + if (pi->aa >= 1023) + pi->aa++; + pic2_fast_write_length(pi, pi->aa); + pic2_fast_flush_chain(pi); + return (-2); /* end */ + } +} + +static int pic2_fast_saver_init(pi, line) +struct pic2_info *pi; +pixel **line; +{ + pi->ynow = 0; + + /* check the color depth */ + if (pi->header->depth % 3) + pic2_error(pi, PIC2_DEPTH); + + /* set next line function */ + pi->next_line = pic2_fast_press_line; + if (line != NULL) + *line = pi->vram_next + 4; + + pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET); + + /* clear bit field marker */ + pi->bs.rest = 0; + pi->bs.cur = 0; + + return (0); +} + +/* + * These functions are beta pic2 format compressor. + */ +static int pic2_beta_press_line(pi, line) +struct pic2_info *pi; +pixel **line; +{ + int i, xw, ymax; + byte *p; + pixel *pc; + short depth, pixbyte, colbits; + + depth = pi->header->depth; + pixbyte = depth / 8 + ((depth % 8) > 0); + colbits = depth / 3; + + xw = pi->block->x_wid; + ymax = pi->block->y_wid - 1; + + pc = pi->vram_now; + p = (byte *) pi->vram_prev; + if (pixbyte == 3) { + for (i = 0; i < xw; i++, pc++) { + *p++ = *pc >> 16; + *p++ = *pc >> 8; + *p++ = *pc; + } + pic2_write_file(pi, pi->vram_prev, (size_t) (xw * 3)); + } else if (pixbyte == 2) { + if (strncmp(pi->block->id, "P2BM", 4) == 0) + for (i = 0; i < xw; i++, pc++) { + if (colbits == 5) { + *pc = pic2_exchange_rg(*pc, colbits); + *pc <<= 1; + } + *p++ = *pc >> 8; + *p++ = *pc; + } + else + for (i = 0; i < xw; i++, pc++) { + if (colbits == 5) { + *pc = pic2_exchange_rg(*pc, colbits); + *pc <<= 1; + } + *p++ = *pc; + *p++ = *pc >> 8; + } + pic2_write_file(pi, pi->vram_prev, (size_t) (xw * 2)); + } else { + for (i = 0; i < xw; i++, pc++) + *p++ = *pc; + pic2_write_file(pi, pi->vram_prev, (size_t) xw); + } + if (line != NULL) + *line = pi->vram_now; + + pi->ynow++; + if (pi->ynow > ymax) + return (-2); + return (pi->ynow); +} + +static int pic2_beta_saver_init(pi, line) +struct pic2_info *pi; +pixel **line; +{ + pi->ynow = 0; + + *line = pi->vram_now; + pi->next_line = pic2_beta_press_line; + pic2_seek_file(pi, pi->next_pos + PIC2_BLOCK_HEADER_SIZE, SEEK_SET); + return (0); +} + +/* + * This function saves compressed data. + */ +static void pic2_write_data(pi, data, ptype, x_offset, y_offset, w, h, + rmap, gmap, bmap, type, depth) +struct pic2_info *pi; +byte *data; +int ptype; +int x_offset, y_offset; +int w, h; +byte *rmap, *gmap, *bmap; +int type, depth; +{ + int i, line; + pixel *linep; + short colbits; + + colbits = pi->header->depth / 3; + + line = pic2_save_block(pi, &linep, x_offset, y_offset, w, h, + form_tab[type].id, 0xffffffff); + while (line >= 0) { + byte r, g, b; + int pic_idx; + + pic_idx = line * w * ((ptype == PIC24) ? 3 : 1); + + for (i = 0; i < w; i++) { + if (ptype != PIC24) { + r = rmap[data[pic_idx]]; + g = gmap[data[pic_idx]]; + b = bmap[data[pic_idx]]; + pic_idx++; + } else { + r = data[pic_idx++]; + g = data[pic_idx++]; + b = data[pic_idx++]; + } + if (pi->writing_grey) + r = g = b = MONO(r, g, b); + + r = pic2_convert_color_bits(r, 8, colbits); + g = pic2_convert_color_bits(g, 8, colbits); + b = pic2_convert_color_bits(b, 8, colbits); + + linep[i] = ((pixel) r << (colbits * 2)) + | ((pixel) g << colbits ) + | ((pixel) b ); + } + line = pic2_next_line(pi, &linep); + WaitCursor(); + } +} + +/* + * This function compress/extract one line buffer. + */ +static int pic2_next_line(pi, line) +struct pic2_info *pi; +pixel **line; +{ + int res; + + res = pi->next_line(pi, line); + if (res == -2) { + if (pi->mode == PIC2_WRITE_MODE) { + long new_pos; + + new_pos = pic2_tell_file(pi); + pi->block->size = new_pos - pi->next_pos; + pic2_seek_file(pi, pi->next_pos, SEEK_SET); + pic2_write_block_header(pi); + pi->next_pos = new_pos; + if (DEBUG) + pic2_show_pic2_info(pi); + } + pic2_free_buffer(pi); + } + return (res); +} + +/* + * These functions find the pic2 image block. + * pic2_next_block: + * moves the file pointer to the next image block. + * pic2_find_block: + * find the first image block and move the file pointer to there. + */ +static int pic2_next_block(pi) +struct pic2_info *pi; +{ + int i; + + if (pi->mode != PIC2_READ_MODE) + return (-1); + + /* go to block for read */ + pic2_seek_file(pi, pi->next_pos, SEEK_SET); + + /* read the head of block header */ + pic2_read_block_header1(pi); + + /* end block ? */ + if (pi->block->id[0] == 0) + return (0); + + /* set current block */ + pi->block_pos = pi->next_pos; + + /* set next block */ + pi->next_pos += pi->block->size; + + /* check block id */ + for (i = 0; i < n_form_tab; i++) { + if (xvbcmp(pi->block->id, form_tab[i].id, (size_t) 4) == 0) + break; + } + if (i == n_form_tab) + return (2); + + /* read the rest of block header */ + pic2_read_block_header2(pi); + + if (pi->block->x_offset + pi->block->x_wid > pi->x_max) + pi->x_max = pi->block->x_offset + pi->block->x_wid; + + if (pi->block->y_offset + pi->block->y_wid > pi->y_max) + pi->y_max = pi->block->y_offset + pi->block->y_wid; + + if (DEBUG) + pic2_show_pic2_info(pi); + return (1); +} + +static int pic2_find_block(pi) +struct pic2_info *pi; +{ + if (pi->mode != PIC2_READ_MODE) + return (-1); + + pi->next_pos = pi->header->size; + return (pic2_next_block(pi)); +} + +/* + * These functions load/save the pic2 image block. + * pic2_load_block: + * initializes loader informations by current block information. + * pic2_save_block: + * initializes saver informations. + */ +static int pic2_load_block(pi) +struct pic2_info *pi; +{ + int i; + + for (i = 0; i < n_form_tab; i++) { + if (xvbcmp(pi->block->id, form_tab[i].id, (size_t) 4) == 0) + break; + } + if (i == n_form_tab) + return (2); + + pic2_alloc_buffer(pi); + return (form_tab[i].loader_init(pi)); +} + +static int pic2_save_block(pi, line, x, y, xw, yw, id, opaque) +struct pic2_info *pi; +pixel **line; +int x, y, xw, yw; +char *id; +pixel opaque; +{ + int i; + + for (i = 0; i < n_form_tab; i++) { + if (xvbcmp(id, form_tab[i].id, (size_t) 4) == 0) + break; + } + if (i == n_form_tab) + return (2); + + strncpy(pi->block->id, id, 4); + pi->block->x_wid = xw; + pi->block->y_wid = yw; + pi->block->x_offset = x; + pi->block->y_offset = y; + pi->block->reserve = 0; + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (x + xw > pi->x_max) + pi->x_max = x + xw; + if (y + yw > pi->y_max) + pi->y_max = y + yw; + + if (opaque != 0xffffffff) { + pi->block->flag = 1; + pi->block->opaque = opaque; + } else { + pi->block->flag = 0; + pi->block->opaque = 0; + } + pic2_alloc_buffer(pi); + + return (form_tab[i].saver_init(pi, line)); +} + +/* + * These functions set/get palettes. + * pic2_read_palette: + * copy the palettes from pic2_info to PICINFO. + * pic2_write_palette: + * copy the palettes from PICINFO to pic2_info. + */ +#ifndef PIC2_IGNORE_UNUSED_FUNCTIONS +static void pic2_read_palette(pi, r, g, b) +struct pic2_info *pi; +byte *r, *g, *b; +{ + int i; + + if (pi->n_pal > 256) + pi->n_pal = 256; + + if (pi->pal_bits > 8) + pi->pal_bits = 8; + + for (i = 0; i < pi->n_pal; i++) { + *r++ =pic2_convert_color_bits(pi->pal[i][0] >> (8 - pi->pal_bits), + pi->pal_bits, 8); + *g++ =pic2_convert_color_bits(pi->pal[i][1] >> (8 - pi->pal_bits), + pi->pal_bits, 8); + *b++ =pic2_convert_color_bits(pi->pal[i][2] >> (8 - pi->pal_bits), + pi->pal_bits, 8); + } +} + +static void pic2_write_palette(pi, n_pal, pal_bits, r, g, b) +struct pic2_info *pi; +int n_pal, pal_bits; +byte *r, *g, *b; +{ + int i; + + if (n_pal > 256) + pi->n_pal = 256; + else + pi->n_pal = n_pal; + + if (pal_bits > 8) + pi->pal_bits = 8; + else + pi->pal_bits = pal_bits; + + for (i = 0; i < n_pal; i++) { + pi->pal[i][0] = pic2_convert_color_bits(*r++, 8, pal_bits) + << (8 - pal_bits); + pi->pal[i][1] = pic2_convert_color_bits(*g++, 8, pal_bits) + << (8 - pal_bits); + pi->pal[i][2] = pic2_convert_color_bits(*b++, 8, pal_bits) + << (8 - pal_bits); + } +} +#endif /* PIC2_IGNORE_UNUSED_FUNCTIONS */ + +/* + * These function handle color bit. + * pic2_convert_color_bits: + * converts color bits. + * pic2_pad_color_bits: + * pads color bits. + * pic2_reduce_color_bits: + * reduces color bits. + * pic2_exchange_rg: + * exchanges red and green value. + */ +static byte pic2_convert_color_bits(c, from, to) +int c, from, to; +{ + if (from == to) + return ((byte) c); + else if (from < to) + return (pic2_pad_color_bits(c, from, to)); + else + return (pic2_reduce_color_bits(c, from, to)); +} + +static byte pic2_pad_color_bits(c, from, to) +int c, from, to; +{ + byte p = 0; + + do { + to -= from; + p |= pic2_shift_bits(c, to); + } while (to >= 0); + return (p); +} + +static byte pic2_reduce_color_bits(c, from, to) +int c, from, to; +{ + return ((byte) (c >> (from - to))); +} + +static pixel pic2_exchange_rg(p, colbits) +pixel p; +int colbits; +{ + pixel rmask, gmask, bmask; + + rmask = (0xff >> (8 - colbits)) << (colbits * 2); + gmask = (0xff >> (8 - colbits)) << colbits; + bmask = (0xff >> (8 - colbits)); + + p = ((p << colbits) & rmask) + | ((p >> colbits) & gmask) + | ( p & bmask); + return (p); +} + +/* + * This function handles work memory buffer. + */ +static void pic2_handle_para(pi, mode) +struct pic2_info *pi; +int mode; +{ + static pixel *vram_prev, *vram_now, *vram_next; + static short *flag_now, *flag_next; + static short *flag2_now, *flag2_next, *flag2_next2; + + switch (mode) { + case 0: + vram_prev = pi->vram_prev; + vram_now = pi->vram_now; + vram_next = pi->vram_next; + flag_now = pi->flag_now; + flag_next = pi->flag_next; + flag2_now = pi->flag2_now; + flag2_next = pi->flag2_next; + flag2_next2 = pi->flag2_next2; + pi->vram_prev += 4; + pi->vram_now += 4; + pi->vram_next += 4; + pi->flag_now += 4; + pi->flag_next += 4; + pi->flag2_now += 4; + pi->flag2_next += 4; + pi->flag2_next2 += 4; + break; + case 1: + pi->vram_prev = vram_now; + pi->vram_now = vram_next; + pi->vram_next = vram_prev; + pi->flag_now = flag_next; + pi->flag_next = flag_now; + pi->flag2_now = flag2_next; + pi->flag2_next = flag2_next2; + pi->flag2_next2 = flag2_now; + break; + } +} + +/* + * These functions alloc/free work memory. + * pic2_alloc_buffer: + * alloc work memory buffer. + * pic2_free_buffer: + * free work memory buffer. + */ +static int pic2_alloc_buffer(pi) +struct pic2_info *pi; +{ + int wid; + byte *p; + + if (pi->buf != NULL) + return (-1); + + wid = pi->block->x_wid; + + p = pi->buf = (byte *) pic2_new((wid + 8) * sizeof(pixel) * 3 + + sizeof(pi->cache[0]) * 8 * 8 * 8 + + sizeof(pi->cache_pos[0]) * 8 * 8 * 8 + + sizeof(pi->mulu_tab[0]) * 16384 + + sizeof(pi->flag_now[0]) * ((wid+8) * 5), + "pic2_alloc_buffer"); + + pi->vram_prev = (pixel *) p; + p += (wid + 8) * sizeof(pixel); + pi->vram_now = (pixel *) p; + p += (wid + 8) * sizeof(pixel); + pi->vram_next = (pixel *) p; + p += (wid + 8) * sizeof(pixel); + pi->cache = (pixel (*)[PIC2_ARITH_CACHE]) p; + p += sizeof(pi->cache[0]) * 8 * 8 * 8; + pi->cache_pos = (unsigned short *) p; + p += sizeof(pi->cache_pos[0]) * 8 * 8 * 8; + pi->mulu_tab = (unsigned short *) p; + p += sizeof(pi->mulu_tab[0]) * 16384; + pi->flag_now = (short *) p; + p += sizeof(pi->flag_now[0]) * (wid + 8); + pi->flag_next = (short *) p; + p += sizeof(pi->flag_next[0]) * (wid + 8); + pi->flag2_now = (short *) p; + p += sizeof(pi->flag2_now[0]) * (wid + 8); + pi->flag2_next = (short *) p; + p += sizeof(pi->flag2_next[0]) * (wid + 8); + pi->flag2_next2 = (short *) p; + p += sizeof(pi->flag2_next2[0]) * (wid + 8); + return (0); +} + +static void pic2_free_buffer(pi) +struct pic2_info *pi; +{ + free(pi->buf); + pi->buf = NULL; +} + +/* + * These functions handle the file pointer. + * pic2_seek_file: + * moves the file pointer. + * pic2_tell_file: + * tells a location of the file pointer. + */ +static long pic2_seek_file(pi, offset, whence) +struct pic2_info *pi; +long offset; +int whence; +{ + long n; + + n = fseek(pi->fp, offset, whence); + if (n < 0) + pic2_file_error(pi, PIC2_CORRUPT); + + return (n); +} + +static long pic2_tell_file(pi) +struct pic2_info *pi; +{ + return (ftell(pi->fp)); +} + +/* + * These functions handle file. + * pic2_read_file: + * reads data from the file. + * pic2_read_long: + * reads long word data from the file and converts to internal expression. + * pic2_read_short: + * reads word data from the file and converts to internal expression. + * pic2_read_char: + * reads byte data from the file. + * pic2_write_file: + * writes data to the file. + * pic2_write_long: + * converts long word data to common expression and writes to the file. + * pic2_write_short: + * converts word data to common expression and writes to the file. + * pic2_write_char: + * writes byte data to the file. + */ +static int pic2_read_file(pi, buf, size) +struct pic2_info *pi; +void *buf; +size_t size; +{ + if (fread(buf, (size_t) 1, size, pi->fp) < size) + pic2_file_error(pi, PIC2_CORRUPT); + return (0); +} + +static long pic2_read_long(pi) +struct pic2_info *pi; +{ + byte buf[4]; + + if (fread(buf, (size_t) 4, (size_t) 1, pi->fp) < 1) + pic2_file_error(pi, PIC2_CORRUPT); + return (pic2_cextolong(buf)); +} + +static short pic2_read_short(pi) +struct pic2_info *pi; +{ + byte buf[2]; + + if (fread(buf, (size_t) 2, (size_t) 1, pi->fp) < 1) + pic2_file_error(pi, PIC2_CORRUPT); + return (pic2_cextoshort(buf)); +} + +static char pic2_read_char(pi) +struct pic2_info *pi; +{ + int c; + + if ((c = fgetc(pi->fp)) == EOF) + pic2_file_error(pi, PIC2_CORRUPT); + return ((char) c); +} + +static int pic2_write_file(pi, buf, size) +struct pic2_info *pi; +void *buf; +size_t size; +{ + if (fwrite(buf, (size_t) 1, size, pi->fp) < size) + pic2_error(pi, PIC2_WRITE); + return (0); +} + +static int pic2_write_long(pi, n) +struct pic2_info *pi; +long n; +{ + byte buf[4]; + + pic2_longtocex(buf, n); + if (fwrite(buf, (size_t) 4, (size_t) 1, pi->fp) < 1) + pic2_error(pi, PIC2_WRITE); + return (0); +} + +static int pic2_write_short(pi, n) +struct pic2_info *pi; +int n; +{ + byte buf[2]; + + pic2_shorttocex(buf, n); + if (fwrite(buf, (size_t) 2, (size_t) 1, pi->fp) < 1) + pic2_error(pi, PIC2_WRITE); + return (0); +} + +static int pic2_write_char(pi, c) +struct pic2_info *pi; +int c; +{ + if (fputc(c, pi->fp) == EOF) + pic2_error(pi, PIC2_WRITE); + return (0); +} + +/* + * These functions access the bit stream. + * pic2_read_bits: + * reads the specified bits from the file. + * pic2_write_bits: + * writes the specified bits to the file. + * pic2_flush_bits: + * flushes bit buffer to the file. + */ +static unsigned long pic2_read_bits(pi, bits) +struct pic2_info *pi; +int bits; +{ + unsigned long r = 0; + + while (bits > 0) { + while (pi->bs.rest > 0 && bits > 0) { + r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0); + pi->bs.cur <<= 1; + pi->bs.rest--; + bits--; + } + if (bits > 0) { + int c; + if ((c = fgetc(pi->fp)) == EOF) + pic2_file_error(pi, PIC2_CORRUPT); + pi->bs.cur = (byte) c; + pi->bs.rest = 8; + } + } + return r; +} + +static void pic2_write_bits(pi, dat, bits) +struct pic2_info *pi; +unsigned long dat; +int bits; +{ + unsigned long dat_mask = 1 << (bits - 1); + + while (bits > 0) { + while (pi->bs.rest < 8 && bits > 0) { + pi->bs.cur <<= 1; + if (dat & dat_mask) + pi->bs.cur |= 1; + pi->bs.rest++; + bits--; + dat_mask >>= 1; + } + if (pi->bs.rest >= 8) { + if ((fputc((int) pi->bs.cur, pi->fp)) == EOF) + pic2_error(pi, PIC2_WRITE); + pi->bs.cur = 0; + pi->bs.rest = 0; + } + } +} + +static void pic2_flush_bits(pi) +struct pic2_info *pi; +{ + if (pi->bs.rest < 8) { + pi->bs.cur <<= 8 - pi->bs.rest; + if (fputc((int) pi->bs.cur, pi->fp) == EOF) + pic2_error(pi, PIC2_WRITE); + pi->bs.cur = 0; + pi->bs.rest = 0; + } +} + +/* + * These functions initialize or clean up structures. + * pic2_init_info: + * initializes a pic2_info structure. + * pic2_cleanup_pic2_info: + * cleans up a pic_info structure. + * pic2_cleanup_pinfo: + * cleans up a PICINFO structure. + */ +static void pic2_init_info(pi) +struct pic2_info *pi; +{ + xvbzero((char *) pi, sizeof(struct pic2_info)); + pi->header = pic2_new(sizeof(struct pic2_header), "pic2_init_info#1"); + pi->block = pic2_new(sizeof(struct pic2_block), "pic2_init_info#2"); +} + +static void pic2_cleanup_pic2_info(pi, writing) +struct pic2_info *pi; +int writing; +{ + if (!writing && pi->fp) + fclose(pi->fp); + if (pi->header) + free(pi->header); + if (pi->block) + free(pi->block); + pi->fp = NULL; + pi->header = NULL; + pi->block = NULL; + pi->comment = NULL; +} + +static void pic2_cleanup_pinfo(pinfo) +PICINFO *pinfo; +{ + if (pinfo->pic){ + free(pinfo->pic); + pinfo->pic = NULL; + } + if (pinfo->comment){ + free(pinfo->comment); + pinfo->comment = NULL; + } +} + +/* + * Error Handlers. + * pic2_memory_error: + * shows an error message, and terminates. + * pic2_error: + * shows an non-file error message, and jumps to the entry for errors. + * pic2_file_error: + * shows an file error message, and jumps to the entry for errors. + */ +static void pic2_memory_error(scm, fn) +char *scm, *fn; +{ + char buf[128]; + sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn); + FatalError(buf); +} + +static void pic2_error(pi, mn) +struct pic2_info *pi; +int mn; +{ + SetISTR(ISTR_WARNING, "%s", pic2_msgs[mn]); + longjmp(pi->jmp, 1); +} + +static void pic2_file_error(pi, mn) + struct pic2_info *pi; + int mn; +{ + if (feof(pi->fp)) + SetISTR(ISTR_WARNING, "%s (end of file)", pic2_msgs[mn]); + else + SetISTR(ISTR_WARNING, "%s (%s)", pic2_msgs[mn], ERRSTR(errno)); + longjmp(pi->jmp, 1); +} + +static void pic2_show_pic2_info(pi) + struct pic2_info *pi; +{ + fprintf(stderr, "file size: %ld.\n", pi->fsize); + fprintf(stderr, "full image size: %dx%d\n", pi->x_max, pi->y_max); + fprintf(stderr, "number of palettes: %d\n", pi->n_pal); + fprintf(stderr, "depth of palettes: %d\n", pi->pal_bits); + fprintf(stderr, "current block position: %d\n", pi->block_pos); + fprintf(stderr, "next block position: %d\n\n", pi->next_pos); + + fprintf(stderr, "header flag: %x\n", pi->header->flag); + fprintf(stderr, "header size: %d\n", pi->header->size); + fprintf(stderr, "x_aspect: %d, y_aspect: %d\n", + pi->header->x_aspect, pi->header->y_aspect); + fprintf(stderr, "number of color bits: %d\n\n", pi->header->depth); + + fprintf(stderr, "image block id: %s\n", pi->block->id); + fprintf(stderr, "image block size: %d\n", pi->block->size); + fprintf(stderr, "block flag: %x\n", pi->block->flag); + + fprintf(stderr, "block image size: %dx%d\n", + pi->block->x_wid, pi->block->y_wid); + fprintf(stderr, "x_offset: %d\n", pi->block->x_offset); + fprintf(stderr, "y_offset: %d\n", pi->block->y_offset); + fprintf(stderr, "opaque color: %x\n\n", pi->block->opaque); +} + +/* + * This function is simular to strncpy. + * But this fills whitespaces after the null charactor. + */ +static char *pic2_strncpy(dest, src, n) +char *dest, *src; +size_t n; +{ + char *r; + + r = dest; + while (n--) + if ((src != NULL) && (*src != '\r') && (*src != '\n') && *src) + *dest++ = *src++; + else + *dest++ = ' '; + return (r); +} + +/* + * These function create memory block. + */ +static void *pic2_malloc(size, fn) +size_t size; +char *fn; +{ + void *p; + + p = (void *) malloc(size); + if (p == NULL) + pic2_memory_error("malloc", fn); + return (p); +} + +static void *pic2_new(size, fn) +size_t size; +char *fn; +{ + void *p; + + p = (void *) pic2_malloc(size, fn); + xvbzero((char *) p, size); + return (p); +} + + + + +/**** Stuff for PIC2Dialog box ****/ + +#define TWIDE 320 +#define THIGH 178 +#define T_NBUTTS 2 +#define T_BOK 0 +#define T_BCANC 1 +#define BUTTH 24 + +static void drawTD PARM((int,int,int,int)); +static void clickTD PARM((int,int)); +static void doCmd PARM((int)); +static void writePIC2 PARM((void)); + +/* local variables */ +static FILE *fp; +static char *filename; +static int colorType; +static int append; +static int x_offset; +static int y_offset; +static BUTT tbut[T_NBUTTS]; +static RBUTT *typeRB; +static RBUTT *depthRB; + + + +/***************************************************/ +void CreatePIC2W() +{ + int y; + + pic2W = CreateWindow("xv pic2", "XVpic2", NULL, + TWIDE, THIGH, infofg, infobg, 0); + if (!pic2W) + FatalError("can't create pic2 window!"); + + XSelectInput(theDisp, pic2W, + ExposureMask | ButtonPressMask | KeyPressMask); + + BTCreate(&tbut[T_BOK], pic2W, TWIDE-140-1, THIGH-10-BUTTH-1, 60, BUTTH, + "Ok", infofg, infobg, hicol, locol); + + BTCreate(&tbut[T_BCANC], pic2W, TWIDE-70-1, THIGH-10-BUTTH-1, 60, BUTTH, + "Cancel", infofg, infobg, hicol, locol); + + y = 55; + typeRB = RBCreate(NULL, pic2W, 36, y, "P2SS", + infofg, infobg,hicol,locol); + RBCreate(typeRB, pic2W, 36, y+18, "P2SF", + infofg, infobg,hicol,locol); + RBCreate(typeRB, pic2W, 36, y+36, "P2BM", + infofg, infobg, hicol, locol); + RBCreate(typeRB, pic2W, 36, y+54, "P2BI", + infofg, infobg, hicol, locol); + + depthRB = RBCreate(NULL, pic2W, TWIDE/2-16, y, " 3bit", + infofg, infobg,hicol,locol); + RBCreate(depthRB, pic2W, TWIDE/2-16, y+18, " 6bit", + infofg, infobg,hicol,locol); + RBCreate(depthRB, pic2W, TWIDE/2-16, y+36, " 9bit", + infofg, infobg, hicol, locol); + RBCreate(depthRB, pic2W, TWIDE/2-16, y+54, "12bit", + infofg, infobg, hicol, locol); + RBCreate(depthRB, pic2W, TWIDE/4*3-16, y, "15bit", + infofg, infobg, hicol, locol); + RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+18, "18bit", + infofg, infobg, hicol, locol); + RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+36, "21bit", + infofg, infobg, hicol, locol); + RBCreate(depthRB, pic2W, TWIDE/4*3-16, y+54, "24bit", + infofg, infobg, hicol, locol); + + XMapSubwindows(theDisp, pic2W); +} + + +/***************************************************/ +void PIC2Dialog(vis) +int vis; +{ + if (vis) { + CenterMapWindow(pic2W, tbut[T_BOK].x + tbut[T_BOK].w/2, + tbut[T_BOK].y + tbut[T_BOK].h/2, TWIDE, THIGH); + } + else XUnmapWindow(theDisp, pic2W); + pic2Up = vis; +} + + +/***************************************************/ +int PIC2CheckEvent(xev) +XEvent *xev; +{ + /* check event to see if it's for one of our subwindows. If it is, + deal accordingly, and return '1'. Otherwise, return '0' */ + + int rv; + rv = 1; + + if (!pic2Up) + return (0); + + if (xev->type == Expose) { + int x,y,w,h; + XExposeEvent *e = (XExposeEvent *) xev; + x = e->x; y = e->y; w = e->width; h = e->height; + + if (e->window == pic2W) drawTD(x, y, w, h); + else rv = 0; + } + + else if (xev->type == ButtonPress) { + XButtonEvent *e = (XButtonEvent *) xev; + int x,y; + x = e->x; y = e->y; + + if (e->button == Button1) { + if (e->window == pic2W) clickTD(x,y); + else rv = 0; + } /* button1 */ + else rv = 0; + } /* button press */ + + + else if (xev->type == KeyPress) { + XKeyEvent *e = (XKeyEvent *) xev; + char buf[128]; KeySym ks; XComposeStatus status; + int stlen; + + stlen = XLookupString(e,buf,128,&ks,&status); + buf[stlen] = '\0'; + + if (e->window == pic2W) { + if (stlen) { + if (buf[0] == '\r' || buf[0] == '\n') { /* enter */ + FakeButtonPress(&tbut[T_BOK]); + } + else if (buf[0] == '\033') { /* ESC */ + FakeButtonPress(&tbut[T_BCANC]); + } + } + } + else rv = 0; + } + else rv = 0; + + if (rv == 0 && (xev->type == ButtonPress || xev->type == KeyPress)) { + XBell(theDisp, 50); + rv = 1; /* eat it */ + } + + return (rv); +} + + +/***************************************************/ +int PIC2SaveParams(fname, col) +char *fname; +int col; +{ + filename = fname; + colorType = col; + + /* see if we can open the output file before proceeding */ + fp = pic2_OpenOutFile(filename, &append); + if (!fp) + return (-1); + + RBSetActive(typeRB,0,1); + RBSetActive(typeRB,1,1); + RBSetActive(typeRB,2,1); + RBSetActive(typeRB,3,1); + RBSelect(typeRB,0); + + + if (append) { + struct pic2_info pic2; + + pic2_init_info(&pic2); + pic2.fp = fp; + pic2_read_header(&pic2); + + RBSetActive(depthRB,0,0); + RBSetActive(depthRB,1,0); + RBSetActive(depthRB,2,0); + RBSetActive(depthRB,3,0); + RBSetActive(depthRB,4,0); + RBSetActive(depthRB,5,0); + RBSetActive(depthRB,6,0); + RBSetActive(depthRB,7,0); + + switch (pic2.header->depth) { + case 3: + RBSetActive(depthRB,0,1); + RBSelect(depthRB,0); + RBSetActive(typeRB,3,0); + break; + case 6: + RBSetActive(depthRB,1,1); + RBSelect(depthRB,1); + RBSetActive(typeRB,3,0); + break; + case 9: + RBSetActive(depthRB,2,1); + RBSelect(depthRB,2); + break; + case 12: + RBSetActive(depthRB,3,1); + RBSelect(depthRB,3); + break; + case 15: + RBSetActive(depthRB,4,1); + RBSelect(depthRB,4); + break; + case 18: + RBSetActive(depthRB,5,1); + RBSelect(depthRB,5); + RBSetActive(typeRB,3,0); + break; + case 21: + RBSetActive(depthRB,6,1); + RBSelect(depthRB,6); + RBSetActive(typeRB,3,0); + break; + case 24: + RBSetActive(depthRB,7,1); + RBSelect(depthRB,7); + RBSetActive(typeRB,3,0); + break; + default: { + char str[512]; + sprintf(str, "unsupported PIC2 file '%s'.", filename); + ErrPopUp(str, "\nBummer"); + CloseOutFile(fp, filename, 0); + fp = OpenOutFile(fname); + if (!fp) + return (-1); + break; + } + } + pic2_seek_file(&pic2, 0, SEEK_SET); + pic2_cleanup_pic2_info(&pic2, 1); + } else { + RBSetActive(depthRB,0,1); + RBSetActive(depthRB,1,1); + RBSetActive(depthRB,2,1); + RBSetActive(depthRB,3,1); + RBSetActive(depthRB,4,1); + RBSetActive(depthRB,5,1); + RBSetActive(depthRB,6,1); + RBSetActive(depthRB,7,1); + RBSelect(depthRB,7); + RBSetActive(typeRB,3,0); + } + return (0); +} + + +/***************************************************/ +static void drawTD(x,y,w,h) +int x,y,w,h; +{ + char *title = "Save PIC2 file..."; + int i; + XRectangle xr; + + xr.x = x; xr.y = y; xr.width = w; xr.height = h; + XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted); + + XSetForeground(theDisp, theGC, infofg); + XSetBackground(theDisp, theGC, infobg); + + for (i = 0; i < T_NBUTTS; i++) + BTRedraw(&tbut[i]); + + ULineString(pic2W, typeRB->x-16, typeRB->y-3-DESCENT, "FormatType"); + ULineString(pic2W, depthRB->x-16, depthRB->y-3-DESCENT, "ColorDepth"); + RBRedraw(typeRB, -1); + RBRedraw(depthRB, -1); + + DrawString(pic2W, 20, 29, title); + + XSetClipMask(theDisp, theGC, None); +} + +static void clickTD(x,y) +int x,y; +{ + int i; + BUTT *bp; + + /* check BUTTs */ + + /* check the RBUTTS first, since they don't DO anything */ + if ((i = RBClick(typeRB, x,y)) >= 0) { + (void) RBTrack(typeRB, i); + return; + } else if ((i = RBClick(depthRB, x,y)) >= 0) { + (void) RBTrack(depthRB, i); + if ((2 <= i) && (i <= 4)) + RBSetActive(typeRB,3,1); + else { + RBSetActive(typeRB,3,0); + if (RBWhich(typeRB) == 3) + RBSelect(typeRB,0); + return; + } + } + for (i = 0; i < T_NBUTTS; i++) { + bp = &tbut[i]; + if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) + break; + } + if (i < T_NBUTTS) /* found one */ + if (BTTrack(bp)) + doCmd(i); +} + + + +/***************************************************/ +static void doCmd(cmd) +int cmd; +{ + switch (cmd) { + case T_BOK: { + char *fullname; + char buf[64], *x_offsetp, *y_offsetp; + static char *labels[] = { "\nOk", "\033Cancel" }; + XEvent event; + int i; + + strcpy(buf, "0,0"); + i = GetStrPopUp("Enter offset (x,y):", labels, 2, buf, 64, + "01234567890,", 1); + + if (i) + return; + if (strlen(buf)==0) + return; + + x_offsetp = buf; + y_offsetp = index(buf, ','); + if (!y_offsetp) + return; + *(y_offsetp++) = '\0'; + if ((*x_offsetp == '\0') || (*y_offsetp == '\0')) + return; + x_offset = atoi(x_offsetp); + y_offset = atoi(y_offsetp); + + XNextEvent(theDisp, &event); + HandleEvent(&event, &i); + + writePIC2(); + PIC2Dialog(0); + + fullname = GetDirFullName(); + if (!ISPIPE(fullname[0])) { + XVCreatedFile(fullname); + StickInCtrlList(0); + } + } + break; + case T_BCANC: + pic2_KillNullFile(fp); + PIC2Dialog(0); + break; + default: + break; + } +} + + +/*******************************************/ +static void writePIC2() +{ + int w, h, nc, rv, type, depth, ptype, pfree; + byte *inpix, *rmap, *gmap, *bmap; + + + WaitCursor(); + inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap); + + if (colorType == F_REDUCED) + colorType = F_FULLCOLOR; + + switch (RBWhich(typeRB)) { + case 0: type = P2SS; break; + case 1: type = P2SF; break; + case 2: type = P2BM; break; + case 3: type = P2BI; break; + default: type = P2SS; break; + } + switch (RBWhich(depthRB)) { + case 0: depth = 3; break; + case 1: depth = 6; break; + case 2: depth = 9; break; + case 3: depth = 12; break; + case 4: depth = 15; break; + case 5: depth = 18; break; + case 6: depth = 21; break; + case 7: depth = 24; break; + default: depth = 24; break; + } + rv = WritePIC2(fp, inpix, ptype, w, h, + rmap, gmap, bmap, nc, colorType, filename, + type, depth, x_offset, y_offset, append, picComments); + + if (CloseOutFile(fp, filename, rv) == 0) + DirBox(0); + + if (pfree) + free(inpix); +} +#endif /* HAVE_PIC2 */ diff -urN xv-3.10a/xvtext.c xv-3.10a-jp-extension-current/xvtext.c --- xv-3.10a/xvtext.c Sat Jan 14 08:46:28 1995 +++ xv-3.10a-jp-extension-current/xvtext.c Thu Nov 21 16:38:20 1996 @@ -19,9 +19,13 @@ #include "copyright.h" #include "xv.h" - +#ifdef TV_MULTILINGUAL +#include "xvml.h" +#endif -#define BUTTW 80 +#define BUTTW1 80 +#define BUTTW2 60 +#define BUTTW3 110 #define BUTTH 24 #define TOPMARGIN 30 /* from top of window to top of text window */ @@ -36,11 +40,28 @@ #define TV_ASCII 0 #define TV_HEX 1 #define TV_CLOSE 2 -#define TV_NBUTTS 3 + +#define TV_E_NBUTTS 3 + +#ifdef TV_L10N +# define TV_RESCAN 3 +# define TV_USASCII 4 +# define TV_JIS 5 +# define TV_EUCJ 6 +# define TV_MSCODE 7 +# define TV_J_NBUTTS 8 +#endif #define TITLELEN 128 +#ifdef TV_MULTILINGUAL +struct coding_spec { + struct coding_system coding_system; + char *(*converter)PARM((char *, int, int *)); +}; +#endif + /* data needed per text window */ typedef struct { Window win, textW; int vis, wasvis; @@ -57,16 +78,89 @@ int chwide, chhigh; /* size of textW, in chars */ int hexmode; /* true if disp Hex, else Ascii */ SCRL vscrl, hscrl; - BUTT but[TV_NBUTTS], nopBut; +#ifdef TV_L10N + int code; /* current charactor code */ + BUTT but[TV_J_NBUTTS], nopBut; +#else + BUTT but[TV_E_NBUTTS], nopBut; +#endif +#ifdef TV_MULTILINGUAL +/* int codeset; */ + struct coding_spec ccs; /* current coding_spec */ + BUTT csbut; + char *cv_text; + int cv_len; + struct context *ctx; + struct ml_text *txt; + struct csinfo_t *cs; +#endif } TVINFO; static TVINFO tinfo[MAXTVWIN]; static int hasBeenSized = 0; static int haveWindows = 0; +static int nbutts; /* # of buttons */ static int mfwide, mfhigh, mfascent; /* size of chars in mono font */ static int *event_retP, *event_doneP; /* used in tvChkEvent() */ - +#ifdef TV_MULTILINGUAL +# define TV_PLAIN 0 +# define TV_ISO_8859_1 1 +# define TV_ISO_2022_JP 2 +# define TV_EUC_JAPAN 3 +# define TV_ISO_2022_INT_1 4 +# define TV_ISO_2022_KR 5 +# define TV_EUC_KOREA 6 +# define TV_ISO_2022_SS2_8 7 +# define TV_ISO_2022_SS2_7 8 +# define TV_SHIFT_JIS 9 +# define TV_NCSS 10 +static char *codeSetNames[TV_NCSS] = { + "plain", + "iso-8859-1", + "iso-2022-jp", + "euc-japan", + "iso-2022-int-1", + "iso-2022-kr", + "euc-korea", + "iso-2022-ss2-8", + "iso-2022-ss2-7", + "Shift JIS", +}; +static struct coding_spec coding_spec[TV_NCSS] = { + /* --- G0 --- --- G1 --- --- G2 --- --- G3 --- GL GR EOL SF LS */ + /* plain */ + {{{{ 1,94,'B'}, { 1,94,'B'}, { 1,94,'B'}, { 1,94,'B'}}, 0, 0, 0, 1, 1}, + NULL}, + /* iso-8859-1 */ + {{{{ 1,94,'B'}, { 1,96,'A'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 0}, + NULL}, + /* iso-2022-jp */ + {{{{ 1,94,'B'}, {-1,94,'B'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 0, 0, 1, 0}, + NULL}, + /* euc-japan */ + {{{{ 1,94,'B'}, { 2,94,'B'}, { 1,94,'J'}, { 2,94,'D'}}, 0, 1, 0, 1, 0}, + NULL}, + /* iso-2022-int-1 */ + {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 1, 1}, + NULL}, + /* iso-2022-kr */ + {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 1}, + NULL}, + /* euc-korea */ + {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 0}, + NULL}, + /* iso-2022-ss2-8 */ + {{{{ 1,94,'B'}, {-1,94,'C'}, { 0,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 0}, + NULL}, + /* iso-2022-ss2-7 */ + {{{{ 1,94,'B'}, {-1,94,'C'}, { 0,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 1, 0}, + NULL}, + /* shift jis */ + {{{{ 1,94,'B'}, { 2,94,'B'}, { 1,94,'J'}, { 2,94,'D'}}, 0, 1, 1, 1, 0}, + sjis_to_jis}, +}; +#endif static void closeText PARM((TVINFO *)); static int tvChkEvent PARM((TVINFO *, XEvent *)); @@ -82,7 +176,15 @@ static void textKey PARM((TVINFO *, int)); static void doHexAsciiCmd PARM((TVINFO *, int)); static void computeText PARM((TVINFO *)); - +#ifdef TV_L10N +static int selectCodeset PARM((TVINFO *)); +#endif +#ifdef TV_MULTILINGUAL +static void setCodingSpec PARM((TVINFO *, struct coding_spec *)); +static void createCsWins PARM((char *)); +static void openCsWin PARM((TVINFO *)); +static void closeCsWin PARM((TVINFO *)); +#endif /* HEXMODE output looks like this: 0x00000000: 00 11 22 33 44 55 66 77 - 88 99 aa bb cc dd ee ff 0123456789abcdef @@ -99,11 +201,51 @@ XSetWindowAttributes xswa; TVINFO *tv; int gx,gy,gw,gh,gset,gx1,gy1; - +#ifdef TV_MULTILINGUAL + int default_codeset; +#endif + +#ifdef TV_L10N + if (!xlocale) { +#endif + mfwide = monofinfo->max_bounds.width; + mfhigh = monofinfo->ascent + monofinfo->descent; + mfascent = monofinfo->ascent; + + nbutts = TV_E_NBUTTS; /* # of buttons */ +#ifdef TV_L10N + } + else { + mfwide = monofsetinfo->max_logical_extent.width / 2; /* shit! */ + mfhigh = monofsetinfo->max_logical_extent.height + 1; + mfascent = mfhigh; + + nbutts = TV_J_NBUTTS; /* # of buttons */ + } +#endif - mfwide = monofinfo->max_bounds.width; - mfhigh = monofinfo->ascent + monofinfo->descent; - mfascent = monofinfo->ascent; +#ifdef TV_MULTILINGUAL + { + char *dc = XGetDefault(theDisp, "xv", "codeSet"); + if (dc == NULL) + default_codeset = TV_DEFAULT_CODESET; + else { + for (i = 0; i < TV_NCSS; i++) { + if (strcmp(dc, codeSetNames[i]) == 0) + break; + } + if (i >= TV_NCSS) { + if (strcmp(dc, "iso-2022") == 0) + default_codeset = TV_PLAIN; + else { + SetISTR(ISTR_WARNING, "%s: unknown codeset.", dc); + default_codeset = TV_PLAIN; + } + } else + default_codeset = i; + } + } +#endif /* compute default size of textview windows. should be big enough to hold an 80x24 text window */ @@ -119,6 +261,14 @@ for (i=0; ictx = ml_create_context(ScreenOfDisplay(theDisp, theScreen)); + tv->txt = NULL; + tv->cv_text = NULL; + tv->cv_len = 0; + ml_set_charsets(tv->ctx, &coding_spec[TV_PLAIN].coding_system); +#endif + tv->win = CreateWindow((itextW, ExposureMask | ButtonPressMask); - BTCreate(&(tv->but[TV_ASCII]), tv->win, 0,0,BUTTW,BUTTH, + BTCreate(&(tv->but[TV_ASCII]), tv->win, 0,0,BUTTW1,BUTTH, "Ascii",infofg,infobg,hicol,locol); - BTCreate(&(tv->but[TV_HEX]), tv->win, 0,0,BUTTW,BUTTH, + BTCreate(&(tv->but[TV_HEX]), tv->win, 0,0,BUTTW1,BUTTH, "Hex",infofg,infobg,hicol,locol); - BTCreate(&(tv->but[TV_CLOSE]), tv->win, 0,0,BUTTW,BUTTH, + BTCreate(&(tv->but[TV_CLOSE]), tv->win, 0,0,BUTTW1,BUTTH, "Close",infofg,infobg,hicol,locol); +#ifdef TV_L10N + if (xlocale) { + BTCreate(&(tv->but[TV_RESCAN]), tv->win, 0,0,BUTTW2,BUTTH, + "RESCAN",infofg,infobg,hicol,locol); + BTCreate(&(tv->but[TV_USASCII]), tv->win, 0,0,BUTTW2,BUTTH, + "ASCII",infofg,infobg,hicol,locol); + BTCreate(&(tv->but[TV_JIS]), tv->win, 0,0,BUTTW2,BUTTH, + "JIS",infofg,infobg,hicol,locol); + BTCreate(&(tv->but[TV_EUCJ]), tv->win, 0,0,BUTTW2,BUTTH, + "EUC-j",infofg,infobg,hicol,locol); + BTCreate(&(tv->but[TV_MSCODE]), tv->win, 0,0,BUTTW2,BUTTH, + "MS Kanji",infofg,infobg,hicol,locol); + } +#endif + BTCreate(&(tv->nopBut), tv->win, 0,0, (u_int) tv->vscrl.tsize+1, (u_int) tv->vscrl.tsize+1, "", infofg, infobg, hicol, locol); tv->nopBut.active = 0; XMapSubwindows(theDisp, tv->win); +#ifdef TV_MULTILINGUAL + BTCreate(&tv->csbut, tv->win, 0, 0, BUTTW1, BUTTH, "Code Sets", + infofg, infobg, hicol, locol); +#endif + tv->text = (char *) NULL; tv->textlen = 0; tv->title[0] = '\0'; +#ifdef TV_L10N + tv->code = (xlocale ? LOCALE_DEFAULT : 0); +#endif +#ifdef TV_MULTILINGUAL + tv->ccs = coding_spec[default_codeset]; +#endif } - +#ifdef TV_MULTILINGUAL + get_monofont_size(&mfwide, &mfhigh); + /* recalculate sizes. */ + defwide = 80 * mfwide + 2*LRMARGINS + 8 + 20; /* -ish */ + defhigh = 24 * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20; /* ish */ + cmthigh = 6 * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20; /* ish */ +#endif for (i=0; itext = (char *) NULL; tv->lines = (char **) NULL; tv->numlines = tv->textlen = tv->hexmode = 0; + +#ifdef TV_MULTILINGUAL + closeCsWin(tv); +#endif } @@ -636,7 +836,9 @@ int i, maxw, maxh, hmax, hpage, vmax, vpage; XSizeHints hints; +#ifndef TV_MULTILINGUAL if (tv->wide == w && tv->high == h) return; /* no change in size */ +#endif if (XGetNormalHints(theDisp, tv->win, &hints)) { hints.width = w; @@ -660,10 +862,23 @@ XMoveResizeWindow(theDisp, tv->textW, LRMARGINS, TOPMARGIN, (u_int) tv->twWide, (u_int) tv->twHigh); - for (i=0; ibut[i].x = tv->wide - (TV_NBUTTS-i) * (BUTTW+5); + for (i=0; ibut[i].x = tv->wide - (TV_E_NBUTTS-i) * (BUTTW1+5); tv->but[i].y = tv->high - BUTTH - 5; } +#ifdef TV_MULTILINGUAL + tv->csbut.x = 5; + tv->csbut.y = tv->high - BUTTH - 5; +#endif + +#ifdef TV_L10N + if (xlocale) { + for (; ibut[i].x = 5 + (i-TV_E_NBUTTS) * (BUTTW2+5); + tv->but[i].y = tv->high - BUTTH - 5; + } + } +#endif computeScrlVals(tv); @@ -714,6 +929,29 @@ case TV_CLOSE: if (tv == &tinfo[CMTWIN]) CloseCommentText(); else closeText(tv); break; + +#ifdef TV_L10N + case TV_RESCAN: + tv->code = selectCodeset(tv); + drawTextW(0, &tv->vscrl); + break; + case TV_USASCII: + tv->code = LOCALE_USASCII; + drawTextW(0, &tv->vscrl); + break; + case TV_JIS: + tv->code = LOCALE_JIS; + drawTextW(0, &tv->vscrl); + break; + case TV_EUCJ: + tv->code = LOCALE_EUCJ; + drawTextW(0, &tv->vscrl); + break; + case TV_MSCODE: + tv->code = LOCALE_MSCODE; + drawTextW(0, &tv->vscrl); + break; +#endif /* TV_L10N */ } } @@ -748,8 +986,10 @@ drawNumLines(tv); /* draw the buttons */ - for (i=0; ibut[i])); - + for (i=0; ibut[i])); +#ifdef TV_MULTILINGUAL + BTRedraw(&tv->csbut); +#endif BTRedraw(&tv->nopBut); } @@ -820,6 +1060,10 @@ SCRL *sptr; { int i, j, lnum, hpos, cpos, extrach, lwide; +#ifdef TV_L10N + int desig_stat; /* for ISO 2022-JP */ + /* 0: ASCII, 1: JIS X 0208, 2: GL is JIS X 0201 kana */ +#endif TVINFO *tv; char linestr[512]; u_char *sp, *ep, *lp; @@ -846,6 +1090,31 @@ /* draw text */ if (!tv->hexmode) { /* ASCII mode */ +#ifdef TV_MULTILINGUAL + XClearArea(theDisp, tv->textW, 0, 0, + (u_int) tv->twWide, (u_int) tv->twHigh, False); + if(tv->txt == NULL) + return; + else { + int i; + int y; + struct ml_text *tp = tv->txt; + struct ml_line *lp; + + XSetFunction(theDisp, theGC, GXcopy); + XSetClipMask(theDisp, theGC, None); + y = 3; + for (lp = &tp->lines[tv->vscrl.val], i = tp->nlines - tv->vscrl.val; + i > 0; lp++, i--) { + XDrawText16(theDisp, tv->textW, theGC, + -mfwide * hpos + 3, y + lp->ascent, + lp->items, lp->nitems); + y += lp->ascent + lp->descent; + if (y > tv->twHigh) + break; + } + } +#else for (i=0; ichhigh; i++) { /* draw each line */ lnum = i + tv->vscrl.val; if (lnum < tv->numlines-1) { @@ -868,7 +1137,13 @@ cpos--; sp++; } else if (*sp < 32) extrach = 1; + +#ifdef TV_L10N + else if (!tv->code && *sp > 127) extrach = 3; +#else else if (*sp > 127) extrach = 3; +#endif + else sp++; } else { @@ -884,6 +1159,10 @@ /* build up the linestr buffer, which is the current line, padded with blanks to a width of exactly tv->chwide chars */ +#ifdef TV_L10N + desig_stat = 0; /* for ISO 2022-JP */ + /* 0: ASCII, 1: JIS X 0208, 2: GL is JIS X 0201 kana */ +#endif for (cpos=0, lp=(byte *) linestr; cpos=ep) *lp = ' '; else { @@ -897,13 +1176,117 @@ cpos--; lp--; sp++; } +#ifdef TV_L10N + else if (*sp < 32 && !(tv->code == LOCALE_JIS && *sp == 0x1b)) { +#else else if (*sp < 32) { +#endif if (!extrach) extrach = 2; if (extrach == 2) *lp = '^'; else if (extrach == 1) *lp = *sp + 64; } - + +#ifdef TV_L10N + /* convert to EUC-Japan */ + else if (tv->code == LOCALE_JIS) { + if (*sp == 0x1b) { /* ESC */ + if (*(sp+1) == '$') { + if (*(sp+2) == 'B' || *(sp+2) == 'A' || *(sp+2) == '@') { + /* ESC $ B, ESC $ A, ESC $ @ */ + desig_stat = 1; + sp += 3; cpos--; lp--; + } + else if (*(sp+2) == '(' && *(sp+3) == 'B') { + /* ESC $ ( B */ + desig_stat = 1; + sp += 4; cpos--; lp--; + } + } + else if (*(sp+1) == '(') { + if (*(sp+2) == 'B' || *(sp+2) == 'J' || *(sp+2) == 'H') { + /* ESC ( B, ESC ( J, ESC ( H */ + desig_stat = 0; + sp += 3; cpos--; lp--; + } + else if (*(sp+2) == 'I') { + /* ESC ( I */ + desig_stat = 2; + sp += 3; cpos--; lp--; + } + } + else if (*(sp+1) == ')' && *(sp+2) == 'I') { + /* ESC ) I */ + desig_stat = 2; + sp += 3; cpos--; lp--; + } + else { /* error */ + *lp = ' '; sp++; + } + } + + else { + switch (desig_stat) { + case 0: /* ASCII */ + *lp = *sp++; + break; + case 1: /* JIS X 0208 */ + *lp++ = *sp++ | 0x80; + *lp = *sp++ | 0x80; + cpos++; + break; + case 2: /* JIS X 0201 kana */ +#if defined(__osf__) && !defined(X_LOCALE) + *lp = '='; sp++; +#else + *lp++ = 0x8e; /* ^N | 0x80 */ + *lp = *sp++ | 0x80; +#endif + break; + default: /* error */ + *lp = *sp++; + break; + } + } + } + + else if (tv->code == LOCALE_MSCODE) { + if ((*sp >= 0x81 && *sp <= 0x9f) + || (*sp >= 0xe0 && *sp <= 0xef)) { + static u_char c1, c2; + +/*fprintf(stderr, "(%x,%x)->", *sp, *(sp+1));*/ + c1 = ((*sp - ((*sp>=0xe0) ? 0xb0 : 0x70)) << 1) + - ((*(sp+1)<=0x9e) ? 1 : 0); + c2 = *(sp+1); + if (c2 >= 0x9f) c2 -= 0x7e; /* 0x9F - 0xFC */ + else if (c2 >= 0x80) c2 -= 0x20; /* 0x80 - 0x9E */ + else c2 -= 0x1f; /* 0x40 - 0x7E */ + + *lp++ = c1 | 0x80; + *lp = c2 | 0x80; + sp += 2; +/*fprintf(stderr, "(%x %x) ", c1 | 0x80, c2 | 0x80);*/ + cpos++; + } + + else if (*sp >= 0xa1 && *sp <= 0xdf) { /* JIS X 0201 kana */ +#if defined(__osf__) && !defined(X_LOCALE) + *lp = '='; sp++; +#else + *lp++ = 0x8e; /* ^N | 0x80 */ + *lp = *sp++; +#endif + } + + else *lp = *sp++; + } +#endif /* TV_L10N */ + +#ifdef TV_L10N + else if (!tv->code && *sp > 127) { +#else else if (*sp > 127) { +#endif if (!extrach) extrach = 4; if (extrach == 4) *lp = '\\'; else if (extrach == 3) *lp = ((u_char)(*sp & 0700) >> 6) + '0'; @@ -919,6 +1302,9 @@ } } } +#ifdef TV_L10N + *lp = '\0'; /* terminate linestr */ +#endif } else { /* below bottom of file. Just build a blank str */ @@ -926,9 +1312,16 @@ } /* draw the line */ - XDrawImageString(theDisp, tv->textW, theGC, - 3, i*mfhigh + 3 + mfascent, linestr, lwide); +#ifdef TV_L10N + if (xlocale) + XmbDrawImageString(theDisp, tv->textW, monofset, theGC, + 3, i*mfhigh + 1 + mfascent, linestr, strlen(linestr)); + else +#endif + XDrawImageString(theDisp, tv->textW, theGC, + 3, i*mfhigh + 3 + mfascent, linestr, lwide); } /* for i ... */ +#endif /* TV_MULTILINGUAL */ } /* if hexmode */ @@ -960,7 +1353,11 @@ for (j=0; j<16; j++) { if (sp+j < ep) { +#ifdef TV_L10N + if (sp[j] >= 32 && (sp[j] <= 127 || tv->code)) *lp++ = sp[j]; +#else if (sp[j] >= 32 && sp[j] <= 127) *lp++ = sp[j]; +#endif else *lp++ = '.'; } else *lp++ = ' '; @@ -1008,14 +1405,21 @@ int i; BUTT *bp; - for (i=0, bp=tv->but; ibut; ix,bp->y,bp->w,bp->h)) break; } - if (icsbut.x, tv->csbut.y, tv->csbut.w, tv->csbut.h)) { + if (BTTrack(&tv->csbut)) + openCsWin(tv); + } +#endif } @@ -1045,13 +1449,38 @@ /* keyboard equivalents */ switch (buf[0]) { - case '\001': doCmd(tv, TV_ASCII); break; /* ^A = Ascii */ - case '\010': doCmd(tv, TV_HEX); break; /* ^H = Hex */ - - case '\033': doCmd(tv, TV_CLOSE); break; /* ESC = Close window */ + case '\001': case 'a': case 'A': + doCmd(tv, TV_ASCII); break; /* ^A = Ascii */ + case '\010': case 'h': case 'H': + doCmd(tv, TV_HEX); break; /* ^H = Hex */ + + case '\021': case 'q': case 'Q': + case '\003': case 'c': case 'C': + case '\033': + doCmd(tv, TV_CLOSE); break; /* ESC = Close window */ default: break; } + +#ifdef TV_L10N + if (xlocale) { + switch (buf[0]) { + case '\022': case 'r': case 'R': + doCmd(tv, TV_RESCAN); break; + case '\012': case 'j': case 'J': + doCmd(tv, TV_JIS); break; + case '\005': case 'e': case 'E': + case '\025': case 'u': case 'U': + doCmd(tv, TV_EUCJ); break; + case '\015': case 'm': case 'M': + case '\023': case 's': case 'S': + doCmd(tv, TV_MSCODE); break; + + default: break; + } + } +#endif /* TV_L10N */ + } @@ -1114,7 +1543,20 @@ if (inumlines-1) SCSetVal(&tv->vscrl, i); } +#ifdef TV_L10N + /* redraw text */ + if (xlocale) { + XClearArea(theDisp, tv->textW, 0, 0, + (u_int) tv->twWide, (u_int) tv->twHigh, False); + + drawTextW(0, &tv->vscrl); + } +#endif +#ifdef TV_MULTILINGUAL + XClearArea(theDisp, tv->textW, 0, 0, + (u_int) tv->twWide, (u_int) tv->twHigh, False); drawTextW(0, &tv->vscrl); +#endif } @@ -1127,9 +1569,22 @@ int i,j,wide,maxwide,space; byte *sp; +#ifdef TV_L10N + /* select code-set */ + if (xlocale) + tv->code = selectCodeset(tv); +#endif /* TV_L10N */ + if (!tv->text) { tv->numlines = tv->hexlines = 0; tv->lines = (char **) NULL; +#ifdef TV_MULTILINGUAL + if (tv->cv_text != NULL) { + free(tv->cv_text); + tv->cv_text = NULL; + } + tv->txt = NULL; +#endif return; } @@ -1177,17 +1632,134 @@ wide += space; } else if (*sp < 32) wide += 2; +#ifdef TV_L10N + else if (*sp > 127 && !tv->code) wide += 4; +#else else if (*sp > 127) wide += 4; +#endif else wide++; } if (wide > maxwide) maxwide = wide; } tv->maxwide = maxwide; +#ifdef TV_MULTILINGUAL + ml_set_charsets(tv->ctx, &tv->ccs.coding_system); + if (tv->cv_text != NULL) { + free(tv->cv_text); + tv->cv_text = NULL; + } + if (tv->ccs.converter == NULL) { + tv->txt = ml_draw_text(tv->ctx, tv->text, tv->textlen); + } else { + tv->cv_text = (*tv->ccs.converter)(tv->text, tv->textlen, &tv->cv_len); + tv->txt = ml_draw_text(tv->ctx, tv->cv_text, tv->cv_len); + } + tv->maxwide = tv->txt->width / mfwide; + tv->numlines = tv->txt->height / mfhigh + 1; +#endif + tv->hexlines = (tv->textlen + 15) / 16; } +/***************************************************/ +#ifdef TV_L10N +static int selectCodeset(tv) + TVINFO *tv; +{ + u_char *sp; + int i, len; + int code; + + len = tv->textlen; + + /* select code-set */ + if (xlocale) { + code = LOCALE_USASCII; /* == 0 */ + + sp = (u_char *) tv->text; i = 0; + while (i < len - 1) { + if (*sp == 0x1b && + (*(sp+1) == '$' || *(sp+1) == '(' || *(sp+1) == ')')) { + code = LOCALE_JIS; + break; + } + + else if (*sp >= 0xa1 && *sp <= 0xdf) { + if (*(sp+1) >= 0xf0 && *(sp+1) <= 0xfe) { + code = LOCALE_EUCJ; + break; + } +# if (LOCALE_DEFAULT == LOCALE_EUCJ) + else { + sp++; i++; + } +# endif + } + + else if ((*sp >= 0x81 && *sp <= 0x9f) || (*sp >= 0xe0 && *sp <= 0xef)) { + if ((*(sp+1) >= 0x40 && *(sp+1) <= 0x7e) || *(sp+1) == 0x80) { + code = LOCALE_MSCODE; + break; + } + else if (*(sp+1) == 0xfd || *(sp+1) == 0xfe) { + code = LOCALE_EUCJ; + break; + } + else { + sp++; i++; + } + } + + else if (*sp >= 0xf0 && *sp <= 0xfe) { + code = LOCALE_EUCJ; + break; + } + + sp++; i++; + } + if (!code) code = LOCALE_DEFAULT; +# if 0 /* obsolete method */ + setlocale(LC_ALL, localeList[code]); +# endif +/*fprintf(stderr, "\n%s\n\n", localeList[code]);*/ + } + + return code; +} +#endif /* TV_L10N */ + +#ifdef TV_MULTILINGUAL +static void setCodingSpec(tv, cs) + TVINFO *tv; + struct coding_spec *cs; +{ + if (xvbcmp((char *) &tv->ccs, (char *) cs, sizeof *cs) == 0) + return; + + tv->ccs = *cs; +#if 0 + ml_set_charsets(tv->ctx, &tv->ccs.coding_system); + if (tv->cv_text != NULL) { + free(tv->cv_text); + tv->cv_text = NULL; + } + if (tv->ccs.converter == NULL) { + tv->txt = ml_draw_text(tv->ctx, tv->text, tv->textlen); + } else { + tv->cv_text = (*tv->ccs.converter)(tv->text, tv->textlen, &tv->cv_len); + tv->txt = ml_draw_text(tv->ctx, tv->cv_text, tv->cv_len); + } +#else + computeText(tv); + computeScrlVals(tv); +#endif + /* drawTextW(0, &tv->vscrl); */ +} +#endif + + /**********************************************************************/ /* BUILT-IN TEXT FILES ************************************************/ /**********************************************************************/ @@ -1560,7 +2132,517 @@ OpenTextView(keyhelp, (int) strlen(keyhelp), "XV Help", 0); } +#ifdef TV_MULTILINGUAL + +#define TV_ML_ACCEPT TV_NCSS +#define TV_ML_CLOSE (TV_ML_ACCEPT + 1) +#define TV_ML_NBUTTS (TV_ML_CLOSE + 1) + +#define TV_ML_RETCODE 0 +# define TV_ML_RET_LF 0 +# define TV_ML_RET_CRLF 1 +# define TV_ML_RET_CR 2 +# define TV_ML_RET_ANY 3 +#define TV_ML_GL 1 +#define TV_ML_GR 2 +#define TV_ML_CVTR 3 +#define TV_ML_NRBUTTS 4 + +#define TV_ML_SHORT 0 +#define TV_ML_LOCK 1 +#define TV_ML_NCBUTTS 2 + +#define TV_ML_NLISTS 4 + +#define CSWIDE (BUTTW3 * 5 + 5 * 6) +#define CSHIGH 450 + +typedef struct csinfo_t { + TVINFO *tv; + RBUTT *rbt[TV_ML_NRBUTTS]; + CBUTT cbt[TV_ML_NCBUTTS]; + LIST ls[TV_ML_NLISTS]; + BUTT bt[TV_ML_NBUTTS]; + int up; + Window win; + struct coding_spec tcs; /* temporary coding_spec */ +} CSINFO; +CSINFO csinfo[MAXTVWIN]; +static char **regs; +static int nregs; + +static int csCheckEvent PARM((CSINFO *, XEvent *)); +static void csReflect PARM((CSINFO *)); +static void csRedraw PARM((CSINFO *)); +static void csListRedraw PARM((LIST *)); +static void csLsRedraw PARM((int, SCRL *)); +static void create_registry_list PARM((void)); + +static char *(*cvtrtab[])PARM((char *, int, int *)) = { + NULL, + sjis_to_jis, +}; + +static void createCsWins(geom) + char *geom; +{ + XSetWindowAttributes xswa; + char **t; + int i, j; + + create_registry_list(); + + xswa.backing_store = WhenMapped; + for (i = 0; i < MAXTVWIN; i++) { + char nam[8]; + TVINFO *tv = &tinfo[i]; + CSINFO *cs = &csinfo[i]; + tv->cs = cs; + cs->tv = tv; + sprintf(nam, "XVcs%d", i); + cs->win = CreateWindow("xv codeset", nam, geom, + CSWIDE, CSHIGH, infofg, infobg, 0); + if (!cs->win) FatalError("couldn't create 'charset' window!"); +#ifdef BACKING_STORE + XChangeWindowAttributes(theDisp, cs->win, CWBackingStore, &xswa); +#endif + XSelectInput(theDisp, cs->win, ExposureMask | ButtonPressMask); + + DrawString(cs->win, 5, 5 + ASCENT, "Initial States"); + for (i = 0; i < TV_ML_NLISTS; i++) { + int x, y; + char buf[80]; + + if (i / 2 == 0) + x = 15; + else + x = 280; + if (i % 2 == 0) + y = 5 + LINEHIGH * 1; + else + y = 5 + LINEHIGH * 7 + SPACING * 3; + + sprintf(buf, "Designation for G%d:", i + 1); + DrawString(cs->win, x, y + ASCENT, buf); + + LSCreate(&cs->ls[i], cs->win, x + 15, y + LINEHIGH, + 200, LINEHIGH * 5, 5, + regs, nregs + 2, + infofg, infobg, hicol, locol, csLsRedraw, 0, 0); + cs->ls[i].selected = 0; + } + + for (i = 0; i < 2; i++) { + char *p; + int n; + int x, y; + int j; + + if ((p = (char *) malloc(3 * 4)) == NULL) + FatalError("out of memory in createCsWins()."); + strcpy(p, "G1 G2 G3 G4"); + p[2] = p[5] = p[8] = '\0'; + n = (i == 0 ? TV_ML_GL : TV_ML_GR); + x = (i == 0 ? 15 : 280); + y = 235; + DrawString(cs->win, x, y + ASCENT, "Assignment for GL:"); + x += 15; + y += LINEHIGH; + cs->rbt[n] = RBCreate(NULL, cs->win, + x, y, p, infofg, infobg, hicol, locol); + for (j = 1; j < 4; j++) { + p += 3; + x += 50; + RBCreate(cs->rbt[n], cs->win, + x, y, p, infofg, infobg, hicol, locol); + } + } + + DrawString(cs->win, 5, 280 + ASCENT, "Ret Code:"); + cs->rbt[TV_ML_RETCODE] = + RBCreate(NULL, cs->win, 20, 300, "LF", infofg,infobg, hicol,locol); + RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 20, 300 + 20, "CR+LF", + infofg, infobg, hicol, locol); + RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 90, 300, "CR", + infofg, infobg, hicol, locol); + RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 90, 300 + 20, "Any", + infofg, infobg, hicol, locol); + + DrawString(cs->win, 350, 280 + ASCENT, "Converter:"); + cs->rbt[TV_ML_CVTR] = + RBCreate(NULL, cs->win, 365, 300, "Nothing", + infofg, infobg, hicol, locol); + RBCreate(cs->rbt[TV_ML_CVTR], cs->win, 365, 300 + 20, "Shift JIS", + infofg, infobg, hicol, locol); + + CBCreate(&cs->cbt[TV_ML_SHORT], cs->win, 200, 300, "Short Form", + infofg, infobg, hicol, locol); + CBCreate(&cs->cbt[TV_ML_LOCK], cs->win, 200, 320, "Locking Shift", + infofg, infobg, hicol, locol); + + for (j = 0; j < TV_NCSS; j++) { + BTCreate(&cs->bt[j], cs->win, + 5 + (BUTTW3 + 5) * (j % 5), + 350 + 5 + (BUTTH + 5) * (j / 5), + BUTTW3, BUTTH, codeSetNames[j], + infofg, infobg, hicol, locol); + } + BTCreate(&cs->bt[TV_ML_ACCEPT], cs->win, + CSWIDE - 10 - BUTTW3 * 2, CSHIGH - 5 - BUTTH, BUTTW3, BUTTH, + "Accept", infofg, infobg, hicol, locol); + BTCreate(&cs->bt[TV_ML_CLOSE], cs->win, + CSWIDE - 5 - BUTTW3, CSHIGH - 5 - BUTTH, BUTTW3, BUTTH, + "Close", infofg, infobg, hicol, locol); + + XMapSubwindows(theDisp, cs->win); + cs->up = 0; + } +} + +static void openCsWin(tv) + TVINFO *tv; +{ + CSINFO *cs = tv->cs; + if (cs->up) + return; + + XMapRaised(theDisp, cs->win); + cs->up = 1; + cs->tcs = cs->tv->ccs; + csReflect(cs); +} + +static void closeCsWin(tv) + TVINFO *tv; +{ + CSINFO *cs = tv->cs; + if (!cs->up) + return; + cs->up = 0; + XUnmapWindow(theDisp, cs->win); +} + +int CharsetCheckEvent(xev) + XEvent *xev; +{ + int i; + CSINFO *cs; + + for (cs = csinfo, i = 0; i < MAXTVWIN; cs++, i++) { + if (!cs->up) + continue; + if (csCheckEvent(cs, xev)) + break; + } + if (i < MAXTVWIN) + return 1; + return 0; +} + +static int csCheckEvent(cs, xev) + CSINFO *cs; + XEvent *xev; +{ + TVINFO *tv = cs->tv; + RBUTT **rbp; + CBUTT *cbp; + LIST *ls; + BUTT *bp; + int i, j; + int n; + + if (xev->type == Expose) { + int x, y, w, h; + XExposeEvent *e = (XExposeEvent *) xev; + x = e->x; y = e->y; w = e->width; h = e->height; + + if (cs->win == e->window){ + csRedraw(cs); + return 1; + } else { + for (i = 0; i < TV_ML_NLISTS; i++) { + if (cs->ls[i].win == e->window) { + LSRedraw(&cs->ls[i], 0); + return 1; + } + } + for (i = 0; i < TV_ML_NLISTS; i++) { + if (cs->ls[i].scrl.win == e->window) { + SCRedraw(&cs->ls[i].scrl); + return 1; + } + } + } + } else if (xev->type == ButtonPress) { + int x, y; + XButtonEvent *e = (XButtonEvent *) xev; + x = e->x; y = e->y; + if (cs->win == e->window) { + for (bp = cs->bt, i = 0; i < TV_ML_NBUTTS; bp++, i++) { + if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) + break; + } + if (i < TV_ML_NBUTTS) { + if (BTTrack(bp)) { + if (i < TV_NCSS) { + cs->tcs = coding_spec[i]; + csReflect(cs); + } else { + switch (i) { + case TV_ML_ACCEPT: + setCodingSpec(cs->tv, &cs->tcs); + break; + case TV_ML_CLOSE: + closeCsWin(cs->tv); + break; + } + } + } + return 1; + } + for (cbp = cs->cbt, i = 0; i < TV_ML_NCBUTTS; cbp++, i++) { + if (CBClick(cbp, x, y) && CBTrack(cbp)) + break; + } + if (i < TV_ML_NCBUTTS) { + switch (i) { + case TV_ML_SHORT: + cs->tcs.coding_system.short_form = cbp->val; + break; + case TV_ML_LOCK: + cs->tcs.coding_system.lock_shift = cbp->val; + break; + } + return 1; + } + for (rbp = cs->rbt, i = 0; i < TV_ML_NRBUTTS; rbp++, i++) { + if ((n = RBClick(*rbp, x, y)) >= 0 && RBTrack(*rbp, n)) { + break; + } + } + if (i < TV_ML_NRBUTTS) { + switch (i) { + case TV_ML_RETCODE: + cs->tcs.coding_system.eol = n; + break; + case TV_ML_GL: + cs->tcs.coding_system.gl = n; + break; + case TV_ML_GR: + cs->tcs.coding_system.gr = n; + break; + case TV_ML_CVTR: + cs->tcs.converter = cvtrtab[n]; + break; + } + return 1; + } + } else { + for (ls = cs->ls, i = 0; i < TV_ML_NLISTS; ls++, i++) { + if (ls->win == e->window) { + LSClick(ls, e); + n = ls->selected; + if (n < nregs) { + char r[32], *p = r; + int b7; + strcpy(r, regs[n]); + if ((p = strrchr(r, '/')) != NULL) { + *p = '\0'; + b7 = (*(p + 1) == 'R' ? 1 : 0); + } else + b7 = 0; /* shouldn't occur */ + cs->tcs.coding_system.design[i] = lookup_design(r, b7); + } else if (n == nregs) /* initially none is designed. */ + cs->tcs.coding_system.design[i].bpc = 0; + else + cs->tcs.coding_system.design[i].bpc = -1; + return 1; + } + } + for (ls = cs->ls, i = 0; i < TV_ML_NLISTS; ls++, i++) { + if (ls->scrl.win == e->window) { + SCTrack(&ls->scrl, x, y); + return 1; + } + } + } + } + return 0; +} + +static void csReflect(cs) + CSINFO *cs; +{ + int i; + + RBSelect(cs->rbt[TV_ML_RETCODE], cs->tcs.coding_system.eol); + RBSelect(cs->rbt[TV_ML_GL], cs->tcs.coding_system.gl); + RBSelect(cs->rbt[TV_ML_GR], cs->tcs.coding_system.gr); + for (i = 0; i < sizeof cvtrtab / sizeof cvtrtab[0]; i++) { + if (cs->tcs.converter == cvtrtab[i]) + break; + } + if (i >= sizeof cvtrtab / sizeof cvtrtab[0]) + FatalError("program error in csReflect()."); + RBSelect(cs->rbt[TV_ML_CVTR], i); + + cs->cbt[TV_ML_SHORT].val = cs->tcs.coding_system.short_form; + cs->cbt[TV_ML_LOCK].val = cs->tcs.coding_system.lock_shift; + for (i = 0; i < TV_ML_NLISTS; i++) { + struct design design = cs->tcs.coding_system.design[i]; + char *reg, r[32]; + int b7; + int n = 0; + switch (design.bpc) { + case -1: + n = nregs + 1; + break; + case 0: + n = nregs; + break; + case 1: + case 2: + if ((reg = lookup_registry(design, &b7)) == NULL) + FatalError("internal error in csReflect."); + sprintf(r, "%s/%s", reg, b7 ? "Right" : "Left"); + for (n = 0; n < nregs; n++) { + if (strcmp(regs[n], r) == 0) + break; + } + } + cs->ls[i].selected = n; + ScrollToCurrent(&cs->ls[i]); + } + csRedraw(cs); + for (i = 0; i < TV_ML_NLISTS; i++) + csListRedraw(&cs->ls[i]); +} + +static void csRedraw(cs) + CSINFO *cs; +{ + int i; + + XSetForeground(theDisp, theGC, infofg); + DrawString(cs->win, 5,5 + ASCENT, "Initial States"); + for (i = 0; i < TV_ML_NLISTS; i++) { + int x, y; + char buf[80]; + + if (i / 2 == 0) + x = 15; + else + x = 280; + if (i % 2 == 0) + y = 5 + LINEHIGH * 1; + else + y = 5 + LINEHIGH * 7 + SPACING * 3; + + sprintf(buf, "Designation for G%d:", i); + DrawString(cs->win, x, y + ASCENT, buf); + } + + DrawString(cs->win, 15, 235 + ASCENT, "Invocation for GL:"); + DrawString(cs->win, 280, 235 + ASCENT, "Invocation for GR:"); + DrawString(cs->win, 5, 280 + ASCENT, "Ret Code:"); + DrawString(cs->win, 350, 280 + ASCENT, "Converter:"); + + for (i = 0; i < TV_ML_NBUTTS; i++) + BTRedraw(&cs->bt[i]); + for (i = 0; i < TV_ML_NCBUTTS; i++) + CBRedraw(&cs->cbt[i]); + for (i = 0; i < TV_ML_NRBUTTS; i++) + RBRedraw(cs->rbt[i], -1); +} + +static void csListRedraw(ls) + LIST *ls; +{ + int i; + for (i = 0; i < TV_ML_NLISTS; i++) { + LSRedraw(ls, 0); + SCRedraw(&ls->scrl); + } +} + +static void csLsRedraw(delta, sptr) + int delta; + SCRL *sptr; +{ + int i, j; + for (i = 0; i < MAXTVWIN; i++) { + for (j = 0; j < TV_ML_NLISTS; j++) { + if (sptr == &csinfo[i].ls[j].scrl) { + LSRedraw(&csinfo[i].ls[j], delta); + return; + } + } + } +} + +int CharsetDelWin(win) + Window win; +{ + CSINFO *cs; + int i; + + for (cs = csinfo, i = 0; i < TV_NCSS; cs++, i++) { + if (cs->win == win) { + if (cs->up) { + XUnmapWindow(theDisp, cs->win); + cs->up = 0; + } + return 1; + } + } + return 0; +} + +static int reg_comp PARM((const void *, const void *)); +static void create_registry_list() +{ + struct design d; + char *names, *p; + int i; + + if ((p = names = (char *) malloc(32 * 0x80 * 2 * 2)) == NULL) + FatalError("out of memory in create_name_list#1."); + nregs = 0; + for (d.bpc = 1; d.bpc <=2; d.bpc++) { + for (d.noc = 94; d.noc <= 96; d.noc += 2) { + for (d.des = ' '; (unsigned char) d.des < 0x80; d.des++) { + int b7; + char *r; + if ((r = lookup_registry(d, &b7)) != NULL) { + sprintf(p, "%s/%s", r, b7 ? "Right" : "Left"); + p += strlen(p) + 1; + nregs++; + } + } + } + } + if ((names = (char *) realloc(names, (size_t) (p - names))) == NULL) + FatalError("out of memory in create_name_list#2."); + if ((regs = (char **) malloc(sizeof(char *) * (nregs + 3))) == NULL) + FatalError("out of memory in create_name_list#3."); + p = names; + for (i = 0; i < nregs; i++) { + regs[i] = p; + p += strlen(p) + 1; + } + qsort(regs, (size_t) nregs, sizeof(char *), reg_comp); + regs[i++] = "nothing"; + regs[i++] = "unused"; + regs[i++] = NULL; +} +static int reg_comp(dst, src) + const void *dst, *src; +{ + return strcmp(*(char **) dst, *(char **) src); +} + +#endif diff -urN xv-3.10a/xvtiff.c xv-3.10a-jp-extension-current/xvtiff.c --- xv-3.10a/xvtiff.c Sat Jan 14 04:53:34 1995 +++ xv-3.10a-jp-extension-current/xvtiff.c Wed Oct 9 20:36:29 1996 @@ -1381,7 +1381,7 @@ } } -#define Code2V(c, RB, RW, CR) ((((c)-(int)RB)*(float)CR)/(float)(RW-RB)) +#define Code2V(c, RB, RW, CR) ((((int)(c)-(int)RB)*(float)CR)/(float)(RW-RB)) #define CLAMP(f,min,max) \ (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5) diff -urN xv-3.10a/xvvd.c xv-3.10a-jp-extension-current/xvvd.c --- xv-3.10a/xvvd.c +++ xv-3.10a-jp-extension-current/xvvd.c Wed Oct 9 20:37:21 1996 @@ -0,0 +1,1069 @@ + +/* + * xvvd.c - extract archived file automatically and regard it as a + * directory. + */ + +#define NEEDSDIR + +#include "xv.h" + +#ifdef AUTO_EXPAND + +static void vd_Dirtovd PARM((char *)); +static void vd_Vdtodir PARM((char *)); +static int vd_Mkvdir PARM((char *)); +static int vd_Rmvdir PARM((char *)); +static int vd_Movevdir PARM((char *, char *)); +static void vd_addvdtable PARM((char *)); +static void vd_packvdtable PARM((void)); +static int vd_recursive_mkdir PARM((char *)); +static int vd_recursive_rmdir PARM((char *)); +static void vd_optimize_path PARM((char *)); +static int vd_ftype PARM((char *)); +static int vd_compp PARM((char *, char *)); +static int vd_UncompressFile PARM((char *, char *)); +static int vd_tarc PARM((char *)); +static u_int vd_tar_sumchk PARM((char *)); + +#define VD_VDTABLESIZE 100 + +#define VD_ERR -2 +#define VD_UKN -1 + +static char *ext_command[] = { +/* KEEP 0 */ + NULL, +#define VD_ARC 1 + "arc xo %s", +#define VD_ARJ 2 + "unarj x %s", +#define VD_LZH 3 + "lha -xf %s", +#define VD_TAR 4 + "tar xvf %s", +#define VD_ZIP 5 + "unzip -xo %s", +#define VD_ZOO 6 + "zoo xOS %s", +}; + +int vdcount = 0; + +static char vdroot[MAXPATHLEN+1]; +static char *vdtable[VD_VDTABLESIZE]; + +/* + * These functions initialize and settle virtual directory system. + * Vdinit: + * creates root of virtual directory. + * Vdsettle: + * sweeps virtual directories. + */ +void Vdinit() +{ +#ifndef VMS + char tmp[MAXPATHLEN+1]; + + xv_getwd(tmp, MAXPATHLEN+1); + if (chdir(tmpdir)) { + fprintf(stderr, "Warning: cannot chdir to tmpdir = '%s'.\n", tmpdir); + fprintf(stderr, + " I use current directory '%s' instead of tmpdir.\n", + tmp); + } + xv_getwd(vdroot, MAXPATHLEN+1); + strcat(vdroot, "/.xvvdXXXXXX"); + chdir(tmp); +#else + sprintf(vdroot, "Sys$Scratch:xvvdXXXXXX"); +#endif /* VMS */ + mktemp(vdroot); +} + +void Vdsettle() +{ + int i; + + for (i = 0; i < vdcount; i++) + free(vdtable[i]); + + vdcount = 0; + + vd_recursive_rmdir(vdroot); +} + +/* + * This function chdir to virtual directory, if specified path is in + * virtual directlry. + */ +int Chvdir(dir) +char *dir; +{ + char buf[MAXPATHLEN+1]; + + if (Mkvdir(dir) == VD_ERR) + return -1; + + strcpy(buf, dir); + Dirtovd(buf); + + return (chdir(buf)); +} + +/* + * These functions convert directory <-> virtual directory. + * Dirtovd: + * front interface of vd_Dirtovd. + * vd_Dirtovd: + * converts directory to virtual directry. + * Vdtodir: + * front interface of vd_Vdtodir. + * vd_Vdtodir: + * converts virtual directry to normal directory. + * Dirtosubst: + * converts directry to substance of archive. + */ +void Dirtovd(dir) +char *dir; +{ + int i; + + vd_optimize_path(dir); + + vd_Dirtovd(dir); +} + +static void vd_Dirtovd(dir) +char *dir; +{ + int i; + + for (i = 0; i < vdcount; i++) + if (!strncmp(dir, vdtable[i], strlen(vdtable[i]))) { + char tmp[MAXPATHLEN+1]; + + sprintf(tmp, "%s%s", vdroot, dir); + strcpy(dir, tmp); + Dirtovd(dir); + } +} + +void Vdtodir(dir) +char *dir; +{ + int i; + + vd_optimize_path(dir); + + vd_Vdtodir(dir); +} + +static void vd_Vdtodir(vd) +char *vd; +{ + int i; + char tmp[MAXPATHLEN+1]; + + for (i = vdcount-1; i >= 0; i--) { + sprintf(tmp, "%s%s", vdroot, vdtable[i]); + if(!strncmp(vd, tmp, strlen(tmp))) { + strcpy(tmp, vd+strlen(vdroot)); + strcpy(vd, tmp); + Vdtodir(vd); + } + } +} + +void Dirtosubst(dir) +char *dir; +{ + char tmp[MAXPATHLEN+1]; + + Dirtovd(dir); + + strcpy(tmp, dir+strlen(vdroot)); + + if (Isarchive(tmp)) + strcpy(dir, tmp); +} + +/* + * These functions make virtual directory and extracts archive, if + * specified path is archive. + * Mkvdir: + * front interface of vd_Mkvdir. + * vd_Mkvdir: + * does real work. + * Mkvdir_force: (used by makeThumbDir(in xvbrowse.c) only) + * make virtual directory by force. + */ +int Mkvdir(dir) +char *dir; +{ + char dir1[MAXPATHLEN+1], dir2[MAXPATHLEN+1]; + char *d1, *d2; + int rv; + +#if defined(SYSV) || defined(SVR4) + sighold(SIGHUP); + sighold(SIGCHLD); +#else + int mask; + mask = sigblock(sigmask(SIGHUP)|sigmask(SIGCHLD)); +#endif + + strcpy(dir1, dir); + vd_optimize_path(dir1); + + if ((rv = vd_Mkvdir(dir1)) != VD_ERR) + goto MKVDIR_END; + + strcpy(dir2, dir1); + d2 = dir2 + strlen(dir2); + while (rv == VD_ERR) { + d2--; + while (*d2 != '/') + d2--; + *d2 = '\0'; + rv = vd_Mkvdir(dir2); + } + d1 = dir1 + strlen(dir2); + while ((rv != VD_ERR) && (*d1 != '\0')) { + *d2++ = *d1++; + while ((*d1 != '/') && (*d1 != '\0')) + *d2++ = *d1++; + *d2 = '\0'; + rv = vd_Mkvdir(dir2); + } + +MKVDIR_END: +#if defined(SYSV) || defined(SVR4) + sigrelse(SIGHUP); + sigrelse(SIGCHLD); +#else + sigsetmask(mask); +#endif + + return rv; +} + +static int vd_Mkvdir(dir) +char *dir; +{ + char dir1[MAXPATHLEN+1], dir2[MAXPATHLEN+1], tmp[MAXPATHLEN+1]; + int ftype, i; + struct stat st; + FILE *pfp; + + strcpy(dir1, dir); + Dirtovd(dir1); + strcpy(dir2, dir1); + + WaitCursor(); + + if ((ftype = vd_ftype(dir1)) < 0) { + SetCursors(-1); + return ftype; + } + if (ftype == RFT_COMPRESS) { + if (!(ftype = vd_compp(dir1, tmp))) { + SetCursors(-1); + return ftype; + } + strcpy(dir1, tmp); + } + + if (!stat(dir1, &st)) { + for(i = 0; i < vdcount; i++) + if (!strcmp(vdtable[i], dir2)) { + SetCursors(-1); + return 0; + } + + if (!S_ISDIR(st.st_mode)) { + char origdir[MAXPATHLEN+1], buf[MAXPATHLEN+10], buf1[100]; + + if (vdcount >= VD_VDTABLESIZE) { + ErrPopUp("Sory, you can't make virtual directory any more.", + "\nBummer!"); + goto VD_MKVDIR_ERR; + } + + WaitCursor(); + + xv_getwd(origdir, MAXPATHLEN+1); + + sprintf(tmp, "%s%s", vdroot, dir2); + if (vd_recursive_mkdir(tmp) || chdir(tmp)) { + SetISTR(ISTR_INFO, "fail to make virtual directory."); + Warning(); + goto VD_MKVDIR_ERR; + } + sprintf(buf, ext_command[ftype], dir1); + + WaitCursor(); + + if((pfp = popen(buf, "r")) == NULL) { + SetISTR(ISTR_INFO, "fail to extract archive '%s'.", + BaseName(dir2)); + Warning(); + goto VD_MKVDIR_ERR; + } + while (1) { + if (fread(buf1, 1, sizeof(buf1), pfp) < sizeof(buf1)) + break; + WaitCursor(); + } + if (!feof(pfp)) { + SetISTR(ISTR_INFO, "Pipe was broken."); + Warning(); + pclose(pfp); + goto VD_MKVDIR_ERR; + } + pclose(pfp); + + if (strcmp(dir1, dir2)) + unlink(dir1); + + vd_addvdtable(dir2); + Dirtovd(origdir); + chdir(origdir); + SetCursors(-1); + return 0; + +VD_MKVDIR_ERR: + if (strcmp(dir1, dir2)) + unlink(dir1); + SetCursors(-1); + return VD_ERR; + } + } + SetCursors(-1); + return VD_ERR; +} + +#ifdef VIRTUAL_TD +void Mkvdir_force(dir) +char *dir; +{ + char tmp[MAXPATHLEN+1]; + + if (vdcount >= VD_VDTABLESIZE) { + ErrPopUp("Sory, you can't make virtual directory any more.", + "\nBummer!"); + return; + } + + sprintf(tmp, "%s%s", vdroot, dir); + if (vd_recursive_mkdir(tmp)) { + SetISTR(ISTR_INFO, "fail to make virtual directory."); + Warning(); + return; + } + + vd_addvdtable(dir); +} +#endif /* VIRTUAL_TD */ + +/* + * These functions remove virtual directory, if exists. + * Rmvdir: + * front interface of vd_Rmvdir. + * vd_Rmvdir: + * remove virtual directory function. + */ +int Rmvdir(dir) +char *dir; +{ + int rv; + char buf[MAXPATHLEN+1]; + + strcpy(buf, dir); + vd_optimize_path(buf); + + rv = vd_Rmvdir(buf); + vd_packvdtable(); + return rv; +} + +static int vd_Rmvdir(dir) +char *dir; +{ + int i; + char tmp[MAXPATHLEN+1]; + + for(i = 0; i < vdcount; i++) + if (!strncmp(dir, vdtable[i], strlen(dir))) { + sprintf(tmp, "%s%s", vdroot, vdtable[i]); + if (vd_Rmvdir(tmp)) + return 1; + if (vd_recursive_rmdir(tmp)) + return 1; + vdtable[i][0] = '\0'; + } + return 0; +} + +/* + * These functions move virtual directory, if exists. + * Movevdir: + * front interface of move virtual directory function. + * vd_Movevdir: + * does real works. + */ +int Movevdir(src, dst) +char *src, *dst; +{ +/* + char sbuf[MAXPATHLEN+1], dbuf[MAXPATHLEN+1]; + + strcpy(sbuf, src); + vd_optimize_path(sbuf); + + strcpy(dbuf, dst); + vd_optimize_path(dbuf); + + return (vd_Movevdir(sbuf, dbuf)); +*/ + return (vd_Movevdir(src, dst)); +} + +static int vd_Movevdir(src, dst) +char *src, *dst; +{ + int i; + char *p, *pp; + char tmp[MAXPATHLEN+1], tmps[MAXPATHLEN+1], tmpd[MAXPATHLEN+1]; + + for (i = 0; i < vdcount; i++) + if (!strncmp(src, vdtable[i], strlen(src))) { + sprintf(tmps, "%s%s", vdroot, vdtable[i]); + sprintf(tmp, "%s%s", dst, vdtable[i]+strlen(src)); + sprintf(tmpd, "%s%s", vdroot, tmp); + + if (vd_Movevdir(tmps, tmpd)) + return 1; + + pp = vdtable[i]; + p = (char *) malloc(strlen(tmp)+1); + strcpy(p, tmp); + vdtable[i] = p; + + strcpy(tmp, tmpd); + for (p = tmp+strlen(tmp); *p != '/'; p--) + ; + *p = '\0'; + + if (vd_recursive_mkdir(tmp)) + goto VD_MOVEVDIR_ERR; + + if (rename(tmps, tmpd) < 0) + goto VD_MOVEVDIR_ERR; + + free(pp); + } + return 0; + +VD_MOVEVDIR_ERR: + free(vdtable[i]); + vdtable[i] = pp; + return 1; +} + +/* + * These functions handle table of virual directories. + * vd_addvdtable: + * add virtual directory to table. + * vd_packvdtable: + * remove disused virtual directories from table. + */ +static void vd_addvdtable(vd) +char *vd; +{ + char *p; + p = (char *) malloc(strlen(vd)+1); + strcpy(p, vd); + vdtable[vdcount] = p; + vdcount++; +} + +static void vd_packvdtable() +{ + int i, j; + + for (i = j = 0; i < vdcount; i++) + if (vdtable[i][0] != '\0') + vdtable[j++] = vdtable[i]; + else + free(vdtable[i]); + + vdcount = j; +} + +/* + * These are utility functions. + * vd_recursive_mkdir: + * make directories recursively. + * vd_recursive_rmdir + * remove directories recursively. + */ +static int vd_recursive_mkdir(dir) +char *dir; +{ + char buf[MAXPATHLEN+1], *p; + struct stat st; + + strcpy(buf, dir); + + if (buf[strlen(buf) - 1] == '/') + buf[strlen(buf) - 1] = '\0'; + + p = rindex(buf, '/'); + *p = '\0'; + + if (stat(buf, &st) < 0) + if (vd_recursive_mkdir(buf) < 0) + return (-1); + + *p = '/'; + if (mkdir(buf, 0700) < 0) + return (-1); + + return (0); +} + +static int vd_recursive_rmdir(dir) +char *dir; +{ + char buf[MAXPATHLEN+1], buf2[MAXPATHLEN+1]; + DIR *dp; + struct dirent *di; + + strcpy(buf, dir); + + if (buf[strlen(buf) - 1] == '/') + buf[strlen(buf) - 1] = '\0'; + + if ((dp = opendir(buf)) == NULL) + return (-1); + + while ((di = readdir(dp)) != NULL) { + struct stat st; + + if (!strcmp(di->d_name, ".") || !strcmp(di->d_name, "..")) + continue; + + sprintf(buf2, "%s/%s", dir, di->d_name); + + stat(buf2, &st); + if (S_ISDIR(st.st_mode)) { + if (vd_recursive_rmdir(buf2) < 0) + goto VD_RECURSIVE_RMDIR_ERR; + } else + unlink(buf2); + } + if (rmdir(buf) < 0) + goto VD_RECURSIVE_RMDIR_ERR; + + closedir(dp); + return (0); + +VD_RECURSIVE_RMDIR_ERR: + closedir(dp); + return (-1); +} + +/* + * These functions tests specified path. + * Isarchive: + * tests, is it archive? + * Isvdir: + * tests, is it in the virtual directory? + */ +int Isarchive(path) +char *path; +{ + int ftype; + + if ((ftype = vd_ftype(path)) < 0) + return 0; + + if (ftype == RFT_COMPRESS) + if (!(ftype = vd_compp(path, NULL))) + return 0; + + return ftype; +} + +int Isvdir(path) +char *path; +{ + int rv = 0; + char tmp1[MAXPATHLEN+1], tmp2[MAXPATHLEN+1]; + int archive1, archive2; + + strcpy(tmp1, path); + strcpy(tmp2, path); + + vd_optimize_path(tmp1); + Dirtovd(tmp2); + + archive1 = Isarchive(tmp1); + archive2 = Isarchive(tmp2); + + if (strcmp(tmp1, tmp2)) { + char tmp3[MAXPATHLEN+1], tmp4[MAXPATHLEN+1]; + int archive3, archive4; + + sprintf(tmp3, "%s%s", vdroot, tmp1); + strcpy(tmp4, tmp2+strlen(vdroot)); + + archive3 = Isarchive(tmp3); + archive4 = Isarchive(tmp4); + + if (archive4 && !strcmp(tmp1, tmp4)) { + rv |= 06; + return rv; + } + rv |= 01; + if (archive2) + rv |= 02; + else if (archive4) + rv |= 06; + return rv; + } + if (archive1) + rv |= 02; + + return rv; +} + +/* + * This function optimizes given path. + * Expand '~' to home directory and removes '.', and treat '..'. + */ +static void vd_optimize_path(path) +char *path; +{ + char *tmp, *reserve; + + if (!strcmp(path, STDINSTR)) + return; + + if (*path == '\0') { + xv_getwd(path, MAXPATHLEN+1); + return; + } + if (*path == '~') + Globify(path); + if (*path != '/') { + char tmp[MAXPATHLEN+1]; + + strcpy(tmp, path); + xv_getwd(path, MAXPATHLEN+1); + strcat(path, "/"); + strcat(path, tmp); + } + + reserve = tmp = path; + while(*path != '\0') { + if (*path == '/') { + *tmp++ = *path; + while (*++path == '/') + ; + continue; + } + if ((*path == '.') && (*(path-1) == '/')) { + if (*(path+1) == '/') { + tmp--; + path++; + continue; + } else if (*(path+1) == '\0') { + tmp--; + break; + } else if (*(path+1) == '.') + if (*(path+2) == '/') { + if ((tmp - reserve) > 1) + for (tmp-=2; (*tmp != '/'); tmp--) + ; + else + tmp = reserve; + path+=2; + continue; + } else if (*(path+2) == '\0') { + if ((tmp - reserve) > 1) + for (tmp-=2; (*tmp != '/'); tmp--) + ; + else + tmp = reserve+1; + break; + } + } + *tmp++ = *path++; + } + if (((tmp - reserve) > 1) && *(tmp-1) == '/') + tmp--; + if (tmp == reserve) + *tmp++ = '/'; + + *tmp = '\0'; +} + +/* + * These functions dicide file type. + */ +static int vd_ftype(fname) +char *fname; +{ + /* check archive type */ + + FILE *fp; + byte magicno[30]; /* first 30 bytes of file */ + int rv, n; + struct stat st; + + if (!fname) return VD_ERR; /* shouldn't happen */ + + if ((!stat(fname, &st)) && (st.st_mode & S_IFMT) == S_IFDIR) + return VD_UKN; + fp = xv_fopen(fname, "r"); + if (!fp) return VD_ERR; + + n = fread(magicno, (size_t) 1, (size_t) 30, fp); + fclose(fp); + + if (n<30) return VD_UKN; /* files less than 30 bytes long... */ + + rv = VD_UKN; + + if (magicno[0] == 0x60 && magicno[1]==0xea) rv = VD_ARJ; + + else if (magicno[2] == '-' && magicno[3] == 'l' && + magicno[4] == 'h') rv = VD_LZH; + + else if (strncmp((char *) magicno,"PK", (size_t) 2)==0) rv = VD_ZIP; + + else if (magicno[20]==0xdc && magicno[21]==0xa7 && + magicno[22]==0xc4 && magicno[23]==0xfd) rv = VD_ZOO; + + else if (vd_tarc(fname)) rv = VD_TAR; + + else if (magicno[0]==0x1f && magicno[1]==0x9d) rv = RFT_COMPRESS; + + else if (!strncmp((char *) &magicno[11], "MAJYO", (size_t) 5)) + rv = VD_UKN; /* XXX */ + + else if (magicno[0] == 26) rv = VD_ARC; + +#ifdef GUNZIP + else if (magicno[0]==0x1f && magicno[1]==0x8b) rv = RFT_COMPRESS;/* gzip */ + else if (magicno[0]==0x1f && magicno[1]==0x9e) rv = RFT_COMPRESS;/* old */ + else if (magicno[0]==0x1f && magicno[1]==0x1e) rv = RFT_COMPRESS;/* pack */ +#endif + + return rv; +} + +static int vd_compp(path, newpath) +char *path, *newpath; +{ + /* + * uncompress and check archive type. + * + * If newpath is NULL, uncompress only 512 byte of 'path' and + * check archive type, so it is for SPEED-UP strategy. + * In this case, caller this function does not have to unlink + * tempoary file. + * Unfortunately it does not work in VMS system. + */ + + int file_type, r; + char uncompname[128], basename[128]; + + if (newpath) *newpath = '\0'; + strcpy(basename, path); +#if (defined(VMS) && !defined(GUNZIP)) + /* VMS decompress doesn't like the file to have a trailing .Z in fname + however, GUnZip is OK with it, which we are calling UnCompress */ + *rindex (basename, '.') = '\0'; +#endif +#ifdef VMS + if (UncompressFile(basename, uncompname)) { +#else + if (newpath == NULL) + r = vd_UncompressFile(basename, uncompname); + else + r = UncompressFile(basename, uncompname); + if (r) { +#endif + if ((file_type = vd_ftype(uncompname)) < 0) { + unlink(uncompname); + return 0; + } + if (newpath) strcpy(newpath, uncompname); + else unlink(uncompname); + } else { + return 0; + } + return file_type; +} + +#define HEADERSIZE 512 + +static void vd_Dirtovd PARM((char *)); +static int stderr_on PARM((void)); +static int stderr_off PARM((void)); +static FILE *popen_nul PARM((char *, char *)); + +static int vd_UncompressFile(name, uncompname) +char *name, *uncompname; +{ + /* Yap, I`m nearly same as original `UncompnameFile' function, but, + 1) I extract `name' file ONLY first 512 byte. + 2) I'm called only from UNIX and UNIX like OS, *NOT* VMS */ + /* returns '1' on success, with name of uncompressed file in uncompname + returns '0' on failure */ + + char namez[128], *fname, buf[512], tmp[HEADERSIZE]; + int n; + FILE *pfp, *tfp; + + fname = name; + namez[0] = '\0'; + + +#ifndef GUNZIP + /* see if compressed file name ends with '.Z'. If it *doesn't* we need + temporarly 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 GUNZIP */ + + sprintf(uncompname, "%s/xvuXXXXXX", tmpdir); + mktemp(uncompname); + sprintf(buf,"%s -c %s", UNCOMPRESS, fname); + + SetISTR(ISTR_INFO, "Uncompressing Header '%s'...", BaseName(fname)); + if ((pfp = popen_nul(buf, "r")) == NULL) { + SetISTR(ISTR_INFO, "Cannot extract for archive '%s'.", + BaseName(fname)); + Warning(); + return 0; + } + if ((tfp = fopen(uncompname, "w")) == NULL) { + SetISTR(ISTR_INFO, "Unable to create temporarly file.", + BaseName(uncompname)); + Warning(); + pclose(pfp); + return 0; + } + if ((n = fread(tmp, 1, sizeof(tmp), pfp)) != HEADERSIZE) { + SetISTR(ISTR_INFO, "Unable to read '%s'.", + BaseName(fname)); + Warning(); + pclose(pfp); + fclose(tfp); + return 0; + } + fwrite(tmp, 1, n, tfp); + fclose(tfp); + pclose(pfp); + + /* if we renamed the file to end with a .Z for the sake of 'uncompress', + rename it back to what it once was... */ + + if (strlen(namez)) { + if (rename(namez, name) < 0) { + sprintf(buf, "Error renaming '%s' to '%s': %s", + namez, name, ERRSTR(errno)); + ErrPopUp(buf, "\nBummer!"); + } + } + + return 1; +} + +#define TARBLOCK 512 +#define CKSTART 148 /* XXX */ +#define CKSIZE 8 + +/* + * Tar file: 1, other: 0 + */ +static int vd_tarc(fname) +char *fname; +{ + FILE *fp; + unsigned int sum; + char *ckp, buf[TARBLOCK]; + + if ((fp = fopen(fname, "r")) == NULL) + return 0; + + fread(buf, TARBLOCK, 1, fp); + fclose(fp); + + for (sum = 0, ckp = buf + CKSTART; + (ckp < buf + CKSTART + CKSIZE) && *ckp != '\0'; + ckp++) { + sum *= 8; + if (*ckp == ' ') + continue; + if (*ckp < '0' || '7' < *ckp) + return 0; + sum += *ckp - '0'; + } + if (sum != vd_tar_sumchk(buf)) + return 0; + + return 1; +} + +static unsigned int vd_tar_sumchk(buf) +char *buf; +{ + int i; + unsigned int sum = 0; + + for (i = 0; i < CKSTART; i++) { + sum += *(buf + i); + } + sum += ' ' * 8; + for (i += 8; i < TARBLOCK; i++) { + sum += *(buf + i); + } + return sum; +} + + +static stde = -1; /* fd of stderr */ +static nul = -1; /* fd of /dev/null */ + +/* + * switch off the output to stderr(bypass to /dev/null). + */ +static int stderr_off() +{ + if (nul < 0) + nul = open("/dev/null", O_RDONLY); + if (nul < 0) { + fprintf(stderr, "/dev/null open failure\n"); + return -1; + } + if (stde < 0) + stde = dup(2); + if (stde < 0) { + fprintf(stderr, "duplicate stderr failure\n"); + return -1; + } + close(2); + dup(nul); + return 0; +} + +/* + * turn on stderr output. + */ +static int stderr_on() +{ + if ((stde < 0) || (nul < 0)) { + fprintf(stderr, "stderr_on should call after stderr_off\n"); + return -1; + } + close(2); + dup(stde); + return 0; +} + +/* + * popen with no output to stderr. + */ +static FILE *popen_nul(prog, mode) +char *prog, *mode; +{ + FILE *fp; + + stderr_off(); + fp = popen(prog, mode); + stderr_on(); + return fp; +} + +/* + * These functions are for SIGNAL. + * If XV end by C-c, there are dust of directory which name is .xvvd???, + * made by xvvd. Then, I handle SIGINT, and add good finish. + */ +void vd_HUPhandler() +{ +#if defined(SYSV) || defined(SVR4) + sighold(SIGHUP); +#else + int mask; + mask = sigblock(sigmask(SIGHUP)); +#endif + + Vdsettle(); + +#if defined(SYSV) || defined(SVR4) + sigrelse(SIGHUP); + signal(SIGHUP, (void (*)PARM((int))) vd_HUPhandler); +#else + sigsetmask(mask); +#endif +} + +void vd_handler(sig) +int sig; +{ +#if defined(SYSV) || defined(SVR4) + sighold(sig); +#else + sigblock(sigmask(sig)); +#endif + + Quit(1); /*exit(1);*/ +} + +int vd_Xhandler(disp,event) +Display *disp; +XErrorEvent *event; +{ + Quit(1); /*exit(1);*/ +} + +int vd_XIOhandler(disp) +Display *disp; +{ + fprintf(stderr, "XIO fatal IO error ? (?) on X server\n"); + fprintf(stderr, "You must normal exit in xv usage.\n"); + Quit(1); /*exit(1);*/ +} + +void vd_handler_setup() +{ + signal(SIGHUP, (void (*)PARM((int))) vd_HUPhandler); + signal(SIGINT, (void (*)PARM((int))) vd_handler); + signal(SIGTERM,(void (*)PARM((int))) vd_handler); + + XSetErrorHandler(vd_Xhandler); + XSetIOErrorHandler(vd_XIOhandler); +} +#endif /* AUTO_EXPAND */