[comp.sources.misc] v12i008: DVI2TTY: Part 2 of 2; supports VMS and symbol fonts

marcel@duteca.tudelft.nl (Marcel Mol) (04/14/90)

Posting-number: Volume 12, Issue 8
Submitted-by: marcel@duteca.tudelft.nl (Marcel Mol)
Archive-name: dvi2tty2/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  dvistuff.c dvi2tty.h dvi2tty.1
# Wrapped by marcel@duteca on Thu Mar  1 23:08:08 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dvistuff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dvistuff.c'\"
else
echo shar: Extracting \"'dvistuff.c'\" \(38176 characters\)
sed "s/^X//" >'dvistuff.c' <<'END_OF_FILE'
X
X#include "dvi2tty.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#if defined(VMS) 
X#include types.h
X#include stat
X#endif
X#if defined(MSDOS)
X#include <math.h>
X#endif
X#include "commands.h"
X
X#if defined(VMS) 
X#define mseek vmsseek
X#define ROUND(a)        (a>=0.0 ?  (int) (a + 0.5) : (int) (a - 0.5) )
X#else
X#define mseek fseek
X#endif
X
X#define VERSIONID            2 /* dvi version number that pgm handles      */
X#define VERTICALEPSILON 450000L /* crlf when increasing v more than this   */
X
X#define rightmargin     152    /* nr of columns allowed to the right of h=0*/
X#define leftmargin      -50    /* give some room for negative h-coordinate */
X#define LINELEN         203    /* rightmargin - leftmargin + 1 */
X
X#define MOVE            TRUE   /* if advancing h when outputing a rule     */
X#define STAY            FALSE  /* if not advancing h when outputing a rule */
X
X#define absolute        0      /* for seeking in files                     */
X#define relative        1
X
X#define FORM             12    /* formfeed                                 */
X#define SPACE            32    /* space                                    */
X#define DEL             127    /* delete                                   */
X
X#define LASTCHAR        127    /* max dvi character, above are commands    */
X
X#define IMIN(a, b)      (a<b ? a : b)
X#define IMAX(a, b)      (a>b ? a : b)
X
X#define get1()          num(1)
X#define get2()          num(2)
X#define get3()          num(3)
X#define get4()          num(4)
X#define sget1()         snum(1)
X#define sget2()         snum(2)
X#define sget3()         snum(3)
X#define sget4()         snum(4)
X
Xchar *dvistuff = "@(#) dvistuff.c  4.0 04/02/90 M.J.E. Mol (c) 1989, 1990";
X
X/*---------------------------------------------------------------------------*/
X
Xtypedef struct {
X    long hh;
X    long vv;
X    long ww;
X    long xx;
X    long yy;
X    long zz;
X} stackitem;
X
Xtypedef struct lineptr {        /* the lines of text to be output to outfile */
X    long            vv;                 /* vertical position of the line     */
X    int             charactercount;     /* pos of last char on line          */
X    struct lineptr *prev;               /* preceding line                    */
X    struct lineptr *next;               /* succeeding line                   */
X    char            text[LINELEN+1];    /* leftmargin...rightmargin          */
X} linetype;
X
Xtypedef struct _font {
X    long    num;
X    struct _font * next;
X    char  * name;
X} font;
X
X
X/*---------------------------------------------------------------------------*/
X
Xbool        pageswitchon;       /* true if user-set pages to print           */
Xbool        sequenceon;         /* false if pagesw-nrs refers to TeX-nrs     */
Xbool        scascii;            /* if true make Scand. nat. chars right      */
Xbool        noffd;              /* if true output ^L instead of formfeed     */
X
Xint         opcode;             /* dvi-opcodes                               */
X
Xlong        h, v;               /* coordinates, horizontal and vertical      */
Xlong        w, x, y, z;         /* horizontal and vertical amounts           */
X
Xlong        pagecounter;        /* sequence page number counter              */
Xlong        backpointer;        /* pointer for offset to previous page       */
Xlong        pagenr;             /* TeX page number                           */
Xint         stackmax;           /* stacksize required                        */
X
Xlong        maxpagewidth;       /* width of widest page in file              */
Xlong        charwidth;          /* aprox width of character                  */
X
Xlinetype *  currentline;        /* pointer to current line on current page   */
Xlinetype *  firstline;          /* pointer to first line on current page     */
Xlinetype *  lastline;           /* pointer to last line on current page      */
Xint         firstcolumn;        /* 1st column with something to print        */
X
Xstackitem * stack;              /* stack for dvi-pushes                      */
Xint         sptr;               /* stack pointer                             */
X
Xfont * fonts = NULL;            /* List of fontnames defined                 */
Xint  symbolfont = FALSE;        /* true if font is a symbol font             */
X
X/*---------------------------------------------------------------------------*/
X
X#if defined(MSDOS)
Xvoid            postamble       (void);
Xvoid            preamble        (void);
Xvoid            walkpages       (void);
Xvoid            initpage        (void);
Xvoid            dopage          (void);
Xvoid            skippage        (void);
Xvoid            printpage       (void);
Xbool            inlist          (long);
Xvoid            rule            (bool, long, long);
Xvoid            ruleaux         (long, long, char);
Xlong            horizontalmove  (long);
Xint             skipnops        (void);
Xlinetype    *   getline         (void);
Xlinetype    *   findline        (void);
Xunsigned long   num             (int);
Xlong            snum            (int);
Xvoid            dochar          (char);
Xvoid            symchar         (char);
Xvoid            normchar        (char);
Xvoid            outchar         (char);
Xvoid            putcharacter    (long);
Xvoid            setchar         (long);
Xvoid            fontdef         (int);
Xvoid            setfont         (long);
X#else
Xvoid            postamble       ();
Xvoid            preamble        ();
Xvoid            walkpages       ();
Xvoid            initpage        ();
Xvoid            dopage          ();
Xvoid            skippage        ();
Xvoid            printpage       ();
Xbool            inlist          ();
Xvoid            rule            ();
Xvoid            ruleaux         ();
Xlong            horizontalmove  ();
Xint             skipnops        ();
Xlinetype    *   getline         ();
Xlinetype    *   findline        ();
Xunsigned long   num             ();
Xlong            snum            ();
Xvoid            dochar          ();
Xvoid            symchar         ();
Xvoid            normchar        ();
Xvoid            outchar         ();
Xvoid            putcharacter    ();
Xvoid            setchar         ();
Xvoid            fontdef         ();
Xvoid            setfont         ();
X#if defined(VMS)
Xlong		vmsseek		();
Xlong		vms_ftell	();
Xlong		vms_ungetc	();
X#endif
X#endif
X
X
X/*---------------------------------------------------------------------------*/
X/*---------------------------------------------------------------------------*/
X
X/*
X * The main function for processing the dvi file.
X * Here we assume there are to file pointers: DVIfile and output.
X * Also we have a list of pages pointed to by 'currentpage',
X * which is only used (in 'inlist()') when a page list is given.
X */
X
Xvoid dvimain()
X{
X
X    postamble();                            /* seek and process the postamble */
X    /* note that walkpages *must* immediately follow preamble */
X    preamble();                             /* process preamble               */
X    walkpages();                            /* time to do the actual work!    */
X
X} /* dvimain */
X
X/*---------------------------------------------------------------------------*/
X
Xvoid postamble()            /* find and process postamble, use random access */
X{
X    register long size;
X    register int  count;
X    struct stat st;
X
X    fstat (fileno(DVIfile), &st);
X    size = (long) st.st_size;                   /* get size of file          */
X    count = -1;
X    do {              /* back file up past signature bytes (223), to id-byte */
X        if (size == 0)
X            errorexit(nopst);
X        size--;
X        mseek(DVIfile, size, absolute);
X        opcode = (int) get1();
X        count++;
X    } while (opcode == TRAILER);
X    if (count < 4) {                            /* must have 4 trailer bytes */
X         foo = count;
X         errorexit(fwsgn);
X    }
X    if (opcode != VERSIONID)
X        errorexit(badid);
X    mseek(DVIfile, size-4, absolute);       /* back up to back-pointer       */
X    mseek(DVIfile, sget4(), absolute);      /* and to start of postamble   */
X    if (get1() != POST)
X        errorexit(nopst);
X    mseek(DVIfile, 20L, relative); /* lastpageoffset, numerator, denominator */
X                                   /* magnification, maxpageheight           */
X    maxpagewidth = sget4();
X    charwidth = maxpagewidth / (ttywidth + espace); 
X    stackmax = (int) get2();
X    if ((stack = (stackitem *) malloc(stackmax * sizeof(stackitem))) == NULL)
X       errorexit(stkrq);
X
X    /* get2() -- totalpages */
X    /* fontdefs  do fontdefs in flight ... */
X
X} /* postamble */
X
X/*---------------------------------------------------------------------------*/
X
Xvoid preamble()                 /* process preamble, use random access       */
X{
X
X    mseek(DVIfile, 0L, absolute);       /* read the dvifile from the start   */
X    if ((opcode = skipnops()) != PRE)
X        errorexit(nopre);
X    opcode = (int) get1();        /* check id in preamble, ignore rest of it */
X    if (opcode != VERSIONID)
X        errorexit(badid);
X    mseek(DVIfile, 12L, relative);  /* numerator, denominator, magnification */
X    mseek(DVIfile, get1(), relative);         /* skip job identification     */
X
X} /* preamble */
X
X/*----------------------------------------------------------------------------*/
X
Xvoid walkpages()                  /* process the pages in the DVI-file */
X{
X    register bool wantpage;
X
X    pagecounter = 0L;
X    while ((opcode = skipnops()) != POST) {
X        if (opcode != BOP)              /* should be at start of page now    */
X            errorexit(nobop);
X        else {
X            pagecounter++;
X            pagenr = sget4();           /* get TeX page number               */
X            mseek(DVIfile, 36L, relative); /* skip page header */
X            backpointer = sget4();      /* get previous page offset          */
X            if (pageswitchon)
X                if (sequenceon)
X                    wantpage = inlist(pagecounter);
X                else
X                    wantpage = inlist(pagenr);
X            else
X                wantpage = TRUE;
X
X            if (wantpage) {
X                initpage();
X                dopage();
X                printpage();
X            }
X            else {
X                skippage();
X            }
X        }
X    }
X
X} /* walkpages */
X
X/*---------------------------------------------------------------------------*/
X
Xvoid initpage()
X{
X
X    h = 0L;  v = 0L;                        /* initialize coordinates   */
X    x = 0L;  w = 0L;  y = 0L;  z = 0L;      /* initialize amounts       */
X    sptr = 0;                               /* initialize stack         */
X    currentline = getline();                /* initialize list of lines */
X    currentline->vv = 0L;
X    firstline   = currentline;
X    lastline    = currentline;
X    firstcolumn = rightmargin;
X    if (pageswitchon) {
X        if ((sequenceon && (pagecounter != firstpage->pag)) ||
X            (!sequenceon && (pagenr != firstpage->pag)))
X            if (noffd)
X                fprintf(output, "^L\n");
X            else
X                putc(FORM, output);
X    }
X    else
X        if (backpointer != -1)              /* not FORM at first page   */
X            if (noffd)
X                fprintf(output, "^L\n");
X            else
X                putc(FORM, output);
X
X} /* initpage */
X
X/*----------------------------------------------------------------------------*/
X
Xvoid dopage()
X{
X
X    while ((opcode = (int) get1()) != EOP) {    /* process page until eop */
X        if (opcode <= LASTCHAR)
X            dochar((char) opcode);
X        else if ((opcode >= FONT_00) && (opcode <= FONT_63)) 
X            setfont(opcode - FONT_00);
X        else if (opcode > POST_POST)
X            errorexit(illop);
X        else
X            switch (opcode) {
X                case SET1     : setchar(get1()); break;
X                case SET2     : setchar(get2()); break;
X                case SET3     : setchar(get3()); break;
X                case SET4     : setchar(get4()); break;
X                case SET_RULE : { long height = sget4();
X                                  rule(MOVE, sget4(), height); break;
X                                }
X                case PUT1     : putcharacter(get1()); break;
X                case PUT2     : putcharacter(get2()); break;
X                case PUT3     : putcharacter(get3()); break;
X                case PUT4     : putcharacter(get4()); break;
X                case PUT_RULE : { long height = sget4();
X                                  rule(STAY, sget4(), height); break;
X                                }
X                case NOP      : break;  /* no-op */
X                case BOP      : errorexit(bdbop); break;
X/*              case EOP      : break;  strange place to have EOP */
X                case PUSH     : if (sptr >= stackmax)            /* push */
X                                     errorexit(stkof);
X                                stack[sptr].hh = h;
X                                stack[sptr].vv = v;
X                                stack[sptr].ww = w;
X                                stack[sptr].xx = x;
X                                stack[sptr].yy = y;
X                                stack[sptr].zz = z;
X                                sptr++;
X                                break;
X                case POP      : if (sptr == 0)                   /* pop */
X                                    errorexit(stkuf);
X                                sptr--;
X                                h = stack[sptr].hh;
X                                v = stack[sptr].vv;
X                                w = stack[sptr].ww;
X                                x = stack[sptr].xx;
X                                y = stack[sptr].yy;
X                                z = stack[sptr].zz;
X                                break;
X                case RIGHT1   : (void) horizontalmove(sget1()); break;
X                case RIGHT2   : (void) horizontalmove(sget2()); break;
X                case RIGHT3   : (void) horizontalmove(sget3()); break;
X                case RIGHT4   : (void) horizontalmove(sget4()); break;
X                case W0       : h += w; break;
X                case W1       : w = horizontalmove(sget1()); break;
X                case W2       : w = horizontalmove(sget2()); break;
X                case W3       : w = horizontalmove(sget3()); break;
X                case W4       : w = horizontalmove(sget4()); break;
X                case X0       : h += x; break;
X                case X1       : x = horizontalmove(sget1()); break;
X                case X2       : x = horizontalmove(sget2()); break;
X                case X3       : x = horizontalmove(sget3()); break;
X                case X4       : x = horizontalmove(sget4()); break;
X                case DOWN1    : v += sget1(); break;
X                case DOWN2    : v += sget2(); break;
X                case DOWN3    : v += sget3(); break;
X                case DOWN4    : v += sget4(); break;
X                case Y0       : v += y; break;
X                case Y1       : y = sget1(); v += y; break;
X                case Y2       : y = sget2(); v += y; break;
X                case Y3       : y = sget3(); v += y; break;
X                case Y4       : y = sget4(); v += y; break;
X                case Z0       : v += z; break;
X                case Z1       : z = sget1(); v += z; break;
X                case Z2       : z = sget2(); v += z; break;
X                case Z3       : z = sget3(); v += z; break;
X                case Z4       : z = sget4(); v += z; break;
X                case FNT1     :
X                case FNT2     :
X                case FNT3     :
X                case FNT4     : setfont(num(opcode - FNT1 + 1));
X                                break;
X                case XXX1     : mseek(DVIfile, get1(), relative); break;
X                case XXX2     : mseek(DVIfile, get2(), relative); break;
X                case XXX3     : mseek(DVIfile, get3(), relative); break;
X                case XXX4     : mseek(DVIfile, get4(), relative); break;
X                case FNT_DEF1 :
X                case FNT_DEF2 :
X                case FNT_DEF3 :
X                case FNT_DEF4 : fontdef(opcode - FNT_DEF1 + 1);
X                                break;
X                case PRE      : errorexit(bdpre); break;
X                case POST     : errorexit(bdpst); break;
X                case POST_POST: errorexit(bdpp); break;
X            }
X    }
X
X} /* dopage */
X
X/*----------------------------------------------------------------------------*/
X
Xvoid skippage()                /* skip past one page */
X{
X    register int opcode;
X
X    while ((opcode = (int) get1()) != EOP) {
X        if (opcode > POST_POST)
X            errorexit(illop);
X        else
X            switch (opcode) {
X                case SET1     :
X                case PUT1     :
X                case RIGHT1   :
X                case W1       :
X                case X1       :
X                case DOWN1    :
X                case Y1       :
X                case Z1       : /* assume FNT change can also be skipped */
X                case FNT1     : mseek(DVIfile, 1L, relative); break;
X                case SET2     :
X                case PUT2     :
X                case RIGHT2   :
X                case W2       :
X                case X2       :
X                case DOWN2    :
X                case Y2       :
X                case Z2       :
X                case FNT2     : mseek(DVIfile, 2L, relative); break;
X                case SET3     :
X                case PUT3     :
X                case RIGHT3   :
X                case W3       :
X                case X3       :
X                case DOWN3    :
X                case Y3       :
X                case Z3       :
X                case FNT3     : mseek(DVIfile, 3L, relative); break;
X                case SET4     :
X                case PUT4     :
X                case RIGHT4   :
X                case W4       :
X                case X4       :
X                case DOWN4    :
X                case Y4       :
X                case Z4       :
X                case FNT4     : mseek(DVIfile, 4L, relative); break;
X                case SET_RULE :
X                case PUT_RULE : mseek(DVIfile, 8L, relative); break;
X                case BOP      : errorexit(bdbop); break;
X                case XXX1     : mseek(DVIfile, get1(), relative); break;
X                case XXX2     : mseek(DVIfile, get2(), relative); break;
X                case XXX3     : mseek(DVIfile, get3(), relative); break;
X                case XXX4     : mseek(DVIfile, get4(), relative); break;
X                case FNT_DEF1 :
X                case FNT_DEF2 :
X                case FNT_DEF3 :
X                case FNT_DEF4 : fontdef(opcode - FNT_DEF1 + 1); break;
X                case PRE      : errorexit(bdpre); break;
X                case POST     : errorexit(bdpst); break;
X                case POST_POST: errorexit(bdpp); break;
X        }
X    }
X
X} /* skippage */
X
X/*---------------------------------------------------------------------------*/
X
Xvoid printpage()       /* 'end of page', writes lines of page to output file */
X{
X    register int  i, j;
X    register char ch;
X
X    if (sptr != 0)
X        fprintf(stderr, "dvi2tty: warning - stack not empty at eop.\n");
X    for (currentline = firstline; currentline != nil;
X          currentline = currentline->next) {
X        if (currentline != firstline) {
X            foo = ((currentline->vv - currentline->prev->vv)/VERTICALEPSILON)-1;
X            if (foo > 3)
X                foo = 3;        /* linespacings not too large */
X            for (i = 1; i <= (int) foo; i++)
X                putc('\n', output);
X        }
X        if (currentline->charactercount >= leftmargin) {
X            foo = ttywidth - 2;
X            for (i = firstcolumn, j = 1; i <= currentline->charactercount;
X                   i++, j++) {
X                ch = currentline->text[i - leftmargin];
X                if (ch >= SPACE)
X                    putc(ch, output);
X                if ((j > (int) foo) && (currentline->charactercount > i+1)) {
X                        fprintf(output, "*\n");         /* if line to large */
X                        fprintf(output, " *");          /* mark output      */
X                        j = 2;
X                }
X            } 
X        }
X        putc('\n', output);
X    } 
X
X    currentline = firstline;
X    while (currentline->next != nil) {
X        currentline = currentline->next;
X        free(currentline->prev);
X    }
X    free(currentline);              /* free last line */
X    currentline = nil;
X
X} /* printpage */
X
X/*----------------------------------------------------------------------------*/
X
Xbool inlist(pagenr)                         /* ret true if in list of pages */
Xregister long pagenr;
X{
X
X    while ((currentpage->pag < 0) && (currentpage->pag != pagenr) &&
X           !currentpage->all && (currentpage->nxt != nil))
X        currentpage = currentpage->nxt;
X    if ((currentpage->all && (pagenr < currentpage->pag)) ||
X         (currentpage->pag == pagenr))
X            return TRUE;
X    else if (pagenr > 0) {
X        while ((currentpage->pag < pagenr) && (currentpage->nxt != nil))
X            currentpage = currentpage->nxt;
X        if (currentpage->pag == pagenr)
X            return TRUE;
X    }
X    return FALSE;
X
X} /* inlist */
X
X/*----------------------------------------------------------------------------*/
X
Xvoid rule(moving, rulewt, ruleht)
Xregister bool moving;
Xregister long rulewt, ruleht;
X{   /* output a rule (vertical or horizontal), increment h if moving is true */
X
X    register char ch;               /* character to set rule with            */
X    register long saveh, savev;
X                              /* rule   --   starts up the recursive routine */
X    if (!moving)
X        saveh = h;
X    if ((ruleht <= 0) || (rulewt <= 0))
X        h += rulewt;
X    else {
X        savev = v;
X        if ((ruleht / rulewt) > 0)         /* value < 1 truncates to 0 */
X            ch = '|';
X        else if (ruleht > (VERTICALEPSILON / 2))
X            ch = '=';
X        else
X            ch = '_';
X        ruleaux(rulewt, ruleht, ch);
X        v = savev;
X    }
X    if (!moving)
X        h = saveh;
X
X} /* rule */
X
X
X
Xvoid ruleaux(rulewt, ruleht, ch)     /* recursive  that does the job */
Xregister long rulewt, ruleht;
Xregister char ch;
X{
X    register long wt, lmh, rmh;
X
X    wt = rulewt;
X    lmh = h;                        /* save left margin                      */
X    if (h < 0) {                    /* let rules that start at negative h    */
X        wt -= h;                    /* start at coordinate 0, but let it     */
X        h = 0;                      /*   have the right length               */
X    }
X    while (wt > 0) {                /* output the part of the rule that      */
X        rmh = h;                    /*   goes on this line                   */
X        outchar(ch);
X        wt -= (h-rmh);              /* decrease the width left on line       */
X    }
X    ruleht -= VERTICALEPSILON;      /* decrease the height                   */
X    if (ruleht > VERTICALEPSILON) { /* still more vertical?                  */
X        rmh = h;                    /* save current h (right margin)         */
X        h = lmh;                    /* restore left margin                   */
X        v -= (VERTICALEPSILON + VERTICALEPSILON / 10);
X        ruleaux(rulewt, ruleht, ch);
X        h = rmh;                    /* restore right margin                  */
X    }
X
X} /* ruleaux */
X
X/*----------------------------------------------------------------------------*/
X
Xlong horizontalmove(amount)
Xregister long amount;
X{
X
X#if defined(MSDOS)
X    if (labs(amount) > charwidth / 4L) {
X#else
X    if (abs(amount) > charwidth / 4L) {
X#endif
X        foo = 3*charwidth / 4;
X        if (amount > 0)
X            amount = ((amount+foo) / charwidth) * charwidth;
X        else
X#if defined(VMS)
X            amount = (ROUND( (float) (amount-foo) / charwidth) + 1)* charwidth;
X#else
X            amount = ((amount-foo) / charwidth) * charwidth;
X#endif
X        h += amount;
X        return amount;
X    }
X    else
X        return 0;
X
X}   /* horizontalmove */
X
X/*----------------------------------------------------------------------------*/
X
Xint skipnops()                      /* skips by no-op commands  */
X{
X    register int opcode;
X
X    while ((opcode = (int) num(1)) == NOP);
X    return opcode;
X
X} /* skipnops */
X
X/*----------------------------------------------------------------------------*/
X
Xlinetype *getline()             /* returns an initialized line-object */
X{
X    register int  i;
X    register linetype *temp;
X
X    if ((temp = (linetype *) malloc(sizeof(linetype))) == NULL) 
X        errorexit(lnerq);
X    temp->charactercount = leftmargin - 1;
X    temp->prev = nil;
X    temp->next = nil;
X    for (i = 0; i < LINELEN; i++)
X        temp->text[i] = ' ';
X    temp->text[i] = '\0';
X    return temp;
X
X} /* getline */
X
X/*----------------------------------------------------------------------------*/
X
Xlinetype *findline()            /* find best fit line were text should go */
X{                               /* and generate new line if needed        */
X    register linetype *temp;
X    register long topd, botd;
X
X    if (v <= firstline->vv) {                      /* above first line */
X        if (firstline->vv - v > VERTICALEPSILON) {
X            temp = getline();
X            temp->next = firstline;
X            firstline->prev = temp;
X            temp->vv = v;
X            firstline = temp;
X        }
X        return firstline;
X    }
X
X    if (v >= lastline->vv) {                       /* below last line */
X        if (v - lastline->vv > VERTICALEPSILON) {
X            temp = getline();
X            temp->prev = lastline;
X            lastline->next = temp;
X            temp->vv = v;
X            lastline = temp;
X        }
X        return lastline;
X    }
X
X    temp = lastline;                               /* in between two lines */
X    while ((temp->vv > v) && (temp != firstline))
X        temp = temp->prev;
X
X    /* temp->vv < v < temp->next->vv --- temp is above, temp->next is below */
X    topd = v - temp->vv;
X    botd = temp->next->vv - v;
X    if ((topd < VERTICALEPSILON) || (botd < VERTICALEPSILON))
X        if (topd < botd)                           /* take best fit */
X            return temp;
X        else
X            return temp->next;
X
X    /* no line fits suitable, generate a new one */
X    currentline = getline();
X    currentline->next = temp->next;
X    currentline->prev = temp;
X    temp->next->prev = currentline;
X    temp->next = currentline;
X    currentline->vv = v;
X    return currentline;
X
X} /* findline */
X
X/*----------------------------------------------------------------------------*/
X
Xunsigned long num(size)
Xregister int size;
X{
X    register int i;
X    register long x = 0;
X
X    for (i = 0; i < size; i++)
X        x = (x << 8) + (unsigned) getc(DVIfile);
X    return x;
X
X} /* num */
X
X
Xlong snum(size)
Xregister int size;
X{
X    register int i;
X    register long x = 0;
X
X    x = getc(DVIfile);
X    if (x & 0x80)
X        x -= 0x100;
X    for (i = 1; i < size; i++)
X        x = (x << 8) + (unsigned) getc(DVIfile);
X    return x;
X
X} /* snum */
X
X/*----------------------------------------------------------------------------*/
X
Xvoid dochar(ch)
Xregister char ch;
X{
X
X    if (symbolfont == TRUE)
X        symchar(ch);
X    else
X        normchar(ch);
X
X    return;
X
X} /* dochar */
X
X
X
Xvoid symchar(ch)                     /* output ch to appropriate line */
Xregister char ch;
X{
X
X    switch (ch) {       /* can do a lot more on MSDOS machines ... */
X       case   0: ch = '-'; break;
X       case   1: ch = '.'; break;
X       case   2: ch = 'x'; break;
X       case   3: ch = '*'; break;
X       case  13: ch = 'O'; break;
X       case  14: ch = 'O'; break;
X       case  15: ch = 'o'; break;
X       case  24: ch = '~'; break;
X       case 102: ch = '{'; break;
X       case 103: ch = '}'; break;
X       case 104: ch = '<'; break;
X       case 105: ch = '>'; break;
X       case 106: ch = '|'; break;
X       case 110: ch = '\\'; break;
X    }
X    outchar(ch);
X
X    return;
X
X} /* symchar */
X
X
X
Xvoid normchar(ch)
Xregister char ch;
X{
X
X    switch (ch) {
X        case 11  :  outchar('f'); ch = 'f'; break;  /* ligature        */
X        case 12  :  outchar('f'); ch = 'i'; break;  /* ligature        */
X        case 13  :  outchar('f'); ch = 'l'; break;  /* ligature        */
X        case 14  :  outchar('f'); outchar('f');
X                                  ch = 'i'; break;  /* ligature        */
X        case 15  :  outchar('f'); outchar('f');
X                                  ch = 'l'; break;  /* ligature        */
X        case 16  :  ch = 'i'; break;
X        case 17  :  ch = 'j'; break;
X        case 25  :  outchar('s'); ch = 's'; break;  /* German double s */
X        case 26  :  outchar('a'); ch = 'e'; break;  /* Dane/Norw ae    */
X        case 27  :  outchar('o'); ch = 'e'; break;  /* Dane/Norw oe    */
X        case 28  :  if (scascii)
X                        ch = '|';                   /* Dane/Norw /o    */
X                    else
X                        ch = 'o';
X                    break;
X        case 29  :  outchar('A'); ch = 'E'; break;  /* Dane/Norw AE    */
X        case 30  :  outchar('O'); ch = 'E'; break;  /* Dane/Norw OE    */
X        case 31  :  if (scascii)
X                        ch = '\\';                  /* Dane/Norw /O    */
X                    else
X                        ch = 'O';
X                    break;
X        case 92  :  ch = '"'; break;  /* \ from `` */
X        case 123 :  ch = '-'; break;  /* { from -- */
X        case 124 :  ch = '_'; break;  /* | from --- */
X        case 125 :  ch = '"'; break;  /* } from \H */
X        case 126 :  ch = '"'; break;  /* ~ from \~ */
X        case 127 :  ch = '"'; break;  /* DEL from \" */
X#if 0
X        case 18  :  ch = '`'; break   /* from \` */
X        case 19  :  ch = ''''; break  /* from \' */
X        case 20  :  ch = '~'; break   /* from \v */
X        case 21  :  ch = '~'; break   /* from \u */
X        case 22  :  ch = '~'; break   /* from \= */
X        case 24  :  ch = ','; break   /* from \c */
X        case 94  :  ch = '^'; break   /* ^ from \^ */
X        case 95  :  ch = '`'; break   /* _ from \. */
X#endif
X    }
X    outchar(ch); 
X
X    return;
X
X} /*normchar */
X
X
X
Xvoid outchar(ch)                     /* output ch to appropriate line */
Xregister char ch;
X{
X    register int i, j;
X
X/*     fprintf(stderr, "hor: %ld, ver: %ld\n", h, v); */
X#if defined(MSDOS)
X    if (labs(v - currentline->vv) > VERTICALEPSILON / 2L)
X#else
X    if (abs(v - currentline->vv) > VERTICALEPSILON / 2L)
X#endif
X        currentline = findline();
X
X#if 0
X    j = (int) (((double) h / (double) maxpagewidth) * (ttywidth-1)) + 1;
X#else
X    j = (int) (h / charwidth);
X#endif
X    if (j > rightmargin)     /* leftmargin <= j <= rightmargin */
X        j = rightmargin;
X    else if (j < leftmargin)
X        j = leftmargin;
X    foo = leftmargin - 1;
X    /*
X    /* This code does not really belong here ...
X    /*
X    /*-------------------------------------------------------------*/
X    /* The following is very specialized code, it handles national */
X    /* Swe/Fin characters. They are respectively: a and o with two */
X    /* dots ("a & "o) and a with a circle (Oa). In Swe/Fin "ASCII" */
X    /* these characters replace }{|][ and \.  TeX outputs these by */
X    /* first issuing the dots or circle and then backspace and set */
X    /* the a or o.  When dvitty finds an a or o it searches in the */
X    /* near vicinity for the character codes that represent circle */
X    /* or dots and if one is found the corresponding national char */
X    /* replaces the special character codes.                       */
X    /*-------------------------------------------------------------*/
X    if (scascii) {
X        if ((ch == 'a') || (ch == 'A') || (ch == 'o') || (ch == 'O')) {
X            for (i = IMAX(leftmargin, j-2);
X                 i <= IMIN(rightmargin, j+2);
X                 i++)
X                if ((currentline->text[i - leftmargin] == 127) ||
X                    (currentline->text[i - leftmargin] == 34) ||
X                    (currentline->text[i - leftmargin] == 23))
X                    foo = i;
X            if (foo >= leftmargin) {
X                j = (int) foo;
X                switch (currentline->text[j - leftmargin]) {
X                    case 127 : case 34:
X                               if (ch == 'a')
X                                   ch = '{';
X                               else if (ch == 'A')      /* dots ... */
X                                   ch = '[';
X                               else if (ch == 'o')
X                                   ch = '|';
X                               else if (ch == 'O')
X                                   ch = '\\';
X                               break;
X                    case 23  : if (ch == 'a')
X                                   ch = '}';
X                               else if (ch == 'A')      /* circle */
X                                   ch = ']';
X                               break;
X                }
X            }
X        }
X    }
X    /*----------------- end of 'Scandinavian code' ----------------*/
X    if (foo == leftmargin-1)
X        while ((currentline->text[j - leftmargin] != SPACE)
X               && (j < rightmargin)) {
X            j++;
X            h += charwidth;
X        }
X    if ( ((ch >= SPACE) && (ch != DEL)) ||
X         (scascii && (ch == 23)) ) {
X          /*  (scascii && (ch == DEL)) ) {    if VMS ??? */
X        if (j < rightmargin)
X            currentline->text[j - leftmargin] = ch;
X        else
X            currentline->text[rightmargin - leftmargin] = '@';
X        if (j > currentline->charactercount)
X            currentline->charactercount = j;
X        if (j < firstcolumn)
X            firstcolumn = j;
X        h += charwidth;
X    }
X
X} /* outchar */
X
X/*----------------------------------------------------------------------------*/
X
Xvoid putcharacter(charnr)            /* output character, don't change h */
Xregister long charnr;
X{
X    register long saveh;
X
X    saveh = h;
X    if ((charnr >= 0) && (charnr <= LASTCHAR))
X        outchar((char) charnr);
X    else
X        setchar(charnr);
X    h = saveh;
X
X} /* putcharacter */
X
X/*----------------------------------------------------------------------------*/
X
Xvoid setchar(charnr)
Xlong charnr;
X{    /* should print characters with character code>127 from current font */
X     /* note that the parameter is a dummy, since ascii-chars are<=127    */
X
X    outchar('#');
X
X} /* setchar */
X
X
X/*----------------------------------------------------------------------------*/
X
X
Xvoid fontdef(x)
Xregister int x;
X{
X    register int i;
X    char * name;
X    font * fnt;
X    int namelen;
X    long fntnum;
X    int new = 0;
X
X    fntnum = num(x);
X    (void) get4();                      /* checksum */
X    (void) get4();                      /* scale */
X    (void) get4();                      /* design */
X    namelen = (int) get1() + (int) get1();
X    fnt = fonts;
X    while (fnt != NULL && fnt->num != fntnum)       /* does fontnum exist */
X        fnt = fnt->next;
X    if (fnt == NULL) {
X        if ((fnt = (font *) malloc(sizeof(font))) == NULL) {
X            perror("fontdef");
X            exit(1);
X        }
X        fnt->num = fntnum;
X        new = 1;
X    }
X    else
X        free(fnt->name);    /* free old name */
X    if ((name = (char *) malloc(namelen * sizeof(char))) == NULL) {
X        perror("fontdef");
X        exit(1);
X    }
X    
X    for (i = 0; i < namelen; i++)
X        name[i] = get1();
X    fnt->name = name;
X    if (new) {
X        fnt->next = fonts;
X        fonts = fnt;
X    }
X
X    return;
X
X} /* fontdef */
X
X
X
Xvoid setfont(fntnum)
Xlong fntnum;
X{
X    font * fnt;
X    char * s;
X
X    fnt = fonts;
X    while (fnt != NULL && fnt->num != fntnum)
X        fnt = fnt->next;
X    if (fnt == NULL) {
X        /* error : font not found */
X        symbolfont = FALSE;
X        return;
X    }
X
X    s = fnt->name;
X    while ((s = strchr(s, 's')) != NULL) {
X        if (strncmp("sy", s, 2) == 0) {
X            symbolfont = TRUE;
X            return;
X        }
X    }
X   
X    symbolfont = FALSE;
X    return;
X
X} /* setfont */
X
X
X/*----------------------------------------------------------------------------*/
X
X
X#if defined(VMS)
Xlong vmsseek(fp,n,dir)
XFILE *fp;
Xlong n;
Xlong dir;
X{
X    long k,m,pos,val,oldpos;
X    struct stat buffer;
X
X    for (;;) {                     /*loops only once or twice*/
X        switch (dir) {
X            case 0:            /*from BOF*/
X                    oldpos = vms_ftell(fp);
X                    k = n & 511;
X                    m = n >> 9;
X                    if (((*fp)->_cnt) && ((oldpos >> 9) == m)) {
X                        val = 0; /* still in */
X                        (*fp)->_ptr = ((*fp)->_base) + k;
X                        (*fp)->_cnt = 512 - k;
X                    }
X                    else {
X                        val = fseek(fp, m << 9, 0);
X                        if (val == 0) {
X                            (*fp)->_cnt = 0;
X                            (void) fgetc(fp);
X                            (*fp)->_ptr = ((*fp)->_base) + k;
X                            (*fp)->_cnt = 512 - k;
X                        }
X                    }
X                    return(val);
X
X            case 1: pos = vms_ftell(fp);
X                    if (pos == EOF)
X                        return (EOF);
X                    n += pos;
X                    dir = 0;
X                    break;
X
X            case 2: val = fstat(fileno(fp), &buffer);
X                    if (val == EOF)
X                        return (EOF);
X                    n += buffer.st_size - 1;
X
X                    dir = 0;
X                    break;
X
X            default : return (EOF);
X        }
X    }
X
X} /* vmsseek */
X        
X
X
Xlong vms_ftell(fp)
XFILE *fp;
X{
X    char c;
X    long pos;
X    long val;
X    if ((*fp)->_cnt == 0) {
X        c = fgetc(fp);
X        val = vms_ungetc(c, fp);
X        if (val != c)
X            return (EOF);
X    }
X    pos = ftell(fp);
X    if (pos >= 0)
X        pos += ((*fp)->_ptr) - ((*fp)->_base);
X    return (pos);
X
X} /* vms_ftell */
X
X
X
Xlong vms_ungetc(c,fp)
Xchar c;
XFILE *fp;
X{
X    if ((c == EOF) && feof(fp))
X        return (EOF);
X    else if ((*fp)->_cnt >= 512)
X        return (EOF);
X    else {
X        (*fp)->_cnt++;
X        (*fp)->_ptr--;
X        *((*fp)->_ptr) = c;
X        return (c);
X    }
X
X} /*vms_ungetc */
X#endif
END_OF_FILE
if test 38176 -ne `wc -c <'dvistuff.c'`; then
    echo shar: \"'dvistuff.c'\" unpacked with wrong size!
fi
# end of 'dvistuff.c'
fi
if test -f 'dvi2tty.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dvi2tty.h'\"
else
echo shar: Extracting \"'dvi2tty.h'\" \(3789 characters\)
sed "s/^X//" >'dvi2tty.h' <<'END_OF_FILE'
X#define Copyright "dvi2tty.c  Copyright (C) 1984, 1985, 1986 Svante Lindahl.\n\
XCopyright (C) 1988 M.J.E. Mol 1989, 1990"
X
X#include <stdio.h>
X#include <string.h>
X#if defined(MSDOS)
X#include <stdlib.h>
X#include <malloc.h>
X#endif
X
X#define TRUE        1
X#define FALSE       0
X#define nil         NULL
X
X/*
X * ERROR CODES , don't start with 0
X */
X
X#define illop    1              /* illegal op-code                   */
X#define stkof    2              /* stack over-flow                   */
X#define stkuf    3              /* stack under-flow                  */
X#define stkrq    4              /* stack requirement                 */
X#define lnerq    5              /* line allocation                   */
X#define badid    6              /* id is not right                   */
X#define bdsgn    7              /* signature is wrong                */
X#define fwsgn    8              /* too few signatures                */
X#define nopre    9              /* no pre-amble where expected       */
X#define nobop   10              /* no bop-command where expected     */
X#define nopp    11              /* no postpost where expected        */
X#define bdpre   12              /* unexpected preamble occured       */
X#define bdbop   13              /* unexpected bop-command occured    */
X#define bdpst   14              /* unexpected post-command occured   */
X#define bdpp    15              /* unexpected postpost               */
X#define nopst   16              /* no post-amble where expected      */
X#define illch   17              /* character code out of range       */
X#define filop   18              /* cannot access file                */
X#define filcr   19              /* cannot creat file                 */
X#if !defined(MSDOS)
X#define pipcr   20              /* cannot creat pipe                 */
X#endif
X
X/*---------------------------------------------------------------------------*/
X
Xtypedef char bool;
X
Xtypedef struct prlistptr {      /* list of pages selected for output         */
X    int       pag;                      /* number of pages                   */
X    bool      all;                      /* pages in interval selected        */
X    struct prlistptr *prv;              /* previous item in list             */
X    struct prlistptr *nxt;              /* next item in list                 */
X} printlisttype;
X
X/*---------------------------------------------------------------------------*/
X
Xextern bool   outputtofile;            /* output to file or stdout(dvi2tty.c)*/
Xextern bool   pageswitchon;            /* user-set pages to print(dvistuff.c)*/
Xextern bool   sequenceon;              /* not TeX pagenrs (dvistuff.c)       */
Xextern bool   scascii;                 /* Scand. nat. chars (dvistuff.c)     */
Xextern bool   noffd;                   /* output ^L or formfeed (dvistuff.c) */
X
Xextern printlisttype *currentpage;     /* current page to print (dvi2tty.c)  */
Xextern printlisttype *firstpage;       /* first page selected (dvi2tty.c)    */
Xextern printlisttype *lastpage;        /* last page selected (dvi2tty.c)     */
X
Xextern int            ttywidth;        /* screen width (dvi2tty.c)           */
Xextern int            espace;          /* extra screen width (dvi2tty.c)     */
Xextern long           foo;             /* temporary 'register' (dvi2tty.c)   */
Xextern int            opcode;          /* dvi opcode (dvistuff.c)            */
X
Xextern FILE *DVIfile;                  /* dvi file (dvi2tty.c)               */
Xextern FILE *output;                   /* output file (dvi2tty.c)            */
X
X/*---------------------------------------------------------------------------*/
X
X/* dvi2tty.c */
X#if defined(MSDOS)
Xvoid errorexit(int);
X#else
Xvoid errorexit();
X#endif
X
X/* dvistuff.c */
X#if defined(MSDOS)
Xvoid dvimain(void);
X#else
Xvoid dvimain();
X#endif
END_OF_FILE
if test 3789 -ne `wc -c <'dvi2tty.h'`; then
    echo shar: \"'dvi2tty.h'\" unpacked with wrong size!
fi
# end of 'dvi2tty.h'
fi
if test -f 'dvi2tty.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dvi2tty.1'\"
else
echo shar: Extracting \"'dvi2tty.1'\" \(4291 characters\)
sed "s/^X//" >'dvi2tty.1' <<'END_OF_FILE'
X.TH DVI2TTY Local "7 June 1986"
X.SH NAME
Xdvi2tty \- preview a dvi\-file on an ordinary ascii terminal
X.SH SYNOPSIS
X.B dvi2tty
X[ options ] dvi\-file
X.SH DESCRIPTION
X.I dvi2tty
Xconverts a TeX DVI\-file to a format that is apprporiate for terminals
Xand lineprinters. The program is intended to be used for
Xpreliminary proofreading of TeX-ed documents.
XBy default the output is directed to the terminal,
Xpossibly through a pager (depending on how the program was installed),
Xbut it can be directed to a file or a pipe.
X.PP
XThe output leaves much to be desired, but is still
Xusefull if you want to avoid walking to the
Xlaserprinter (or whatever) for each iteration of your
Xdocument.
X.br
XSince
X.I dvi2tty
Xproduces output for terminals and lineprinters the
Xrepresentation of documents is naturally quite primitive.
XFontchanges are totally ignored, which implies that
Xspecial symbols, such as mathematical symbols, get mapped into the 
Xcharacters at the corresponding positions in the "standard" fonts.
X.PP
XIf the width of the output text requires more columns than fits
Xin one line (c.f. the \-w option) it is broken into several lines by
X.I dvi2tty
Xalthough they will be printed as one line on regular TeX output
Xdevices (e.g.laserprinters). To show that a broken line is really
Xjust one logical line an asterisk (``*'') in the last position
Xmeans that the logical line is continued on the next physical
Xline output by
X.I dvi2tty.
XSuch a continuation line is started with a a space and an asterisk
Xin the first two columns.
X.PP
XOptions may be specified in the environment variable DVI2TTY.
XAny option on the commandline, conflicting with one in the
Xenvironment, will override the one from the environment.
X.PP
X.B Options:
X.PP
X.TP
X.B \-o file
XWrite output to file ``file''.
X.TP
X.B \-p list
XPrint the pages chosen by list.
XNumbers refer to TeX\-page numbers (known as \\count0).
XAn example of format for list is ``1,3:6,8''
Xto choose pages 1, 3 through 6 and 8.
XNegative numbers can be used exactly as in TeX,
Xe g \-1 comes before \-4 as in ``\-p-1:-4,17''.
X.TP
X.B \-P list
XLike \-p except that page numbers refer to
Xthe sequential ordering of the pages in the dvi\-file.
XNegative numbers don't make a lot of sense here...
X.TP
X.B \-w n
XSpecify terminal width
X.I n.
XLegal range 16\-132.
XDefault is 80. If your terminal has the
Xability to display in 132 columns it might
Xbe a good idea to use \-w132 and toggle the
Xterminal into this mode as output will
Xprobably look somewhat better.
X.TP
X.B \-q
XDon't pipe the output through a pager.
XThis may be the default on some systems
X(depending on the whims of the SA installing the program).
X.TP
X.B \-f
XPipe through a pager, $PAGER if defined, or whatever your SA compiled
Xin (often ``more''). This may be the default, but it is still okay
Xto redirect output with ``>'', the pager will not be used if output
Xis not going to a terminal.
X.TP
X.B \-F
XSpecify the pager program to be used.
XThis overides the $PAGER and the default pager.
X.TP
X.B \-Fprog
XUse ``prog'' as program to pipe output into. Can be used to choose an
Xalternate pager (e g ``-Fless'').
X.TP
X.B \-l
XMark pagebreaks with the two-character sequence ``^L''. The default is
Xto mark them with a formfeed character.
X.TP
X.B \-u
XDon't make any attempts to find special Scandinavian characters.
XIf such characters are in the text they will map to ``a'' and ``o''.
XThis is probably the default outside of Scandinavia. (The SA made
Xthe decision when  the program was installed.)
X.TP
X.B \-s
XTry to find the special Scandinavian characters that on most (?)
Xterminals in Scandinavia are mapped to ``{|}[\\]''.
XThis can be the default, and output from files not containing these
Xspecial characters will be identical regardless of this option.
X.SH FILES
X/usr/ucb/more \ \ \ \ 
Xprobably the default pager.
X.SH ENVIRONMENT
XPAGER \ \ \ \ \ \ \ \ \ \ \ \ 
Xthe pager to use.
X.br
XDVI2TTY \ \ \ \ \ \ \ \ \ \ \ 
Xcan be set to hold commandline options.
X.SH "SEE ALSO"
XTeX, dvi2ps
X.SH AUTHOR
XSvante Lindahl, Royal Institute of Technology, Stockholm
X.br
XImproved C version: Marcel Mol
X.br
X{seismo, mcvax}!enea!ttds!zap
X.br
Xmarcel@duteca.UUCP
X.SH BUGS
XBlanks between words get lost quite easy. This is less
Xlikely if you are using a wider output than the default 80.
X.PP
XOnly one file may be specified on the commandline.
END_OF_FILE
if test 4291 -ne `wc -c <'dvi2tty.1'`; then
    echo shar: \"'dvi2tty.1'\" unpacked with wrong size!
fi
# end of 'dvi2tty.1'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
#########################################
# Marcel J.E. Mol                       ######################################
# Delft University of Technology          Pink Elephant Management Services  #
# The Netherlands                         Voorburg                           #
# UUCP: marcel@duteca.tudelft.nl          Tel: 070-694231                    #
#                                      	######################################
#########################################