[net.sources.mac] "write2troff" upgraded for MacWrite v4

info-mac@uw-beaver (05/23/85)

From: van@lbl-rtsg.arpa

I've changed write2troff to handle MacWrite 3.x/4.x documents.
Attached is a "shar" archive of the new version.  This version has
been sporadically tested with most versions of MacWrite from 3.96
onwards & seems to work.  I've been told that it does strange things
with files produced by MacWrite 3.17 but, lacking my own copy of
this antique, I've been unable to verify or remedy the problems.

As always, please send bug reports, fixes, comments, etc., to me
(van@lbl-rtsg.arpa).

 - Van Jacobson, Lawrence Berkeley Lab

#! /bin/sh
#---------------------------->Cut Here<---------------------------
# This is a shell archive.  To extract the files, save the 
# following text to a seperate file and type "sh filename" 
#
# Run this through sh, NOT csh! 
#
echo x - README '	' '-rw-r--r--  1 van           801 May 21 20:13 README'
sed 's/^X//' > README << 'EOF'
Xw2t (MacWrite to troff converter for Unix)
X
XThis is a new version of w2t (a.k.a. write2troff) that will handle
XMacWrite 3.x/4.x format files.  There have been a few bug fixes but
Xno significant changes other than the new MacWrite support.
X
XThe files included are:
X  w2t.c		- converter for MW v4
X  macwrite.h	- structs giving format of MW v4 document
X  oldw2t.c	- converter for MW v2
X  oldmacwrite.h	- structs giving format of MW v2 document
X  w2t.1		- Manual entry for write2troff
X  Makefile	- makefile for w2t & oldw2t
X
XAll of the above files are Copyright (c) 1984, 1985 by Michael Caplinger
Xand Van Jacobson.  They may be freely redistributed & modified provided
X  a) this copyright notice is retained, unmodified, in all copies & all
X     derivatives.
X  b) they are not redistributed for profit.
X
'EOF'
echo -n '		 ' ; ls -l README
echo x - Makefile '	' '-rw-r--r--  1 van           709 May 21 20:22 Makefile'
sed 's/^X//' > Makefile << 'EOF'
X# Makefile for w2t (MacWrite to troff converter)
X
X# The symbol OLDMACWRITE gets you a klugy way of handling old (v2) format
X# MacWrite files.  Define this symbol as the full pathname of the 'oldw2t'
X# program & w2t will exec oldw2t if it encounters a v2 format input file.
X# If you don't define OLDMACWRITE (i.e., delete everything after the equal
X# sign on the OLDMACWRITE=... line), w2t will simply complain if it is
X# given a v2 format input file.
X 
XOLDMACWRITE= -DOLDMACWRITE='"oldw2t"'
XCFLAGS= -O $(OLDMACWRITE)
X
Xall:	w2t oldw2t
X
Xw2t:	w2t.o
X	cc $(CFLAGS) -o w2t w2t.o
X
Xw2t.o:	macwrite.h
X
Xoldw2t:	oldw2t.o
X	cc $(CFLAGS) -o oldw2t oldw2t.o
X
Xoldw2t.o: oldmacwrite.h
X
Xclean:
X	rm -f w2t oldw2t w2t.o oldw2t.o
'EOF'
echo -n '		 ' ; ls -l Makefile
echo x - macwrite.h '	' '-rw-r--r--  1 van          2194 May 21 19:53 macwrite.h'
sed 's/^X//' > macwrite.h << 'EOF'
X/* MacWrite v3.x/4.x Document Format
X *
X * copyright (c) 1985 by Van Jacobson, Lawrence Berkeley Lab
X */
Xtypedef unsigned char byte;
X
X/* Global information about the document (starts at byte 0) */
X
Xstruct MWGlobals {
X    short	versionNumber;	/* =6 for MW 3/4 */
X#define	MW_VERSION 6
X#define OLD_MW_VERSION 3
X    short	paraCount;
X    short	headerParaCount;
X    short	footerParaCount;
X};
X
X#define	TEXT_PAR_INFO	0x108L	/* addr of long that points to text par desc */
X#define	HDR_PAR_INFO	0xDAL	/* addr of long that points to hdr par desc */
X#define	FOOT_PAR_INFO	0xACL	/* addr of long that points to foot par desc */
X
X/* structure of a paragraph descriptor.  16 bytes / paragraph */
X
Xstruct infoArrayElem {
X    short	paraHeight;
X    short	position;
X    short	pageNum; /* 0-based */
X    short	type;		/* (set by w2t: derived from paraHeight) */
X    off_t	dataPtr;
X    short	parBytes;
X    byte	parFlags;	/* moved (from high byte of dataPtr) by w2t */
X#define	PF_LOCALJUST	0x40	/* if par has its own justification */
X#define	PF_COMPRESSED	0x08	/* if text par is compressed */
X    byte	filler;
X};
X
X
X/* paragraph types */
X#define RULERPARA 0
X#define TEXTPARA 1
X#define PICTUREPARA 2
X
X/*
X * On the even word boundary following paragraph text there is
X * a word for the format run length.  Each format consists of six bytes:
X*/
X
Xstruct format {
X    short charPos;
X    byte pointSize;
X    byte style;
X    byte unused;
X    byte fontNumber;
X};
X
X
X/* Data format for a "ruler" paragraph */
X
Xstruct ruler {
X    short leftMargin;
X    short rightMargin;
X    byte justify;
X    byte numTabs;
X    byte flags;
X#define	RF_6LPI	0x80	/* set for 6 lpi, clear for ?? */
X    byte spacing;
X    short paraIndent;
X    short tabs[12];
X};
X
X#define LEFTJUST 0
X#define CENTERJUST 1
X#define RIGHTJUST 2
X#define BOTHJUST 3
X
X#define SINGLESPACE 0
X#define DOUBLESPACE 1
X#define TRIPLESPACE 2
X
X/* bits for text styles */
X#define BOLD 0x1
X#define ITALIC 0x2
X#define	UNDERLINE 0x4
X#define	OUTLINE 0x8
X#define	SHADOW 0x10
X#define RAISE 0x20
X#define LOWER 0x40
X
X
X/* the following should really be taken from the document's resource file
X * but that's a LOT of work so we just wire it in...
X */
X#define	COMPRESSION_STRING " etnroaisdlhcfp"
'EOF'
echo -n '		 ' ; ls -l macwrite.h
echo x - oldmacwrite.h '	' '-rw-r--r--  1 van          2142 May 21 19:53 oldmacwrite.h'
sed 's/^X//' > oldmacwrite.h << 'EOF'
Xtypedef unsigned char byte;
X
Xstruct global { /* should be 140 bytes */
X    short versionNumber;
X    short paraOffset;
X    short paraCount;
X    short headerParaCount;
X    short footerParaCount;
X    byte titlePage;
X    byte scrapShow;
X    byte footerDisplayed;
X    byte headerDisplayed;
X    byte rulersShowing;
X    byte spare;
X    short activeDoc; /* 0 = main, 1 = header, 2 = footer */
X    short startPageNum;
X    byte printingVars[120]; /* ??? */
X};
X
X#define MAINDOC 0
X#define HEADERDOC 1
X#define FOOTERDOC 2
X
Xstruct endpoint {
X    short paraNumber;
X    short charPos;
X};
X
Xstruct position {
X    short vert;
X    short hor;
X};
X
Xstruct document { /* should be 34 bytes */
X    struct endpoint start;
X    struct endpoint end;
X    short vertOffset; /* always <= 0 */
X    short needToRedraw;
X    struct position pageNumberPos;
X    struct position datePos;
X    struct position timePos;
X    struct position timeStringPos;
X    byte iconRedraw;
X    byte iconFlag;
X    short activeFont;
X    short activeStyle;
X};
X
Xstruct infoArrayElem { /* should be 8 bytes */
X    short paraHeight;
X    short position;
X    byte pageNum; /* 0-based */
X    byte unused[3];
X};
X
X/*
X    paragraph data
X*/
X
Xstruct paraHeader {
X    short type; /* 0=ruler, 1=text, 2=picture */
X    short dataLength;
X};
X
X#define RULERPARA 0
X#define TEXTPARA 1
X#define PICTUREPARA 2
X
Xstruct textHeader {
X    short textLength;
X};
X
X/*
X    ASCII data follows.  On the even word boundary following text there is
X    a word for the format run length.  Each format consists of six bytes:
X*/
X
Xstruct format {
X    short charPos;
X    byte pointSize;
X    byte style;
X    byte unused;
X    byte fontNumber;
X};
X
Xstruct ruler {
X    short leftMargin;
X    short rightMargin;
X    byte justify;
X    byte numTabs;
X    byte filler; /* ??? */
X    byte spacing;
X    short paraIndent;
X    short tabs[12];
X};
X
X#define LEFTJUST 0
X#define CENTERJUST 1
X#define RIGHTJUST 2
X#define BOTHJUST 3
X
X#define SINGLESPACE 0
X#define DOUBLESPACE 1
X#define TRIPLESPACE 2
X
X/* bits for text styles */
X#define BOLD 0x1
X#define ITALIC 0x2
X#define	UNDERLINE 0x4
X#define	OUTLINE 0x8
X#define	SHADOW 0x10
X#define RAISE 0x20
X#define LOWER 0x40
'EOF'
echo -n '		 ' ; ls -l oldmacwrite.h
echo x - oldw2t.c '	' '-rw-r--r--  1 van         17313 May 21 19:53 oldw2t.c'
sed 's/^X//' > oldw2t.c << 'EOF'
X/*
X    MacWrite to troff input converter for MacWrite 2.0 documents
X    (i.e., the "old" MacWrite).
X
X    version 0.1, Michael Caplinger (mike@rice.arpa), October 1984.
X    version 0.2-4, Van Jacobson (van@lbl-rtsg.arpa), Dec 84
X		added byte swap routines for Vax, added translations
X		for most of Mac's extended characters, added pass-
X		through for tables & equations, changed font cmds
X		from R-I-B-S form to 1-2-3-4 form to allow font
X		changing with ditroff, corrected a couple of minor
X		glitches, add "-p" flag to output space for pictures.
X    version 0.5, vj, Jan 7, 85.  Made text between .PS/.PE be treated
X		like tbl text.
X*/
X
X/*
X    copyright (c) 1984, Michael Caplinger.
X    May be freely redistributed, but this comment must remain in the
X    program or any derivative.
X*/
X
X#define VERSION "0.5"
X
X#include <stdio.h>
X#include "oldmacwrite.h"
X
Xunsigned short ntohs();
X#define SWAP(s) (s)=ntohs(s);
X
X/* Current Document Context */
Xint curPoint = 12;
Xint curStyle = 0;
Xint curFont;
Xint curJust = -1;
Xint curRight = -1;
Xint curLeft = -1;
Xint curSpacing = -1;
Xfloat curIndent = -1.;
Xfloat curLinelength = -1.0;
Xfloat curParIndent = -1.;
X
X/* Program Option Flags */
Xint verbose = 0;
Xint wrap = 1;
Xint pflag = 0;
Xint basePoint = 2;
Xint raw = 0;
X
Xmain(argc, argv)
Xchar **argv;
X{
X    int f;
X
X    setFlags(argc, argv);
X    argv++;
X    while(*argv) {
X    	if(argv[0][0] != '-') {
X	    f = open(argv[0], 0);
X	    if(f >= 0) processFile(f);
X	}
X	argv++;
X    }
X}
X
XprocessFile(f)
Xint f;
X{
X    struct global global;
X    struct document text, header, footer;
X    struct infoArrayElem *textInfo, *headerInfo, *footerInfo;
X    char *data;
X    struct textHeader *textHeader;
X    struct paraHeader paraHeader;
X    short formatRunLength;
X    char *cp;
X    int i, j, k, col;
X    struct format *fp, *startfp, *endfp;
X    struct ruler *ruler;
X    int needSpace = 0;
X    int skipBlanks = 0;
X    int lastWasFormat = 0;
X    int doingTable = 0;
X
X    read(f, &global, 140);
X    SWAP(global.versionNumber)
X    SWAP(global.paraOffset)
X    SWAP(global.paraCount)
X    SWAP(global.headerParaCount)
X    SWAP(global.footerParaCount)
X    SWAP(global.activeDoc)
X    SWAP(global.startPageNum)
X    read(f, &text, 34);
X    read(f, &header, 34);
X    read(f, &footer, 34);
X    debug("version %d\n", global.versionNumber);
X    debug("%d paragraphs in main text\n", global.paraCount);
X    
X    textInfo = (struct infoArrayElem *) malloc(global.paraCount * 8);
X    headerInfo = (struct infoArrayElem *) malloc(global.headerParaCount * 8);
X    footerInfo = (struct infoArrayElem *) malloc(global.footerParaCount * 8);
X    read(f, textInfo, global.paraCount * 8);
X    for(j=0; j<global.paraCount; j++) {
X	SWAP(textInfo[j].paraHeight)
X	SWAP(textInfo[j].position)
X    }
X    read(f, headerInfo, global.headerParaCount * 8);
X    for(j=0; j<global.headerParaCount; j++) {
X	SWAP(headerInfo[j].paraHeight)
X	SWAP(headerInfo[j].position)
X    }
X    read(f, footerInfo, global.footerParaCount * 8);
X    for(j=0; j<global.footerParaCount; j++) {
X	SWAP(footerInfo[j].paraHeight)
X	SWAP(footerInfo[j].position)
X    }
X
X    doPrelude();
X    for(j = 0; j < global.paraCount; j++) {
X	read(f, &paraHeader, 4);
X	SWAP(paraHeader.type)
X	SWAP(paraHeader.dataLength)
X	debug("type %d paragraph\n", paraHeader.type);
X	debug("%d bytes in paragraph data\n", paraHeader.dataLength);
X	data = (char *) malloc(paraHeader.dataLength);
X	read(f, data, paraHeader.dataLength);
X	debug("height %d, position %d, page #%d\n", textInfo[j].paraHeight,
X	    textInfo[j].position, textInfo[j].pageNum);
X	switch(paraHeader.type) {
X	    case TEXTPARA:
X		textHeader = (struct textHeader *) data;
X		SWAP(textHeader->textLength)
X		debug("%d bytes of text\n", textHeader->textLength);
X		/* check for a null or empty paragraph */
X		cp = data + 2;
X		while( *cp == ' ' || *cp == '\t' )
X		    cp++;
X		if( *cp  == '\r' ) {
X		    /* null paragraph */
X		    needSpace++;
X		    break;
X		}
X	        if(needSpace && !raw) {
X		    if( needSpace > 1 )
X			printf(".sp %d\n", needSpace);
X		    else
X			printf(".sp\n");
X		    needSpace = 0;
X		}
X		cp = data + 2 + textHeader->textLength;
X		if((int) cp & 0x1) cp++; /* even byte boundary */
X		formatRunLength = ntohs(*(short *)cp);
X		formatRunLength /= 6;
X		debug("%d format items\n", formatRunLength);
X		startfp = (struct format *) (cp + 2);
X		SWAP(startfp->charPos)
X		fp = startfp;
X		for(k = 0; k < formatRunLength; k++) {
X		    SWAP(fp->charPos)
X		    debug("pos %d, pointsize %d, style 0x%0x, font %d\n",
X			fp->charPos, fp->pointSize, fp->style, fp->fontNumber);
X		    fp++;
X		}
X		cp = data + 2;
X		fp = startfp;
X		endfp = fp + (formatRunLength - 1);
X		if (*cp == '.') {
X		    lastWasFormat = 1;
X		    if ( (cp[1] == 'T' && cp[2] == 'S') ||
X		         (cp[1] == 'P' && cp[2] == 'S') ||
X		         (cp[1] == 'E' && cp[2] == 'Q') )
X			doingTable = 1;
X		    else if ( (cp[1] == 'T' && cp[2] == 'E') ||
X			      (cp[1] == 'P' && cp[2] == 'E') ||
X			      (cp[1] == 'E' && cp[2] == 'N') )
X			doingTable = 0;
X		}
X		else {
X		    if ( !lastWasFormat && !doingTable) {
X		        printf(".pp\n");
X		    }
X		    lastWasFormat = 0;
X		}
X
X		/* delete any trailing whitespace */
X		i = textHeader->textLength - 1;
X		while( cp[i] == ' ' || cp[i] == '\t' )
X		    i--;
X		textHeader->textLength = i;
X
X		col = 0;
X		for(i = 0; i < textHeader->textLength; i++) {
X		    if(i == fp->charPos) {
X			col += doFormat(fp,i);
X			if(fp != endfp) fp++;
X		    }
X		    if(wrap && *cp == ' ' && col > 65) {
X			skipBlanks = 1;
X			putchar('\n');
X			col = -1;
X			cp++;
X			continue;
X		    }
X		    if(skipBlanks && *cp == ' ')
X			;
X		    else {
X			col += putcharExtended(*cp);
X			skipBlanks = 0;
X		    }
X		    cp++;
X		}
X		/* since we deleted trailing blanks & the final
X		 * \r, we're guaranteed that we need a newline.
X		 * But first reset the style since we will get
X		 * a ".pp" before any text & -me will reset the
X		 * style on the .pp.
X		 */
X		setStyle( 0 );
X		putchar( '\n' );
X		break;
X
X	    case RULERPARA:
X		ruler = (struct ruler *) data;
X		SWAP(ruler->leftMargin)
X		SWAP(ruler->rightMargin)
X		SWAP(ruler->paraIndent)
X		for(i=0; i<ruler->numTabs; i++) {
X		    SWAP(ruler->tabs[i])
X		}
X		debug("leftMargin %d, right %d\n", 
X		    ruler->leftMargin, ruler->rightMargin);
X		debug("just %d, %d tabs, paraIndent %d\n",
X		    ruler->justify, ruler->numTabs, ruler->paraIndent);
X		doRuler(ruler);
X		break;
X
X	    case PICTUREPARA:
X		if ( pflag ) {
X		    printf(".sv %.1fi\n",
X		           -textInfo[j].paraHeight/80. );
X		}
X		break;
X	} /* switch */
X	free(data);
X    } /* for */
X    free(textInfo);
X    free(headerInfo);
X    free(footerInfo);
X}
X
XdoFormat(fp, inParagraph)
Xstruct format *fp;
X{
X    if(fp->pointSize != curPoint) {
X	if(!raw) {
X	    if ( inParagraph )
X		printf( "\\s%d\\&", fp->pointSize - basePoint);
X	    else {
X		printf(".sz %d\n", fp->pointSize - basePoint);
X		printf(".nr pp %d\n", fp->pointSize - basePoint);
X	    }
X	}
X	curPoint = fp->pointSize;
X    }
X    setStyle( fp->style );
X
X    /* this should be the number of chars taken up by the format
X    string, but I'm lazy. */
X    return 4;
X}
X
XsetStyle( style )
X{
X    static int isRaised = 0;
X    static int isLowered = 0;
X    int font;
X
X    if ( style != curStyle ) {
X
X	font = style & (BOLD|SHADOW|ITALIC|UNDERLINE);
X	if( font != (curStyle & (BOLD|SHADOW|ITALIC|UNDERLINE)) ) {
X	    if(font & (ITALIC|UNDERLINE))
X		printf("\\f2");
X	    else if(font & (BOLD|SHADOW))
X		printf("\\f3");
X	    else
X		printf("\\f1");
X	}
X
X	if(style & RAISE) {
X	    printf("\\u");
X	    isRaised = 1;
X	} else if(isRaised) {
X	    printf("\\d");
X	    isRaised = 0;
X	}
X	if(style & LOWER) {
X	    printf("\\d");
X	    isLowered = 1;
X	} else if(isLowered) {
X	    printf("\\u");
X	    isLowered = 0;
X	}
X	curStyle = style;
X    }
X}
X
Xdebug(f, a1, a2, a3, a4, a5, a6, a7, a8, a9)
Xchar *f;
X{
X    if(verbose) fprintf(stdout, f, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X}
X
XsetFlags(argc, argv)
Xchar **argv;
X{
X
X    if(argc == 1) {
X    	printf("usage: %s [-r] [-p] [-d] [-w] [-s<pointadj>] files...\n", argv[0]);
X	exit(1);
X    }
X    while(*argv) {
X	if(argv[0][0] == '-') {
X	    switch(argv[0][1]) {
X		case 'd':
X		    verbose = 1;
X		    break;
X		case 'p':
X		    pflag = 1;
X		    break;
X		case 'w':
X		    wrap = 0;
X		    break;
X		case 's':
X		    basePoint = atoi(*argv + 2);
X		    break;
X		case 'r':
X		    raw = 1;
X		    break;
X	    }
X	}
X	argv++;
X    }
X}
X
XdoRuler(ruler)
Xstruct ruler *ruler;
X{
X    int i;
X
X    if(curJust != ruler->justify) {
X    	curJust = ruler->justify;
X	printf(".br\n"); /* need to put out a break or the last bit of text
X			    gets munged into the new formatting rules. */
X	switch(curJust) {
X	    case LEFTJUST:
X		printf(".ad l\n");
X		break;
X	    case CENTERJUST:
X		printf(".ad c\n");
X		break;
X	    case RIGHTJUST:
X		printf(".ad r\n");
X		break;
X	    case BOTHJUST:
X		printf(".ad b\n");
X		break;
X	}
X    }
X    if ( curSpacing != ruler->spacing ) {
X	curSpacing = ruler->spacing;
X	printf( ".vs %dp\n", (curSpacing+2)*(curPoint - basePoint + 4 )/2 );
X	printf( ".nr $r \\n(.v/\\n(.s\n" ); /* isn't -me wonderful? */
X    }
X    if(curLeft != ruler->leftMargin || curRight != ruler->rightMargin) {
X    	curLeft = ruler->leftMargin;
X	curRight = ruler->rightMargin;
X	/* set indent and line length */
X	if ( curIndent != curLeft / 80. ) {
X	    curIndent = curLeft / 80.;
X	    printf(".ba %.1fi\n", curIndent);
X	    printf(".nr $i %.1fi\n", curIndent);
X	}
X	if ( curLinelength != curRight / 80. ) {
X	    curLinelength = curRight / 80.;
X	    printf(".ll %.1fi\n", curLinelength);
X	}
X	if ( curParIndent != (ruler->paraIndent / 80. - curIndent) ) {
X	    curParIndent = ruler->paraIndent / 80. - curIndent;
X	    printf(".nr pi %.1fi\n", curParIndent );
X	}
X    }
X    printf(".ta ");
X    if ( ruler->numTabs <= 0 && curParIndent < 0 )
X	printf("%.1fi", -curParIndent );
X    else
X	for(i = 0; i < ruler->numTabs; i++) {
X	    printf("%.1fi ", ruler->tabs[i] / 10.0 / 8.0);
X	}
X    putchar('\n');
X}
X
X
X/* standard troff prelude */
XdoPrelude() {
X    printf(".\" this file generated by WtoT version %s\n", 
X	VERSION);
X    printf(".po 1i\n");
X    printf(".nr ps 0\n"); /* kill .pp's interpara spacing */
X    printf(".nr pi 0\n");
X#ifdef no
X    printf(".de pp\n"); /* redefine the .pp macro */
X    printf(".br\n.ti \\(pi\n");
X    printf("..\n");
X#endif
X}
X
X/* this table maps the Mac's extended character set into troff
X * characters.  It's set up for the standard Geneva font.  (it
X * should really be selected based on the current font)
X */
Xchar *ctrans[] = {
X	"\\(sq",	/* 0 */
X	"\\(sq",	/* 1 */
X	"\\(sq",	/* 2 */
X	"\\(sq",	/* 3 */
X	"\\(sq",	/* 4 */
X	"\\(sq",	/* 5 */
X	"\\(sq",	/* 6 */
X	"\\(sq",	/* 7 */
X	"\b",		/* 8 */
X	"\t",		/* 9 */
X	"\n",		/* 10 */
X	"\\(sq",	/* 11 */
X	"\f",		/* 12 */
X	"\n",		/* 13 */
X	"\\(sq",	/* 14 */
X	"\\(sq",	/* 15 */
X	"\\(sq",	/* 16 */
X	"\\(sq",	/* 17 */
X	"\\(sq",	/* 18 */
X	"\\(sq",	/* 19 */
X	"\\(sq",	/* 20 */
X	"\\(sq",	/* 21 */
X	"\\(sq",	/* 22 */
X	"\\(sq",	/* 23 */
X	"\\(sq",	/* 24 */
X	"\\(sq",	/* 25 */
X	"\\(sq",	/* 26 */
X	"\\(sq",	/* 27 */
X	"\\(sq",	/* 28 */
X	"\\(sq",	/* 29 */
X	"\\(sq",	/* 30 */
X	"\\(sq",	/* 31 */
X	" ",	/* 32 */
X	"!",	/* 33 */
X	"\"",	/* 34 */
X	"#",	/* 35 */
X	"$",	/* 36 */
X	"%",	/* 37 */
X	"&",	/* 38 */
X	"'",	/* 39 */
X	"(",	/* 40 */
X	")",	/* 41 */
X	"*",	/* 42 */
X	"+",	/* 43 */
X	",",	/* 44 */
X	"-",	/* 45 */
X	".",	/* 46 */
X	"/",	/* 47 */
X	"0",	/* 48 */
X	"1",	/* 49 */
X	"2",	/* 50 */
X	"3",	/* 51 */
X	"4",	/* 52 */
X	"5",	/* 53 */
X	"6",	/* 54 */
X	"7",	/* 55 */
X	"8",	/* 56 */
X	"9",	/* 57 */
X	":",	/* 58 */
X	";",	/* 59 */
X	"<",	/* 60 */
X	"=",	/* 61 */
X	">",	/* 62 */
X	"?",	/* 63 */
X	"@",	/* 64 */
X	"A",	/* 65 */
X	"B",	/* 66 */
X	"C",	/* 67 */
X	"D",	/* 68 */
X	"E",	/* 69 */
X	"F",	/* 70 */
X	"G",	/* 71 */
X	"H",	/* 72 */
X	"I",	/* 73 */
X	"J",	/* 74 */
X	"K",	/* 75 */
X	"L",	/* 76 */
X	"M",	/* 77 */
X	"N",	/* 78 */
X	"O",	/* 79 */
X	"P",	/* 80 */
X	"Q",	/* 81 */
X	"R",	/* 82 */
X	"S",	/* 83 */
X	"T",	/* 84 */
X	"U",	/* 85 */
X	"V",	/* 86 */
X	"W",	/* 87 */
X	"X",	/* 88 */
X	"Y",	/* 89 */
X	"Z",	/* 90 */
X	"[",	/* 91 */
X	"\\",	/* 92 */
X	"]",	/* 93 */
X	"^",	/* 94 -  hat accent */
X	"_",	/* 95 */
X	"\\(aa",	/* 96 -  acute accent */
X	"a",	/* 97 */
X	"b",	/* 98 */
X	"c",	/* 99 */
X	"d",	/* 100 */
X	"e",	/* 101 */
X	"f",	/* 102 */
X	"g",	/* 103 */
X	"h",	/* 104 */
X	"i",	/* 105 */
X	"j",	/* 106 */
X	"k",	/* 107 */
X	"l",	/* 108 */
X	"m",	/* 109 */
X	"n",	/* 110 */
X	"o",	/* 111 */
X	"p",	/* 112 */
X	"q",	/* 113 */
X	"r",	/* 114 */
X	"s",	/* 115 */
X	"t",	/* 116 */
X	"u",	/* 117 */
X	"v",	/* 118 */
X	"w",	/* 119 */
X	"x",	/* 120 */
X	"y",	/* 121 */
X	"z",	/* 122 */
X	"{",	/* 123 */
X	"|",	/* 124 */
X	"}",	/* 125 */
X	"~",		/* 126 -  circumflex accent */
X	"\\(sq",	/* 127 */
X	"\\zA\\v'-1m'.\\h'-0.1m'.\\v'+1m'",	/* 128 -  upper A with omlat */
X	"\\zA\\u\\(de\\d",	/* 129 -  upper circle A (A) */
X	"C",		/* 130 -  upper C with cedilla */
X	"\\o.E'.",	/* 131 -  upper E accent grave */
X	"\\zN\\u~\\d",	/* 132 -  upper N with circumflex */
X	"\\zO\\v'-1m'.\\h'-0.1m'.\\v'+1m'",	/* 133 -  upper O with omlat */
X	"\\zU\\v'-1m'.\\h'-0.1m'.\\v'+1m'",	/* 134 -  upper U with omlat */
X	"\\o.a'.",	/* 135 -  lower a accent grave */
X	"\\o.a`.",	/* 136 -  lower a accent acute */
X	"\\o.a^.",	/* 137 -  lower a with hat */
X	"\\za\\u.\\h'-0.1m'.\\d",	/* 138 -  lower a with omlat */
X	"\\o.a~.",	/* 139 -  lower a with circumflex */
X	"\\o'a\\(de'",	/* 140 -  lower a with circle */
X	"c",		/* 141 -  c with cedilla */
X	"\\o.e'.",	/* 142 -  lower e accent grave */
X	"\\o.e`.",	/* 143 -  lower e accent acute */
X	"\\o.e^.",	/* 144 -  lower e with hat */
X	"\\ze\\u.\\h'-0.1m'.\\d",	/* 145 -  lower e with omlat */
X	"\\o.i'.",	/* 146 -  lower i accent grave */
X	"\\o.i`.",	/* 147 -  lower i accent acute */
X	"\\o.i^.",	/* 148 -  lower i with hat */
X	"\\zi\\u.\\h'-0.1m'.\\d",	/* 149 - lower i with omlat */
X	"\\o.n~.",	/* 150 -  lower n with circumflex */
X	"\\o.o'.",	/* 151 -  lower o accent grave */
X	"\\o.o`.",	/* 152 -  lower o accent acute */
X	"\\o.o^.",	/* 153 -  lower o with hat */
X	"\\zo\\u.\\h'-0.1m'.\\d",	/* 154 -  lower o with omlat */
X	"\\o.o~.",	/* 155 -  lower o with circumflex */
X	"\\o.u'.",	/* 156 -  lower u accent grave */
X	"\\o.u`.",	/* 157 -  lower u accent acute */
X	"\\o.u^.",	/* 158 -  lower u with hat */
X	"\\zu\\u.\\h'-0.1m'.\\d",	/* 159 -  lower u with omlat */
X	"\\(dg",	/* 160 -  dagger */
X	"\\(de",	/* 161 -  degrees (shift option 8) */
X	"\\o'c/'",	/* 162 -  cents */
X	"\\f2\\o'L-'\\fP",	/* 163 -  pounds (currency) */
X	"\\(sc",	/* 164 -  section mark */
X	"\\(bu",	/* 165 -  bullet */
X	"\\(rh",	/* 166 -  paragraph */
X	"\\(*b",	/* 167 -  beta (german "ss") */
X	"\\(rg",	/* 168 -  registered */
X	"\\(co",	/* 169 -  copyright */
X	"\\u\\s-4TM\\s0\\d",	/* 170 -  trademark */
X	"\\(ag",	/* 171 -  grave accent */
X	"\\u.\\h'-0.1m'.\\d",	/* 172 -  oomlat accent */
X	"\\(!=",	/* 173 -  not equal */
X	"\\f2A\\fP\\h'-0.2m'E",		/* 174 -  upper AE ligature */
X	"\\zO/",	/* 175 -  slash upper O (O) */
X	"\\(if",	/* 176 -  infinity */
X	"\\(+-",	/* 177 -  plus minus (shift option =) */
X	"\\(<=",	/* 178 -  <= */
X	"\\(>=",	/* 179 -  >= */
X	"\\o'Y\\s-2=\\s0'",	/* 180 -  yen */
X	"\\(*m",	/* 181 -  lower mu */
X	"\\(pd",	/* 182 -  "partial" */
X	"\\(*S",	/* 183 -  upper sigma */
X	"\\(*P",	/* 184 -  upper PI (P) */
X	"\\(*p",	/* 185 -  lower pi */
X	"\\(is",	/* 186 -  integral sign */
X	"\\u\\za\\(ul\\d'",	/* 187 -  underbar lowercase a */
X	"\\u\\zo\\(ul\\d'",	/* 188 -  underbar lowercase o */
X	"\\(*W",	/* 189 -  upper omega */
X	"a\\h'-0.2m'e",		/* 190 -  lower ae ligature */
X	"\\o'o/'",	/* 191 -  slashed lower o */
X	"?",		/* 192 -  upside down ? (?) */
X	"\\(*i",	/* 193 -  lower case i */
X	"\\(no",	/* 194 -  negation */
X	"\\(sr",	/* 195 -  square root or check mark */
X	"\\z\\(is\\s-2\\(ci\\s0",	/* 196 -  contour integral */
X	"\\(~=",	/* 197 -  approx */
X	"\\(*D",	/* 198 -  triangle (upper delta) */
X	"\\s-2<\\h'-0.3m'<\\s0",	/* 199 -  open double angle brackets */
X	"\\s-2>\\h'-0.3m'>\\s0",	/* 200 -  close double angles */
X	"...",		/* 201 -  elipses (3 dots) */
X	"\\ ",		/* 202 -  unpaddable space */
X	"\\o'`A'",	/* 203 -  `A */
X	"\\o'~A'",	/* 203 -  A with circumflex */
X	"\\o'~O'",	/* 203 -  O with circumflex */
X	"O\\h'-0.1m'E",		/* 206 -  upper OE ligature */
X	"o\\h'-0.1m'e",		/* 207 -  lower oe ligature */
X	"\\(hy",	/* 208 -  hyphen */
X	"\\(em",	/* 209 -  m dash (shift option -) */
X	"``",		/* 210 -  back double quote */
X	"''",		/* 211 -  close double quote */
X	"`",		/* 212 -  back single quote */
X	"'",		/* 213 -  close single quote */
X	"\\(di",	/* 214 -  divide */
X	"\\(gr",	/* 215 -  diamond (V) */
X	"\\zy\\u.\\h'-0.1m'.\\d",	/* 216 -  y with omlat */
X	"\\(sq",	/* 217 */
X	"\\(sq",	/* 218 */
X	"\\(sq",	/* 219 */
X	"\\(sq",	/* 220 */
X	"\\(sq",	/* 221 */
X	"\\(sq",	/* 222 */
X	"\\(sq",	/* 223 */
X	"\\(sq",	/* 224 */
X	"\\(sq",	/* 225 */
X	"\\(sq",	/* 226 */
X	"\\(sq",	/* 227 */
X	"\\(sq",	/* 228 */
X	"\\(sq",	/* 229 */
X	"\\(sq",	/* 230 */
X	"\\(sq",	/* 231 */
X	"\\(sq",	/* 232 */
X	"\\(sq",	/* 233 */
X	"\\(sq",	/* 234 */
X	"\\(sq",	/* 235 */
X	"\\(sq",	/* 236 */
X	"\\(sq",	/* 237 */
X	"\\(sq",	/* 238 */
X	"\\(sq",	/* 239 */
X	"\\(sq",	/* 240 */
X	"\\(sq",	/* 241 */
X	"\\(sq",	/* 242 */
X	"\\(sq",	/* 243 */
X	"\\(sq",	/* 244 */
X	"\\(sq",	/* 245 */
X	"\\(sq",	/* 246 */
X	"\\(sq",	/* 247 */
X	"\\(sq",	/* 248 */
X	"\\(sq",	/* 249 */
X	"\\(sq",	/* 250 -  box (option h) */
X	"\\(sq",	/* 251 -  box (option k) */
X	"\\(sq",	/* 252 */
X	"\\(sq",	/* 253 */
X	"\\(sq",	/* 254 */
X	"\\(sq",	/* 255 */
X	0 };
X
XputcharExtended(c)
Xunsigned char c;
X{
X    printf("%s", ctrans[c]);
X    return( strlen( ctrans[c] ) );
X}
'EOF'
echo -n '		 ' ; ls -l oldw2t.c
echo x - w2t.1 '	' '-rw-r--r--  1 van          3091 May 21 19:53 w2t.1'
sed 's/^X//' > w2t.1 << 'EOF'
X.TH write2troff local
X.SH NAME
Xwrite2troff \- convert MacWrite files to troff input files
X.SH SYNOPSIS
X.B write2troff
X[
X.BI \-s pointsize
X] [
X.B \-p
X] [
X.B \-d
X] [
X.B \-w
X] [
X.B \-r
X]
Xfile ...
X.br
X.SH DESCRIPTION
X.I write2troff
Xreads MacWrite file(s) and produces a
X.I troff
Xinput file.  The input files to
X.I write2troff
Xshould be 
X.B .data
Xfiles as transferred by
X.I macget(1).
X.PP
XBy default, the converted file will contain enough
X.I -me
Xmacro commands to make the troff output `strongly resemble' the MacWrite
Xoutput.  Currently, this means that justification, spacing, tabs,
Xparagraphing, and certain kinds of text attributes will be the same.  See
XBUGS for a list of things that don't work.
X.PP
XThe usual use of
X.I write2troff
Xis expected to be something like:
X.IP
X.I
Xmacget -d - | write2troff | itroff -me
X.PP
X.I Write2troff
Xoptions are:
X.TP
X.B -p
Xsaves space for pictures.  By default, pictures are ignored completely.
XThis option outputs a
X.I `.sv'
X(save space) directive to reserve enough space to hold the picture.
X.TP
X.BI -s pointsize
Xis used to scale the document type sizes.
X.I pointsize
Xis subtracted from all point sizes in the document.  By default, 
X.I pointsize
Xis 2 which will convert documents from 12 point to 10 point.
X.I Pointsize
Xcan be zero (the MacWrite pointsizes will be used) or negative (the MacWrite
Xpointsizes will be scaled up).
X.TP
X.B -r
Xinserts far fewer
X.I troff
Xcommands in the output.  This may be useful when
Xthe Mac is just being used to draft the text prior to a more rigorous
Xformatting.
X.TP
X.B -w
Xturns off intraparagraph wrapping.  A MacWrite paragraph is a single
Xline of text with no newlines.
X.I Write2troff
Xwill wrap these lines at about 72 columns by default.  I have never seen an
Xapplication where this wrapping was undesirable, but...
X.TP
X.B -d
Xintersperses an immense amount of debugging information
Xwith the output on stdout.
X.PP
XSince the table & math abilities of MacWrite are limitted,
X.BR tbl , eqn and pic
Xcommands can be included in the MacWrite document.  I.e., lines
Xbetween .TS/.TE, .EQ/.EN or .PS/.PE will be treated specially.
XOther 
X.I troff
Xdirectives (lines starting with a `.')
Xwill be passed through but may not do what you expect.
X.PP
X.SH "SEE ALSO"
Xmacget(l)
X.SH BUGS
X.PP
XPictures are barely supported (you will need scissors & glue).
X.PP
XHeaders and footers are ignored.
X.PP
XDecimal tabs are not handled correctly.
X.PP
XThe output is heavily
X.I -me
Xmacro dependent.
X.PP
XAll fonts map into troff's Times Roman.
X.PP
XText attributes are not quite right.  Bold, italic, subscript, and
Xsuperscript work.  Underlining maps to italic.  Shadow maps to bold.
XMixed attributes map to either bold or italic.
X.PP
XAll the special characters of the standard Mac Geneva font map into
Xsome (reasonable?) troff character but the mapping is fixed.  Font dependent
Xcharacter conversions (e.g., for the Princeton math font) should be supported.
X.SH AUTHOR
XOriginal version by Michael Caplinger, Rice University (mike@rice.arpa)
X.br
XAdditions & changes for MacWrite v3/4 by Van Jacobson, Lawrence
XBerkeley Laboratory (van@lbl-csam.arpa).
'EOF'
echo -n '		 ' ; ls -l w2t.1
echo x - w2t.c '	' '-rw-r--r--  1 van         22582 May 21 20:25 w2t.c'
sed 's/^X//' > w2t.c << 'EOF'
X/*
X    MacWrite to troff input converter.
X
X    version 0.1, Michael Caplinger (mike@rice.arpa), October 1984.
X    version 0.2-4, Van Jacobson (van@lbl-rtsg.arpa), Dec 84
X		added byte swap routines for Vax, added translations
X		for most of Mac's extended characters, added pass-
X		through for tables & equations, changed font cmds
X		from R-I-B-S form to 1-2-3-4 form to allow font
X		changing with ditroff, corrected a couple of minor
X		glitches, add "-p" flag to output space for pictures.
X    version 0.5, vj, Jan 7, 85.  Made text between .PS/.PE be treated
X		like tbl text.
X    version 1.0, vj, Apr 27, 85.  Massive changes to handle MacWrite
X		4.x format files.
X*/
X
X/*
X    copyright (c) 1984, 1985 by Michael Caplinger and Van Jacobson.
X    May be freely redistributed, but this comment must remain in the
X    program or any derivative.
X*/
X
X#define VERSION "1.1"
X
X#include <stdio.h>
X#include <sys/types.h>
X#include "macwrite.h"
X
Xunsigned short ntohs();
X#define SWAP(s) (s)=ntohs(s);
Xunsigned long ntohl();
X#define SWAPL(s) (s)=ntohl(s);
X
X/*
X * Current Document Context
X * The following are all in terms of the troff output, not the MacWrite
X * input file.  I.e., if the default "-s2" is in effect, 12-point MacWrite
X * text will make curPoint = 10.
X */
Xint curPoint = 10;
Xint curStyle = 0;
Xint curFont = -1;
Xint curJust = -1;
Xint curRight = -1;
Xint curLeft = -1;
Xint curSpacing = -1;
Xint isRaised = 0;
Xint isLowered = 0;
Xfloat curIndent = -1.;
Xfloat curLinelength = -1.0;
Xfloat curParIndent = -1.;
X
X/* Program Option Flags */
Xint verbose = 0;
Xint wrap = 1;
Xint pflag = 0;
Xint basePoint = 2;
Xint raw = 0;
X
Xchar **gargv;		/* orginal 'argv' (in case we have to exec old w2t) */
X
Xstruct	textDesc {	/* descriptor for text par returned by read_text_par */
X    byte	*text;		/* text of par */
X    struct format *formats;	/* formats for text */
X    short	nchars;		/* number of chars of text */
X    short	nformats;	/* number of format desc */
X};
X
Xstruct	textDesc *read_text_par();
X
Xstruct	infoArrayElem *read_par_info();
Xstruct	ruler *read_ruler_par();
X
Xmain(argc, argv)
Xchar **argv;
X{
X    int f;
X    int gotfile = 0;
X
X    gargv = argv;
X    argv++;
X    while(*argv)
X	{
X	if(argv[0][0] == '-')
X	    {
X	    switch(argv[0][1])
X		{
X		case 'd':
X		    verbose = 1;
X		    break;
X		case 'p':
X		    pflag = 1;
X		    break;
X		case 'w':
X		    wrap = 0;
X		    break;
X		case 's':
X		    basePoint = atoi(*argv + 2);
X		    break;
X		case 'r':
X		    raw = 1;
X		    break;
X		default:
X		    printf("usage: %s [-r] [-p] [-d] [-w] [-s<pointadj>] files...\n",
X			    argv[0]);
X		    exit(1);
X		}
X	    }
X	else
X	    {
X	    gotfile++;
X	    f = open(argv[0], 0);
X	    if(f < 0)
X		{
X		perror( argv[0] );
X		exit(1);
X		}
X	    processFile(f);
X	    }
X	argv++;
X    }
X    if ( gotfile == 0 )
X	processFile( 0 );
X}
X
XprocessFile(f)
Xint f;
X{
X    struct MWGlobals global;
X    struct infoArrayElem *textInfo;
X    struct textDesc *td;
X    byte *cp;
X    int i, j, col;
X    struct format *fp;
X    struct ruler *ruler;
X    int needSpace = 0;
X    int skipBlanks = 0;
X    int lastWasFormat = 0;
X    int doingTable = 0;
X
X    read_doc_info( f, &global );
X    textInfo = read_par_info( f, (off_t)TEXT_PAR_INFO, global.paraCount );
X
X    doPrelude();
X    for(j = 0; j < global.paraCount; j++) {
X	debug("height %d, position %d, page #%d\n", textInfo[j].paraHeight,
X	    textInfo[j].position, textInfo[j].pageNum);
X	switch(textInfo[j].type) {
X
X	    case TEXTPARA:
X		td = read_text_par( f, &textInfo[j] );
X		cp = td->text;
X		fp = td->formats;
X
X		/* check for a null or empty paragraph */
X		while( *cp == ' ' || *cp == '\t' )
X		    cp++;
X		if( *cp  == '\r' ) {
X		    /* null paragraph */
X		    needSpace++;
X		    break;
X		}
X	        if(needSpace && !raw) {
X		    if( needSpace > 1 )
X			printf(".sp %d\n", needSpace);
X		    else
X			printf(".sp\n");
X		    needSpace = 0;
X		}
X		if (*cp == '.') {
X		    lastWasFormat = 1;
X		    if ( (cp[1] == 'T' && cp[2] == 'S') ||
X		         (cp[1] == 'P' && cp[2] == 'S') ||
X		         (cp[1] == 'E' && cp[2] == 'Q') )
X			doingTable = 1;
X		    else if ( (cp[1] == 'T' && cp[2] == 'E') ||
X			      (cp[1] == 'P' && cp[2] == 'E') ||
X			      (cp[1] == 'E' && cp[2] == 'N') )
X			doingTable = 0;
X		}
X		else {
X		    if ( !lastWasFormat && !doingTable) {
X		        printf(".pp\n");
X		    }
X		    lastWasFormat = 0;
X		}
X
X		if ( textInfo[j].parFlags & PF_LOCALJUST )
X		    setJust( textInfo[j].parFlags & 0x3 );
X
X		/* delete any trailing whitespace */
X		cp = td->text;
X		i = td->nchars - 1;
X		while( cp[i] == ' ' || cp[i] == '\t' )
X		    i--;
X		td->nchars = i;
X
X		col = 0;
X		for(i = 0; i < td->nchars; i++) {
X		    if(i == fp->charPos) {
X			col += doFormat(fp,i);
X			if(td->nformats > 0)
X			    fp++;
X		    }
X		    /* (the reason for this "else" is to prevent
X		     * a line break immediately following a format
X		     * change.
X		     */
X		    else if(wrap && *cp == ' ' && col > 65) {
X			skipBlanks = 1;
X			putchar('\n');
X			col = -1;
X			cp++;
X			continue;
X		    }
X		    if(skipBlanks && *cp == ' ')
X			;
X		    else {
X			col += putcharExtended(*cp);
X			skipBlanks = 0;
X		    }
X		    cp++;
X		}
X		/* since we deleted trailing blanks & the final
X		 * \r, we're guaranteed that we need a newline.
X		 * But first reset the style since we will get
X		 * a ".pp" before any new text & -me will reset the
X		 * style on the .pp.
X		 */
X		(void) setStyle( 0 );
X		putchar( '\n' );
X
X		if ( textInfo[j].parFlags & PF_LOCALJUST )
X		    setJust( ruler->justify );
X
X		break;
X
X	    case RULERPARA:
X		ruler = read_ruler_par( f, &textInfo[j] );
X		doRuler(ruler);
X		break;
X
X	    case PICTUREPARA:
X		if ( pflag ) {
X		    printf(".sv %.1fi\n",
X		           -textInfo[j].paraHeight/80. );
X		}
X		break;
X	} /* switch */
X    } /* for */
X    free(textInfo);
X}
X
XdoFormat(fp, inParagraph)
Xstruct format *fp;
X{
X    register int size = 0;
X
X    /* if we're doing super- or sub-scripts, change the style before
X     * changing the size (otherwise the vertical motions won't be
X     * calculated correctly).
X     */
X    if( isRaised || isLowered )
X	size = setStyle( fp->style );
X
X    if((fp->pointSize - basePoint) != curPoint)
X	{
X	curPoint = fp->pointSize - basePoint;
X	if(!raw)
X	    {
X	    if ( inParagraph )
X		{
X		size += 5;
X		printf( "\\s%d\\&", curPoint);
X		}
X	    else
X		{
X		printf(".sz %d\n", curPoint);
X		printf(".nr pp %d\n", curPoint);
X		size = 0;
X		}
X	    }
X	}
X
X    size += setStyle( fp->style );
X
X    return size;
X}
X
XsetStyle( style )
X    register byte	style;
X{
X    register int	font;
X    register int	size = 0;
X
X    if ( style != curStyle )
X	{
X	font = style & (BOLD|SHADOW|ITALIC|UNDERLINE);
X	if( font != (curStyle & (BOLD|SHADOW|ITALIC|UNDERLINE)) )
X	    {
X	    size += 3;
X	    if(font & (ITALIC|UNDERLINE))
X		printf("\\f2");
X	    else if(font & (BOLD|SHADOW))
X		printf("\\f3");
X	    else
X		printf("\\f1");
X	    }
X
X	if(style & RAISE)
X	    {
X	    size += 2;
X	    printf("\\u");
X	    isRaised = 1;
X	    }
X	else if(isRaised)
X	    {
X	    size += 2;
X	    printf("\\d");
X	    isRaised = 0;
X	    }
X
X	if(style & LOWER)
X	    {
X	    size += 2;
X	    printf("\\d");
X	    isLowered = 1;
X	    }
X	else if(isLowered)
X	    {
X	    size += 2;
X	    printf("\\u");
X	    isLowered = 0;
X	    }
X
X	curStyle = style;
X	}
X    return( size );
X}
X
XsetJust( justify )
X    byte	justify;
X{
X    justify &= (LEFTJUST|CENTERJUST|RIGHTJUST|BOTHJUST);
X    if(curJust != justify)
X	{
X    	curJust = justify;
X	printf(".br\n"); /* need to put out a break or the last bit of text
X			    gets munged into the new formatting rules. */
X	switch(curJust)
X	    {
X	    case LEFTJUST:
X		printf(".ad l\n");
X		break;
X	    case CENTERJUST:
X		printf(".ad c\n");
X		break;
X	    case RIGHTJUST:
X		printf(".ad r\n");
X		break;
X	    case BOTHJUST:
X		printf(".ad b\n");
X		break;
X	    }
X	}
X}
X
X/*VARARGS1*/
Xdebug(f, a1, a2, a3, a4, a5, a6, a7, a8, a9)
Xchar *f;
X{
X    if(verbose)
X	fprintf(stdout, f, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X}
X
XdoRuler(ruler)
Xstruct ruler *ruler;
X{
X    int i;
X    int	newSpacing,
X	newLeft,
X	newRight,
X	newIndent,
X	newLinelength;
X
X    setJust( ruler->justify );
X
X    /* we use 4 point leading for normal rulers, 1 point leading for "6lpi"
X     * rulers.  The actual spacing is the leading times the ruler's 1/1.5/2
X     * space factor.  Note that the order of evaluation of the following
X     * expression is important (to avoid truncation errors).
X     */
X    newSpacing = ((ruler->flags & RF_6LPI? 1 : 4) * (ruler->spacing + 2)) / 2;
X    if ( curSpacing != newSpacing ) {
X	curSpacing = newSpacing;
X	printf( ".vs %dp\n", curSpacing + curPoint );
X	printf( ".nr r$ %d\n", curSpacing );  /* see comments in doPrelude */
X	printf( ".nr $r \\n(.v/\\n(.s\n" );
X    }
X    if(curLeft != ruler->leftMargin || curRight != ruler->rightMargin) {
X    	curLeft = ruler->leftMargin;
X	curRight = ruler->rightMargin;
X	/* set indent and line length */
X	if ( curIndent != curLeft / 80. ) {
X	    curIndent = curLeft / 80.;
X	    printf(".ba %.1fi\n", curIndent);
X	    printf(".nr $i %.1fi\n", curIndent);
X	}
X	if ( curLinelength != curRight / 80. ) {
X	    curLinelength = curRight / 80.;
X	    printf(".ll %.1fi\n", curLinelength);
X	}
X	if ( curParIndent != (ruler->paraIndent / 80. - curIndent) ) {
X	    curParIndent = ruler->paraIndent / 80. - curIndent;
X	    printf(".nr pi %.1fi\n", curParIndent );
X	}
X    }
X    printf(".ta ");
X    if ( ruler->numTabs == 0 && curParIndent < 0 )
X	printf("%.1fi", -curParIndent );
X    else
X	for(i = 0; i < ruler->numTabs; i++) {
X	    if ( ruler->tabs[i] > 0 )
X		printf("%.1fi ", ruler->tabs[i] / 10.0 / 8.0);
X	    else
X		printf("%.1fiR ", ruler->tabs[i] / 10.0 / 8.0);
X	}
X    putchar('\n');
X}
X
X
X/* standard troff prelude */
XdoPrelude() {
X    printf(".\" this file generated by WtoT version %s\n", 
X	VERSION);
X    printf(".po 1i\n");
X    printf(".nr ps 0\n"); /* kill .pp's interpara spacing */
X    printf(".nr pi 0\n");
X    /*
X     * The -me ".sz" macro is wrong.  We redefine .sz to be
X     * more nearly correct (so we can adjust the vertical spacing
X     * when we see a ruler).  This new macro assumes that the
X     * current leading (in points) is in the register 'r$'.
X     */
X    printf(".de sz\n");
X    printf(".ps \\\\$1\n");
X    printf(".vs \\\\n(.sp+\\\\n(r$p\n");
X    printf(".bd S B \\\\n(.su/3u\n");
X    printf("..\n");
X}
X
X
X/* read the global document description info from file f into "global" */
X
X#define GET(x)	if(read(f, &(x), sizeof(x)) != sizeof(x))\
X		    error("EOF reading document globals");\
X		SWAP(x)
X
Xread_doc_info( f, global )
X    struct MWGlobals *global;
X{
X    GET(global->versionNumber);
X    debug("version %d\n", global->versionNumber);
X    if ( global->versionNumber != MW_VERSION )
X	{
X#ifdef OLDMACWRITE
X	if ( global->versionNumber == OLD_MW_VERSION )
X	    {
X	    if ( f == 0 )
X		error( "can't handle old macwrite file if taking input from stdin.");
X	    close( f );
X	    execvp( OLDMACWRITE, gargv );
X	    perror( OLDMACWRITE );
X	    }
X#endif
X	error( "input file not in MacWrite v4 format" );
X	}
X    GET(global->paraCount)
X    GET(global->headerParaCount)
X    GET(global->footerParaCount)
X    debug("%d paragraphs in main text\n", global->paraCount);
X    debug("%d paragraphs in header text\n", global->headerParaCount);
X    debug("%d paragraphs in footer text\n", global->footerParaCount);
X}
X
X/* read "count" paragraphs worth of paragraph descriptors from file "f"
X * starting at the location *pointed to* by "info_ptr".
X */
Xstruct infoArrayElem *
Xread_par_info( f, info_ptr, count )
X    int		f;
X    off_t	info_ptr;
X    short	count;
X{
X    struct infoArrayElem *textInfo;
X    off_t	info_start;
X    int		i;
X
X    textInfo = (struct infoArrayElem *) malloc(count * sizeof(*textInfo));
X
X    lseek( f, info_ptr, 0 );
X    if ( read( f, &info_start, sizeof(info_start) ) != sizeof(info_start))
X	error( "error reading paragraph desc. pointer" );
X    SWAPL( info_start );
X    info_start &= 0xffffff;
X
X    lseek( f, info_start, 0 );
X    if ( read(f, textInfo, count * sizeof(*textInfo)) != 
X	 (count * sizeof(*textInfo)))
X	error( "error reading paragraph descriptors" );
X    for(i=0; i < count; i++)
X	{
X	SWAP(textInfo[i].paraHeight)
X	SWAP(textInfo[i].position)
X	SWAP(textInfo[i].pageNum)
X	SWAP(textInfo[i].parBytes)
X	SWAPL(textInfo[i].dataPtr)
X	textInfo[i].parFlags = (textInfo[i].dataPtr >> 24) & 0xff;
X	textInfo[i].dataPtr &= 0xffffff;
X	if ( textInfo[i].paraHeight < 0 )
X	    {
X	    textInfo[i].paraHeight = -textInfo[i].paraHeight;
X	    textInfo[i].type = PICTUREPARA;
X	    }
X	else if ( textInfo[i].paraHeight == 0 )
X	    textInfo[i].type = RULERPARA;
X	else
X	    textInfo[i].type = TEXTPARA;
X	}
X    return (textInfo);
X    }
X
X
X/* round a number up to next block "s" boundary (s must be a power
X * of 2)
X */
X#define round(x,s) (((x - 1) & (s - 1)) + s)
X
X
X/* read the text & format info for the text paragraph given by paragraph
X * descriptor "par".
X */
X
Xstruct textDesc *
Xread_text_par( f, par )
X    int		f;
X    struct infoArrayElem *par;
X{
X    register	byte	*cp;
X    register	byte	*fp;
X    register	byte	last;
X    register	byte	c;
X    register	int	top;
X    register	int	i;
X    register	struct format	*formp;
X    short	nchars;
X    short	nformats;
X    static struct textDesc	td;
X    static int	textBufSize = 0;
X    static int	dataBufSize = 0;
X    static byte	*textBuf = NULL;
X    static byte	*dataBuf = NULL;
X
X    /* get enough space for the paragraph data then read the data */
X
X    if ( par->parBytes > dataBufSize )
X	{
X	if ( dataBuf )
X	    free( dataBuf );
X
X	dataBufSize = round( par->parBytes, 1024 );
X	dataBuf = (byte *)malloc( dataBufSize );
X	}
X    
X    lseek( f, par->dataPtr, 0 );
X    if (read( f, dataBuf, par->parBytes ) != par->parBytes)
X	error( "error reading paragraph text" );
X
X    /* if the text is compressed, unpack it into the text buffer */
X
X    nchars = *(short *)dataBuf;
X    SWAP(nchars);
X    td.nchars = nchars;
X
X    if ( par->parFlags & PF_COMPRESSED )
X	{
X	/* get enough space for the paragraph text then unpack the text */
X
X	if ( nchars > textBufSize )
X	    {
X	    if ( textBuf )
X		free( textBuf );
X
X	    textBufSize = round( par->parBytes, 1024 );
X	    textBuf = (byte *)malloc( textBufSize );
X	    }
X	
X	cp = textBuf;
X	fp = dataBuf + 2;
X	top = !0;
X	for ( i = nchars; i-- > 0; )
X	    {
X	    if ( top )
X		{
X		last = *fp++;
X		c = last >> 4;
X		}
X	    else
X		c = last;
X
X	    top = !top;
X	    c &= 0xf;
X	    if ( c != 0xf )
X		*cp++ = COMPRESSION_STRING[c];
X	    else
X		{
X		if ( top )
X		    *cp++ = *fp++;
X		else
X		    {
X		    c = (last & 0xf) << 4;
X		    last = *fp++;
X		    *cp++ = c | ((last >> 4) & 0xf);
X		    }
X		}
X	    }
X	td.text = textBuf;
X	}
X    else  /* not compressed */
X	{
X	td.text = dataBuf + 2;
X	fp = td.text + nchars;
X	}
X
X    /* at this point, fp points to the start
X     * of the format runs (a short giving the number of bytes
X     * of format info).
X     */
X    if ( (int)fp & 1 )
X	fp++;
X
X    nformats = *(short *)fp;
X    SWAP(nformats);
X    formp = (struct format *)(fp + 2);
X    td.formats = formp;
X    td.nformats = nformats / sizeof(*formp);
X
X    for ( i = nformats; i-- > 0; formp++ )
X	SWAP( formp->charPos );
X
X    return &td;
X}
X
Xstruct ruler *
Xread_ruler_par( f, par )
X    struct infoArrayElem *par;
X{
X    static struct ruler ruler;
X    register int i;
X
X    lseek( f, par->dataPtr, 0 );
X    if (read( f, &ruler, sizeof(ruler) ) != sizeof(ruler))
X	error( "error reading ruler info" );
X    SWAP( ruler.leftMargin );
X    SWAP( ruler.rightMargin );
X    SWAP( ruler.paraIndent );
X    for ( i = 0; i < ruler.numTabs; i++ )
X	SWAP( ruler.tabs[i] );
X
X    return &ruler;
X}
X
X
X
X/* this table maps the Mac's extended character set into troff
X * characters.  It's set up for the standard Geneva font.  (it
X * should really be selected based on the current font)
X */
Xchar *ctrans[] = {
X	"\\(sq",	/* 0 */
X	"\\(sq",	/* 1 */
X	"\\(sq",	/* 2 */
X	"\\(sq",	/* 3 */
X	"\\(sq",	/* 4 */
X	"\\(sq",	/* 5 */
X	"\\(sq",	/* 6 */
X	"\\(sq",	/* 7 */
X	"\b",		/* 8 */
X	"\t",		/* 9 */
X	"\n",		/* 10 */
X	"\\(sq",	/* 11 */
X	"\f",		/* 12 */
X	"\n",		/* 13 */
X	"\\(sq",	/* 14 */
X	"\\(sq",	/* 15 */
X	"\\(sq",	/* 16 */
X	"\\(sq",	/* 17 */
X	"\\(sq",	/* 18 */
X	"\\(sq",	/* 19 */
X	"\\(sq",	/* 20 */
X	"\\(sq",	/* 21 */
X	"\\(sq",	/* 22 */
X	"\\(sq",	/* 23 */
X	"\\(sq",	/* 24 */
X	"\\(sq",	/* 25 */
X	"\\(sq",	/* 26 */
X	"\\(sq",	/* 27 */
X	"\\(sq",	/* 28 */
X	"\\(sq",	/* 29 */
X	"\\(sq",	/* 30 */
X	"\\(sq",	/* 31 */
X	" ",	/* 32 */
X	"!",	/* 33 */
X	"\"",	/* 34 */
X	"#",	/* 35 */
X	"$",	/* 36 */
X	"%",	/* 37 */
X	"&",	/* 38 */
X	"'",	/* 39 */
X	"(",	/* 40 */
X	")",	/* 41 */
X	"*",	/* 42 */
X	"+",	/* 43 */
X	",",	/* 44 */
X	"-",	/* 45 */
X	".",	/* 46 */
X	"/",	/* 47 */
X	"0",	/* 48 */
X	"1",	/* 49 */
X	"2",	/* 50 */
X	"3",	/* 51 */
X	"4",	/* 52 */
X	"5",	/* 53 */
X	"6",	/* 54 */
X	"7",	/* 55 */
X	"8",	/* 56 */
X	"9",	/* 57 */
X	":",	/* 58 */
X	";",	/* 59 */
X	"<",	/* 60 */
X	"=",	/* 61 */
X	">",	/* 62 */
X	"?",	/* 63 */
X	"@",	/* 64 */
X	"A",	/* 65 */
X	"B",	/* 66 */
X	"C",	/* 67 */
X	"D",	/* 68 */
X	"E",	/* 69 */
X	"F",	/* 70 */
X	"G",	/* 71 */
X	"H",	/* 72 */
X	"I",	/* 73 */
X	"J",	/* 74 */
X	"K",	/* 75 */
X	"L",	/* 76 */
X	"M",	/* 77 */
X	"N",	/* 78 */
X	"O",	/* 79 */
X	"P",	/* 80 */
X	"Q",	/* 81 */
X	"R",	/* 82 */
X	"S",	/* 83 */
X	"T",	/* 84 */
X	"U",	/* 85 */
X	"V",	/* 86 */
X	"W",	/* 87 */
X	"X",	/* 88 */
X	"Y",	/* 89 */
X	"Z",	/* 90 */
X	"[",	/* 91 */
X	"\\",	/* 92 */
X	"]",	/* 93 */
X	"^",	/* 94 -  hat accent */
X	"_",	/* 95 */
X	"\\(aa",	/* 96 -  acute accent */
X	"a",	/* 97 */
X	"b",	/* 98 */
X	"c",	/* 99 */
X	"d",	/* 100 */
X	"e",	/* 101 */
X	"f",	/* 102 */
X	"g",	/* 103 */
X	"h",	/* 104 */
X	"i",	/* 105 */
X	"j",	/* 106 */
X	"k",	/* 107 */
X	"l",	/* 108 */
X	"m",	/* 109 */
X	"n",	/* 110 */
X	"o",	/* 111 */
X	"p",	/* 112 */
X	"q",	/* 113 */
X	"r",	/* 114 */
X	"s",	/* 115 */
X	"t",	/* 116 */
X	"u",	/* 117 */
X	"v",	/* 118 */
X	"w",	/* 119 */
X	"x",	/* 120 */
X	"y",	/* 121 */
X	"z",	/* 122 */
X	"{",	/* 123 */
X	"|",	/* 124 */
X	"}",	/* 125 */
X	"~",		/* 126 -  circumflex accent */
X	"\\(sq",	/* 127 */
X	"\\zA\\v'-1m'.\\h'-0.1m'.\\v'+1m'",	/* 128 -  upper A with omlat */
X	"\\zA\\u\\(de\\d",	/* 129 -  upper circle A (A) */
X	"C",		/* 130 -  upper C with cedilla */
X	"\\o.E'.",	/* 131 -  upper E accent grave */
X	"\\zN\\u~\\d",	/* 132 -  upper N with circumflex */
X	"\\zO\\v'-1m'.\\h'-0.1m'.\\v'+1m'",	/* 133 -  upper O with omlat */
X	"\\zU\\v'-1m'.\\h'-0.1m'.\\v'+1m'",	/* 134 -  upper U with omlat */
X	"\\o.a'.",	/* 135 -  lower a accent grave */
X	"\\o.a`.",	/* 136 -  lower a accent acute */
X	"\\o.a^.",	/* 137 -  lower a with hat */
X	"\\za\\u.\\h'-0.1m'.\\d",	/* 138 -  lower a with omlat */
X	"\\o.a~.",	/* 139 -  lower a with circumflex */
X	"\\o'a\\(de'",	/* 140 -  lower a with circle */
X	"c",		/* 141 -  c with cedilla */
X	"\\o.e'.",	/* 142 -  lower e accent grave */
X	"\\o.e`.",	/* 143 -  lower e accent acute */
X	"\\o.e^.",	/* 144 -  lower e with hat */
X	"\\ze\\u.\\h'-0.1m'.\\d",	/* 145 -  lower e with omlat */
X	"\\o.i'.",	/* 146 -  lower i accent grave */
X	"\\o.i`.",	/* 147 -  lower i accent acute */
X	"\\o.i^.",	/* 148 -  lower i with hat */
X	"\\zi\\u.\\h'-0.1m'.\\d",	/* 149 - lower i with omlat */
X	"\\o.n~.",	/* 150 -  lower n with circumflex */
X	"\\o.o'.",	/* 151 -  lower o accent grave */
X	"\\o.o`.",	/* 152 -  lower o accent acute */
X	"\\o.o^.",	/* 153 -  lower o with hat */
X	"\\zo\\u.\\h'-0.1m'.\\d",	/* 154 -  lower o with omlat */
X	"\\o.o~.",	/* 155 -  lower o with circumflex */
X	"\\o.u'.",	/* 156 -  lower u accent grave */
X	"\\o.u`.",	/* 157 -  lower u accent acute */
X	"\\o.u^.",	/* 158 -  lower u with hat */
X	"\\zu\\u.\\h'-0.1m'.\\d",	/* 159 -  lower u with omlat */
X	"\\(dg",	/* 160 -  dagger */
X	"\\(de",	/* 161 -  degrees (shift option 8) */
X	"\\o'c/'",	/* 162 -  cents */
X	"\\f2\\o'L-'\\fP",	/* 163 -  pounds (currency) */
X	"\\(sc",	/* 164 -  section mark */
X	"\\(bu",	/* 165 -  bullet */
X	"\\(rh",	/* 166 -  paragraph */
X	"\\(*b",	/* 167 -  beta (german "ss") */
X	"\\(rg",	/* 168 -  registered */
X	"\\(co",	/* 169 -  copyright */
X	"\\u\\s-4TM\\s0\\d",	/* 170 -  trademark */
X	"\\(ag",	/* 171 -  grave accent */
X	"\\u.\\h'-0.1m'.\\d",	/* 172 -  oomlat accent */
X	"\\(!=",	/* 173 -  not equal */
X	"\\f2A\\fP\\h'-0.2m'E",		/* 174 -  upper AE ligature */
X	"\\zO/",	/* 175 -  slash upper O (O) */
X	"\\(if",	/* 176 -  infinity */
X	"\\(+-",	/* 177 -  plus minus (shift option =) */
X	"\\(<=",	/* 178 -  <= */
X	"\\(>=",	/* 179 -  >= */
X	"\\o'Y\\s-2=\\s0'",	/* 180 -  yen */
X	"\\(*m",	/* 181 -  lower mu */
X	"\\(pd",	/* 182 -  "partial" */
X	"\\(*S",	/* 183 -  upper sigma */
X	"\\(*P",	/* 184 -  upper PI (P) */
X	"\\(*p",	/* 185 -  lower pi */
X	"\\(is",	/* 186 -  integral sign */
X	"\\u\\za\\(ul\\d'",	/* 187 -  underbar lowercase a */
X	"\\u\\zo\\(ul\\d'",	/* 188 -  underbar lowercase o */
X	"\\(*W",	/* 189 -  upper omega */
X	"a\\h'-0.2m'e",		/* 190 -  lower ae ligature */
X	"\\o'o/'",	/* 191 -  slashed lower o */
X	"?",		/* 192 -  upside down ? (?) */
X	"\\(*i",	/* 193 -  lower case i */
X	"\\(no",	/* 194 -  negation */
X	"\\(sr",	/* 195 -  square root or check mark */
X	"\\z\\(is\\s-2\\(ci\\s0",	/* 196 -  contour integral */
X	"\\(~=",	/* 197 -  approx */
X	"\\(*D",	/* 198 -  triangle (upper delta) */
X	"\\s-2<\\h'-0.3m'<\\s0",	/* 199 -  open double angle brackets */
X	"\\s-2>\\h'-0.3m'>\\s0",	/* 200 -  close double angles */
X	"...",		/* 201 -  elipses (3 dots) */
X	"\\ ",		/* 202 -  unpaddable space */
X	"\\o'`A'",	/* 203 -  `A */
X	"\\o'~A'",	/* 203 -  A with circumflex */
X	"\\o'~O'",	/* 203 -  O with circumflex */
X	"O\\h'-0.1m'E",		/* 206 -  upper OE ligature */
X	"o\\h'-0.1m'e",		/* 207 -  lower oe ligature */
X	"\\(hy",	/* 208 -  hyphen */
X	"\\(em",	/* 209 -  m dash (shift option -) */
X	"``",		/* 210 -  back double quote */
X	"''",		/* 211 -  close double quote */
X	"`",		/* 212 -  back single quote */
X	"'",		/* 213 -  close single quote */
X	"\\(di",	/* 214 -  divide */
X	"\\(gr",	/* 215 -  diamond (V) */
X	"\\zy\\u.\\h'-0.1m'.\\d",	/* 216 -  y with omlat */
X	"\\(sq",	/* 217 */
X	"\\(sq",	/* 218 */
X	"\\(sq",	/* 219 */
X	"\\(sq",	/* 220 */
X	"\\(sq",	/* 221 */
X	"\\(sq",	/* 222 */
X	"\\(sq",	/* 223 */
X	"\\(sq",	/* 224 */
X	"\\(sq",	/* 225 */
X	"\\(sq",	/* 226 */
X	"\\(sq",	/* 227 */
X	"\\(sq",	/* 228 */
X	"\\(sq",	/* 229 */
X	"\\(sq",	/* 230 */
X	"\\(sq",	/* 231 */
X	"\\(sq",	/* 232 */
X	"\\(sq",	/* 233 */
X	"\\(sq",	/* 234 */
X	"\\(sq",	/* 235 */
X	"\\(sq",	/* 236 */
X	"\\(sq",	/* 237 */
X	"\\(sq",	/* 238 */
X	"\\(sq",	/* 239 */
X	"\\(sq",	/* 240 */
X	"\\(sq",	/* 241 */
X	"\\(sq",	/* 242 */
X	"\\(sq",	/* 243 */
X	"\\(sq",	/* 244 */
X	"\\(sq",	/* 245 */
X	"\\(sq",	/* 246 */
X	"\\(sq",	/* 247 */
X	"\\(sq",	/* 248 */
X	"\\(sq",	/* 249 */
X	"\\(sq",	/* 250 -  box (option h) */
X	"\\(sq",	/* 251 -  box (option k) */
X	"\\(sq",	/* 252 */
X	"\\(sq",	/* 253 */
X	"\\(sq",	/* 254 */
X	"\\(sq",	/* 255 */
X	0 };
X
XputcharExtended(c)
Xunsigned char c;
X{
X    printf("%s", ctrans[c]);
X    return( strlen( ctrans[c] ) );
X}
X
Xerror( str )
X    char	*str;
X{
X    fprintf( stderr, "-w2t: %s.\n", str );
X    exit(1);
X}
'EOF'
echo -n '		 ' ; ls -l w2t.c