summaryrefslogtreecommitdiff
path: root/dviware/dvipaste
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvipaste
Initial commit
Diffstat (limited to 'dviware/dvipaste')
-rw-r--r--dviware/dvipaste/DOS-EXE/DVIPASTE.EXEbin0 -> 42339 bytes
-rw-r--r--dviware/dvipaste/Makefile38
-rw-r--r--dviware/dvipaste/NOTE42
-rw-r--r--dviware/dvipaste/config.MS.h6
-rw-r--r--dviware/dvipaste/config.h14
-rw-r--r--dviware/dvipaste/config.sun-gcc.h14
-rw-r--r--dviware/dvipaste/dvipaste.c2035
-rw-r--r--dviware/dvipaste/dvipaste.doc145
-rw-r--r--dviware/dvipaste/dvipaste.patch.0176
l---------dviware/dvipaste/dvipaste.txt1
-rw-r--r--dviware/dvipaste/test/boxes1.tex27
-rw-r--r--dviware/dvipaste/test/boxes2.tex19
-rw-r--r--dviware/dvipaste/test/dvipaste.tex331
-rw-r--r--dviware/dvipaste/test/join.tex37
14 files changed, 2785 insertions, 0 deletions
diff --git a/dviware/dvipaste/DOS-EXE/DVIPASTE.EXE b/dviware/dvipaste/DOS-EXE/DVIPASTE.EXE
new file mode 100644
index 0000000000..7184319b9d
--- /dev/null
+++ b/dviware/dvipaste/DOS-EXE/DVIPASTE.EXE
Binary files differ
diff --git a/dviware/dvipaste/Makefile b/dviware/dvipaste/Makefile
new file mode 100644
index 0000000000..1368ae8eb6
--- /dev/null
+++ b/dviware/dvipaste/Makefile
@@ -0,0 +1,38 @@
+# Makefile for TeXplorators dvipaste
+#
+# config.sun-gcc.h is supplied as a model.
+# UnixTeX would like to hear of any interesting
+# configuration files for other systems.
+# Copy the appropriate config.*.h to config.h
+# then make
+#
+# This Makefile may not work for MSDOS. Make your
+# own one, or compile by hand.
+#
+CFLAGS = -g
+CC = gcc
+
+all: dvipaste
+
+dvipaste: dvipaste.o
+ cc -o dvipaste dvipaste.o
+
+dvipaste.o: dvipaste.c config.h
+
+config.h:
+ @if test ! -f config.h ; then \
+ echo "You must first copy the right config.*.h file" ; \
+ echo "into config.h" ; exit 1 ; \
+ fi
+
+test: ./test/boxes1.tex ./test/boxes2.tex \
+ ./test/dvipaste.tex ./test/join.tex
+ -(cd test ; tex boxes1 ; tex boxes2 ; tex join ; \
+ ../dvipaste join newjoin )
+
+clean:
+ rm -f *.o *~ \#* core *.log
+
+veryclean: clean
+ rm -f config.h dvipaste *.dat *.dvi
+ (cd test ; rm -rf *.dvi *.log)
diff --git a/dviware/dvipaste/NOTE b/dviware/dvipaste/NOTE
new file mode 100644
index 0000000000..8b008ea53f
--- /dev/null
+++ b/dviware/dvipaste/NOTE
@@ -0,0 +1,42 @@
+
+[ This is ./DVIware/dvitools/dvipaste/NOTE
+ for users of the Unix TeX distribution.
+
+ August 1991 ]
+
+
+Instructions are in the Makefile. Make all, make test,
+then install the executable.
+
+From the "LAMS-TeX Installation Manual":
+
+ Although the "dvipaste" program was written
+ specifically for LAMS-TeX, it can actually
+ be used for numerous general TeX purposes,
+ in conjunction with an extra macro package
+ "dvipaste.tex." The file "dvipaste.doc"
+ describes such usage, which is further
+ illustrated by the files "boxes1.tex,"
+ "boxes2.tex," and "join.tex."
+
+
+You will find dvipaste.doc in this directory.
+
+The *.tex files mentioned above, however, are in the directory
+./TeX3.14/LAMS-TeX/inputs.
+
+The "dvipaste" program, originally for DOS and Macintosh
+systems, has been ported to Unix by Pierre MacKay. Gcc
+compiles it readily, with or without optimization.
+
+Cc complains about macro recursion near the end of the file.
+If you fix this problem, please let us know.
+
+
+E-mail: mackay@cs.washington.edu
+ elisabet#max.u.washington.edu
+
+Phone: (206) 543-6259
+
+
+============================EOF===============================
diff --git a/dviware/dvipaste/config.MS.h b/dviware/dvipaste/config.MS.h
new file mode 100644
index 0000000000..28244eca43
--- /dev/null
+++ b/dviware/dvipaste/config.MS.h
@@ -0,0 +1,6 @@
+/* default environment */
+#define MICROSOFTC
+#define LITTLENDIAN
+#define ANSI
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
diff --git a/dviware/dvipaste/config.h b/dviware/dvipaste/config.h
new file mode 100644
index 0000000000..5d9442863b
--- /dev/null
+++ b/dviware/dvipaste/config.h
@@ -0,0 +1,14 @@
+#define int short
+#undef ANSI /* To use old-style K&R functions */
+#undef MICROSOFTC
+#undef LITTLENDIAN
+
+#ifdef ANSI
+/* Other things in ANSI C are good, but this is a crock */
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
+#else
+/* The good old simple and logical K&R I/O */
+#define READ_BINARY "r"
+#define WRITE_BINARY "w"
+#endif
diff --git a/dviware/dvipaste/config.sun-gcc.h b/dviware/dvipaste/config.sun-gcc.h
new file mode 100644
index 0000000000..5d9442863b
--- /dev/null
+++ b/dviware/dvipaste/config.sun-gcc.h
@@ -0,0 +1,14 @@
+#define int short
+#undef ANSI /* To use old-style K&R functions */
+#undef MICROSOFTC
+#undef LITTLENDIAN
+
+#ifdef ANSI
+/* Other things in ANSI C are good, but this is a crock */
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
+#else
+/* The good old simple and logical K&R I/O */
+#define READ_BINARY "r"
+#define WRITE_BINARY "w"
+#endif
diff --git a/dviware/dvipaste/dvipaste.c b/dviware/dvipaste/dvipaste.c
new file mode 100644
index 0000000000..c09d0ed428
--- /dev/null
+++ b/dviware/dvipaste/dvipaste.c
@@ -0,0 +1,2035 @@
+/************************************************************************/
+/* File: DVIPASTE.C */
+/************************************************************************/
+/* DEVELOPER: The TeXplorators Corporation */
+/* PRODUCT: DVIPASTE */
+/* Version: 1.21 */
+/************************************************************************/
+/*
+ SOFTWARE LICENSE AGREEMENT
+
+1. PURPOSE
+ This agreement recites the terms and conditions under which
+The TeXplorators Corporation ("TEXPLORATORS") agrees to grant you a
+free, nonexclusive, transferable license to use the DVIPASTE software.
+
+2. UNDERTAKINGS BY TEXPLORATORS
+ 2A. Ownership: Ownership of the DVIPASTE software remains
+exclusively in TEXPLORATORS.
+ 2B. License Fee: TEXPLORATORS makes the DVIPASTE software
+available to you free of any license fee.
+ 2C. Disclaimers: TEXPLORATORS DISCLAIMS ALL EXPRESS OR IMPLIED
+WARRANTIES OF DVIPASTE'S MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
+PURPOSE.
+ 2D. Liability: TEXPLORATORS' LIABILITY, IF ANY, IS LIMITED TO
+THE DISTRIBUTION FEE YOU PAID, AND DOES NOT INCLUDE SPECIAL AND/OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF, OR IN CONNECTION WITH, THE USE
+OF DVIPASTE. SINCE SOME STATES DISALLOW LIMITATION OR EXCLUSION OF
+LIABILITY, THIS LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU.
+
+3. UNDERTAKINGS BY YOU.
+ 3A. Proper Use: You agree to use the DVIPASTE software in
+compliance with the terms and conditions hereof.
+ 3B. Notices on Authorized Copies: You agree to take reasonable
+precautions to preserve the propriety of the DVIPASTE software by
+duplicating verbatim, on all copies thereof, the notices of TEXPLORATORS'
+interests recited thereon. You agree to note that source code is
+available upon request, if you do not distribute source code with the
+DVIPASTE software.
+ 3C. Distribution: You are encouraged to freely distribute the
+DVIPASTE software, including source code, on or through any common media
+including diskettes and electronic bulletin board systems. You agree to
+distribute this license with each and every copy so distributed, and to
+either distribute source code therewith or make source code available upon
+request. You may charge a distribution fee to cover the cost of diskettes,
+handling and shipping.
+ 3D. Modifications: You are authorized to make modifications to
+DVIPASTE, but these modifications must be conspicuously noted and dated
+therewith.
+ 3E. License Fee: You may not charge a license fee for the
+DVIPASTE software, either in its original or modified form. However, you
+may charge a license fee for your software which is broader in scope
+than DVIPASTE, whereby DVIPASTE is not a primary functional unit thereof.
+
+4. SCOPE
+ This Software License Agreement constitutes the entire agreement
+between TEXPLORATORS and you regarding the DVIPASTE software, and shall
+be construed under the laws of the State of TEXAS.
+
+ The TeXplorators Corporation
+ By: Michael Spivak, President
+*/
+/*
+
+Page*/
+/* Comments:
+ The following I/O routines may have to be changed for other
+ architectures.
+ GetByte();
+ GetWord();
+ GetTrio();
+ GetQuad();
+ PutByte();
+ PutWord();
+ PutTrio();
+ PutQuad();
+ GetSignedWord();
+ */
+/* Configuration and defines for Unix 05/08/1991, P. A. MacKay */
+
+/* System-dependent defines */
+
+#include "config.h"
+
+/*------------------------------*/
+/* includes */
+/*------------------------------*/
+#include <stdio.h>
+#include <string.h>
+#ifdef MICROSOFTC
+#include <process.h>
+#endif
+#include <malloc.h>
+
+/*------------------------------*/
+/* defines */
+/*------------------------------*/
+#define STRINGSIZE (5124) /* maximum string size */
+#define TRUE 1
+#define FALSE 0
+
+/*------------------------------*/
+/* typedefs */
+/*------------------------------*/
+typedef long integer;
+#ifdef MICROSOFTC
+typedef int shalfword;
+typedef unsigned int halfword;
+#else
+typedef short shalfword;
+typedef unsigned short halfword;
+#endif
+typedef unsigned char quarterword;
+typedef float real;
+typedef char Boolean;
+
+typedef struct
+{
+ quarterword cmd;
+ integer k;
+ integer checksum;
+ integer scaledsize;
+ integer designsize;
+ quarterword a;
+ quarterword l;
+ char *name;
+} FontType;
+
+
+typedef struct
+{
+ integer p;
+ integer num;
+ integer den;
+ integer mag;
+ integer l;
+ integer u;
+ halfword s;
+ halfword t;
+} PostType;
+
+
+typedef struct
+{
+ integer q;
+ quarterword i;
+} PostPostType;
+
+
+typedef struct
+{
+ integer fn;
+ char *name;
+ integer scaledsize;
+ integer designsize;
+} DeclaredFontType;
+
+typedef struct
+{
+ integer fn;
+ integer new;
+ char *name;
+} SubListType;
+
+typedef struct
+{
+ int cmd;
+ integer k;
+} FontNumType;
+
+/*------------------------------*/
+/* function declarations */
+/*------------------------------*/
+#ifdef ANSI /* Use ANSI C prototypes */
+void AddFontList(void);
+void AlignPara(FILE *);
+
+void beep(void);
+void BeginSpecial(integer);
+void bop(void);
+
+void DefFont(int);
+void DoSpecial(int);
+
+int EndSpecial(integer, int);
+void error(char *,char *);
+
+void FindPage(void);
+void FntNum(int);
+void FontDef(int);
+
+shalfword GetByte(FILE *);
+integer GetQuad(FILE *);
+shalfword GetSignedByte(FILE *);
+shalfword GetSignedWord(FILE *);
+integer GetTrio(FILE *);
+integer GetUniqueNumber(void);
+halfword GetWord(FILE *);
+
+void Initialize(void);
+
+int main(int argc, char *argv[]);
+
+void PopsAndPushes(int);
+void PutByte(int, FILE *);
+void PutQuad(integer, FILE *);
+void PutTrio(long,FILE *);
+void PutWord(int, FILE *);
+void PutFntNum( integer fn );
+
+void ReadPostamble(void);
+void ReadPreamble(void);
+void ReadSubFile(void);
+
+void SkipOver(integer,FILE *);
+void SubDefFont(int);
+void SubFontDef(int);
+void SubPreamble(void);
+void SubPostamble(void);
+
+void TransferTable(void);
+
+void WritePostamble(void);
+
+void xxxFontDef(int);
+
+#else /* Use old-style K&R functions */
+void AddFontList();
+void AlignPara();
+
+void beep();
+void BeginSpecial();
+void bop();
+
+void DefFont();
+void DoSpecial();
+
+int EndSpecial();
+void error();
+
+void FindPage();
+void FntNum();
+void FontDef();
+
+shalfword GetByte();
+integer GetQuad();
+shalfword GetSignedByte();
+shalfword GetSignedWord();
+integer GetTrio();
+integer GetUniqueNumber();
+halfword GetWord();
+
+void Initialize();
+
+int main();
+
+void PopsAndPushes();
+void PutByte();
+void PutQuad();
+void PutTrio();
+void PutWord();
+void PutFntNum();
+
+void ReadPostamble();
+void ReadPreamble();
+void ReadSubFile();
+
+void SkipOver();
+void SubDefFont();
+void SubFontDef();
+void SubPreamble();
+void SubPostamble();
+
+void TransferTable();
+
+void WritePostamble();
+
+void xxxFontDef();
+/* An ANSI string function, not guaranteed elsewhere */
+char *strstr();
+#endif
+/*------------------------------*/
+/* data structures */
+/*------------------------------*/
+FontType *main_fontlist[256]; /* Main font list pointers */
+FontType *sub_fontlist[256]; /* Sub font list pointers */
+ /* list of dynamically declared fonts */
+DeclaredFontType declared_fonts[256];
+SubListType sublist[100]; /* substitution list */
+PostType post; /* postamble */
+PostPostType post_post; /* post postamble */
+FontNumType fnt; /* current font */
+char newname[13]; /* new dvi file name */
+char dviname[13]; /* dvi file name */
+char subname[13]; /* sub file name */
+char strings[STRINGSIZE]; /* strings buffer */
+char *nextstr, *maxstr; /* string pointers */
+FILE *dvifile; /* dvi file handle */
+FILE *newfile; /* new file handle */
+FILE *subfile; /* sub file handle */
+int mfonts; /* number of fonts in main_fontlist */
+int sfonts; /* number of fonts in sub_fontlist */
+int dfonts; /* number of fonts in declared fonts */
+integer pagenum; /* page number */
+int pushes; /* current number of pushes */
+int pops; /* current number of pops */
+int max_stack_depth; /* max pushes over pops */
+long prevbop; /* previous bop */
+integer subpost_p; /* sub file postamble pointer */
+int push; /* number of pushes */
+int ColumnPos; /* column position */
+
+
+/*------------------------------*/
+/* functions */
+/*------------------------------*/
+
+/* align binary file on a 16-byte boundary */
+void AlignPara(f)
+FILE *f;
+{
+ long fpos, pad, i;
+ fpos = ftell(f);
+ pad = fpos%16L;
+ if (pad!=0L)
+ pad=16L-pad;
+ /* put out trailer bytes */
+ for (i=0; i<pad; i++)
+ PutByte(223,f);
+ return;
+}
+
+
+/* a quick and dirty way to sound the system horn */
+void beep()
+{
+ printf("\007\b"); return;
+}
+
+
+/* print error message and die */
+void error(s1,s2)
+char *s1, *s2;
+{
+ beep();
+ printf("\n%s %s",s1,s2); printf("\n");
+ exit(1);
+}
+
+shalfword GetByte(f)
+FILE *f;
+{ shalfword i;
+ i = fgetc(f);
+ return(i);
+}
+
+halfword GetWord(f)
+FILE *f;
+{ halfword i;
+ i = GetByte(f) ;
+ return(i*256+GetByte(f)) ;
+}
+
+integer GetTrio(f)
+FILE *f;
+{ integer i ;
+ i = GetWord(f) ;
+ return(i*256+GetByte(f)) ;
+}
+
+shalfword GetSignedByte(f)
+FILE *f;
+{ shalfword i;
+ i = fgetc(f);
+ if (i<128) return(i);
+ else return(i-256);
+}
+
+shalfword GetSignedWord(f)
+FILE *f;
+{ shalfword i;
+ i = GetSignedByte(f) ;
+ return(i*256+GetByte(f)) ;
+}
+
+
+integer GetQuad(f)
+FILE *f;
+{ integer i;
+ i = GetSignedWord(f);
+ return(i*65536+GetWord(f));
+}
+
+void PutByte(byte,f)
+int byte;
+FILE *f;
+{
+ fputc(byte,f);
+ if ( ferror(f) )
+ error("! File error - out of space",newname);
+ return;
+}
+
+
+void PutWord(num, f)
+int num;
+FILE *f;
+{
+ char *p;
+ p=(char *)&num;
+#ifdef LITTLENDIAN
+ PutByte(*(p+1), f);
+ PutByte(*p, f);
+#else
+ PutByte(*p, f);
+ PutByte(*(p+1), f);
+#endif
+ return;
+}
+
+
+void PutTrio(trio,f)
+long trio;
+FILE *f;
+{
+ int i;
+ char *p;
+ p = (char *)&trio;
+#ifdef LITTLENDIAN
+ for (i=2; i>=0; i--)
+#else
+ for (i=0; i<3; i++)
+#endif
+ PutByte( *(p+i), f);
+ return;
+}
+
+void PutQuad(quad,f)
+long quad;
+FILE *f;
+{
+ int i;
+ char *p;
+ p = (char *)&quad;
+#ifdef LITTLENDIAN
+ for (i=3; i>=0; i--)
+#else
+ for (i=0; i<4; i++)
+#endif
+ PutByte( *(p+i), f );
+ return;
+}
+
+
+void PopsAndPushes(cmd)
+int cmd;
+{
+int diff;
+
+ switch (cmd)
+ {
+ case 141: pushes++; break;
+ case 142: pops++; break;
+ }
+ diff = pushes - pops;
+ if ( diff > max_stack_depth )
+ max_stack_depth = diff;
+ return;
+}
+
+
+void ReadPreamble()
+{
+ integer num, den, mag;
+ int i;
+ quarterword k;
+ shalfword id, pre, byte;
+
+ pre = GetByte(dvifile); PutByte(pre,newfile);
+ id = GetByte(dvifile); PutByte(id,newfile);
+ num = GetQuad(dvifile); PutQuad(num,newfile);
+ den = GetQuad(dvifile); PutQuad(den,newfile);
+ mag = GetQuad(dvifile); PutQuad(mag,newfile);
+ k = (quarterword) GetByte(dvifile); PutByte(k,newfile);
+ /* skip over TeX comment */
+ for (i=0; i<k; i++)
+ { byte=GetByte(dvifile); PutByte(byte,newfile); }
+
+ return;
+}
+
+void ReadPostamble()
+{
+ long offset;
+ int cmd;
+ Boolean done;
+ integer k;
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#define SEEK_CUR 1
+#define SEEK_SET 0
+#endif
+ fseek(dvifile,0L,SEEK_END);
+ /* skip backwards over 223's until the id byte. */
+ fseek(dvifile,-1L,SEEK_CUR);
+ cmd = GetByte(dvifile);
+ while (cmd==223)
+ {
+ fseek(dvifile,-2L,SEEK_CUR);
+ if ( ftell(dvifile)==0L )
+ { error("! error in reading postamble",dviname); }
+ cmd = GetByte(dvifile);
+ }
+
+ /* back up and read q */
+ fseek(dvifile,-5L,SEEK_CUR);
+ offset= GetQuad(dvifile);
+ fseek(dvifile,offset,SEEK_SET);
+ cmd = GetByte(dvifile);
+
+ /* this must be the post cmd */
+ if (cmd!=248)
+ { error("! error in reading postamble",dviname); }
+
+ post.p = GetQuad(dvifile);
+ post.num = GetQuad(dvifile);
+ post.den = GetQuad(dvifile);
+ post.mag = GetQuad(dvifile);
+ post.l = GetQuad(dvifile);
+ post.u = GetQuad(dvifile);
+ post.s = GetWord(dvifile);
+ post.t = GetWord(dvifile);
+
+ /* read in font defs */
+ done = FALSE;
+ while ( !done )
+ {
+ cmd = GetByte(dvifile);
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ case 244: /* fnt_def2 */
+ case 245: /* fnt_def3 */
+ case 246: /* fnt_def4 */
+ FontDef(cmd);
+ break;
+ default: done=TRUE; break;
+ }
+ }
+
+ /* Now, we will try to assign a fnt number.
+ To make life easier, we will pick the first one. There must be
+ at least one font def in main_fontlist, otherwise font 0 will
+ be assigned for better or for worse. */
+ if ( main_fontlist[0]!=NULL )
+ {
+ k = main_fontlist[0]->k;
+ if ( k < 64L ) fnt.cmd = (quarterword) (k+171L) ;
+ else if ( k < 256L ) { fnt.cmd = 235; fnt.k = k; }
+ else if ( k < 65536L ) { fnt.cmd = 236; fnt.k = k; }
+ else if ( k < 16777216L ) { fnt.cmd = 237; fnt.k = k; }
+ else { fnt.cmd = 238; fnt.k = k; }
+ }
+ else
+ fnt.cmd = 171;
+
+ return;
+}
+
+void WritePostamble()
+{
+ int i,j,n;
+ Boolean found;
+ FontType *fp;
+ char *p;
+
+ /* set max stack depth */
+ post.s = max_stack_depth;
+ PutQuad(post.p,newfile);
+ PutQuad(post.num,newfile);
+ PutQuad(post.den,newfile);
+ PutQuad(post.mag,newfile);
+ PutQuad(post.l,newfile);
+ PutQuad(post.u,newfile);
+ PutWord(post.s,newfile);
+ PutWord(post.t,newfile);
+
+ /* send out font defs that are actually used in the combined file */
+ /* - use declared_fonts list since this is the correct list. */
+ for (i=0; i<dfonts; i++)
+ {
+ fp = NULL; found = FALSE;
+ for (j=0; j<mfonts && !found; j++)
+ {
+ if ( declared_fonts[i].fn==main_fontlist[j]->k )
+ { found = TRUE; fp = main_fontlist[j]; }
+ }
+
+ if ( fp!=NULL )
+ {
+ PutByte(fp->cmd,newfile);
+ switch (fp->cmd)
+ {
+ case 243:
+ PutByte((quarterword)fp->k,newfile); break;
+ case 244:
+ PutWord((halfword)fp->k,newfile); break;
+ case 245:
+ PutTrio(fp->k,newfile); break;
+ case 246:
+ PutQuad(fp->k,newfile); break;
+ }
+ PutQuad(fp->checksum,newfile);
+ PutQuad(fp->scaledsize,newfile);
+ PutQuad(fp->designsize,newfile);
+ PutByte(fp->a,newfile);
+ PutByte(fp->l,newfile);
+ p = fp->name;
+ /* directory */
+ for (n=0; n<fp->a; n++)
+ PutByte(*p++, newfile);
+ p++;
+ /* font name */
+ for (n=0; n<fp->l; n++)
+ PutByte(*p++,newfile);
+ }
+ }
+
+ /* now the post_post command */
+ PutByte(249, newfile);
+ PutQuad(post_post.q,newfile);
+ PutByte(2,newfile);
+ /* put out enough trailer bytes */
+ for (i=0; i<4; i++)
+ PutByte(223,newfile);
+ AlignPara(newfile);
+ return;
+}
+
+
+void Initialize()
+{
+ int i;
+ for (i=0; i<256; i++)
+ main_fontlist[i] = NULL;
+ nextstr = strings;
+ maxstr = strings + STRINGSIZE - 1;
+ mfonts = 0;
+ sfonts = 0;
+ dfonts = 0;
+ subname[0]= 0;
+ subfile = NULL;
+ pops = pushes = max_stack_depth = 0;
+ prevbop = -1L;
+ ColumnPos = 0;
+ return;
+}
+
+void FontDef(cmd)
+int cmd;
+{
+ int i,f;
+ integer fn;
+ FontType *fp;
+ quarterword found;
+
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ fn = GetByte(dvifile); break;
+ case 244: /* fnt_def2 */
+ fn = GetWord(dvifile); break;
+ case 245: /* fnt_def3 */
+ fn = GetTrio(dvifile); break;
+ case 246: /* fnt_def4 */
+ fn = GetQuad(dvifile); break;
+ }
+
+ /* walk thru main_fontlist */
+ found = FALSE;
+ for (f=0; f<mfonts && !found; f++)
+ {
+ if (main_fontlist[f]->k == fn ) found=TRUE;
+ }
+
+ if ( !found )
+ {
+ fp = (FontType *)malloc(sizeof(FontType));
+ if (fp==NULL)
+ error("! ran out of memory",dviname);
+ main_fontlist[mfonts++] = fp;
+ fp->cmd = (quarterword) cmd;
+ fp->k = fn;
+ fp->checksum = GetQuad(dvifile);
+ fp->scaledsize = GetQuad(dvifile);
+ fp->designsize = GetQuad(dvifile);
+ fp->a = (quarterword) GetByte(dvifile);
+ fp->l = (quarterword) GetByte(dvifile);
+ /* check strings space */
+ if ( ( nextstr + fp->a + fp->l ) > maxstr )
+ error("! out of string space",dviname);
+ fp->name = nextstr ;
+ for (i=0; i<fp->a; i++)
+ *nextstr++ = (char) GetByte(dvifile);
+ *nextstr++ = 0;
+ for (i=0; i<fp->l; i++)
+ *nextstr++ = (char) GetByte(dvifile);
+ *nextstr++ = 0;
+ }
+ /* font already defined, skip over it */
+ else
+ {
+ SkipOver(12L,dvifile); /* c[4]...n[a+l] */
+ i = GetByte(dvifile) + GetByte(dvifile);
+ SkipOver((long)i,dvifile);
+ }
+
+ return;
+}
+
+void DefFont(cmd)
+int cmd;
+{
+ quarterword byte, byte1;
+ int i;
+ integer fn;
+ quarterword found;
+ char name[13];
+ integer checksum, scaledsize, designsize;
+
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ fn = GetByte(dvifile); PutByte((quarterword)fn,newfile);
+ break;
+ case 244: /* fnt_def2 */
+ fn = GetWord(dvifile); PutByte((halfword)fn,newfile);
+ break;
+ case 245: /* fnt_def3 */
+ fn = GetTrio(dvifile); PutTrio(fn,newfile);
+ break;
+ case 246: /* fnt_def4 */
+ fn = GetQuad(dvifile); PutQuad(fn,newfile);
+ break;
+ }
+
+ checksum = GetQuad(dvifile);
+ scaledsize = GetQuad(dvifile);
+ designsize = GetQuad(dvifile);
+ PutQuad(checksum, newfile);
+ PutQuad(scaledsize, newfile);
+ PutQuad(designsize, newfile);
+
+ byte = (quarterword) GetByte(dvifile);
+ byte1 = (quarterword) GetByte(dvifile);
+ PutByte(byte,newfile); PutByte(byte1, newfile);
+ i = byte;
+ for (i=0; i<byte; i++)
+ { byte = (quarterword) GetByte(dvifile); PutByte(byte,newfile); }
+ i = byte1;
+ for (i=0; i<byte1; i++)
+ { byte = (quarterword) GetByte(dvifile);
+ name[i]=byte; PutByte(byte,newfile); }
+ name[i]=0;
+
+ /* keep a list of declared fonts */
+ found = FALSE;
+ for (i=0; i<dfonts && !found; i++)
+ {
+ if ( (stricmp(declared_fonts[i].name,name)==0)
+ && (scaledsize==declared_fonts[i].scaledsize)
+ && (designsize==declared_fonts[i].designsize)
+ )
+ found = TRUE;
+ }
+
+ if ( !found )
+ {
+ declared_fonts[dfonts].name = nextstr;
+ for (i=0; i<byte1; i++)
+ *nextstr++ = name[i];
+ *nextstr++ = 0;
+ declared_fonts[dfonts].fn = fn;
+ declared_fonts[dfonts].scaledsize = scaledsize;
+ declared_fonts[dfonts].designsize = designsize;
+ dfonts++;
+ }
+
+ return;
+}
+
+
+void SubFontDef(cmd)
+int cmd;
+{ int i,f;
+ integer fn;
+ FontType *fp;
+ quarterword found;
+
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ fn = GetByte(subfile); break;
+ case 244: /* fnt_def2 */
+ fn = GetWord(subfile); break;
+ case 245: /* fnt_def3 */
+ fn = GetTrio(subfile); break;
+ case 246: /* fnt_def4 */
+ fn = GetQuad(subfile); break;
+ }
+
+
+ /* walk thru sub_fontlist */
+ found = FALSE;
+ for (f=0; f<sfonts && !found; f++)
+ {
+ if (sub_fontlist[f]->k == fn ) found=TRUE;
+ }
+
+
+ if ( !found )
+ {
+ fp = (FontType *)malloc(sizeof(FontType)) ;
+ if (fp==NULL)
+ error("! sorry, out of memory",subname);
+
+ sub_fontlist[sfonts++] = fp;
+ fp->cmd = (quarterword) cmd;
+ fp->k = fn;
+ fp->checksum = GetQuad(subfile);
+ fp->scaledsize = GetQuad(subfile);
+ fp->designsize = GetQuad(subfile);
+ fp->a = (quarterword) GetByte(subfile);
+ fp->l = (quarterword) GetByte(subfile);
+
+ /* check strings space */
+ if ( ( nextstr + fp->a + fp->l ) > maxstr )
+ error("! out of string space",subname);
+
+ fp->name = nextstr;
+ for (i=0; i<fp->a; i++)
+ *nextstr++ = (char) GetByte(subfile);
+ *nextstr++ = 0;
+ for (i=0; i<fp->l; i++)
+ *nextstr++ = (char) GetByte(subfile) ;
+ *nextstr++ = 0 ;
+ }
+ /* font already defined */
+ else
+ {
+ SkipOver(12L,subfile); /* c[4]...n[a+l] */
+ i = GetByte(subfile) + GetByte(subfile);
+ SkipOver((long)i,subfile);
+ }
+
+ return;
+}
+
+
+void SubDefFont(cmd)
+int cmd;
+{
+ quarterword byte, byte1;
+ int i;
+ integer fn;
+ char name[13];
+
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ fn = GetByte(subfile);
+ break;
+ case 244: /* fnt_def2 */
+ fn = GetWord(subfile);
+ break;
+ case 245: /* fnt_def3 */
+ fn = GetTrio(subfile);
+ break;
+ case 246: /* fnt_def4 */
+ fn = GetQuad(subfile);
+ break;
+ }
+
+ for (i=0; i<12; i++)
+ GetByte(subfile);
+
+ byte = (quarterword) GetByte(subfile);
+ byte1 = (quarterword) GetByte(subfile);
+ i = byte;
+ for (i=0; i<byte; i++)
+ { byte = (quarterword) GetByte(subfile); }
+ i = byte1;
+ for (i=0; i<byte1; i++)
+ { byte = (quarterword) GetByte(subfile); name[i]=byte; }
+ name[i]=0;
+
+ return;
+}
+
+void xxxFontDef(cmd)
+int cmd;
+{ int i;
+ integer fn;
+ quarterword a, l;
+ quarterword found;
+ integer checksum, scaledsize, designsize;
+ char name[13];
+ char directory[80];
+
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ fn = (integer) GetByte(subfile); break;
+ case 244: /* fnt_def2 */
+ fn = (integer) GetWord(subfile); break;
+ case 245: /* fnt_def3 */
+ fn = (integer) GetTrio(subfile); break;
+ case 246: /* fnt_def4 */
+ fn = GetQuad(subfile); break;
+ }
+
+ checksum = GetQuad(subfile);
+ scaledsize = GetQuad(subfile);
+ designsize = GetQuad(subfile);
+ a = (quarterword) GetByte(subfile);
+ l = (quarterword) GetByte(subfile);
+
+ for (i=0; i<a; i++)
+ directory[i] = (char) GetByte(subfile);
+ directory[i]=0;
+ for (i=0; i<l; i++)
+ name[i] = (char) GetByte(subfile);
+ name[i]=0;
+
+ /* walk thru list of declared fonts */
+ found = FALSE;
+ for (i=0; i<dfonts && !found; i++)
+ {
+ if ( (stricmp(declared_fonts[i].name,name)==0)
+ && (scaledsize == declared_fonts[i].scaledsize)
+ && (designsize == declared_fonts[i].designsize)
+ )
+ found = TRUE;
+ }
+
+ if ( !found )
+ {
+ PutByte(cmd,newfile);
+ /* substitute font number before tranfer */
+ found = FALSE;
+ for (i=0; i<sfonts && !found; i++)
+ {
+ if ( fn == sublist[i].fn )
+ { fn = sublist[i].new; found = TRUE; }
+ }
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ PutByte((quarterword)fn,newfile); break;
+ case 244: /* fnt_def2 */
+ PutWord((halfword)fn,newfile); break;
+ case 245: /* fnt_def3 */
+ PutTrio(fn,newfile); break;
+ case 246: /* fnt_def4 */
+ PutQuad(fn,newfile); break;
+ }
+
+ PutQuad(checksum, newfile);
+ PutQuad(scaledsize,newfile);
+ PutQuad(designsize,newfile);
+ PutByte(a,newfile);
+ PutByte(l,newfile);
+ for (i=0; i<a; i++)
+ PutByte(directory[i],newfile);
+ for (i=0; i<l; i++)
+ PutByte(name[i],newfile);
+
+ /* add font to declared_fonts list */
+ declared_fonts[dfonts].name = nextstr;
+ for (i=0; i<l; i++)
+ *nextstr++ = name[i];
+ *nextstr++ = 0;
+ declared_fonts[dfonts].fn = fn;
+ declared_fonts[dfonts].scaledsize = scaledsize;
+ declared_fonts[dfonts].designsize = designsize;
+ dfonts++;
+ }
+ return;
+}
+
+
+void SkipOver(i,f)
+integer i;
+FILE *f;
+{
+ fseek(f,i,SEEK_CUR);
+ return;
+}
+
+
+void PutFntNum(fn)
+integer fn;
+{
+ if ( fn >= 0 && fn < 64 )
+ PutByte((quarterword)(171L+fn),newfile);
+ else
+ {
+ if ( fn >= 64L && fn < 256L )
+ { PutByte(235,newfile); PutByte((quarterword)fn,newfile); }
+ else
+ {
+ if ( fn >= 0 && fn < 65536L )
+ { PutByte(236,newfile); PutWord((halfword)fn,newfile); }
+ else
+ { /* combine 237 and 238 */
+ PutByte(238,newfile); PutQuad(fn,newfile);
+ }
+ }
+ }
+ return;
+}
+
+void FntNum(cmd)
+int cmd;
+{
+integer fn;
+Boolean found;
+char name[13];
+char *p;
+FontType *fp;
+int i;
+integer scaledsize, designsize;
+
+ switch(cmd)
+ {
+ case 235: /* fnt1 */
+ fn=GetByte(subfile); break;
+ case 236: /* fnt2 */
+ fn=GetWord(subfile); break;
+ case 237: /* fnt3 */
+ fn=GetTrio(subfile); break;
+ case 238: /* fnt4 */
+ fn=GetQuad(subfile); break;
+ default:
+ fn = (long)cmd - 171L; break;
+ }
+
+ found = FALSE;
+ for (i=0; i<sfonts && !found; i++)
+ {
+ if ( fn == sub_fontlist[i]->k )
+ { found = TRUE ;
+ p = sub_fontlist[i]->name + sub_fontlist[i]->a + 1;
+ strcpy(name,p);
+ scaledsize = sub_fontlist[i]->scaledsize;
+ designsize = sub_fontlist[i]->designsize;
+ }
+ }
+
+ if ( !found )
+ error(" ! cannot find font name",subname);
+
+ /* walk thru list of declared fonts */
+ found = FALSE;
+ for (i=0; i<dfonts && !found; i++)
+ {
+ if ( (stricmp(declared_fonts[i].name,name)==0)
+ && (scaledsize==declared_fonts[i].scaledsize)
+ && (designsize==declared_fonts[i].designsize)
+ )
+ found = TRUE;
+ }
+
+ if ( found )
+ {
+ /* substitute font number before transfer */
+ found = FALSE;
+ for (i=0; i<sfonts && !found; i++)
+ {
+ if ( fn == sublist[i].fn )
+ { fn = sublist[i].new; found = TRUE; }
+ }
+ PutFntNum(fn);
+ }
+ else
+ {
+ /* Get font number from sub font list */
+ found = FALSE;
+ for (i=0; i<sfonts && !found; i++)
+ {
+ if ( fn == sublist[i].fn )
+ { fn = sublist[i].new; found = TRUE; }
+ }
+
+ found = FALSE;
+ for (i=0; i<mfonts && !found; i++)
+ {
+ if ( fn == main_fontlist[i]->k )
+ {
+ found = TRUE;
+ fp = main_fontlist[i];
+ }
+ }
+
+ if ( !found )
+ error(" ! fnt number not in main list",subname);
+
+ /* now, we send out a fnt_def */
+ PutByte((quarterword)fp->cmd,newfile);
+ switch (fp->cmd)
+ {
+ case 243: PutByte((quarterword)fp->k,newfile); break;
+ case 244: PutWord((halfword)fp->k,newfile); break;
+ case 245: PutTrio(fp->k,newfile); break;
+ case 246: PutQuad(fp->k,newfile); break;
+ }
+ PutQuad(fp->checksum,newfile);
+ PutQuad(fp->scaledsize,newfile);
+ PutQuad(fp->designsize,newfile);
+ PutByte(fp->a,newfile);
+ PutByte(fp->l,newfile);
+ for (i=0; i<fp->a; i++)
+ PutByte(*(fp->name+i),newfile);
+ for (i=0; i<fp->l; i++)
+ PutByte(*(fp->name+fp->a+1+i),newfile);
+ /* now we have to send out the fnt_num cmd */
+ PutFntNum(fn);
+
+ /* add font to declared_fonts list */
+ declared_fonts[dfonts].name = nextstr;
+ for (i=0; i<fp->l; i++)
+ *nextstr++ = name[i];
+ *nextstr++ = 0;
+ declared_fonts[dfonts].fn = fn;
+ declared_fonts[dfonts].scaledsize = fp->scaledsize;
+ declared_fonts[dfonts].designsize = fp->designsize;
+ dfonts++;
+
+ }
+ return;
+}
+
+
+void DoSpecial(cmd)
+int cmd;
+{
+ integer i;
+ char str[90];
+ char opcode[80];
+ char name[80];
+ integer numbytes;
+ integer offset;
+
+ switch (cmd)
+ {
+ case 239: /* xxx1 */
+ numbytes=GetByte(dvifile);
+ break;
+ case 240: /* xxx2 */
+ numbytes=GetWord(dvifile);
+ break;
+ case 241: /* xxx3 */
+ numbytes=GetTrio(dvifile);
+ break;
+ case 242: /* xxx4 */
+ numbytes=GetQuad(dvifile);
+ break;
+ }
+
+ offset = ftell(dvifile);
+
+ for (i=0; i<numbytes && i<79; i++)
+ str[i] = (char) GetByte(dvifile);
+ str[i] = 0;
+ sscanf(str,"%s%s%ld",opcode,name,&pagenum);
+ strcat(name,".dvi");
+
+ /* process only {dvipaste: <file> n} commands */
+ if (strnicmp(opcode,"dvipaste:",9)==0)
+ {
+ fseek(dvifile,offset,SEEK_SET);
+ SkipOver( numbytes, dvifile );
+
+ /* read in new subfile if different */
+ if (stricmp(name,subname)!=0)
+ {
+ strcpy(subname,name);
+ ReadSubFile();
+ }
+
+
+ /* now we transfer table n from subfile */
+ TransferTable();
+
+ /* we must set previous fnt num before returning to dvifile */
+ switch( fnt.cmd )
+ {
+ case 235:
+ PutByte(fnt.cmd,newfile);
+ PutByte((quarterword)fnt.k,newfile);
+ break;
+ case 236:
+ PutByte(fnt.cmd,newfile);
+ PutWord((halfword)fnt.k,newfile);
+ break;
+ case 237:
+ PutByte(fnt.cmd,newfile);
+ PutTrio(fnt.k,newfile);
+ break;
+ case 238:
+ PutByte(fnt.cmd,newfile);
+ PutQuad(fnt.k,newfile);
+ break;
+ default:
+ PutByte(fnt.cmd,newfile);
+ break;
+ }
+ }
+ else
+ { /* pass the special thru. not the ones we care about */
+ PutByte(cmd,newfile);
+ switch (cmd)
+ {
+ case 239: /* xxx1 */
+ PutByte((quarterword)numbytes,newfile);
+ break;
+ case 240: /* xxx2 */
+ PutWord((halfword)numbytes,newfile);
+ break;
+ case 241: /* xxx3 */
+ PutTrio(numbytes,newfile);
+ break;
+ case 242: /* xxx4 */
+ PutQuad(numbytes,newfile);
+ break;
+ }
+
+ fseek(dvifile,offset,SEEK_SET);
+ for (i=0; i<numbytes; i++)
+ PutByte(GetByte(dvifile),newfile);
+
+ }
+
+ return;
+}
+
+#ifndef MICROSOFTC
+#define strnicmp strncmp
+#define strcmp strcmp
+#endif
+
+int EndSpecial(numbytes, cmd)
+integer numbytes;
+int cmd;
+{
+ integer i;
+ char str[90];
+ char opcode[80];
+ integer offset;
+
+ offset = ftell(subfile);
+ for (i=0; i<numbytes && i<79; i++)
+ str[i] = (char) GetByte(subfile);
+ str[i] = 0;
+ sscanf(str,"%s",opcode);
+
+ if (strnicmp(opcode,"endpaste:",9)==0)
+ {
+ fseek(subfile,offset,SEEK_SET);
+ SkipOver( numbytes, subfile );
+
+ /* balance out pushes and pops */
+ for (; push>0; push--)
+ {
+ PutByte(142,newfile);
+ PopsAndPushes(142);
+ }
+ return( TRUE );
+ }
+
+ /* send out embedded special */
+ PutByte(cmd,newfile);
+ switch( cmd )
+ {
+ case 239: /* xxx1 */
+ PutByte((quarterword)numbytes,newfile);
+ break;
+ case 240: /* xxx2 */
+ PutWord((halfword)numbytes,newfile);
+ break;
+ case 241: /* xxx3 */
+ PutTrio(numbytes,newfile);
+ break;
+ case 242: /* xxx4 */
+ PutQuad(numbytes,newfile);
+ break;
+ }
+
+ fseek(subfile,offset,SEEK_SET);
+ for (i=0; i<numbytes; i++)
+ PutByte(GetByte(subfile),newfile);
+
+ return(FALSE);
+}
+
+
+void BeginSpecial(numbytes)
+integer numbytes;
+{
+ integer i;
+ char str[90];
+ char opcode[80];
+ Boolean done;
+ integer ii;
+ int cmd;
+ integer offset;
+
+ offset = ftell(subfile);
+ for (i=0; i<numbytes && i<79; i++)
+ str[i] = (char) GetByte(subfile);
+ str[i] = 0;
+ sscanf(str,"%s",opcode);
+
+ if (strnicmp(opcode,"beginpaste:",11)==0)
+ {
+ fseek(subfile,offset,SEEK_SET);
+ SkipOver( numbytes, subfile );
+
+ done=FALSE; push = 0;
+ while ( !done )
+ {
+ cmd=GetByte(subfile);
+
+ switch (cmd)
+ {
+ case 139: /* bop */
+ case 140: /* eop */
+ error("! illegal commands inside special",subname);
+ break;
+ case 141: /* push */
+ PutByte((quarterword)cmd, newfile);
+ PopsAndPushes(cmd);
+ push++; break;
+ case 142: /* pop */
+ PutByte((quarterword)cmd, newfile);
+ PopsAndPushes(cmd);
+ push--; break;
+ /* fnt_def1...fnt_def4 */
+ case 243: case 244: case 245: case 246:
+ /* xxx1...xxx4 - embedded specials */
+ case 239: case 240: case 241: case 242:
+ /* don't put out cmd byte yet */
+ break;
+ /* fnt1...fnt4 */
+ case 235: case 236: case 237: case 238:
+ FntNum(cmd); break;
+ default:
+ /* fnt_num_0 thru fnt_num_63 */
+ if (cmd>=171 && cmd<=234)
+ { FntNum(cmd); break; }
+ PutByte((quarterword)cmd, newfile); break;
+ }
+
+ switch( cmd )
+ {
+ /* eight bytes */
+ case 132: /* set_rule */
+ case 137: /* put_rule */
+ PutQuad(GetQuad(subfile),newfile);
+ /* four bytes */
+ case 131: /* set4 */
+ case 136: /* put4 */
+ case 146: /* right4 */
+ case 151: /* w4 */
+ case 156: /* x4 */
+ case 160: /* down4 */
+ case 165: /* y4 */
+ case 170: /* z4 */
+ PutByte(GetByte(subfile),newfile);
+ /* three bytes */
+ case 130: /* set3 */
+ case 135: /* put3 */
+ case 145: /* right3 */
+ case 150: /* w3 */
+ case 155: /* x3 */
+ case 159: /* down3 */
+ case 164: /* y3 */
+ case 169: /* z3 */
+ PutByte(GetByte(subfile),newfile);
+ /* two bytes */
+ case 129: /* set2 */
+ case 134: /* put2 */
+ case 144: /* right2 */
+ case 149: /* w2 */
+ case 154: /* x2 */
+ case 158: /* down2 */
+ case 163: /* y2 */
+ case 168: /* z2 */
+ PutByte(GetByte(subfile),newfile);
+ /* one byte */
+ case 128: /* set1 */
+ case 133: /* put1 */
+ case 143: /* right1 */
+ case 148: /* w1 */
+ case 153: /* x1 */
+ case 157: /* down1 */
+ case 162: /* y1 */
+ case 167: /* z1 */
+ PutByte(GetByte(subfile),newfile); break;
+ break;
+ case 138: /* nop */
+ case 141: /* push */
+ case 142: /* pop */
+ case 147: /* w0 */
+ case 152: /* x0 */
+ case 161: /* y0 */
+ case 166: /* z0 */
+ break;
+ case 239: /* xxx1 */
+ ii=GetByte(subfile);
+ if ( EndSpecial(ii, cmd) )
+ done=TRUE;
+ break;
+ case 240: /* xxx2 */
+ ii=GetWord(subfile);
+ if ( EndSpecial(ii, cmd) )
+ done=TRUE;
+ break;
+ case 241: /* xxx3 */
+ ii=GetTrio(subfile);
+ if ( EndSpecial(ii,cmd) )
+ done=TRUE;
+ break;
+ case 242: /* xxx4 */
+ ii=GetQuad(subfile);
+ if ( EndSpecial(ii,cmd) )
+ done=TRUE;
+ break;
+ /* fnt_def1...fnt_def4 */
+ case 243: case 244: case 245: case 246:
+ xxxFontDef(cmd);
+ break;
+ case 248: /* post */
+ done=TRUE; break;
+ }
+
+ } /* while !done */
+
+ }
+ /* skip over special */
+ else
+ {
+ fseek(subfile,offset,SEEK_SET);
+ SkipOver( numbytes, subfile );
+ }
+
+ return;
+}
+
+
+void FindPage()
+{
+int cmd;
+integer count,offset;
+Boolean found;
+
+ /* position to the final bop */
+ fseek(subfile,subpost_p,SEEK_SET);
+ cmd = GetByte(subfile);
+ if ( cmd!=139 )
+ error(" ! cannot locate final page ",subname);
+ count = GetQuad(subfile);
+ if ( count == pagenum )
+ found = TRUE;
+ else { offset = 0L; found=FALSE; }
+
+ while ( !found && offset !=-1L )
+ {
+ SkipOver(36L,subfile);
+ offset = GetQuad(subfile);
+ if ( offset != -1L )
+ {
+ fseek(subfile,offset,SEEK_SET);
+ cmd = GetByte(subfile);
+ count = GetQuad(subfile);
+ if ( count == pagenum )
+ found = TRUE;
+ }
+
+ }
+
+ if ( !found )
+ { printf("\n ! cannot find page %ld in %s",pagenum,subname);
+ exit(1);
+ }
+
+ SkipOver(40L,subfile);
+ return;
+}
+
+
+void TransferTable()
+{
+Boolean done;
+integer ii;
+int cmd;
+
+ FindPage();
+
+ done=FALSE;
+ while ( !done )
+ {
+ cmd=GetByte(subfile);
+
+ /* set_char_0 thru set_char_127 */
+ /* cmd>=0 && cmd<=127 */
+
+ /* fnt_num_0 thru fnt_num_63 */
+ /* cmd>=171 && cmd<=234 ) */
+ if (cmd>=171 && cmd<=234)
+ FntNum(cmd);
+
+ switch (cmd)
+ {
+ /* eight bytes */
+ case 132: /* set_rule */
+ case 137: /* put_rule */
+ GetQuad(subfile);
+ /* four bytes */
+ case 131: /* set4 */
+ case 136: /* put4 */
+ case 146: /* right4 */
+ case 151: /* w4 */
+ case 156: /* x4 */
+ case 160: /* down4 */
+ case 165: /* y4 */
+ case 170: /* z4 */
+ GetByte(subfile);
+ /* three bytes */
+ case 130: /* set3 */
+ case 135: /* put3 */
+ case 145: /* right3 */
+ case 150: /* w3 */
+ case 155: /* x3 */
+ case 159: /* down3 */
+ case 164: /* y3 */
+ case 169: /* z3 */
+ GetByte(subfile);
+ /* two bytes */
+ case 129: /* set2 */
+ case 134: /* put2 */
+ case 144: /* right2 */
+ case 149: /* w2 */
+ case 154: /* x2 */
+ case 158: /* down2 */
+ case 163: /* y2 */
+ case 168: /* z2 */
+ GetByte(subfile);
+ /* one byte */
+ case 128: /* set1 */
+ case 133: /* put1 */
+ case 143: /* right1 */
+ case 148: /* w1 */
+ case 153: /* x1 */
+ case 157: /* down1 */
+ case 162: /* y1 */
+ case 167: /* z1 */
+ GetByte(subfile); break;
+ break;
+ case 139: /* bop */
+ /* filter thru c0[4]...c9[4] and p[4] */
+ SkipOver(44L,subfile);
+ break;
+ case 138: /* nop */
+ case 140: /* eop */
+ case 141: /* push */
+ case 142: /* pop */
+ case 147: /* w0 */
+ case 152: /* x0 */
+ case 161: /* y0 */
+ case 166: /* z0 */
+ break;
+ case 235: /* fnt1 */
+ case 236: /* fnt2 */
+ case 237: /* fnt3 */
+ case 238: /* fnt4 */
+ FntNum(cmd); break;
+ case 239: /* xxx1 */
+ ii=GetByte(subfile);
+ BeginSpecial(ii);
+ done = TRUE;
+ break;
+ case 240: /* xxx2 */
+ ii=GetWord(subfile);
+ BeginSpecial(ii);
+ done = TRUE;
+ break;
+ case 241: /* xxx3 */
+ ii=GetTrio(subfile);
+ BeginSpecial(ii);
+ done=TRUE;
+ break;
+ case 242: /* xxx4 */
+ ii=GetQuad(subfile);
+ BeginSpecial(ii);
+ done=TRUE;
+ break;
+ /* fnt_def1...fnt_def4 */
+ case 246: case 245: case 244: case 243:
+ SubDefFont(cmd);
+ break;
+ case 248: /* post */
+ done=TRUE; break;
+ }
+
+ }
+ return;
+}
+
+
+integer GetUniqueNumber()
+{
+ integer fn;
+ int i,j;
+ Boolean found, assigned;
+
+ fn = 0L; found = FALSE;
+ for (i=0; i<mfonts && !found; i++)
+ {
+ assigned = FALSE;
+ for (j=0; j<mfonts && !assigned; j++)
+ {
+ if (fn == main_fontlist[j]->k)
+ { fn++; assigned=TRUE; }
+ }
+ if ( !assigned ) found = TRUE;
+ }
+
+ return(fn);
+}
+
+
+void AddFontList()
+{
+ Boolean found;
+ int i,j;
+ FontType *f1, *f2, *fp;
+ char *p, *q;
+ integer fn;
+
+ for (i=0; i<sfonts; i++)
+ {
+ f1 = sub_fontlist[i];
+ p = f1->name + f1->a + 1;
+ found = FALSE;
+ for (j=0; j<mfonts && !found; j++)
+ {
+ f2 = main_fontlist[j];
+ q = f2->name + f2->a + 1;
+ if ( (stricmp(p,q)==0)
+ &&(f1->scaledsize==f2->scaledsize)
+ &&(f1->designsize==f2->designsize)
+ )
+ { found = TRUE; fn = f2->k; fp = f2; }
+ }
+
+ if ( !found )
+ {
+ fp = (FontType *)malloc(sizeof(FontType));
+ if (fp==NULL)
+ error("! ran out of memory","");
+ main_fontlist[mfonts++] = fp;
+ fp->cmd = f1->cmd;
+ fp->checksum = f1->checksum;
+ fp->scaledsize = f1->scaledsize;
+ fp->designsize = f1->designsize;
+ fp->a = f1->a;
+ fp->l = f1->l;
+ fp->name = f1->name;
+ fn = GetUniqueNumber();
+ fp->k = fn;
+ }
+ /* add to sub list */
+ sublist[i].fn = f1->k;
+ sublist[i].new = fn;
+ sublist[i].name = fp->name + fp->a + 1;
+ }
+ return;
+}
+
+
+void SubPostamble()
+{
+integer offset;
+int cmd;
+Boolean done;
+
+ fseek(subfile,0L,SEEK_END);
+
+ /* skip backwards over 223's until the id byte. */
+ fseek(subfile,-1L,SEEK_CUR);
+ cmd = GetByte(subfile);
+ while (cmd==223)
+ {
+ fseek(subfile,-2L,SEEK_CUR);
+ if ( ftell(subfile)==0L )
+ error("\n ! error in reading postamble",subname);
+ cmd = GetByte(subfile);
+ }
+
+ /* back up and read q */
+ fseek(subfile,-5L,SEEK_CUR);
+ offset=GetQuad(subfile);
+ fseek(subfile,offset,SEEK_SET);
+ cmd = GetByte(subfile);
+
+ /* this must be the post cmd */
+ if (cmd!=248)
+ error("\n ! error in reading postamble",subname);
+
+ /* skip over post parameters */
+ subpost_p = GetQuad(subfile);
+ SkipOver(24L,subfile);
+ /* font defs */
+ done = FALSE;
+ while ( !done )
+ {
+ cmd = GetByte(subfile);
+ switch (cmd)
+ {
+ case 243: /* fnt_def1 */
+ case 244: /* fnt_def2 */
+ case 245: /* fnt_def3 */
+ case 246: /* fnt_def4 */
+ SubFontDef(cmd);
+ break;
+ default: done=TRUE; break;
+ }
+ }
+ return;
+}
+
+
+void SubPreamble()
+{
+ integer num, den, mag;
+ quarterword pre, id, k;
+
+ pre = (quarterword) GetByte(subfile);
+ id = (quarterword) GetByte(subfile);
+ num = GetQuad(subfile);
+ den = GetQuad(subfile);
+ mag = GetQuad(subfile);
+ k = (quarterword) GetByte(subfile);
+ /* skip over TeX comment */
+ SkipOver((long)k,subfile);
+
+ return;
+}
+
+
+void ReadSubFile()
+{
+int i;
+
+ if ( subfile!= NULL )
+ fclose(subfile);
+
+ subfile = fopen(subname, READ_BINARY);
+ if (subfile==NULL)
+ error("\n ! couldn't open file",subname);
+
+ for (i=0; i<sfonts; i++)
+ {
+ free(sub_fontlist[i]); sub_fontlist[i]=NULL;
+ }
+
+ sfonts = 0;
+ SubPostamble();
+ AddFontList();
+
+ return;
+}
+
+
+void bop()
+{
+int i,j;
+char tmp[80];
+integer pageno[10];
+char string[200];
+int done;
+
+ post.p = ftell(newfile)-1L;
+
+ /* filter thru c0[4]...c9[4] */
+ for (i=0; i<10; i++ )
+ {
+ pageno[i] = GetQuad(dvifile);
+ PutQuad(pageno[i],newfile);
+ }
+
+ j = 0; done = FALSE;
+ for (i=9; i>0 && !done; i--)
+ {
+ if ( pageno[i]!=0 )
+ { j = i; done = TRUE ; }
+ }
+
+ done = FALSE; string[0] = 0;
+ sprintf(string,"[%ld",pageno[0]);
+ for (i=1; i<=j; i++)
+ {
+ sprintf(tmp,".%ld",pageno[i]);
+ strcat(string,tmp);
+ }
+ strcat(string,"]");
+
+ i = strlen( string );
+ if ( ( ColumnPos + i ) > 80 )
+ { printf("\r\n"); ColumnPos = 0; }
+ printf("%s",string);
+ ColumnPos += i;
+
+ /* p[4] */
+ GetQuad(dvifile);
+ PutQuad(prevbop,newfile);
+
+ prevbop = post.p ;
+
+ return;
+}
+
+/* 08/06/1991 PAM Give main a predictable return value for the OS */
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+int cmd,i;
+Boolean done;
+
+ if ( argc<2 )
+ {
+ printf("\n\t\tUsage: dvipaste dvifile [newfile]");
+ printf("\n\t\tNote: newfile is optional\n");
+ exit(0);
+ }
+
+
+ printf("\nThis is DVIPASTE, Version 1.21");
+ printf("\nCopyright (c) 1989-91, The TeXplorators Corporation.");
+ printf("\nAll rights reserved.\n");
+
+ strcpy(dviname,argv[1]);
+ if (strstr(dviname,".")==NULL)
+ strcat(dviname,".dvi");
+
+ if ( argc<=2 )
+ {
+ strcpy(newname,dviname);
+ i = strlen(newname);
+ newname[i-1] = 'x';
+ }
+ else
+ {
+ strcpy(newname,argv[2]);
+ if (strstr(newname,".")==NULL)
+ strcat(newname,".dvi");
+ }
+
+ dvifile = fopen(dviname, READ_BINARY ) ;
+ if (dvifile==NULL)
+ error("! couldn't open file",dviname);
+
+ newfile = fopen(newname, WRITE_BINARY);
+ if (newfile==NULL)
+ error("! couldn't open file",newname);
+
+ Initialize();
+ ReadPostamble();
+
+ fseek(dvifile,0L,SEEK_SET);
+ ReadPreamble();
+
+ done=FALSE;
+ while ( !done )
+ {
+ cmd=GetByte(dvifile);
+
+ /* let's take a peek first at the current cmd before
+ running thru it. */
+ switch (cmd)
+ { /* this are specials; handle with care. */
+ case 239: case 240: case 241: case 242:
+ /* don't send out cmd yet */
+ break;
+ default:
+ PutByte(cmd,newfile); break;
+ }
+
+ /* set_char_0 thru set_char_127 */
+ /* cmd>=0 && cmd<=127 */
+
+ /* fnt_num_0 thru fnt_num_63 */
+ if ( cmd>=171 && cmd<=234 )
+ fnt.cmd = cmd;
+
+ switch (cmd)
+ {
+ /* eight bytes */
+ case 132: /* set_rule */
+ case 137: /* put_rule */
+ PutQuad(GetQuad(dvifile),newfile);
+ /* four bytes */
+ case 131: /* set4 */
+ case 136: /* put4 */
+ case 146: /* right4 */
+ case 151: /* w4 */
+ case 156: /* x4 */
+ case 160: /* down4 */
+ case 165: /* y4 */
+ case 170: /* z4 */
+ PutByte(GetByte(dvifile),newfile);
+ /* three bytes */
+ case 130: /* set3 */
+ case 135: /* put3 */
+ case 145: /* right3 */
+ case 150: /* w3 */
+ case 155: /* x3 */
+ case 159: /* down3 */
+ case 164: /* y3 */
+ case 169: /* z3 */
+ PutByte(GetByte(dvifile),newfile);
+ /* two bytes */
+ case 129: /* set2 */
+ case 134: /* put2 */
+ case 144: /* right2 */
+ case 149: /* w2 */
+ case 154: /* x2 */
+ case 158: /* down2 */
+ case 163: /* y2 */
+ case 168: /* z2 */
+ PutByte(GetByte(dvifile),newfile);
+ /* one byte */
+ case 128: /* set1 */
+ case 133: /* put1 */
+ case 143: /* right1 */
+ case 148: /* w1 */
+ case 153: /* x1 */
+ case 157: /* down1 */
+ case 162: /* y1 */
+ case 167: /* z1 */
+ PutByte(GetByte(dvifile),newfile);
+ break;
+ case 139: /* bop */
+ bop();
+ break;
+ case 141: /* push */
+ case 142: /* pop */
+ PopsAndPushes(cmd);
+ break;
+ case 138: /* nop */
+ case 140: /* eop */
+ case 147: /* w0 */
+ case 152: /* x0 */
+ case 161: /* y0 */
+ case 166: /* z0 */
+ break;
+ case 235: /* fnt1 */
+ fnt.cmd = cmd; fnt.k = GetByte(dvifile);
+ PutByte((quarterword)fnt.k,newfile);
+ break;
+ case 236: /* fnt2 */
+ fnt.cmd = cmd; fnt.k = GetWord(dvifile);
+ PutWord((halfword)fnt.k,newfile); break;
+ case 237: /* fnt3 */
+ fnt.cmd = cmd; fnt.k = GetTrio(dvifile);
+ PutTrio(fnt.k,newfile);
+ break;
+ case 238: /* fnt4 */
+ fnt.cmd = cmd; fnt.k = GetQuad(dvifile);
+ PutQuad(fnt.k,newfile);
+ break;
+ case 239: /* xxx1 */
+ case 240: /* xxx2 */
+ case 241: /* xxx3 */
+ case 242: /* xxx4 */
+ DoSpecial(cmd);
+ break;
+ /* fnt_def1...fnt_def4 */
+ case 243: case 244: case 245: case 246:
+ DefFont(cmd);
+ break;
+ case 248: /* post */
+ post_post.q = ftell(newfile) -1L;
+ done=TRUE;
+ break;
+ }
+ }
+
+ WritePostamble();
+ fclose(dvifile); fclose(newfile);
+ if ( subfile != NULL )
+ fclose(subfile);
+
+ if ( argc<=2 )
+ {
+ unlink(dviname); rename(newname,dviname);
+ }
+ printf("\n");
+ return(0);
+}
+
+
+/*
+ Add strstr() to the strings functions.
+ Some versions of SUN cc complain about macros in
+ loops, but gcc has no trouble with them. Depends
+ on how the macro is written, I suppose, but I think
+ gcc uses the same macro text as cc in this case.
+*/
+#ifndef ANSI
+char *
+ strstr(s,t)
+char *s,*t;
+{
+ char *ss;
+ ss = s;
+ while ( *ss != '\0' ) {
+ if ((strcmp(ss,t)) == 0) return ss;
+ ss++;
+ }
+ return(NULL);
+}
+#endif
diff --git a/dviware/dvipaste/dvipaste.doc b/dviware/dvipaste/dvipaste.doc
new file mode 100644
index 0000000000..10934333a4
--- /dev/null
+++ b/dviware/dvipaste/dvipaste.doc
@@ -0,0 +1,145 @@
+The dvipaste program was first described in the article
+
+ HI-TeX Cutting & Pasting
+
+in TUGboat, Volume 10 (1989), No. 2, pages 164--165. Consult this article
+for further details. (``TUGboat, The Communications of the TeX Users Group'',
+is published by TeX Users Group, P. O. Box 9506, Providence, RI 02940.)
+
+The dvipaste program is designed to produce files that conform to the TeX
+specifications for .dvi files, even though they may actually be too big to be
+produced with normal implementations of TeX (because of limitations on memory
+size). More particularly, it allows the material appearing on individual
+pages of a `secondary' file to be inserted into a `main' file.
+
+The `secondary' file, say `extra.tex', should be of the form
+
+ \input dvipaste
+ \input <macro packages>
+
+ <define a control sequence, say \csq, to stand for a complicated object>
+ or
+ <store some complicated object in a TeX box, say in \box0 >
+
+ \sendout{\csq} or \sendout{\box0 }
+
+ <store another object>
+ \sendout{...}
+ . . .
+ \end
+
+The main file, say `big.tex', should have
+
+ \input dvipaste
+
+at the beginning, and then
+
+ \paste{extra}{<number>}
+
+at any point, to indicate that the material on page <number> of `extra.dvi'
+is to be pasted in at that point.
+
+The secondary file `extra.tex' must be TeX'ed before the main file, because
+the \paste commands use information from a file `extra.dat' that is created
+when the secondary file is TeX'ed.
+
+When the main file is TeX'ed, blank spaces of the proper size will appear at
+the points where the \paste commands were placed. After using the dvipaste
+program,
+
+ dvipaste big
+
+the new big.dvi file will actually have the proper material from the
+secondary file pasted in, and will give the desired result when printed out.
+
+[You can also type
+
+ dvipaste big newbig
+
+if you want to save the big.dvi file, and create a new .dvi file, newbig.dvi.
+(With TeXtures you MUST choose a new name, because TeXtures won't allow you
+to make a TeXtures document out of a different big.dvi when the first one
+already exists as a resource to big.tex.)]
+
+The dvipaste.tex macro package will not allow both a \sendout and a \paste to
+occur in the same file, so that a file must be used either as a main file or
+as a secondary file. However, an arbitrary number of secondary files can be
+used in a main file, and the <number>'s appearing in \paste commands do not
+have to be consecutive.
+
+ * * *
+
+The lamstex.tex macro package essentially includes the part of the
+dvipaste.tex macro packages that is used to make \paste be defined.
+
+The lamstbl.tex macro package essentially includes the part of the
+dvipaste.tex macro package that is used to make \sendout be defined.
+However, \sendout is never actually used in LamS-TeX because an \endtable in
+a LamS-TeX tables file essentially does the \sendout.
+
+ * * *
+
+One possible use for dvipaste.tex is for files produced by PiCTeX. The
+.dvi files that PiCTeX produces for a figure are often so large that
+although the figure alone can be printed, it cannot be combined with other
+text on that page, because TeX doesn't have enough memory to store such a
+large .dvi file (especially when it has to store all the macros being
+used). For such situations, one could create a secondary file for the
+pictures,
+
+ \input dvipaste
+ \input pictex
+ <store a picture in a box or a control sequence>
+ \sendout{the picture}
+ . . .
+
+and then \paste the pictures into the main file at the appropriate point.
+
+This should be applicable with LamS-TeX also. The secondary file, say
+`pictures.tex', should be treated as an ordinary TeX file, NOT as a LamS-TeX
+file (if the pictures include some text, new fonts can be introduced after
+the \input pictex line, if necessary). Then in the main LamS-TeX file,
+
+ \paste{pictures}{<number>}
+
+can be inserted at any point. For example, you might use such a \paste
+instead of an \hbyw{...}{...} construction in a \figure ... \endfigure.
+
+ * * * * * *
+
+ EXAMPLE OF THE USE OF DVIPASTE
+
+The files boxes1.tex, boxes2.tex, and join.tex all begin with
+
+ \input dvipaste
+
+and illustrate the general use of the dvipaste program. To see it action,
+
+(1) First do
+
+ tex boxes1
+and
+ tex boxes2
+
+This will produce boxes1.dvi and boxes2.dvi, which you can print or view,
+as well as boxes1.dat and boxes2.dat.
+
+(2) Then, once boxes1.dat and boxes2.dat have been produced, do
+
+ tex join
+
+producing join.dvi, which you can print or view.
+
+(3) Finally, do
+
+ dvipaste join newjoin
+
+to produce a newjoin.dvi. When you view or print this, the boxes will have
+been pasted in.
+
+(4) You can also simply do
+
+ dvipaste join
+
+if you want the old join.dvi to be replaced by a new one, with the boxes
+pasted in (not possible with TeXtures).
diff --git a/dviware/dvipaste/dvipaste.patch.01 b/dviware/dvipaste/dvipaste.patch.01
new file mode 100644
index 0000000000..0102c7e59e
--- /dev/null
+++ b/dviware/dvipaste/dvipaste.patch.01
@@ -0,0 +1,76 @@
+This should fix dvipaste.c so that it will work on big-endian
+machines as well.
+
+ Ed Sznyter
+ ews@babel.COM
+ Jun 3, 1993
+
+*** dvipaste.c.new Thu Jun 3 09:30:02 1993
+--- dvipaste.c Thu Jun 3 09:29:23 1993
+***************
+*** 338,347 ****
+ int num;
+ FILE *f;
+ {
+! char *p;
+! p=(char *)&num;
+! PutByte(*(p+1), f);
+! PutByte(*p, f);
+ return;
+ }
+
+--- 346,353 ----
+ int num;
+ FILE *f;
+ {
+! PutByte( (num>>8) , f);
+! PutByte( (num>>0) , f);
+ return;
+ }
+
+***************
+*** 351,360 ****
+ FILE *f;
+ {
+ int i;
+! char *p;
+! p = (char *)&trio;
+! for (i=2; i>=0; i--)
+! PutByte( *(p+i), f);
+ return;
+ }
+
+--- 357,365 ----
+ FILE *f;
+ {
+ int i;
+! PutByte( (trio>>16) , f);
+! PutByte( (trio>>8) , f);
+! PutByte( (trio>>0) , f);
+ return;
+ }
+
+***************
+*** 362,372 ****
+ long quad;
+ FILE *f;
+ {
+! int i;
+! char *p;
+! p = (char *)&quad;
+! for (i=3; i>=0; i--)
+! PutByte( *(p+i), f );
+ return;
+ }
+
+--- 367,376 ----
+ long quad;
+ FILE *f;
+ {
+! PutByte( (quad>>24) , f);
+! PutByte( (quad>>16) , f);
+! PutByte( (quad>>8) , f);
+! PutByte( (quad>>0) , f);
+ return;
+ }
+
diff --git a/dviware/dvipaste/dvipaste.txt b/dviware/dvipaste/dvipaste.txt
new file mode 120000
index 0000000000..80991625c4
--- /dev/null
+++ b/dviware/dvipaste/dvipaste.txt
@@ -0,0 +1 @@
+dvipaste.doc \ No newline at end of file
diff --git a/dviware/dvipaste/test/boxes1.tex b/dviware/dvipaste/test/boxes1.tex
new file mode 100644
index 0000000000..5faaffd0bb
--- /dev/null
+++ b/dviware/dvipaste/test/boxes1.tex
@@ -0,0 +1,27 @@
+\input dvipaste
+
+
+\font\bf=cmbx10
+\font\sl=cmsl10
+\font\it=cmti10
+\def\rm{\tenrm}
+
+\def\rulebox#1#2#3{\hbox{\vrule\kern-.4pt
+ \vbox to#2{\hrule width#1\vfil\hbox{#3}\vfil\hrule width#1}\kern-.4pt\vrule}}
+
+\setbox0\rulebox{140pt}{210pt}{\bf ABC\it DEF}
+\sendout{\box0}
+
+\setbox0\rulebox{125pt}{234pt}{\sl GHI\rm J\it K}
+\sendout{\box0}
+
+\setbox0\rulebox{225pt}{117pt}{\it ABC}
+\sendout{\box0}
+
+\setbox0\rulebox{123pt}{234pt}{\vbox{\hrule\hbox{\vrule height 30pt
+ ABC\vrule}\hrule}}
+\sendout{\box0}
+
+
+\end
+
diff --git a/dviware/dvipaste/test/boxes2.tex b/dviware/dvipaste/test/boxes2.tex
new file mode 100644
index 0000000000..f5ed9ded45
--- /dev/null
+++ b/dviware/dvipaste/test/boxes2.tex
@@ -0,0 +1,19 @@
+\input dvipaste
+
+
+\font\sl=cmsl10
+\font\bf=cmsl10
+\font\it=cmti10
+\def\rm{\tenrm}
+
+\def\rulebox#1#2#3{\hbox{\vrule\kern-.4pt
+ \vbox to#2{\hrule width#1\vfil\hbox{#3}\vfil\hrule width#1}\kern-.4pt\vrule}}
+
+
+\setbox0\rulebox{70pt}{140pt}{\bf ABC\it DEF}
+\sendout{\box0}
+
+\setbox0\rulebox{75pt}{135pt}{\sl ZZ}
+\sendout{\box0}
+
+\end \ No newline at end of file
diff --git a/dviware/dvipaste/test/dvipaste.tex b/dviware/dvipaste/test/dvipaste.tex
new file mode 100644
index 0000000000..465f9cd473
--- /dev/null
+++ b/dviware/dvipaste/test/dvipaste.tex
@@ -0,0 +1,331 @@
+% Copyright (C) The TeXplorators Corporation 1989
+
+% This is DVIPASTE.TEX, to be used with DVIPASTE.EXE, which is
+% Copyright (C) The TeXplorators Corporation 1989.
+
+% First we want to have a control sequence that stands for the current
+% category code of @, so that we can restore this category code at the end,
+% after temporarily making @ a letter (PLAIN makes @ category 12, but
+% AmS-TeX, for example, makes @ category 13). Using \csname CCC@\endcsname,
+% we can even let this control sequence be called \CCC@, before actually
+% making @ a letter, except that this won't work when @ has category
+% code 13, so instead we have to use the \uccode and \uppercase trick.
+
+{\uccode`\Z=`\@
+ \uppercase{\expandafter\xdef\csname CCCZ\endcsname{\the\catcode`\@}}
+}
+
+% Now we make @ a letter.
+
+\catcode`\@=11
+
+
+% \eat@ gobbles a token; it is the same as in AmS-TeX.
+
+\def\eat@#1{}
+
+
+% We need to know if a \sendout or \paste has already occurred. The
+% following are made true once the respective condition has occurred.
+
+\newif\ifsendout@
+\newif\ifpaste@
+
+
+% We need to allocate places for writing or reading the .dat file.
+
+\newwrite\writedata@
+\newread\readdata@
+
+
+% The definition of \sendout has the following features (%1, %2, etc.
+% refer to lines so marked within the definition of \sendout):
+
+%1 If \paste has occurred, we won't allow a \sendout to occur, because
+% these shouldn't both occur in the same file; in fact, files having
+% \sendout's will redefine the \output routine.
+
+% In the \errmessage, we can't say \string\sendout, because \sendout is
+% outer. So we use \expandafter\eat@\string\\ to get the \, and then
+% spell out sendout.
+
+%2 If a \paste hasn't occurred, we see if a previous \sendout has occurred,
+% and if it hasn't, we do the following:
+
+%3 Open the .dat file for writing.
+
+%4 Declare \t@nrm to use for the name of the file and the page number
+% in the footline (it is possible that no font with the necessary
+% characters in it has been used in the file); the declaration is made
+% \global, just in case \sendout was used in a group, though it really
+% shouldn't be.
+
+%5 Set \topskip to 0pt.
+
+%6 Change the \output routine, to simply \shipout the current page,
+% followed by a line 2pc below with the name of the file, and the
+% page number.
+
+%7 We also want to redefine \bye, to close out the .dat file. We can't
+% put \gdef\bye within the definition of \sendout, since \bye is outer,
+% but we can say \expandafter\gdef\csname bye\endcsname !
+
+%8 And we make \ifsendout@ true.
+
+%9 In any case (i.e., whether or not a previous \sendout has occurred),
+% we now put #1 in \box0, so that we can refer to its height, depth and
+% width (usually #1 will be a \box, but we don't know which one).
+
+%10 Then we write this data to the .dat file; each \space will expand to a
+% space (PLAIN has \def\space{ }).
+
+%11 We start the page with an invisible \hrule (so that the next \vskip
+% won't disappear).
+
+%12 We move down to the bottom of the page.
+
+%13 We emit a special, which tells where the .dvi instructions for
+% printing \box0 begin.
+
+%14 We set the dimensions of \box0 to 0pt.
+
+%15 We start an unindented paragraph with \box0.
+
+%16 Then we emit another special, which tells where the .dvi instructions
+% for printing \box0 end.
+
+%17 Finally, we put in a smashed (and tiny) \vrule. Since this \vrule
+% has to occur exactly at the same position where the \noindent began,
+% the .dvi instructions for printing \box0 will bring us right back to
+% the position we started at.
+
+%18 Then we \eject, so that the \output routine will simply print \box0 on
+% a separate page.
+
+\outer\def\sendout#1{%
+ \ifpaste@ %1
+ \errmessage{\expandafter\eat@\string\\sendout and
+ \string\paste\space not allowed in same file
+ (\string\paste\space has already appeared)}%
+ \else %2
+ \ifsendout@
+ \else
+ \immediate\openout\writedata@=\jobname.dat %3
+ \global\font\t@nrm=cmr10 %4
+ \global\topskip\z@ %5
+ \global\output{\shipout\vbox{\vbox to\vsize{\unvbox255 }% %6
+ \baselineskip2pc
+ \line{\hfil\t@nrm File [\jobname], \#\number\pageno\hfil}}%
+ \global\advance\pageno\@ne}%
+ \expandafter\gdef\csname bye\endcsname %7
+ {\immediate\closeout\writedata@\par\vfill\supereject\end}%
+ \global\sendout@true %8
+ \fi
+ \setbox\z@\hbox{#1}% %9
+ \immediate\write\writedata@
+ {\the\ht\z@\space\the\dp\z@\space\the\wd\z@}% %10
+ \hrule height\z@ %11
+ \vskip\vsize %12
+ \special{beginpaste:}% %13
+ \ht\z@=\z@\dp\z@=\z@\wd\z@=\z@ %14
+ \noindent\box\z@ %15
+ \special{endpaste:}% %16
+ \smash{\vrule height1sp width1sp depth\z@}% %17
+ \eject %18
+ \fi}
+
+
+% The scratch tokens \toks@@ are already used in AmS-TeX.
+
+\toksdef\toks@@=2
+
+
+% \rightappend@ is from The TeXbook, page 378.
+
+\long\def\rightappend@#1\to#2{\toks@{\\{#1}}%
+ \toks@@=\expandafter{#2}\xdef#2{\the\toks@@\the\toks@}}
+
+
+% \ifreading@ will be true while still reading the data file; it is simply
+% the opposite of \ifeof, but we need an \if... with these reversed values,
+% to use within a \loop.
+
+\newif\ifreading@
+
+
+% The last line of the data file will produce a \par, so we need to have
+% something to test against \par.
+
+\def\Par@{\par}
+
+
+% The definition of \paste has the following features:
+
+%1 If \sendout has occurred, we won't allow a \paste to occur.
+
+%2 If a \paste hasn't occurred, we do the following:
+
+%3 We make \ifpaste@ true.
+
+%4 When we read in a data file `file'.dat, we will record all the data
+% in a control sequence \`file'@dat. This will be a list macro, as in
+% The TeXbook, page 378.
+
+% To see whether we have read in the data file yet, we just see whether
+% this control sequence, as specified by \csname, is \relax.
+
+%5 If not, we haven't read the file yet, so we immediately open it for
+% reading.
+
+%6 We use \ifeof to test whether the file really exists.
+
+%7 Assuming the file does exist, we do the following.
+
+%8 We are going to temporarily store the data in the control sequence
+% \next@, and at the end \let\`file'@dat=\next@. We do this because it
+% is rather awkward to continually refer to the control sequence
+% \`file'@dat, which can only be named using \csname. We begin by
+% setting \next@ to be empty.
+
+%9 We set \ifreading@ to be true (it will be false when we get to the
+% end of the data file).
+
+%10 We read using a \loop.
+
+%11 The \loop needs a test that is true if we are going to keep reading,
+% so we set \ifreading@ false when \ifeof gives true.
+
+%12 If we are still reading the file, we read a line to \next@ii.
+
+%13 The file has a \par at the end, so \ifx\next@ii\Par@ is true when we
+% are at the last line.
+
+%14 If that is not the case, then we want to add the data in \next@ii to
+% \next@. We need \expandafter\rightappend@; otherwise we would just
+% get \next@ii in the token list, rather than the values it now has.
+
+%15 And we just keep doing that until the file is all read.
+
+%16 Then we close the file.
+
+%17 And then we want to \global\let\`file'@dat=\next@. We need to expand
+% the \csname...\endcsname after a \global\let, which requires the
+% triple \expandafter trick of The TeXbook, page 374.
+
+%18 In any case (i.e., whether or not we first had to read in the data
+% file), we now want to apply the \getdata@ construction, defined
+% below, to \`file'@dat and the second argument #2 of \paste. This
+% also requires an \expandafter.
+
+%19 \ifgetdata@ will be true if #2 is actually the number of a line in
+% the data file.
+
+%20 In this case, the three pieces of data will be stored in \data@ht,
+% \data@dp, and \data@wd, and we will want to put in a box of that
+% height, depth and width. The easiest way is to lower a box of that
+% height+depth by the depth, so we first set \dimen@ to that sum.
+
+%21 We make an \hbox containing the special, and then the empty box with
+% the desired dimensions. NOTE: It is important to put the \special
+% in the \hbox, in case this empty box turns out to be the first
+% thing on the page. For some reason, \tex\ doesn't position such
+% an empty box at the right place, although it does position anything
+% that will actually appear on the page in the right place; a box
+% with a \special in it is NOT treated as an empty box in this process.
+
+%22 If #2 is not the number of a line in the data file, we just give an
+% error message ``No data for File [<data file>], #[<value of #2>]''
+% In order to have # appear in the error message, rather than ##, we
+% temporarily make # the \lccode of Z, put Z where we want the # to
+% appear, and then \lowercase the \errmessage. However, we want to
+% have uppercase N and F in this message, so we have to also set
+% the \lccode of N to N, and of F to F.
+
+
+\def\paste#1#2{%
+ \ifsendout@ %1
+ \errmessage{\string\paste\space and
+ \expandafter\eat@\string\\sendout not allowed in same file
+ (\expandafter\eat@\string\\sendout has already appeared)}%
+ \else %2
+ \global\paste@true %3
+ \expandafter\ifx\csname #1@dat\endcsname\relax %4
+ \immediate\openin\readdata@=#1.dat %5
+ \ifeof\readdata@\errmessage{No file #1.dat}% %6
+ \else %7
+ \def\next@{}% %8
+ \reading@true %9
+ \loop %10
+ \ifeof\readdata@\reading@false\fi %11
+ \ifreading@ %12
+ \read\readdata@ to\next@ii
+ \ifx\next@ii\Par@\else %13
+ \expandafter\rightappend@\next@ii\to\next@\fi %14
+ \repeat %15
+ \immediate\closein\readdata@ %16
+ \expandafter\expandafter\expandafter\global\expandafter
+ \let\csname#1@dat\endcsname\next@ %17
+ \fi
+ \fi
+ \expandafter\getdata@\csname#1@dat\endcsname{#2}% %18
+ \ifgetdata@ %19
+ \dimen@=\data@ht\advance\dimen@\data@dp %20
+ \hbox{\special{dvipaste: #1 #2}% %21
+ \lower\data@dp\vbox to\dimen@{\hbox to\data@wd{\hfil}\vfil}}%
+ \else %22
+ {\lccode`\Z=`\#\lccode`\N=`\N\lccode`\F=`\F%
+ \lowercase{\errmessage{No data for File [#1], Z#2}}}%
+ \fi
+ \fi}
+
+
+% \data@ht, \data@dp, and \data@wd are registers in which \getdata@ will
+% store the data gotten.
+
+\newdimen\data@ht
+\newdimen\data@dp
+\newdimen\data@wd
+
+
+% We also use a flag \ifgetdata@ to tell whether there was data on the line
+% requested.
+
+\newif\ifgetdata@
+
+
+% Argument #1 for \getdata@ is a list macro, and #2 a number.
+
+%1 We start by setting the counter \count@ to 0, and \ifgetdata@ to
+% false.
+
+%2 We temporarily (i.e., within a group), define \\ to: (a) advance
+% \count@ by 1 (so that \count@ is k when we are looking at the kth
+% thing on the list); (b) if \count@=#2 (we are at the element of the
+% lists specified by #2), set \ifgetdata@ true (so it is true only if
+% there are at least #2 pieces of data); (c) and then use \getdata@@ to
+% get the data out of this piece.
+
+%3 And then we apply this \\ to the list.
+
+
+\def\getdata@#1#2{\count@\z@\getdata@false %1
+ {\def\\##1{\advance\count@\@ne\ifnum\count@=#2\relax\global\getdata@true
+ \getdata@@##1\getdata@@\fi %2
+ }#1}} %3
+
+
+% The elements of the list macro will be of the form
+
+% [...]pt [...]pt [...]pt
+
+% with a space after the first and second pt, so we just have \getdata@
+% delimit its first two arguments with spaces.
+
+
+\def\getdata@@#1 #2 #3\getdata@@{%
+ \global\data@ht=#1\relax\global\data@dp=#2\relax\global\data@wd=#3\relax}
+
+
+% Finally, we return @ to its old \catcode.
+
+\catcode`\@\CCC@
diff --git a/dviware/dvipaste/test/join.tex b/dviware/dvipaste/test/join.tex
new file mode 100644
index 0000000000..0801ee07e3
--- /dev/null
+++ b/dviware/dvipaste/test/join.tex
@@ -0,0 +1,37 @@
+\input dvipaste
+
+\font\it=cmti10
+\def\rm{\tenrm}
+
+Here is some text that we have before the joined boxes. Now we will have the
+boxes joined by a line segment:
+
+\hbox{\paste{boxes1}1%
+ \vrule height 30pt depth-29pt width1in
+ \paste{boxes2}2}
+And this is the text that we have after it.
+
+Here is just a lot of stuff \it that we will continue to put in italics,
+for the rest of the file, in fact.
+
+\vfil\eject
+
+
+This is some more text.
+
+
+\hbox{\paste{boxes1}4%
+ \vrule height 30pt depth-29pt width1in
+ \paste{boxes2}1}
+And this is the text that we have after it.
+
+\vfil\eject
+
+\rm Now we are back to roman type.
+
+\hbox{\paste{boxes1}3%
+ \vrule height 30pt depth-29pt width1in
+ \paste{boxes1}4}
+And this is the text that we have after it.
+
+\bye \ No newline at end of file