home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume07 / texdvi2.tty < prev    next >
Encoding:
Text File  |  1988-09-11  |  59.6 KB  |  1,507 lines

  1. Subject:  v07i022:  TeX DVI driver for TTY's, etc.
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: seismo!enea!ttds!zap (Svante Lindahl)
  6. Mod.sources: Volume 7, Issue 22
  7. Archive-name: texdvi2tty
  8.  
  9. [  I have only verified that this unpacks correctly.  Non-4.[23] sites
  10.    note:  this script uses 'echo -n'  --r$  ]
  11.  
  12. : This shar archive as submitted to mod.sources contains the
  13. : following files:    README
  14. :            dvitty.1
  15. :            Makefile
  16. :            dvitty.p
  17. :            sys.h
  18. :            sys.c
  19. :
  20. : This is a shar archive.  Extract with sh, not csh.
  21. : This archive ends with exit, so do not worry about trailing junk.
  22. echo 'Extracting README'
  23. sed 's/^X//' > README << '+ END-OF-FILE README'
  24. Xdvitty is intended for previewing dvi-files on text-only devices
  25. X(terminals and lineprinters). The output is not very pretty many
  26. Xtimes, but it still saves quite a lot of work, especially if you
  27. Xhave a little ways to walk to a laserprinter, for example.
  28. X
  29. XThe program was originally written in Hedrick-Pascal, running on
  30. XTOPS-20, and was later ported to UNIX (BSD, Berkeley-pascal).
  31. X
  32. XIt is not very smart in all situations, but still serves it pur-
  33. Xpose fairly well.
  34. X
  35. XFor information on how to use see the man-page.
  36. X
  37. XBefore compiling and installing inspect the  "compile-time cust-
  38. Xomization constants" and change them to suit your site.
  39. XThese constants configure default pager and a little more.
  40. X
  41. XPlease report complaints, suggestions, bugs and/or fixes to:
  42. X
  43. XSvante Lindahl, NADA, KTH            Numerical Analysis & Computer Science 
  44. XUUCP: {seismo,mcvax}!enea!ttds!zap   Royal Institute of Technology, Sweden
  45. XARPA: enea!ttds!zap@seismo.CSS.GOV   EAN: zap@cs.kth.sunet
  46. X
  47. XThe TOPS-20 version of the program can also be obtained from the above
  48. Xaddress.
  49. + END-OF-FILE README
  50. chmod 'u=rw,g=rw,o=r' 'README'
  51. echo '    -rw-rw-r--  1 zap          1050 Aug 15 22:11 README        (as sent)'
  52. echo -n '    '
  53. /bin/ls -l README
  54. echo 'Extracting dvitty.1'
  55. sed 's/^X//' > dvitty.1 << '+ END-OF-FILE dvitty.1'
  56. X.TH DVITTY Local "7 June 1986"
  57. X.SH NAME
  58. Xdvitty \- preview a dvi\-file on an ordinary ascii terminal
  59. X.SH SYNOPSIS
  60. X.B dvitty
  61. X[ options ] dvi\-file
  62. X.SH DESCRIPTION
  63. X.I dvitty
  64. Xconverts a TeX DVI\-file to a format that is apprporiate for terminals
  65. Xand lineprinters. The program is intended to be used for
  66. Xpreliminary proofreading of TeX:ed documents.
  67. XBy default the output is directed to the terminal,
  68. Xpossibly through a pager (depending on how the program was installed),
  69. Xbut it can be directed to a file or a pipe.
  70. X.PP
  71. XThe output leaves much to be desired, but is still
  72. Xusefull if you want to avoid walking to the
  73. Xlaserprinter (or whatever) for each iteration of your
  74. Xdocument.
  75. X.br
  76. XSince
  77. X.I dvitty
  78. Xproduces output for terminals and lineprinters the
  79. Xrepresentation of documents is naturally quite primitive.
  80. XFontchanges are totally ignored, which implies that
  81. Xspecial symbols, such as mathematical symbols, get mapped into the 
  82. Xcharacters at the corresponding positions in the "standard" fonts.
  83. X.PP
  84. XIf the width of the output text requires more columns than fits
  85. Xin one line (c.f. the \-w option) it is broken into several lines by
  86. X.I dvitty
  87. Xalthough they will be printed as one line on regular TeX output
  88. Xdevices (e.g.laserprinters). To show that a broken line is really
  89. Xjust one logical line an asterisk (``*'') in the last position
  90. Xmeans that the logical line is continued on the next physical
  91. Xline output by
  92. X.I dvitty.
  93. XSuch a continuation line is started with a a space and an asterisk
  94. Xin the first two columns.
  95. X.PP
  96. XOptions may be specified in the environment variable DVITTY.
  97. XAny option on the commandline, conflicting with one in the
  98. Xenvironment, will override the one from the environment.
  99. X.PP
  100. X.B Options:
  101. X.PP
  102. X.TP
  103. X.B \-o file
  104. XWrite output to file ``file''.
  105. X.TP
  106. X.B \-p list
  107. XPrint the pages chosen by list.
  108. XNumbers refer to TeX\-page numbers (known as \\count0).
  109. XAn example of format for list is ``1,3:6,8''
  110. Xto choose pages 1, 3 through 6 and 8.
  111. XNegative numbers can be used exactly as in TeX,
  112. Xe g \-1 comes before \-4 as in ``\-p-1:-4,17''.
  113. X.TP
  114. X.B \-P list
  115. XLike \-p except that page numbers refer to
  116. Xthe sequential ordering of the pages in the dvi\-file.
  117. XNegative numbers don't make a lot of sense here...
  118. X.TP
  119. X.B \-w n
  120. XSpecify terminal width
  121. X.I n.
  122. XLegal range 16\-132.
  123. XDefault is 80. If your terminal has the
  124. Xability to display in 132 columns it might
  125. Xbe a good idea to use \-w132 and toggle the
  126. Xterminal into this mode as output will
  127. Xprobably look somewhat better.
  128. X.TP
  129. X.B \-q
  130. XDon't pipe the output through a pager.
  131. XThis may be the default on some systems
  132. X(depending on the whims of the SA installing the program).
  133. X.TP
  134. X.B \-f
  135. XPipe through a pager, $PAGER if defined, or whatever your SA compiled
  136. Xin (often ``more''). This may be the default, but it is still okay
  137. Xto redirect output with ``>'', the pager will not be used if output
  138. Xis not going to a terminal.
  139. X.TP
  140. X.B \-Fprog
  141. XUse ``prog'' as program to pipe output into. Can be used to choose an
  142. Xalternate pager (e g ``-Fless'').
  143. X.TP
  144. X.B \-l
  145. XMark pagebreaks with the two-character sequence ``^L''. The defualt is
  146. Xto mark them with a formfeed character.
  147. X.TP
  148. X.B \-u
  149. XDon't make any attempts to find special Scandinavian characters.
  150. XIf such characters are in the text they will map to ``a'' and ``o''.
  151. XThis is probably the default outside of Scandinavia. (The SA made
  152. Xthe decision when  the program was installed.)
  153. X.TP
  154. X.B \-s
  155. XTry to find the special Scandinavian characters that on most (?)
  156. Xterminals in Scandinavia are mapped to ``{|}[\\]''.
  157. XThis can be the default, and output from files not containing these
  158. Xspecial characters will be identical regardless of this option.
  159. X.SH FILES
  160. X/usr/ucb/more \ \ \ \ 
  161. Xprobably the default pager.
  162. X.SH ENVIRONMENT
  163. XPAGER \ \ \ \ \ \ \ \ \ \ \ \ 
  164. Xthe pager to use.
  165. X.br
  166. XDVITTY \ \ \ \ \ \ \ \ \ \ \ 
  167. Xcan be set to hold commandline options.
  168. X.SH "SEE ALSO"
  169. XTeX, dvi2ps
  170. X.SH AUTHOR
  171. XSvante Lindahl, Royal Institute of Technology, Stockholm
  172. X.br
  173. X{seismo, mcvax}!enea!ttds!zap
  174. X.SH BUGS
  175. XBlanks between words get lost quite easy. This is less
  176. Xlikely if you are using a wider output than the default 80.
  177. X.PP
  178. XOnly one file may be specified on the commandline.
  179. + END-OF-FILE dvitty.1
  180. chmod 'u=rw,g=rw,o=r' 'dvitty.1'
  181. echo '    -rw-rw-r--  1 zap          4127 Aug 15 20:02 dvitty.1        (as sent)'
  182. echo -n '    '
  183. /bin/ls -l dvitty.1
  184. echo 'Extracting Makefile'
  185. sed 's/^X//' > Makefile << '+ END-OF-FILE Makefile'
  186. Xall:    dvitty
  187. X
  188. Xdvitty:    sys.o dvitty.o
  189. X    pc -O -w -o dvitty dvitty.o sys.o
  190. X
  191. Xdvitty.o:    dvitty.p
  192. X    pc -c -w -O dvitty.p
  193. X
  194. Xsys.o:    sys.c
  195. X    cc -c -O sys.c
  196. + END-OF-FILE Makefile
  197. chmod 'u=rw,g=r,o=r' 'Makefile'
  198. echo '    -rw-r--r--  1 zap           143 Aug  8 00:32 Makefile        (as sent)'
  199. echo -n '    '
  200. /bin/ls -l Makefile
  201. echo 'Extracting dvitty.p'
  202. sed 's/^X//' > dvitty.p << '+ END-OF-FILE dvitty.p'
  203. X(******************************************************************************
  204. X * bogart:/usr/alla/zap/dvitty/dvitty.p  1986-08-15 20:24:31,
  205. X *               Version to be sent to mod.sources ready.
  206. X * New option since last version:
  207. X *   -Fprog      Pipe output to prog. Can be used to get a different
  208. X *               pager than the default.
  209. X * bogart:/usr/alla/zap/dvitty/dvitty.p  1986-01-13 21:49:31,
  210. X *   Environment variable DVITTY is read and options can be set from it.
  211. X *   These are the currently implemented options:
  212. X *      -ofile   Write output to file, else write to stdout,
  213. X *               possibly piped through a pager if stdout is a tty.
  214. X *      -plist   Print pages whos TeX-page-number are in list.
  215. X *               List is on the form  1,3:6,8  to choose pages
  216. X *               1,3-6 and 8. TeX-nrs can be negative: -p-1:-4,4
  217. X *      -Plist   Print pages whos sequential number are in list.
  218. X *      -wn      Print the lines with width n characters, default is
  219. X *               80. Wider lines gives better results.
  220. X *      -q       Don't try to pipe to a pager.
  221. X *      -f       Try to pipe to a pager if output is a tty.
  222. X *               Default of -q and -f is a compile time option, a constant.
  223. X *      -l       Write '^L' instead of formfeed between pages.
  224. X *      -u       Don't try to find Scandinavian characters (they will
  225. X *               print as a:s and o:s if this option is choosen).
  226. X *      -s       Scandinavian characters printed as }{|][\.
  227. X *               Default of -s and -u is a compile time option, a constant.
  228. X * bogart:/usr/alla/zap/dvitty/dvitty.p  1986-01-10 18:51:03,
  229. X *   Argument parsing, and random access functions (external, in C)
  230. X *   and other OS-dependent stuff (in C). Removed private 'pager' &
  231. X *   tries to pipe through PAGER (environment var) or, if PAGER not
  232. X *   defined, /usr/ucb/more. Some changes for efficency.
  233. X * bogart:/usr/alla/svante/dvitty/dvitty.p  1985-07-15 20:51:00,
  234. X *   The code for processing dvi-files running on UNIX (UCB-Pascal)
  235. X *   but no argument parsing.
  236. X * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.140, 30-Mar-85 05:43:56,
  237. X *   Edit: Svante Lindahl
  238. X * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.136, 15-Jan-85 13:52:59,
  239. X *   Edit: Svante Lindahl, final Twenex version !!!??
  240. X * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.121, 14-Jan-85 03:10:22,
  241. X *   Edit: Svante Lindahl, cleaned up and fixed a lot of little things
  242. X * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.25, 15-Dec-84 05:29:56,
  243. X *   Edit: Svante Lindahl, COMND-interface, including command line scanning
  244. X * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.23, 10-Dec-84 21:24:41,
  245. X *   Edit: Svante Lindahl, added command line scanning with Rscan-JSYS
  246. X * VERA::<SVANTE-LINDAHL.DVITTY>DVITTY.PAS.48,  8-Oct-84 13:26:30,
  247. X *  Edit: Svante Lindahl, fixed switch-parsing, destroyed by earlier patches
  248. X * VERA::<SVANTE-LINDAHL.DVITTY>DVITTY.PAS.45, 29-Sep-84 18:29:53,
  249. X *  Edit: Svante Lindahl
  250. X *
  251. X * dvitty - get an ascii representation of a dvi-file, suitable for ttys
  252. X *
  253. X * This program, and any documentation for it, is copyrighted by Svante
  254. X * Lindahl. It may be copied for non-commercial use only, provided that
  255. X * any and all copyright notices are preserved.
  256. X *
  257. X * Please report any bugs and/or fixes to:
  258. X *
  259. X * UUCP: {seismo,mcvax,cernvax,diku,ukc,unido}!enea!ttds!zap
  260. X * ARPA: enea!ttds!zap@seismo.CSS.GOV
  261. X *  or   Svante_Lindahl_NADA%QZCOM.MAILNET@MIT-MULTICS.ARPA
  262. X * EAN:  zap@cs.kth.sunet
  263. X *)
  264. X
  265. Xprogram dvitty(input, output);
  266. X
  267. Xconst Copyright = 'dvitty.p  Copyright (C) 1984, 1985, 1986 Svante Lindahl.';
  268. X
  269. X
  270. X      {-----------------------------------------------------------------------}
  271. X      { The following two constants may be toggled before compilation to      }
  272. X      { customize the default behaviour of the program for your site.         }
  273. X      { Whichever their settings are, the defaults can be overridden at       }
  274. X      { runtime.                                                              }
  275. X      {-----------------------------------------------------------------------}
  276. X
  277. X      defscand        = true;   { default is Scandinavian, toggle this if you }
  278. X                                { don't have terminals with Scand. nat. chars }
  279. X      defpage         = true;   { default: try to pipe through a pager (like  }
  280. X                                { more) if stdout is tty and no -o switch     }
  281. X      pathlen = 40;             { length of string for path to pager program  }
  282. X      defpath = '/usr/ucb/more                           ';   { pathlen chars }
  283. X
  284. X      {------------------ end of customization constants ---------------------}
  285. X
  286. X      versionid       =      2; { version number of dvifiles that pgm handles }
  287. X      stackmax        =    100; { allows 100 dvi-pushes                       }
  288. X      verticalepsilon = 450000; { crlf when increasing v more than this       }
  289. X
  290. X      rightmargin     = 152;    { nr of columns allowed to the right of h=0   }
  291. X      leftmargin      = -50;    { give some room for negative h-coordinate    }
  292. X
  293. X      stringlength    = 100;    { size of char-arrays for strings             }
  294. X
  295. X      advance         = true;   { if advancing h when outputing a rule        }
  296. X      stay            = false;  { if not advancing h when outputing a rule    }
  297. X
  298. X      absolute        = 0;
  299. X      relative        = 1;
  300. X
  301. X      chffd           =  12;    { formfeed                                    }
  302. X      chspc           =  32;    { space                                       }
  303. X      chdel           = 127;    { delete                                      }
  304. X
  305. X      { some dvi op-codes (digit at end tells dvi-version-#)                  }
  306. X      nop2      = 138;          { no-op                                       }
  307. X      bop2      = 139;          { beginning of page                           }
  308. X      eop2      = 140;          { end of page                                 }
  309. X      post2     = 248;          { post-amble                                  }
  310. X      pre2      = 247;          { pre-amble                                   }
  311. X      postpost2 = 249;          { post-post-amble                             }
  312. X      lastchar  = 127;          { highest char-code                           }
  313. X
  314. X{-----------------------------------------------------------------------------}
  315. X
  316. Xtype ubyte     = 0..255;        { dvi-files consists of eight-bit-bytes       }
  317. X     sbyte     = -128..127;     { UCB-pascal reads 16 bits if unsigned byte   }
  318. X
  319. X     string    = packed array [1..stringlength] of char;
  320. X     pathtype  = packed array [1..pathlen] of char;
  321. X     charset   = set of char;
  322. X
  323. X     stackitem = record
  324. X                   hh, vv, ww, xx, yy, zz : integer;
  325. X                 end;
  326. X     stacktype = record         { stack for dvi-pushes                        }
  327. X                   items : array [1..stackmax] of stackitem;
  328. X                   top   : 0..stackmax;
  329. X               end;   { stacktype }
  330. X
  331. X     lineptr   = ^linetype;
  332. X     linetype  = record         { the lines of text to be output to outfile   }
  333. X                   vv   : integer;            { vertical position of the line }
  334. X                   charactercount : integer;  { pos of last char on line      }
  335. X                   prev : lineptr;            { preceding line                }
  336. X                   next : lineptr;            { succeding line                }
  337. X                   text : packed array [leftmargin..rightmargin] of char;
  338. X               end;   { linetype }
  339. X
  340. X     printlistptr  = ^printlisttype;
  341. X     printlisttype = record               { list of pages selected for output }
  342. X                     pag : integer;       { the nr of the page                }
  343. X                     all : boolean;       { pages in intervall selected       }
  344. X                     prv : printlistptr;  { previous item in list             }
  345. X                     nxt : printlistptr;  { next item in list                 }
  346. X                     adr : integer;       { nr of byte in file where bop is   }
  347. X                 end;   { printlisttype }
  348. X
  349. X     useagecodetype= (wrnge,              { width switch arg out of range     }
  350. X                      ign,                { ignore cause, print'Usage:..'     }
  351. X                      nan,                { not a number where one expected   }
  352. X                      gae,                { garbage at end                    }
  353. X                      bdlst,              { bad page-numberlist               }
  354. X                      onef,               { only one dvifile allowed          }
  355. X                      bdopt,              { bad option                        }
  356. X                      lngpth,             { pathname too long (for -F)        }
  357. X                      noarg);             { argument expected                 }
  358. X
  359. X     errorcodetype = (illop,              { illegal op-code                   }
  360. X                      stkof,              { stack over-flow                   }
  361. X                      stkuf,              { stack under-flow                  }
  362. X                      stkrq,              { stack requirement                 }
  363. X                      badid,              { id is not right                   }
  364. X                      bdsgn,              { signature is wrong                }
  365. X                      fwsgn,              { too few signatures                }
  366. X                      nopre,              { no pre-amble where expected       }
  367. X                      nobop,              { no bop-command where expected     }
  368. X                      nopp,               { no postpost where expected        }
  369. X                      bdpre,              { unexpected preamble occured       }
  370. X                      bdbop,              { unexpected bop-command occured    }
  371. X                      bdpst,              { unexpected post-command occured   }
  372. X                      bdpp,               { unexpected postpost               }
  373. X                      nopst,              { no post-amble where expected      }
  374. X                      illch,              { character code out of range       }
  375. X                      filop,              { cannot access file                }
  376. X                      filcr);             { cannot creat file                 }
  377. X
  378. X     DVIfiletype = file of sbyte;
  379. X
  380. X{-----------------------------------------------------------------------------}
  381. X
  382. Xvar  opcode       : ubyte;         { dvi-opcodes                             }
  383. X     foo          : integer;       { utility variable, "register"            }
  384. X
  385. X     h, v         : integer;       { coordinates, horizontal and vertical    }
  386. X     w, x, y, z   : integer;       { horizontal and vertical amounts         }
  387. X
  388. X     outputtofile : boolean;       { tells if output goes to file or stdout  }
  389. X     pager        : boolean;       { tells if output is piped to a pager     }
  390. X     pageswitchon : boolean;       { true if user-set pages to print         }
  391. X     sequenceon   : boolean;       { false if pagesw-nrs refers to TeX-nrs   }
  392. X     scascii      : boolean;       { if true make Scand. nat. chars right    }
  393. X     noffd        : boolean;       { if true output ^L instead of formfeed   }
  394. X     ttywidth     : integer;       { max nr of chars per printed line        }
  395. X     path         : pathtype;      { name of the pager to run                }
  396. X     pathpgm      : boolean;       { use 'defpath' if this is true           }
  397. X
  398. X     maxpagewidth : integer;       { width of widest page in file            }
  399. X     charwidth    : integer;       { aprox width of charachter               }
  400. X
  401. X     currentpage  : printlistptr;  { current page to print                   }
  402. X     firstpage    : printlistptr;  { first page selected                     }
  403. X     lastpage     : printlistptr;  { last page selected                      }
  404. X     currentline  : lineptr;       { pointer to current line on current page }
  405. X     firstline    : lineptr;       { pointer to first line on current page   }
  406. X     lastline     : lineptr;       { pointer to last line on current page    }
  407. X     firstcolumn  : integer;       { 1st column with something to print      }
  408. X
  409. X     stack        : stacktype;
  410. X
  411. X     DVIfile      : DVIfiletype;
  412. X     ERRfile      : text;
  413. X     DVIfilename  : string;
  414. X     OUTfilename  : string;
  415. X
  416. X{-----------------------------------------------------------------------------}
  417. X
  418. X#include "sys.h"                           { headers for external C-routines }
  419. X
  420. X{-----------------------------------------------------------------------------}
  421. X
  422. Xprocedure errorexit(errorcode : errorcodetype);
  423. X    begin
  424. X        write(ERRfile,'dvitty: ');
  425. X        case errorcode of
  426. X            illop : writeln(ERRfile,'Illegal op-code found: ',opcode:0);
  427. X            stkof : writeln(ERRfile,'Stack overflow.');
  428. X            stkuf : writeln(ERRfile,'Stack underflow.');
  429. X            stkrq : writeln(ERRfile,'Too much stack required : ',foo:0);
  430. X            badid : writeln(ERRfile,'Id-byte is not correct: ',opcode:0);
  431. X            bdsgn : writeln(ERRfile,'Bad signature: ',foo:0,' (not 223).');
  432. X            fwsgn : writeln(ERRfile,foo:0,' signature bytes (min. 4).');
  433. X            nopre : writeln(ERRfile,'Missing preamble.');
  434. X            nobop : writeln(ERRfile,'Missing beginning-of-page command.');
  435. X            nopp  : writeln(ERRfile,'Missing post-post command.');
  436. X            bdpre : writeln(ERRfile,'Preamble occured inside a page.');
  437. X            bdbop : writeln(ERRfile,'BOP-command occured inside a page.');
  438. X            bdpst : writeln(ERRfile,'Postamble occured before end-of-page.');
  439. X            bdpp  : writeln(ERRfile,'Postpost occured before post-command.');
  440. X            nopst : writeln(ERRfile,'Missing postamble.');
  441. X            illch : writeln(ERRfile,'Character code out of range, 0..127');
  442. X            filop : writeln(ERRfile,'Cannot open dvifile');
  443. X            filcr : writeln(ERRfile,'Cannot create outfile');
  444. X        end;
  445. X        if outputtofile then delete(output);
  446. X        exit(-1);
  447. X    end;  { errorexit }
  448. X
  449. X{-----------------------------------------------------------------------------}
  450. X
  451. Xprocedure usage(uerr : useagecodetype);
  452. X    begin
  453. X        if uerr<>ign then begin
  454. X            write(ERRfile,'dvitty: ');
  455. X        case uerr of
  456. X        ign    : writeln(ERRfile, Copyright);
  457. X        wrnge  : writeln(ERRfile,'width arg out of range:16-132');
  458. X        nan    : writeln(ERRfile,'numeric argument expected');
  459. X        gae    : writeln(ERRfile,'garbage at end of argument');
  460. X        bdlst  : writeln(ERRfile,'mal-formed list of pagenumbers');
  461. X        onef   : writeln(ERRfile,'only one infile argument allowed');
  462. X        noarg  : writeln(ERRfile,'option argument expected');
  463. X                lngpth : writeln(ERRfile,'path too long for -F');
  464. X        bdopt  : writeln(ERRfile,'bad option');
  465. X        end;
  466. X        end;
  467. X        writeln(ERRfile,'Usage: dvitty [ options ] dvifile[.dvi]');
  468. X        writeln(ERRfile,'Options are:');
  469. X        writeln(ERRfile,
  470. X            ' -ofile   Write output to file, else write to stdout.');
  471. X        writeln(ERRfile,
  472. X            ' -plist   Print pages whos TeX-page-number are in list.');
  473. X        writeln(ERRfile,
  474. X            ' -Plist   Print pages whos sequential number are in list.');
  475. X        writeln(ERRfile,
  476. X            ' -wn      Print the lines with width n characters, default 80.');
  477. X        write(ERRfile,' -f       Try to pipe to a pager if output is a tty');
  478. X        if defpage then writeln(ERRfile,' (default).')
  479. X        else writeln(ERRfile,'.');
  480. X        write(ERRfile,' -q       Don''t try to pipe to a pager');
  481. X        if defpage then writeln(ERRfile,'.')
  482. X        else writeln(ERRfile,' (default).');
  483. X        writeln(ERRfile,
  484. X            ' -l       Write ''^L'' instead of formfeed between pages.');
  485. X        write(ERRfile,
  486. X            ' -u       National Swedish characters printed as aaoAAO');
  487. X        if defscand then writeln(ERRfile,'.')
  488. X        else writeln(ERRfile,' (default).');
  489. X        write(ERRfile,
  490. X            ' -s       National Swedish characters printed as }{|][\');
  491. X        if defscand then writeln(ERRfile,' (default).')
  492. X        else writeln(ERRfile,'.');
  493. X        exit(1);
  494. X    end;  { usage }
  495. X
  496. X{-----------------------------------------------------------------------------}
  497. X
  498. Xprocedure getname(var str : string);
  499. X    var   i     : integer;
  500. X    begin
  501. X        i:=stringlength;
  502. X        while (i>1) and (str[i]=' ') do i:=i-1;
  503. X        if (i=1) and (str[1]=' ') then usage(ign);
  504. X        if not ((i>=5) and (str[i]='i') and (str[i-1]='v')
  505. X          and (str[i-2]='d') and (str[i-3]='.')) then begin
  506. X            str[i+1]:='.';
  507. X            str[i+2]:='d';
  508. X            str[i+3]:='v';
  509. X            str[i+4]:='i';
  510. X        end;
  511. X        DVIfilename:=str;
  512. X    end;  { getname }
  513. X
  514. X{-----------------------------------------------------------------------------}
  515. X
  516. Xfunction getinteger(var j: integer; var str : string; def : integer) : integer;
  517. X    var  cum : integer;
  518. X         sgn : boolean;
  519. X    begin
  520. X        if not (str[j] in ['0'..'9','-']) then getinteger:=def
  521. X        else begin
  522. X        cum:=0;
  523. X            sgn:=false;
  524. X        if str[j]='-' then begin
  525. X                sgn:=true;
  526. X        j:=j+1;
  527. X        end;
  528. X            if not (str[j] in ['0'..'9']) then getinteger:=def
  529. X        else begin
  530. X                 while str[j] in ['0'..'9'] do begin
  531. X            cum:=cum*10+ord(str[j])-ord('0');
  532. X                    j:=j+1;
  533. X                end;
  534. X                if sgn then getinteger:=-cum else getinteger:=cum;
  535. X            end;
  536. X        end;
  537. X    end;   { getinteger }
  538. X
  539. X{-----------------------------------------------------------------------------}
  540. X
  541. Xprocedure getpages(j : integer; var str : string);
  542. X    var   i : integer;
  543. X
  544. X    procedure plcnxt(pagnr : integer);      { place page-nr next in list }
  545. X        begin
  546. X            currentpage:=lastpage;
  547. X            currentpage^.pag:=pagnr;
  548. X            new(lastpage);
  549. X            lastpage^.all:=false;
  550. X            lastpage^.nxt:=nil;
  551. X            lastpage^.pag:=0;
  552. X            currentpage^.nxt:=lastpage;
  553. X        end;   { plcnxt }
  554. X
  555. X    begin   { getpages }
  556. X        pageswitchon:=true;
  557. X        new(firstpage);
  558. X        firstpage^.all:=false;
  559. X        firstpage^.nxt:=nil; 
  560. X        firstpage^.pag:=0;
  561. X        lastpage:=firstpage;
  562. X        currentpage:=firstpage;
  563. X        if not (str[j] in ['1'..'9','-']) then usage(nan);
  564. X        foo:=getinteger(j,str,0);
  565. X        while foo<>0 do begin
  566. X            plcnxt(foo);
  567. X            if str[j]=',' then begin
  568. X                j:=j+1;
  569. X                if not (str[j] in ['1'..'9','-']) then usage(nan);
  570. X            end else if str[j]=':' then begin
  571. X                j:=j+1;
  572. X                if not (str[j] in ['1'..'9','-']) then usage(nan);
  573. X                foo:=getinteger(j,str,0);
  574. X                if currentpage^.pag<0 then begin
  575. X                    if (foo>0) then begin
  576. X                        currentpage^.all:=true;
  577. X                        plcnxt(foo);
  578. X                    end else if foo<currentpage^.pag then
  579. X                        for i:=(currentpage^.pag-1) downto foo do plcnxt(i)
  580. X                    else usage(bdlst);
  581. X                end else begin
  582. X                    if foo<currentpage^.pag then usage(bdlst);
  583. X                    for i:=(currentpage^.pag+1) to foo do plcnxt(i);
  584. X                end;
  585. X                if str[j]=',' then begin
  586. X                    j:=j+1;
  587. X                    if not (str[j] in ['1'..'9','-']) then usage(nan);
  588. X                end;
  589. X            end;
  590. X            foo:=getinteger(j, str, 0);
  591. X        end;
  592. X        if str[j]<>' ' then usage(gae);
  593. X        currentpage:=firstpage;
  594. X    end;   { getpages }
  595. X
  596. X{-----------------------------------------------------------------------------}
  597. X
  598. Xprocedure setoption(optch : char; var optset, optwarg : charset;
  599. X                    var str : string; var i : integer; j : integer);
  600. X    var   k : integer;
  601. X    begin
  602. X        while optch in optset do begin
  603. X        case optch of
  604. X        'q' : pager:=false;
  605. X        'f' : pager:=true;
  606. X        'l' : noffd:=true;
  607. X        's' : scascii:=true;
  608. X        'u' : scascii:=false;
  609. X        'p' : begin
  610. X            optset:=optset-['P']; { can't have both -P & -p }
  611. X            getpages(j, str);
  612. X              end;
  613. X        'P' : begin
  614. X            sequenceon:=true;
  615. X            optset:=optset-['p']; { can't have both -P & -p }
  616. X            getpages(j, str);
  617. X              end;
  618. X        'w' : begin
  619. X            if not (str[j] in ['0'..'9','-']) then usage(nan);
  620. X            ttywidth:=getinteger(j, str, 80);
  621. X            if str[j]<>' ' then usage(gae);
  622. X            if (ttywidth<16) or (ttywidth>132) then usage(wrnge);
  623. X              end;
  624. X        'o' : begin
  625. X            for k:=1 to stringlength-j+1 do
  626. X                          OUTfilename[k]:=str[j+k-1];
  627. X            for k:=stringlength-j+2 to stringlength do
  628. X              OUTfilename[k]:=' ';
  629. X            outputtofile:=true;
  630. X                        j:=stringlength;
  631. X              end;
  632. X        'F' : begin
  633. X                        for k:=1 to pathlen do
  634. X                            path[k]:=str[k+j-1];
  635. X                        if path[pathlen]<>' ' then usage(lngpth);
  636. X                        j:=stringlength;
  637. X                        pathpgm:=false;
  638. X                      end;
  639. X        end;
  640. X        optch:=str[j];
  641. X        j:=j+1;
  642. X            if optch in optwarg then if str[j]=' ' then begin
  643. X        i:=i+1;
  644. X                if i>=argc then usage(noarg);
  645. X                argv(i, str);
  646. X                j:=1;
  647. X            end;
  648. X        end;
  649. X    end;  { setoption }
  650. X
  651. X{-----------------------------------------------------------------------------}
  652. X
  653. Xprocedure getargs;
  654. X    var   i, j             : integer;
  655. X          str              : string;
  656. X      DVIfilenamefound : boolean;
  657. X          optset, optwarg  : charset;
  658. X          optch            : char;
  659. X    begin
  660. X        if argc<=1 then usage(ign);
  661. X        pageswitchon:=false;    { default: all pages                         }
  662. X        sequenceon:=false;      { default: selected pages are TeX-numbered   }
  663. X        outputtofile:=false;    { default: write to stdout                   }
  664. X        noffd:=false;           { default: print formfeed between pages      }
  665. X        scascii:=defscand;      { default: see compile time adjustable const }
  666. X        pager:=defpage;         { default: see compile time adjustable const }
  667. X        path:=defpath;          { default: use the default path to the pager }
  668. X        pathpgm:=true;          { default:            -   "  -               }
  669. X        ttywidth:=80;           { default                                    }
  670. X        DVIfilenamefound:=false;
  671. X    optset:=['w','p','P','o','u','s','q','l','f','F'];   { legal options }
  672. X        optwarg:=['w','p','P','o','F'];                  { options with args }
  673. X        i:=0;
  674. X        while envargs(optch, str) do   { get options from environ var DVITTY }
  675. X            setoption(optch, optset, optwarg, str, i, 1);
  676. X    i:=1;
  677. X    while i<argc do begin
  678. X            argv(i, str);
  679. X            optch:=str[2];                        { cache this one           }
  680. X            if str[1]<>'-' then begin
  681. X                if DVIfilenamefound then usage(onef);
  682. X                getname(str);
  683. X                DVIfilenamefound:=true;
  684. X            end else if optch in optset then begin
  685. X                j:=3;
  686. X                if (optch in optwarg) and (str[j]=' ') then begin
  687. X                    i:=i+1;
  688. X                    if i>=argc then usage(noarg);
  689. X                    argv(i, str);
  690. X                    j:=1;
  691. X                end;
  692. X                setoption(optch, optset, optwarg, str, i, j);
  693. X            end else usage(bdopt);
  694. X            i:=i+1;
  695. X        end;
  696. X        if not DVIfilenamefound then usage(ign)
  697. X    end;   { getargs }
  698. X
  699. X{-----------------------------------------------------------------------------}
  700. X
  701. Xfunction getbyte : integer;              { get next byte from dvi-file }
  702. X    var   b : sbyte;
  703. X    begin
  704. X        read(DVIfile, b);
  705. X        if b<0 then getbyte:=b+256 else getbyte:=b
  706. X    end;  { getbyte }
  707. X
  708. X{-----------------------------------------------------------------------------}
  709. X
  710. Xfunction get2 : integer;          { returns the next two bytes, unsigned }
  711. X    begin
  712. X        foo:=getbyte;
  713. X        get2:=foo*256+getbyte
  714. X    end;  { get2 }
  715. X
  716. X{-----------------------------------------------------------------------------}
  717. X
  718. Xfunction get3 : integer;         { returns the next three bytes, unsigned }
  719. X    begin
  720. X        foo:=getbyte;
  721. X        foo:=foo*256+getbyte;
  722. X        get3:=foo*256+getbyte
  723. X    end;  { get3 }
  724. X
  725. X{-----------------------------------------------------------------------------}
  726. X
  727. Xfunction signedbyte : integer;     { returns next byte fr dvi-file, signed }
  728. X    var   b : sbyte;
  729. X    begin
  730. X        read(DVIfile, b);
  731. X        signedbyte:=b;
  732. X    end;  { signedbyte }
  733. X
  734. X{-----------------------------------------------------------------------------}
  735. X
  736. Xfunction signed2 : integer;          { returns the next two bytes, signed }
  737. X    begin
  738. X        read(DVIfile, foo);
  739. X        signed2:=foo*256+getbyte
  740. X    end;  { signed2 }
  741. X
  742. X{-----------------------------------------------------------------------------}
  743. X
  744. Xfunction signed3 : integer;       { returns the next three bytes, signed }
  745. X    begin
  746. X        read(DVIfile, foo);
  747. X        foo:=foo*256+getbyte;
  748. X        signed3:=foo*256+getbyte
  749. X    end;  { signed3 }
  750. X
  751. X{-----------------------------------------------------------------------------}
  752. X
  753. Xfunction signed4 : integer;         { returns the next four bytes, signed }
  754. X    begin
  755. X        read(DVIfile, foo);
  756. X        foo:=foo*256+getbyte;
  757. X        foo:=foo*256+getbyte;
  758. X        signed4:=foo*256+getbyte
  759. X    end;  { signed4 }
  760. X
  761. X{-----------------------------------------------------------------------------}
  762. X
  763. Xfunction imin(a, b : integer) : integer;  { returns the least of two int:s }
  764. X    begin
  765. X        if a<b then imin:=a
  766. X        else imin:=b;
  767. X    end;
  768. X
  769. X{-----------------------------------------------------------------------------}
  770. X
  771. Xfunction skipnoops(goal : integer) : boolean; { skips by no-op commands  }
  772. X    begin                                     { ret true if opcode=goal  }
  773. X        repeat
  774. X            opcode:=getbyte;
  775. X        until opcode<>nop2;
  776. X        skipnoops:=(opcode=goal)
  777. X    end;  { skipnoops }
  778. X
  779. X{-----------------------------------------------------------------------------}
  780. X
  781. Xfunction getline : lineptr;          { returns an initialized line-object }
  782. X    var   i    : integer;
  783. X          temp : lineptr;
  784. X    begin
  785. X        new(temp);
  786. X        with temp^ do begin
  787. X            charactercount:=leftmargin-1;   prev:=nil;    next:=nil;
  788. X            for i:=leftmargin to rightmargin do text[i]:=' '
  789. X        end;
  790. X        getline:=temp
  791. X    end;  { getline }
  792. X
  793. X{-----------------------------------------------------------------------------}
  794. X
  795. Xfunction findline : lineptr;            { find line where text should go, }
  796. X    var   temp : lineptr;               { generate a new line if needed   }
  797. X    begin
  798. X        if ((v>currentline^.vv) and (currentline=lastline))
  799. X          or ((v<currentline^.vv) and (currentline=firstline))
  800. X          or (v-lastline^.vv>verticalepsilon) then begin
  801. X            temp:=getline;
  802. X            with temp^ do begin
  803. X                prev:=lastline;
  804. X                vv:=v;
  805. X                lastline^.next:=temp;
  806. X                lastline:=temp
  807. X            end
  808. X        end else begin
  809. X            temp:=lastline;
  810. X            while (temp^.vv>v) and (temp<>firstline) do temp:=temp^.prev;
  811. X            if abs(temp^.vv-v)>verticalepsilon then begin
  812. X                if temp^.next^.vv-v < verticalepsilon then temp:=temp^.next
  813. X                else if (temp=firstline) and (v<temp^.vv) then begin
  814. X                    temp:=getline;
  815. X                    with temp^ do begin
  816. X                        next:=firstline;
  817. X                        vv:=v;
  818. X                        firstline^.prev:=temp;
  819. X                        firstline:=temp
  820. X                    end
  821. X                end else begin
  822. X                    currentline:=temp;
  823. X                    temp:=getline;
  824. X                    with temp^ do begin
  825. X                        next:=currentline^.next;
  826. X                        prev:=currentline;
  827. X                        currentline^.next:=temp;
  828. X                        currentline:=temp;
  829. X                        temp^.next^.prev:=temp;
  830. X                        vv:=v
  831. X                    end
  832. X                end
  833. X            end
  834. X        end;
  835. X        findline:=temp
  836. X    end;  { findline }
  837. X
  838. X{-----------------------------------------------------------------------------}
  839. X
  840. Xprocedure outchar(ch : char);              { output ch to appropriate line }
  841. X    var   i, j : integer;
  842. X    begin
  843. X        if abs(v-currentline^.vv)>verticalepsilon
  844. X            then currentline:=findline;
  845. X        if (ord(ch) in [11..17, 25..31, 92, 123..126]) then
  846. X        case ord(ch) of
  847. X            11  :  begin outchar('f'); ch:='f'  end; { ligature        }
  848. X            12  :  begin outchar('f'); ch:='i'  end; { ligature        }
  849. X            13  :  begin outchar('f'); ch:='l'  end; { ligature        }
  850. X            14  :  begin outchar('f');
  851. X                         outchar('f'); ch:='i'  end; { ligature        }
  852. X            15  :  begin outchar('f');
  853. X                         outchar('f'); ch:='l'  end; { ligature        }
  854. X            16  :  ch:='i';
  855. X            17  :  ch:='j';
  856. X            25  :  begin outchar('s'); ch:='s'  end; { German double s }
  857. X            26  :  begin outchar('a'); ch:='e'  end; { Dane/Norw ae    }
  858. X            27  :  begin outchar('o'); ch:='e'  end; { Dane/Norw oe    }
  859. X            28  :  if scascii then ch:='|'           { Dane/Norw /o    }
  860. X                   else ch:='o';
  861. X            29  :  begin outchar('A'); ch:='E'  end; { Dane/Norw AE    }
  862. X            30  :  begin outchar('O'); ch:='E'  end; { Dane/Norw OE    }
  863. X            31  :  if scascii then ch:='\'           { Dane/Norw /O    }
  864. X                   else ch:='O';
  865. X            92  :  ch:='"';                          { beginnig qoute  }
  866. X            123 :  ch:='-';
  867. X            124 :  ch:='_';
  868. X            125 :  ch:='"';
  869. X            126 :  ch:='"';
  870. X        end;
  871. X        j:=round((h/maxpagewidth)*(ttywidth-1)+1.0);
  872. X        if j>rightmargin then j:=rightmargin
  873. X        else if j<leftmargin then j:=leftmargin;
  874. X        with currentline^ do begin
  875. X            foo:=leftmargin-1;
  876. X            {-------------------------------------------------------------}
  877. X            { The following is very specialized code, it handles national }
  878. X            { Swedish characters. They are respectively: a and o with two }
  879. X            { dots ("a & "o) and a with a circle (Oa). In Swedish "ASCII" }
  880. X            { these characters replace }{|][ and \.  TeX outputs these by }
  881. X            { first issuing the dots or circle and then backspace and set }
  882. X            { the a or o.  When dvitty finds an a or o it searches in the }
  883. X            { near vicinity for the character codes that represent circle }
  884. X            { or dots and if one is found the corresponding national char }
  885. X            { replaces the special character codes.                       }
  886. X            {-------------------------------------------------------------}
  887. X            if scascii then begin
  888. X                if (ch='a') or (ch='A') or (ch='o') or (ch='O') then begin
  889. X                    for i:=-(imin(-leftmargin, -(j-2)))
  890. X                      to imin(rightmargin, j+2) do
  891. X                        if ((ord(text[i])=127) or (ord(text[i])=23)) then
  892. X                          foo:=i;
  893. X                    if foo>=leftmargin then begin
  894. X                        j:=foo;
  895. X                        case ord(text[j]) of
  896. X                            127 :  if ch='a' then ch:='{' else   { dots   }
  897. X                                      if ch='A' then ch:='[' else
  898. X                                      if ch='o' then ch:='|' else
  899. X                                      if ch='O' then ch:='\';
  900. X                            23  :  if ch='a' then ch:='}' else   { circle }
  901. X                                      if ch='A' then ch:=']'
  902. X                        end;  { case }
  903. X                    end;
  904. X                end;
  905. X            end;
  906. X            {----------------- end of 'Scandinavian code' ----------------}
  907. X            if foo=leftmargin-1 then while (text[j]<>' ') and (j<rightmargin)
  908. X            do begin
  909. X                j:=j+1;
  910. X                h:=h+charwidth
  911. X            end;
  912. X            if (scascii and ((ord(ch)>=chspc) or (ord(ch)=23))) or
  913. X              (not scascii and (ord(ch)>=chspc) and (ord(ch)<>chdel)) then
  914. X              begin
  915. X                if j<rightmargin then text[j]:=ch
  916. X                else text[rightmargin]:='@';
  917. X                if j>charactercount then charactercount:=j;
  918. X                if j<firstcolumn then firstcolumn:=j;
  919. X                h:=h+charwidth
  920. X            end
  921. X        end   { with currentline^ do }
  922. X    end;  { outchar }
  923. X
  924. X{-----------------------------------------------------------------------------}
  925. X
  926. Xprocedure setchar(charnr : integer);
  927. X    { should print characters with character code>127 from current font }
  928. X    { note that the parameter is a dummy, since ascii-chars are<=127    }
  929. X    begin
  930. X        outchar('#')
  931. X    end;  { setchar }
  932. X
  933. X{-----------------------------------------------------------------------------}
  934. X
  935. Xprocedure putcharacter(charnr : integer); { output character, don't change h }
  936. X    var   saveh : integer;
  937. X    begin
  938. X        saveh:=h;
  939. X        if (charnr>=0) and (charnr<=lastchar) then outchar(chr(charnr))
  940. X        else setchar(charnr);
  941. X        h:=saveh;
  942. X    end;  { putcharacter }
  943. X
  944. X{-----------------------------------------------------------------------------}
  945. X
  946. Xprocedure rule(moving : boolean; rulewt, ruleht : integer);
  947. X    { output a rule (vertical or horizontal), increment h if moving is true }
  948. X    var   ch               : char;       { character to set rule with       }
  949. X          saveh, savev, wt : integer;
  950. X
  951. X    procedure ruleaux;              { recursive procedure that does the job }
  952. X        var   lmh, rmh : integer;
  953. X        begin
  954. X            wt:=rulewt;
  955. X            lmh:=h;                 { save left margin                      }
  956. X            if h<0 then begin       { let rules that start at negative h    }
  957. X                wt:=wt-h;           { start at coordinate 0, but let it     }
  958. X                h:=0;               {   have the right length               }
  959. X            end;
  960. X            while wt>0 do begin     { output the part of the rule that      }
  961. X                rmh:=h;             {   goes on this line                   }
  962. X                outchar(ch);
  963. X                wt:=wt-(h-rmh);     { decrease the width left on line       }
  964. X            end;
  965. X            ruleht:=ruleht-verticalepsilon;       { decrease the height     }
  966. X            if ruleht>verticalepsilon then begin  { still more vertical?    }
  967. X                rmh:=h;             { save current h (right margin)         }
  968. X                h:=lmh;             { restore left margin                   }
  969. X                v:=v-(verticalepsilon+(verticalepsilon div 10));
  970. X                ruleaux;
  971. X                h:=rmh;             { restore right margin                  }
  972. X            end;
  973. X        end;  { ruleaux }
  974. X
  975. X    begin  { rule   --   starts up the recursive routine }
  976. X        if not moving then saveh:=h;
  977. X        if (ruleht<=0) or (rulewt<=0) then h:=h+rulewt
  978. X        else begin
  979. X            savev:=v;
  980. X            if (ruleht div rulewt)>0 then  ch:='!'
  981. X            else if ruleht>(verticalepsilon div 2) then ch:='='
  982. X            else ch:='_';
  983. X            ruleaux;
  984. X            v:=savev;
  985. X        end;
  986. X        if not moving then h:=saveh;
  987. X    end;  { rule }
  988. X
  989. X{-----------------------------------------------------------------------------}
  990. X
  991. Xprocedure fontdef(param : integer);      { ignore font-definition command }
  992. X    begin
  993. X        setpos(DVIfile, param+12, relative);
  994. X        setpos(DVIfile, getbyte+getbyte, relative);
  995. X    end;  { fontdef }
  996. X
  997. X{-----------------------------------------------------------------------------}
  998. X
  999. Xprocedure horizontalmove(amount : integer; var worx : integer);
  1000. X    begin
  1001. X        if amount<>worx then
  1002. X      if abs(amount)<=(charwidth div 4) then worx:=amount
  1003. X      else begin
  1004. X          foo:=3*charwidth div 4;
  1005. X          if amount>0 then worx:=((amount+foo) div charwidth)*charwidth
  1006. X          else worx:=((amount-foo) div charwidth)*charwidth;
  1007. X          end;
  1008. X        h:=h+worx
  1009. X    end;   { horizontalmove }
  1010. X
  1011. X{-----------------------------------------------------------------------------}
  1012. X
  1013. Xfunction inlist(pagenr : integer) : boolean; { ret true if in list of pages }
  1014. X    begin
  1015. X        inlist:=false;
  1016. X        while (currentpage^.pag<0) and (currentpage^.pag<>pagenr)
  1017. X          and not currentpage^.all and (currentpage^.nxt<>nil) do
  1018. X            currentpage:=currentpage^.nxt;
  1019. X        if (currentpage^.all and (pagenr<currentpage^.pag))
  1020. X            or (currentpage^.pag=pagenr) then inlist:=true
  1021. X        else if pagenr>0 then begin
  1022. X            while (currentpage^.pag<>pagenr) and (currentpage^.nxt<>nil) do
  1023. X                currentpage:=currentpage^.nxt;
  1024. X            if currentpage^.pag=pagenr then inlist:=true
  1025. X        end
  1026. X    end;   { inlist }
  1027. X
  1028. X{-----------------------------------------------------------------------------}
  1029. X
  1030. Xfunction bop(var pagecounter, backpointer, pagenr : integer) : boolean;
  1031. X    begin
  1032. X        pagecounter:=pagecounter+1;
  1033. X        pagenr:=signed4;
  1034. X        setpos(DVIfile, 36, relative);
  1035. X        backpointer:=signed4;
  1036. X        if pageswitchon then
  1037. X            if sequenceon then bop:=inlist(pagecounter)
  1038. X            else bop:=inlist(pagenr)
  1039. X        else bop:=true;
  1040. X    end;  { bop }
  1041. X
  1042. X{-----------------------------------------------------------------------------}
  1043. X
  1044. Xprocedure initpage(backpointer, pagenr, pagecounter : integer);
  1045. X    begin
  1046. X        h:=0;  v:=0;                          { initialize coordinates   }
  1047. X        x:=0;  w:=0;  y:=0;  z:=0;            { initialize amounts       }
  1048. X        stack.top:=0;                         { initialize stack         }
  1049. X        currentline:=getline;                 { initialize list of lines }
  1050. X        currentline^.vv:=0;
  1051. X        firstline:=currentline;
  1052. X        lastline:=currentline;
  1053. X        firstcolumn:=rightmargin;
  1054. X        if pageswitchon then
  1055. X          if (sequenceon and (pagecounter<>firstpage^.pag))
  1056. X          or (not sequenceon and (pagenr<>firstpage^.pag)) then
  1057. X            if noffd then writeln('^L') else writeln(chr(chffd));
  1058. X        if not pageswitchon then if backpointer<>-1 then
  1059. X            if noffd then writeln('^L') else writeln(chr(chffd));
  1060. X    end;   { initpage }
  1061. X
  1062. X{-----------------------------------------------------------------------------}
  1063. X
  1064. Xprocedure dover2page;
  1065. X    begin
  1066. X        opcode:=getbyte;
  1067. X        while opcode<>eop2 do begin    { process page until eop reached }
  1068. X            if opcode>postpost2 then errorexit(illop)
  1069. X            else if opcode<=lastchar then outchar(chr(opcode))
  1070. X            else if opcode in [128..170, 235..249] then
  1071. X            case opcode of
  1072. X                128 :  setchar(getbyte);
  1073. X                129 :  setchar(get2);
  1074. X                130 :  setchar(get3);
  1075. X                131 :  setchar(signed4);
  1076. X                132 :  rule(advance, signed4, signed4);
  1077. X                133 :  putcharacter(getbyte);
  1078. X                134 :  putcharacter(get2);
  1079. X                135 :  putcharacter(get3);
  1080. X                136 :  putcharacter(signed4);
  1081. X                137 :  rule(stay, signed4, signed4);
  1082. X                nop2:  ;  { no-op }
  1083. X                bop2:  errorexit(bdbop);
  1084. X                141 :  with stack do begin                         { push }
  1085. X               if top>stackmax-1 then errorexit(stkof);
  1086. X                           top:=top+1;
  1087. X                           with items[top] do begin
  1088. X                   hh:=h;   vv:=v;   ww:=w;
  1089. X                               xx:=x;   yy:=y;   zz:=z;
  1090. X               end;
  1091. X               end;
  1092. X                142 :  with stack do begin                         { pop  }
  1093. X               if top=0 then errorexit(stkuf);
  1094. X                           with items[top] do begin
  1095. X                               h:=hh;   v:=vv;   w:=ww;
  1096. X                               x:=xx;   y:=yy;   z:=zz;
  1097. X                           end;
  1098. X               top:=top-1;
  1099. X               end;
  1100. X                143 :  h:=h+signedbyte;
  1101. X                144 :  h:=h+signed2;
  1102. X                145 :  h:=h+signed3;
  1103. X                146 :  h:=h+signed4;
  1104. X                147 :  horizontalmove(w, w);
  1105. X                148 :  horizontalmove(signedbyte, w);
  1106. X                149 :  horizontalmove(signed2, w);
  1107. X                150 :  horizontalmove(signed3, w);
  1108. X                151 :  horizontalmove(signed4, w);
  1109. X                152 :  horizontalmove(x, x);
  1110. X                153 :  horizontalmove(signedbyte, x);
  1111. X                154 :  horizontalmove(signed2, x);
  1112. X                155 :  horizontalmove(signed3, x);
  1113. X                156 :  horizontalmove(signed4, x);
  1114. X                157 :  v:=v+signedbyte;
  1115. X                158 :  v:=v+signed2;
  1116. X                159 :  v:=v+signed3;
  1117. X                160 :  v:=v+signed4;
  1118. X                161 :  v:=v+y;
  1119. X                162 :  begin   y:=signedbyte; v:=v+y  end;
  1120. X                163 :  begin   y:=signed2;    v:=v+y  end;
  1121. X                164 :  begin   y:=signed3;    v:=v+y  end;
  1122. X                165 :  begin   y:=signed4;    v:=v+y  end;
  1123. X                166 :  v:=v+z;
  1124. X                167 :  begin   z:=signedbyte; v:=v+z  end;
  1125. X                168 :  begin   z:=signed2;    v:=v+z  end;
  1126. X                169 :  begin   z:=signed3;    v:=v+z  end;
  1127. X                170 :  begin   z:=signed4;    v:=v+z  end;
  1128. X                235, 236, 237,                          { ignore font changes }
  1129. X                238 :  setpos(DVIfile, opcode-234, relative);
  1130. X                239 :  setpos(DVIfile, getbyte, relative);
  1131. X                240 :  setpos(DVIfile, get2, relative);
  1132. X                241 :  setpos(DVIfile, get3, relative);
  1133. X                242 :  setpos(DVIfile, signed4, relative);
  1134. X                243,244,245,
  1135. X                246 :  fontdef(opcode-242);
  1136. X                pre2     : errorexit(bdpre);
  1137. X                post2    : errorexit(bdpst);
  1138. X                postpost2: errorexit(bdpp);
  1139. X            end;
  1140. X            opcode:=getbyte
  1141. X        end
  1142. X    end;   { dover2page }
  1143. X
  1144. X{-----------------------------------------------------------------------------}
  1145. X
  1146. Xprocedure eop;        { 'end of page', writes lines of page to output file }
  1147. X    var   i, j : integer;
  1148. X          ch   : char;
  1149. X    begin
  1150. X        if stack.top<>0 then
  1151. X            writeln(ERRfile, 'dvitty: warning - stack not empty at eop.');
  1152. X        currentline:=firstline;
  1153. X        repeat
  1154. X        with currentline^ do begin
  1155. X        if currentline<>firstline then begin
  1156. X            foo:=((vv-prev^.vv) div verticalepsilon)-1;
  1157. X            if foo>0 then foo:=imin(foo, 3);
  1158. X            for i:=1 to foo do writeln;
  1159. X        end;
  1160. X        if charactercount>=leftmargin then begin
  1161. X            i:=firstcolumn;  j:=1;  foo:=ttywidth-2;
  1162. X            repeat
  1163. X            ch:=text[i];
  1164. X            if (ord(ch)>=chspc) and (ord(ch)<>chdel) then
  1165. X                          write(ch);
  1166. X            if j>foo then if charactercount>i+1 then begin
  1167. X                writeln('*');
  1168. X                write(' *');
  1169. X                j:=2
  1170. X            end;
  1171. X            i:=i+1;  j:=j+1
  1172. X            until i>charactercount;
  1173. X        end
  1174. X        end;
  1175. X        writeln;
  1176. X            currentline:=currentline^.next;
  1177. X        until currentline^.next=nil;
  1178. X    end;  { eop }
  1179. X
  1180. X{-----------------------------------------------------------------------------}
  1181. X
  1182. Xprocedure skipver2page;           { skip past one page }
  1183. X    begin
  1184. X        opcode:=getbyte;
  1185. X        while opcode<>eop2 do begin
  1186. X            if opcode>postpost2 then errorexit(illop)
  1187. X            else if opcode in [128..170, 235..249] then
  1188. X            case opcode of
  1189. X                nop2,141, 142, 147, 152,      161, 166      : ;
  1190. X                128, 133, 143, 148, 153, 157, 162, 167, 235 :
  1191. X                                                setpos(DVIfile, 1, relative);
  1192. X                129, 134, 144, 149, 154, 158, 163, 168, 236 :
  1193. X                                                setpos(DVIfile, 2, relative);
  1194. X                130, 135, 145, 150, 155, 159, 164, 169, 237 :
  1195. X                                                setpos(DVIfile, 3, relative);
  1196. X                131, 136, 146, 151, 156, 160, 165, 170, 238 :
  1197. X                                                setpos(DVIfile, 4, relative);
  1198. X                132, 137  : setpos(DVIfile, 8, relative);
  1199. X                139       : errorexit(bdbop);
  1200. X                239       : setpos(DVIfile, getbyte, relative);
  1201. X                240       : setpos(DVIfile, get2, relative);
  1202. X                241       : setpos(DVIfile, get3, relative);
  1203. X                242       : setpos(DVIfile, signed4, relative);
  1204. X                243,244,245,
  1205. X                246       : fontdef(opcode-242);
  1206. X                pre2      : errorexit(bdpre);
  1207. X                post2     : errorexit(bdpst);
  1208. X                postpost2 : errorexit(bdpp);
  1209. X            end;
  1210. X            opcode:=getbyte;
  1211. X        end;
  1212. X    end;   { skipver2page }
  1213. X
  1214. X{-----------------------------------------------------------------------------}
  1215. X
  1216. Xprocedure dopages;                       { process the pages in the DVI-file }
  1217. X    var   pagecounter, backpointer, pagenr : integer;
  1218. X    begin
  1219. X        setpos(DVIfile, 0, absolute);    { read the dvifile from the start   }
  1220. X        pagecounter:=0;
  1221. X        if not skipnoops(pre2) then errorexit(nopre);
  1222. X    opcode:=getbyte;           { check id in preamble, ignore rest of it }
  1223. X    if opcode<>versionid then errorexit(badid);
  1224. X    setpos(DVIfile, 12, relative);
  1225. X    setpos(DVIfile, getbyte, relative);
  1226. X        if not skipnoops(bop2) then errorexit(nobop)  { should be at start }
  1227. X        else while opcode<>post2 do begin             {   of page now      }
  1228. X            if opcode<>bop2 then errorexit(nobop)
  1229. X            else begin
  1230. X                if not bop(pagecounter, backpointer, pagenr) then skipver2page
  1231. X                else begin
  1232. X                    initpage(backpointer, pagenr, pagecounter);
  1233. X                    dover2page;
  1234. X                    eop;
  1235. X                end;
  1236. X                repeat opcode:=getbyte until opcode<>nop2
  1237. X            end
  1238. X        end;
  1239. X    end;  { dopages }
  1240. X
  1241. X{-----------------------------------------------------------------------------}
  1242. X
  1243. Xprocedure postamble;         { find and process postamble, use random access }
  1244. X    var   size, count : integer;
  1245. X    begin
  1246. X        size:=sizef(DVIfile);                             { get size of file }
  1247. X        count:=-1;
  1248. X        repeat         { back file up past signature bytes (223), to id-byte }
  1249. X            if size=0 then errorexit(nopst);
  1250. X            size:=size-1;
  1251. X            setpos(DVIfile, size, absolute);
  1252. X            opcode:=getbyte;
  1253. X            count:=count+1;                { has to be at least 4 sign-bytes }
  1254. X        until opcode<>223;
  1255. X        if count<4 then begin foo:=count; errorexit(fwsgn); end;
  1256. X        if opcode<>versionid then errorexit(badid);
  1257. X        setpos(DVIfile, size-4, absolute);   { back up to back-pointer       }
  1258. X    setpos(DVIfile, signed4, absolute);  { back up to start of postamble }
  1259. X        if getbyte<>post2 then errorexit(nopst);
  1260. X        setpos(DVIfile, 20, relative);
  1261. X        maxpagewidth:=signed4;
  1262. X        charwidth:=maxpagewidth div ttywidth;
  1263. X    foo:=get2;
  1264. X    if foo>stackmax then errorexit(stkrq);   { too much stack required   }
  1265. X    end;  { postamble }
  1266. X
  1267. X(*****************************************************************************
  1268. X *
  1269. X *     M A I N
  1270. X *)
  1271. X
  1272. Xbegin
  1273. X    rewrite(ERRfile, '/dev/tty');         { get a pascal file               }
  1274. X    tostderr(ERRfile);                    { and redirect it to stderr       }
  1275. X    getargs;                              { read the command line arguments }
  1276. X    if not readp(DVIfilename) then
  1277. X        errorexit(filop);                 { can't open dvifile              }
  1278. X    reset(DVIfile, DVIfilename);
  1279. X    if outputtofile then begin            { open the outfile                }
  1280. X        if not writep(OUTfilename) then
  1281. X            errorexit(filcr);             { can't create outfile            }
  1282. X        rewrite(output, OUTfilename);
  1283. X        pager:=false;
  1284. X    end else
  1285. X        if ttyp(output) and pager then    { try to pipe to a pager          }
  1286. X            pager:=popenp(output, path, pathpgm);
  1287. X    postamble;                            { seek and process the postamble  }
  1288. X    dopages;                              { time to do the actual work!     }
  1289. X    if pager then pcloseit(output);       { have to use pclose if popened   }
  1290. Xend.
  1291. + END-OF-FILE dvitty.p
  1292. chmod 'u=rw,g=rw,o=r' 'dvitty.p'
  1293. echo '    -rw-rw-r--  1 zap         47572 Aug 15 20:29 dvitty.p        (as sent)'
  1294. echo -n '    '
  1295. /bin/ls -l dvitty.p
  1296. echo 'Extracting sys.h'
  1297. sed 's/^X//' > sys.h << '+ END-OF-FILE sys.h'
  1298. Xprocedure exit(i : integer); external;            { in libc }
  1299. X
  1300. Xprocedure setpos(var f : DVIfiletype; p, m : integer); external;
  1301. X
  1302. Xfunction sizef(var f : DVIfiletype) : integer; external;
  1303. X
  1304. Xprocedure delete(var f : text); external;
  1305. X
  1306. Xfunction readp(var filename : string) : boolean; external;
  1307. X
  1308. Xfunction writep(var filename : string) : boolean; external;
  1309. X
  1310. Xprocedure tostdout(var f  :text); external;
  1311. X
  1312. Xprocedure tostderr(var f : text); external;
  1313. X
  1314. Xfunction ttyp(var f :text) : boolean; external;
  1315. X
  1316. Xfunction popenp(var f :text; var path : pathtype;
  1317. X                                pathpgm : boolean) : boolean; external;
  1318. X
  1319. Xprocedure pcloseit(var f :text); external;
  1320. X
  1321. Xfunction envargs(var optch :char; var str :string) : boolean; external;
  1322. + END-OF-FILE sys.h
  1323. chmod 'u=rw,g=r,o=r' 'sys.h'
  1324. echo '    -rw-r--r--  1 zap           720 Aug  8 00:22 sys.h        (as sent)'
  1325. echo -n '    '
  1326. /bin/ls -l sys.h
  1327. echo 'Extracting sys.c'
  1328. sed 's/^X//' > sys.c << '+ END-OF-FILE sys.c'
  1329. X#include <stdio.h>
  1330. X#include <sys/types.h>
  1331. X#include <sys/stat.h>
  1332. X
  1333. X#define NAMSIZ        76
  1334. X#define    SYNC    0x004    /* 1 => window is out of sync */
  1335. X
  1336. Xtypedef enum {FALSE, TRUE} bool;
  1337. X
  1338. Xstruct iorec {
  1339. X    char        *fileptr;    /* ptr to file window */
  1340. X    long        lcount;        /* number of lines printed */
  1341. X    long        llimit;        /* maximum number of text lines */
  1342. X    FILE        *fbuf;        /* FILE ptr */
  1343. X    struct iorec    *fchain;    /* chain to next file */
  1344. X    struct iorec    *flev;        /* ptr to associated file variable */
  1345. X    char        *pfname;    /* ptr to name of file */
  1346. X    short        funit;        /* file status flags */
  1347. X    unsigned short    fblk;        /* index into active file table */
  1348. X    long        fsize;        /* size of elements in the file */
  1349. X    char        fname[NAMSIZ];    /* name of associated UNIX file */
  1350. X    char        buf[BUFSIZ];    /* I/O buffer */
  1351. X    char        window[1];    /* file window element */
  1352. X};
  1353. X
  1354. Xsetpos(f, p, m)                /* seek on a pascal file       */
  1355. Xstruct iorec *f;
  1356. Xint p, m;
  1357. X{
  1358. X    f->funit |= SYNC;
  1359. X    (void) fseek (f->fbuf, (long) p, m);
  1360. X}
  1361. X
  1362. Xint
  1363. Xsizef(f)                /* return size of file           */
  1364. Xstruct iorec *f;
  1365. X{
  1366. X    struct stat st;
  1367. X
  1368. X    (void) fstat (fileno(f->fbuf), &st);
  1369. X    return (st.st_size);
  1370. X}
  1371. X
  1372. Xdelete(f)                /* remove a link to a file       */
  1373. Xstruct iorec *f;
  1374. X{
  1375. X    (void) unlink (f->pfname);
  1376. X}
  1377. X
  1378. Xbool
  1379. Xreadp(filename)                /* check if a file may be read        */
  1380. Xchar *filename;
  1381. X{
  1382. X    register char *p;
  1383. X        register bool ok;
  1384. X
  1385. X    for(p=filename; *p!=' '; p++)    /* pascal strings are space-padded */
  1386. X        ;
  1387. X    *p='\0';            /* make it a C-string           */
  1388. X    if (access(filename, 04) == 0)    /* check if we can read this file  */
  1389. X        ok=TRUE;
  1390. X    else
  1391. X        ok=FALSE;
  1392. X    *p=' ';                /* "re-pasclify" the string       */
  1393. X    return(ok);
  1394. X}
  1395. X
  1396. Xbool
  1397. Xwritep(filename)            /* check if a file may be written   */
  1398. Xchar *filename;
  1399. X{
  1400. X    register char *p;
  1401. X        register bool ok;
  1402. X    int f;
  1403. X
  1404. X    for(p=filename; *p!=' '; p++)    /* pascal strings are space-padded */
  1405. X        ;
  1406. X    *p='\0';            /* make it a C-string           */
  1407. X    if ((f=creat(filename, 0666)) >= 0) {    /* can we create this file?*/
  1408. X        (void) close(f);
  1409. X        ok = TRUE;
  1410. X    } else
  1411. X        ok = FALSE;
  1412. X    *p=' ';                /* "re-pasclify" the string       */
  1413. X    return(ok);
  1414. X}
  1415. X
  1416. Xtostdout(f)                /* make file appear on stdout       */
  1417. Xstruct iorec *f;
  1418. X{
  1419. X    (void) fflush (f->fbuf);
  1420. X    f->fbuf = stdout;
  1421. X}
  1422. X
  1423. Xtostderr(f)                /* make file appear on stderr       */
  1424. Xstruct iorec *f;
  1425. X{
  1426. X    (void) fflush (f->fbuf);
  1427. X    f->fbuf = stderr;
  1428. X}
  1429. X
  1430. Xbool
  1431. Xttyp(f)                    /* is file associated with a tty?  */
  1432. Xstruct iorec *f;
  1433. X{
  1434. X    if (isatty(fileno(f->fbuf))==1)
  1435. X        return(TRUE);
  1436. X    else
  1437. X        return(FALSE);
  1438. X}
  1439. X
  1440. Xbool
  1441. Xpopenp(f, path, pthpgm)            /* can this file be piped into a   */
  1442. Xstruct iorec  *f;            /*   pager (like more)?           */
  1443. Xchar *path;
  1444. Xbool pthpgm;
  1445. X{
  1446. X    char *getenv(), *p;
  1447. X    FILE *popen(), *g;
  1448. X
  1449. X    if (pthpgm==FALSE) {            /* -Fpath option used       */
  1450. X        for(p=path; *p !=' ' && *p != '\0'; p++)
  1451. X            ;
  1452. X        *p = '\0';
  1453. X    } else if ((p=getenv("PAGER"))==NULL) { /* find prefered pager     */
  1454. X        for(p=path; *p !=' ' && *p != '\0'; p++)
  1455. X            ;            /* didn't have one, use    */
  1456. X        *p = '\0';            /* the default one for pgm */
  1457. X    } else
  1458. X        path = p;            /* default pager from env  */
  1459. X    if ((g=popen(path, "w"))!=NULL) {    /* get a pipe to the pager */
  1460. X        (void) fflush (f->fbuf);    /* make output to f go to  */
  1461. X        f->fbuf = g;            /*   the pager           */
  1462. X        return(TRUE);
  1463. X    } else
  1464. X        return(FALSE);            /* couldn't do it       */
  1465. X}
  1466. X
  1467. Xpcloseit(f)                    /* popend stream has to be */
  1468. Xstruct iorec *f;                /*   pclosed           */
  1469. X{
  1470. X    (void) pclose (f->fbuf);
  1471. X}
  1472. X
  1473. Xbool
  1474. Xenvargs(optch, str)
  1475. Xchar *optch, *str;
  1476. X{
  1477. X    char *getenv(), *q;
  1478. X    static char *p;
  1479. X    static int foo = 0;
  1480. X
  1481. X    switch (foo) {
  1482. X    case 0:    if ((p=getenv("DVITTY"))==NULL)    /* 1st time only, get var  */
  1483. X            return(FALSE);        /* sorry, no var       */
  1484. X        foo++;        /* remember we've been here to next call   */
  1485. X                /* fall through                */
  1486. X    default:
  1487. X        if (*p!=' ' && *p!='\0')    /* anything here?        */
  1488. X            *optch = *p++;        /* yes, it's our optchar   */
  1489. X        else
  1490. X            return(FALSE);        /* sorry, no more       */
  1491. X        q=str;                /* get args or whatever    */
  1492. X        while (*p!=' ' && *p!='\0')
  1493. X            *q++ = *p++;
  1494. X        *q=' ';            /* the pascal program wants ' '    */
  1495. X        while (*p==' ')        /* step to next or end             */
  1496. X            p++;
  1497. X        return(TRUE);
  1498. X    }
  1499. X}
  1500. + END-OF-FILE sys.c
  1501. chmod 'u=rw,g=r,o=r' 'sys.c'
  1502. echo '    -rw-r--r--  1 zap          3999 Aug  8 00:24 sys.c        (as sent)'
  1503. echo -n '    '
  1504. /bin/ls -l sys.c
  1505. exit 0
  1506.  
  1507.