allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (06/04/89)
Posting-number: Volume 7, Issue 7 Submitted-by: everson@compsci.bristol.ac.uk Archive-name: thack Enclosed please find thack, a Troff C/A/T to Postscript filter, written by a colleague of mine, Gareth Waddell. Sample usage of thack is, say: troff -t -man /usr/man/sh.1 | thack | lpr -Ppostscript It does not claim to be perfect, but I personally have used it for printing many documents in the past, especially manual pages and found it very useful. It was written under SunOS3.5, but has been run on a 3B2 running System V and produces particularly nice output under SunOS4.0 or later as Sun altered the troff font width tables to match those of Postscript at that release. The Postscript produced by this program has been successfully printed on an Apple Laserwriter I and an Apple Laserwriter IINTX. It can also be previewed under Sunview with the Rutherford Postscript Interpreter. Phill Everson Computer Science Dept., University of Bristol, UK #! /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 1 (of 1)." # Contents: COPYRIGHT MANIFEST Makefile th.h thack.1 thack.c # Wrapped by everson@kukini on Mon May 22 12:29:59 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'COPYRIGHT'\" else echo shar: Extracting \"'COPYRIGHT'\" \(1092 characters\) sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE' Copyright 1989 Gareth Waddell X This notice and any statement of authorship must be reproduced on all copies. The author does not make any warranty expressed or implied, or assumes any liability or responsiblity for the use of this software. X Any distributor of copies of this software shall grant the recipient permission for further redistribution as permitted by this notice. Any distributor must distribute this software without any fee or other monetary gains, unless expressed written permission is granted by the author. X This software or its use shall not be: sold, rented, leased, traded, or otherwise marketed without the expressed written permission of the author. X If the software is modified in a manner creating derivative copyrights, appropriate legends may be placed on derivative work in addition to that set forth above. X Permission is hereby granted to copy, reproduce, redistribute or otherwise use this software as long as the conditions above are met. X All rights not granted by this notice are reserved. X Author: Gareth Waddell X Phill Everson <everson@uk.ac.bris.cs> END_OF_FILE if test 1092 -ne `wc -c <'COPYRIGHT'`; then echo shar: \"'COPYRIGHT'\" unpacked with wrong size! fi # end of 'COPYRIGHT' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(300 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X COPYRIGHT 1 X MANIFEST 1 This shipping list X Makefile 1 X th.h 1 X thack.1 1 X thack.c 1 END_OF_FILE if test 300 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(91 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X.PRECIOUS: thack.c th.h X thack: thack.o X cc -o thack thack.o X thack.c: th.h X touch thack.c END_OF_FILE if test 91 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'th.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'th.h'\" else echo shar: Extracting \"'th.h'\" \(366 characters\) sed "s/^X//" >'th.h' <<'END_OF_FILE' X#include <stdio.h> char *table[2][2]= X { /* FONT 0,1,2,4,5,6,7 */ X " htnmlizsdbxfjuk p ; a_c`e'o r v-wq/.g ,&y % QTOHNMLRGIPCVEZDBSY", X " FXAWJUK0123456789* ()[] = :+ ! ? | $$$$$$$$$$$$$$$$$$$", X /* FONT 3 */ X " yqnmlizsdbxhfuk p a c e=o r t_ Y g w FQW VL-G P D S ", X " >X</ U {} # ~ * + $$$$$$$$$$$$$$$$$$", X }; END_OF_FILE if test 366 -ne `wc -c <'th.h'`; then echo shar: \"'th.h'\" unpacked with wrong size! fi # end of 'th.h' fi if test -f 'thack.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'thack.1'\" else echo shar: Extracting \"'thack.1'\" \(1324 characters\) sed "s/^X//" >'thack.1' <<'END_OF_FILE' X.\" .TH name section cent-foot X.TH THACK 1 "28 August 1987" X.SH NAME X.\" name \- function thack \- hack about with TROFF output X.SH SYNOPSIS X.\" Bold keywords, Italic variables, [] options, | alternatives. X.B thack X.SH DESCRIPTION X.\" Italic files, commands, IR manual-entry (manual-section) X.I Thack is a hack to convert X.IR troff (1) output into postscript. The postscript it produces is not highly efficient. X.\".SH OPTIONS X.\" Itemised list of options X.\".SH FILES X.\" List of all files used by the program X.SH "SEE ALSO" X.\" List of references, textual, and MAN pages. troff(1), nroff(1), eqn(1), tbl(1) X.br XFormatting Documents on the Sun Workstation X.br Postscript Language Reference Manual X.SH DIAGNOSTICS X.\" List of error messages and return codes the user may expect Cryptic Messages such as L3/16 indicate that an uncatered for code has been sent (24 have yet to be identified). More interesting messages such as 'Sequence Bell Logo is not allowed' are also printed. There are five of these cases. However, some illegal sequences are intercepted and used as additional font information. X.SH BUGS X.\" Known Limitations or Desirable additions to the command Like all hacks, there are plenty. X.br The code is highly inefficient. X.br Many Special characters are Wrong. X.br XEqn(1) & Tbl(1) are not 100% compatible. END_OF_FILE if test 1324 -ne `wc -c <'thack.1'`; then echo shar: \"'thack.1'\" unpacked with wrong size! fi # end of 'thack.1' fi if test -f 'thack.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'thack.c'\" else echo shar: Extracting \"'thack.c'\" \(10227 characters\) sed "s/^X//" >'thack.c' <<'END_OF_FILE' X#include "th.h" X int xpos, ypos, cx, cy; int font, cfont, size, csize, tfont, tsize; char *pstr, *cstr(); X main() X{ X int c, i; X int sflag; X int hdist, vdist; X int esc, lead; X int fh; X X hdist = vdist = 0; X cfont = csize = -1; X tfont = font = 0; X tsize = size = 12; X esc = lead = 1; X cy = ypos = 1692; X cx = xpos = 0; X sflag = 0; X prolog(); X newpage(); X while ((c = getchar()) != EOF) { X font = tfont; X size = tsize; X if (c & 0x80) X hdist += ~c & 0x7f; X else if ((c & 0xe0) == 0x60) X vdist += ~c & 0x1f; X if ((c & 0xc0) == 0) { X if ((c & 0x3f) != 0) { X if (hdist || vdist) { X xpos += esc * hdist; X ypos -= lead * vdist; X if (ypos <= 0) { X endpage(); X newpage(); X while (ypos < 0) X ypos += 1584; X } X hdist = 0; X vdist = 0; X } X sflag = 1; X if (table[(font % 4) == 3][fh][c & 0x3f] == ' ') { X if (font % 4 != 3) X if (fh == 0) X switch (c & 0x3f) { X case 18: X pstr = "\\320"; X break; /* \(em */ X case 28: X illegal("1/4"); X break; /* \(14 */ X case 30: X illegal("1/2"); X break; /* \(12 */ X case 38: X illegal("3/4"); X break; /* \(34 */ X default: X fprintf(stderr, ">>>>> L%d/%d\n", font, c & 0x3f); X } X else X switch (c & 0x3f) { X case 19: X pstr = "\\320"; X break; /* \- */ X case 20: X pstr = "\\256"; X break; /* fi */ X case 21: X pstr = "\\257"; X break; /* fl */ X case 22: X pstr = "ff"; X break; /* ff */ X case 23: X pstr = "\\242"; X break; /* cent */ X case 24: X pstr = "f\\257"; X break; /* ffl */ X case 25: X pstr = "f\\256"; X break; /* ffi */ X case 30: X fontps(3, size, "\\260"); X break; /* degree */ X case 31: X pstr = "\\262"; X break; /* dagger */ X case 33: X fontps(3, size, "\\322"); X break; /* reg */ X case 38: X pstr = "\\267"; X break; /* bullet */ X case 40: X fontps(3, size, "\\242"); X break; /* footmark */ X case 43: X fontps(3, size, "\\323"); X break; /* c'right */ X case 44: X pstr = "\\250"; X break; /* square ? */ X default: X fprintf(stderr, ">>>>> U%d/%d\n", font, c & 0x3f); X } X else if (fh == 0) X switch (c & 0x3f) { X case 18: X fontps(0, size, "@"); X break; /* @ */ X case 19: X pstr = "\\257"; X break; /* down arrow */ X case 22: X pstr = cstr('|'); X break; /* OR */ X case 24: X fontps(0, size, "\""); X break; /* " */ X case 28: X pstr = "\\254"; X break; /* <- */ X case 30: X pstr = "\\255"; X break; /* up arrow */ X case 33: X fontps(0, size, "\\\\"); X break; /* Backslash ! */ X case 35: X illegal("Bell Logo"); X break; /* Bell Logo */ X case 36: X pstr = "\\245"; X break; /* infinity */ X case 38: X pstr = "\\312"; X break; /* impr. super */ X case 39: X pstr = "\\265"; X break; /* proportional */ X case 40: X pstr = "\\336"; X break; /* right hand */ X case 43: X pstr = "\\321"; X break; /* grad */ X case 48: X pstr = "\\310"; X break; /* union */ X case 49: X pstr = "\\140"; X break; /* sqrtroof */ X case 54: X pstr = "\\362"; X break; /* integral */ X case 56: X pstr = "\\314"; X break; /* subset */ X case 57: X pstr = "\\311"; X break; /* superset */ X case 58: X pstr = cstr('~'); X break; /* approximate */ X case 59: X pstr = "\\256"; X break; /* partial */ X case 61: X pstr = "\\326"; X break; /* sqrt */ X case 63: X pstr = "\\273"; X break; /* ~= */ X default: X fprintf(stderr, ">>>>> L%d/%d\n", font, c & 0x3f); X } X else X switch (c & 0x3f) { X case 5: X pstr = "\\307"; X break; /* intersect */ X case 7: X pstr = "\\330"; X break; /* not */ X case 8: X pstr = "\\371"; X break; /* righceil, sq */ X case 9: X pstr = "\\354"; X break; /* leftop, curly */ X case 10: X pstr = "\\357"; X break; /* bold vertical */ X case 11: X pstr = "\\355"; X break; /* lefcent, curly */ X case 12: X pstr = "\\356"; X break; /* leftbot, curly */ X case 13: X pstr = "\\374"; X break; /* rightop, curly */ X case 14: X pstr = "\\375"; X break; /* righcen, curly */ X case 15: X pstr = "\\376"; X break; /* rightbot, curly */ X case 16: X pstr = "\\373"; X break; /* rigfloor, sq */ X case 17: X pstr = "\\353"; X break; /* lefloor, sq */ X case 18: X pstr = "\\351"; X break; /* leftceil, sq */ X case 19: X pstr = "\\264"; X break; /* times */ X case 20: X pstr = "\\270"; X break; /* divide */ X case 21: X pstr = "\\261"; X break; /* +- */ X case 22: X pstr = "\\243"; X break; /* <= */ X case 23: X pstr = "\\263"; X break; /* >= */ X case 24: X pstr = "\\272"; X break; /* ident. equ */ X case 25: X pstr = "\\271"; X break; /* != */ X case 28: X fontps(0, size, "\\302"); X break; /* acute */ X case 29: X fontps(0, size, "\\301"); X break; /* grave */ X case 30: X fontps(0, size, "^"); X break; /* ^ */ X case 32: X pstr = "\\334"; X break; /* left hand */ X case 33: X pstr = "\\316"; X break; /* Member of */ X case 35: X pstr = "\\306"; X break; /* Empty set */ X case 37: X fontps(0, size, "\\263"); X break; /* doubdagg */ X case 38: X pstr = "\\275"; X break; /* box vertical */ X case 40: X pstr = "\\315"; X break; /* impr. subset */ X case 41: X illegal("circle"); X break; /* circle */ X case 44: X pstr = "\\256"; X break; /* -> */ X case 45: X fontps(0, size, "\\247"); X break; /* section */ X default: X fprintf(stderr, ">>>>> U%d/%d\n", font, c & 0x3f); X } X } X else { X switch (table[(font % 4) == 3][fh][c & 0x3f]) { X case '(': X pstr = "\\("; X break; X case ')': X pstr = "\\)"; X break; X default: X pstr = cstr(table[(font % 4) == 3][fh][c & 0x3f]); X break; X } X } X tprint(); X } X } X else if ((c & 0xf0) == 0x50) { X switch (c & 0x0f) { X case 0: X size = 7; X break; X case 1: X size = 8; X break; X case 2: X size = 10; X break; X case 3: X size = 11; X break; X case 4: X size = 12; X break; X case 5: X size = 14; X break; X case 6: X size = 18; X break; X case 7: X size = 9; X break; X case 8: X size = 6; X break; X case 9: X size = 16; X break; X case 10: X size = 20; X break; X case 11: X size = 22; X break; X case 12: X size = 24; X break; X case 13: X size = 28; X break; X case 14: X size = 36; X break; X default: X fprintf(stderr, "Size: %x\n", c & 0x0f); X } X crsize(csize, size); X tsize = size; X } X else if ((c & 0xf0) == 0x40) { X c &= 0xf; X switch (c) { X case 0:/* fprintf(stderr,"INIT\n"); */ X break; X case 1: X font &= 30; X break; X case 2: X font |= 1; X break; X case 3: X font |= 2; X break; X case 4: X font &= 29; X break; X case 5: X fh = 0; X break; X case 6: X fh = 1; X break; X case 7: X esc = 1; X break; X case 8: X esc = -1; X break; X case 9:/* fprintf(stderr,"STOP\n"); */ X break; X case 10: X lead = 1; X break; X case 12: X lead = -1; X break; X case 14: X font |= 4; X break; X case 15: X font &= 27; X break; X default: X fprintf(stderr, "ILLEGAL\n"); X break; X } X tfont = font; X } X } X if (sflag) X endpage(); X} X tprint() X{ X if (font != cfont || size != csize) { X printf("%d ", size * 6); X switch (font) { X case 0: X printf("TR"); X break; X case 1: X printf("TI"); X break; X case 2: X printf("TB"); X break; X case 3: X printf("S"); X break; X case 8: X printf("H"); X break; X case 9: X printf("HO"); X break; X case 10: X printf("HB"); X break; X case 11: X printf("S"); X break; X case 16: X printf("C"); X break; X case 17: X printf("CO"); X break; X case 18: X printf("CB"); X break; X case 19: X printf("S"); X break; X case 24: X printf("TBI"); X break; X case 25: X printf("HBO"); X break; X case 26: X printf("CBO"); X break; X case 27: X printf("S"); X break; X default: X fprintf(stderr, "Illegal Font %d\n", font); X } X printf(" F\n"); X cfont = font; X csize = size; X } X if (ypos == cy) X printf("(%s)%d X\n", pstr, xpos); X else X printf("(%s)%d %d P\n", pstr, xpos, 3 * ypos); X cx = xpos; X cy = ypos; X} X fontps(f1, ps, str) char *str; X{ X tfont = cfont; X tsize = csize; X pstr = str; X size = ps; X font = f1; X} X illegal(s) char *s; X{ X fprintf(stderr, "Sequence %s is not allowed\n", s); X} X crsize(old, new) X{ X if ((old == 16 || old >= 20) && (new != 16 && new < 20)) X xpos += 55; X else if ((new == 16 || new >= 20) && (old != 16 && old < 20)) X xpos -= 55; X} X char * cstr(c) char c; X{ X static char s[2] = " "; X X *s = c; X return s; X} X newpage() X{ X printf("save\n"); X} X prolog() X{ X printf("/P {moveto show} def\n"); X printf("/X {currentpoint exch pop moveto show} def\n"); X printf("/F {findfont exch scalefont setfont} def\n"); X printf("/TR /Times-Roman def\n"); X printf("/TI /Times-Italic def\n"); X printf("/TB /Times-Bold def\n"); X printf("/S /Symbol def\n"); X printf("/H /Helvetica def\n"); X printf("/HO /Helvetica-Oblique def\n"); X printf("/HB /Helvetica-Bold def\n"); X printf("/C /Courier def\n"); X printf("/CO /Courier-Oblique def\n"); X printf("/CB /Courier-Bold def\n"); X printf("/TBI /Times-BoldItalic def\n"); X printf("/HBO /Helvetica-BoldOblique def\n"); X printf("/CBO /Courier-BoldOblique def\n"); X printf("1 6 div dup scale\n"); X} X endpage() X{ X printf("showpage\n"); X printf("restore\n"); X cfont = csize = -1; /* Doing this will cause a new font message */ X} END_OF_FILE if test 10227 -ne `wc -c <'thack.c'`; then echo shar: \"'thack.c'\" unpacked with wrong size! fi # end of 'thack.c' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. 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