diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvipaste |
Initial commit
Diffstat (limited to 'dviware/dvipaste')
-rw-r--r-- | dviware/dvipaste/DOS-EXE/DVIPASTE.EXE | bin | 0 -> 42339 bytes | |||
-rw-r--r-- | dviware/dvipaste/Makefile | 38 | ||||
-rw-r--r-- | dviware/dvipaste/NOTE | 42 | ||||
-rw-r--r-- | dviware/dvipaste/config.MS.h | 6 | ||||
-rw-r--r-- | dviware/dvipaste/config.h | 14 | ||||
-rw-r--r-- | dviware/dvipaste/config.sun-gcc.h | 14 | ||||
-rw-r--r-- | dviware/dvipaste/dvipaste.c | 2035 | ||||
-rw-r--r-- | dviware/dvipaste/dvipaste.doc | 145 | ||||
-rw-r--r-- | dviware/dvipaste/dvipaste.patch.01 | 76 | ||||
l--------- | dviware/dvipaste/dvipaste.txt | 1 | ||||
-rw-r--r-- | dviware/dvipaste/test/boxes1.tex | 27 | ||||
-rw-r--r-- | dviware/dvipaste/test/boxes2.tex | 19 | ||||
-rw-r--r-- | dviware/dvipaste/test/dvipaste.tex | 331 | ||||
-rw-r--r-- | dviware/dvipaste/test/join.tex | 37 |
14 files changed, 2785 insertions, 0 deletions
diff --git a/dviware/dvipaste/DOS-EXE/DVIPASTE.EXE b/dviware/dvipaste/DOS-EXE/DVIPASTE.EXE Binary files differnew file mode 100644 index 0000000000..7184319b9d --- /dev/null +++ b/dviware/dvipaste/DOS-EXE/DVIPASTE.EXE 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 *)# +#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 *)# +! 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 |