home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / unix / unix_mw4.sha / README
Encoding:
Text File  |  1985-05-23  |  48.6 KB  |  2,033 lines

  1. w2t (MacWrite to troff converter for Unix)
  2.  
  3. This is a new version of w2t (a.k.a. write2troff) that will handle
  4. MacWrite 3.x/4.x format files.  There have been a few bug fixes but
  5. no significant changes other than the new MacWrite support.
  6.  
  7. The files included are:
  8.   w2t.c        - converter for MW v4
  9.   macwrite.h    - structs giving format of MW v4 document
  10.   oldw2t.c    - converter for MW v2
  11.   oldmacwrite.h    - structs giving format of MW v2 document
  12.   w2t.1        - Manual entry for write2troff
  13.   Makefile    - makefile for w2t & oldw2t
  14.  
  15. All of the above files are Copyright (c) 1984, 1985 by Michael Caplinger
  16. and Van Jacobson.  They may be freely redistributed & modified provided
  17.   a) this copyright notice is retained, unmodified, in all copies & all
  18.      derivatives.
  19.   b) they are not redistributed for profit.
  20.  
  21. 'EOF'
  22. echo -n '         ' ; ls -l README
  23. echo x - Makefile '    ' '-rw-r--r--  1 van           709 May 21 20:22 Makefile'
  24. sed 's/^X//' > Makefile << 'EOF'
  25. # Makefile for w2t (MacWrite to troff converter)
  26.  
  27. # The symbol OLDMACWRITE gets you a klugy way of handling old (v2) format
  28. # MacWrite files.  Define this symbol as the full pathname of the 'oldw2t'
  29. # program & w2t will exec oldw2t if it encounters a v2 format input file.
  30. # If you don't define OLDMACWRITE (i.e., delete everything after the equal
  31. # sign on the OLDMACWRITE=... line), w2t will simply complain if it is
  32. # given a v2 format input file.
  33.  
  34. OLDMACWRITE= -DOLDMACWRITE='"oldw2t"'
  35. CFLAGS= -O $(OLDMACWRITE)
  36.  
  37. all:    w2t oldw2t
  38.  
  39. w2t:    w2t.o
  40.     cc $(CFLAGS) -o w2t w2t.o
  41.  
  42. w2t.o:    macwrite.h
  43.  
  44. oldw2t:    oldw2t.o
  45.     cc $(CFLAGS) -o oldw2t oldw2t.o
  46.  
  47. oldw2t.o: oldmacwrite.h
  48.  
  49. clean:
  50.     rm -f w2t oldw2t w2t.o oldw2t.o
  51. 'EOF'
  52. echo -n '         ' ; ls -l Makefile
  53. echo x - macwrite.h '    ' '-rw-r--r--  1 van          2194 May 21 19:53 macwrite.h'
  54. sed 's/^X//' > macwrite.h << 'EOF'
  55. /* MacWrite v3.x/4.x Document Format
  56.  *
  57.  * copyright (c) 1985 by Van Jacobson, Lawrence Berkeley Lab
  58.  */
  59. typedef unsigned char byte;
  60.  
  61. /* Global information about the document (starts at byte 0) */
  62.  
  63. struct MWGlobals {
  64.     short    versionNumber;    /* =6 for MW 3/4 */
  65. #define    MW_VERSION 6
  66. #define OLD_MW_VERSION 3
  67.     short    paraCount;
  68.     short    headerParaCount;
  69.     short    footerParaCount;
  70. };
  71.  
  72. #define    TEXT_PAR_INFO    0x108L    /* addr of long that points to text par desc */
  73. #define    HDR_PAR_INFO    0xDAL    /* addr of long that points to hdr par desc */
  74. #define    FOOT_PAR_INFO    0xACL    /* addr of long that points to foot par desc */
  75.  
  76. /* structure of a paragraph descriptor.  16 bytes / paragraph */
  77.  
  78. struct infoArrayElem {
  79.     short    paraHeight;
  80.     short    position;
  81.     short    pageNum; /* 0-based */
  82.     short    type;        /* (set by w2t: derived from paraHeight) */
  83.     off_t    dataPtr;
  84.     short    parBytes;
  85.     byte    parFlags;    /* moved (from high byte of dataPtr) by w2t */
  86. #define    PF_LOCALJUST    0x40    /* if par has its own justification */
  87. #define    PF_COMPRESSED    0x08    /* if text par is compressed */
  88.     byte    filler;
  89. };
  90.  
  91.  
  92. /* paragraph types */
  93. #define RULERPARA 0
  94. #define TEXTPARA 1
  95. #define PICTUREPARA 2
  96.  
  97. /*
  98.  * On the even word boundary following paragraph text there is
  99.  * a word for the format run length.  Each format consists of six bytes:
  100. */
  101.  
  102. struct format {
  103.     short charPos;
  104.     byte pointSize;
  105.     byte style;
  106.     byte unused;
  107.     byte fontNumber;
  108. };
  109.  
  110.  
  111. /* Data format for a "ruler" paragraph */
  112.  
  113. struct ruler {
  114.     short leftMargin;
  115.     short rightMargin;
  116.     byte justify;
  117.     byte numTabs;
  118.     byte flags;
  119. #define    RF_6LPI    0x80    /* set for 6 lpi, clear for ?? */
  120.     byte spacing;
  121.     short paraIndent;
  122.     short tabs[12];
  123. };
  124.  
  125. #define LEFTJUST 0
  126. #define CENTERJUST 1
  127. #define RIGHTJUST 2
  128. #define BOTHJUST 3
  129.  
  130. #define SINGLESPACE 0
  131. #define DOUBLESPACE 1
  132. #define TRIPLESPACE 2
  133.  
  134. /* bits for text styles */
  135. #define BOLD 0x1
  136. #define ITALIC 0x2
  137. #define    UNDERLINE 0x4
  138. #define    OUTLINE 0x8
  139. #define    SHADOW 0x10
  140. #define RAISE 0x20
  141. #define LOWER 0x40
  142.  
  143.  
  144. /* the following should really be taken from the document's resource file
  145.  * but that's a LOT of work so we just wire it in...
  146.  */
  147. #define    COMPRESSION_STRING " etnroaisdlhcfp"
  148. 'EOF'
  149. echo -n '         ' ; ls -l macwrite.h
  150. echo x - oldmacwrite.h '    ' '-rw-r--r--  1 van          2142 May 21 19:53 oldmacwrite.h'
  151. sed 's/^X//' > oldmacwrite.h << 'EOF'
  152. typedef unsigned char byte;
  153.  
  154. struct global { /* should be 140 bytes */
  155.     short versionNumber;
  156.     short paraOffset;
  157.     short paraCount;
  158.     short headerParaCount;
  159.     short footerParaCount;
  160.     byte titlePage;
  161.     byte scrapShow;
  162.     byte footerDisplayed;
  163.     byte headerDisplayed;
  164.     byte rulersShowing;
  165.     byte spare;
  166.     short activeDoc; /* 0 = main, 1 = header, 2 = footer */
  167.     short startPageNum;
  168.     byte printingVars[120]; /* ??? */
  169. };
  170.  
  171. #define MAINDOC 0
  172. #define HEADERDOC 1
  173. #define FOOTERDOC 2
  174.  
  175. struct endpoint {
  176.     short paraNumber;
  177.     short charPos;
  178. };
  179.  
  180. struct position {
  181.     short vert;
  182.     short hor;
  183. };
  184.  
  185. struct document { /* should be 34 bytes */
  186.     struct endpoint start;
  187.     struct endpoint end;
  188.     short vertOffset; /* always <= 0 */
  189.     short needToRedraw;
  190.     struct position pageNumberPos;
  191.     struct position datePos;
  192.     struct position timePos;
  193.     struct position timeStringPos;
  194.     byte iconRedraw;
  195.     byte iconFlag;
  196.     short activeFont;
  197.     short activeStyle;
  198. };
  199.  
  200. struct infoArrayElem { /* should be 8 bytes */
  201.     short paraHeight;
  202.     short position;
  203.     byte pageNum; /* 0-based */
  204.     byte unused[3];
  205. };
  206.  
  207. /*
  208.     paragraph data
  209. */
  210.  
  211. struct paraHeader {
  212.     short type; /* 0=ruler, 1=text, 2=picture */
  213.     short dataLength;
  214. };
  215.  
  216. #define RULERPARA 0
  217. #define TEXTPARA 1
  218. #define PICTUREPARA 2
  219.  
  220. struct textHeader {
  221.     short textLength;
  222. };
  223.  
  224. /*
  225.     ASCII data follows.  On the even word boundary following text there is
  226.     a word for the format run length.  Each format consists of six bytes:
  227. */
  228.  
  229. struct format {
  230.     short charPos;
  231.     byte pointSize;
  232.     byte style;
  233.     byte unused;
  234.     byte fontNumber;
  235. };
  236.  
  237. struct ruler {
  238.     short leftMargin;
  239.     short rightMargin;
  240.     byte justify;
  241.     byte numTabs;
  242.     byte filler; /* ??? */
  243.     byte spacing;
  244.     short paraIndent;
  245.     short tabs[12];
  246. };
  247.  
  248. #define LEFTJUST 0
  249. #define CENTERJUST 1
  250. #define RIGHTJUST 2
  251. #define BOTHJUST 3
  252.  
  253. #define SINGLESPACE 0
  254. #define DOUBLESPACE 1
  255. #define TRIPLESPACE 2
  256.  
  257. /* bits for text styles */
  258. #define BOLD 0x1
  259. #define ITALIC 0x2
  260. #define    UNDERLINE 0x4
  261. #define    OUTLINE 0x8
  262. #define    SHADOW 0x10
  263. #define RAISE 0x20
  264. #define LOWER 0x40
  265. 'EOF'
  266. echo -n '         ' ; ls -l oldmacwrite.h
  267. echo x - oldw2t.c '    ' '-rw-r--r--  1 van         17313 May 21 19:53 oldw2t.c'
  268. sed 's/^X//' > oldw2t.c << 'EOF'
  269. /*
  270.     MacWrite to troff input converter for MacWrite 2.0 documents
  271.     (i.e., the "old" MacWrite).
  272.  
  273.     version 0.1, Michael Caplinger (mike@rice.arpa), October 1984.
  274.     version 0.2-4, Van Jacobson (van@lbl-rtsg.arpa), Dec 84
  275.         added byte swap routines for Vax, added translations
  276.         for most of Mac's extended characters, added pass-
  277.         through for tables & equations, changed font cmds
  278.         from R-I-B-S form to 1-2-3-4 form to allow font
  279.         changing with ditroff, corrected a couple of minor
  280.         glitches, add "-p" flag to output space for pictures.
  281.     version 0.5, vj, Jan 7, 85.  Made text between .PS/.PE be treated
  282.         like tbl text.
  283. */
  284.  
  285. /*
  286.     copyright (c) 1984, Michael Caplinger.
  287.     May be freely redistributed, but this comment must remain in the
  288.     program or any derivative.
  289. */
  290.  
  291. #define VERSION "0.5"
  292.  
  293. #include <stdio.h>
  294. #include "oldmacwrite.h"
  295.  
  296. unsigned short ntohs();
  297. #define SWAP(s) (s)=ntohs(s);
  298.  
  299. /* Current Document Context */
  300. int curPoint = 12;
  301. int curStyle = 0;
  302. int curFont;
  303. int curJust = -1;
  304. int curRight = -1;
  305. int curLeft = -1;
  306. int curSpacing = -1;
  307. float curIndent = -1.;
  308. float curLinelength = -1.0;
  309. float curParIndent = -1.;
  310.  
  311. /* Program Option Flags */
  312. int verbose = 0;
  313. int wrap = 1;
  314. int pflag = 0;
  315. int basePoint = 2;
  316. int raw = 0;
  317.  
  318. main(argc, argv)
  319. char **argv;
  320. {
  321.     int f;
  322.  
  323.     setFlags(argc, argv);
  324.     argv++;
  325.     while(*argv) {
  326.         if(argv[0][0] != '-') {
  327.         f = open(argv[0], 0);
  328.         if(f >= 0) processFile(f);
  329.     }
  330.     argv++;
  331.     }
  332. }
  333.  
  334. processFile(f)
  335. int f;
  336. {
  337.     struct global global;
  338.     struct document text, header, footer;
  339.     struct infoArrayElem *textInfo, *headerInfo, *footerInfo;
  340.     char *data;
  341.     struct textHeader *textHeader;
  342.     struct paraHeader paraHeader;
  343.     short formatRunLength;
  344.     char *cp;
  345.     int i, j, k, col;
  346.     struct format *fp, *startfp, *endfp;
  347.     struct ruler *ruler;
  348.     int needSpace = 0;
  349.     int skipBlanks = 0;
  350.     int lastWasFormat = 0;
  351.     int doingTable = 0;
  352.  
  353.     read(f, &global, 140);
  354.     SWAP(global.versionNumber)
  355.     SWAP(global.paraOffset)
  356.     SWAP(global.paraCount)
  357.     SWAP(global.headerParaCount)
  358.     SWAP(global.footerParaCount)
  359.     SWAP(global.activeDoc)
  360.     SWAP(global.startPageNum)
  361.     read(f, &text, 34);
  362.     read(f, &header, 34);
  363.     read(f, &footer, 34);
  364.     debug("version %d\n", global.versionNumber);
  365.     debug("%d paragraphs in main text\n", global.paraCount);
  366.     
  367.     textInfo = (struct infoArrayElem *) malloc(global.paraCount * 8);
  368.     headerInfo = (struct infoArrayElem *) malloc(global.headerParaCount * 8);
  369.     footerInfo = (struct infoArrayElem *) malloc(global.footerParaCount * 8);
  370.     read(f, textInfo, global.paraCount * 8);
  371.     for(j=0; j<global.paraCount; j++) {
  372.     SWAP(textInfo[j].paraHeight)
  373.     SWAP(textInfo[j].position)
  374.     }
  375.     read(f, headerInfo, global.headerParaCount * 8);
  376.     for(j=0; j<global.headerParaCount; j++) {
  377.     SWAP(headerInfo[j].paraHeight)
  378.     SWAP(headerInfo[j].position)
  379.     }
  380.     read(f, footerInfo, global.footerParaCount * 8);
  381.     for(j=0; j<global.footerParaCount; j++) {
  382.     SWAP(footerInfo[j].paraHeight)
  383.     SWAP(footerInfo[j].position)
  384.     }
  385.  
  386.     doPrelude();
  387.     for(j = 0; j < global.paraCount; j++) {
  388.     read(f, ¶Header, 4);
  389.     SWAP(paraHeader.type)
  390.     SWAP(paraHeader.dataLength)
  391.     debug("type %d paragraph\n", paraHeader.type);
  392.     debug("%d bytes in paragraph data\n", paraHeader.dataLength);
  393.     data = (char *) malloc(paraHeader.dataLength);
  394.     read(f, data, paraHeader.dataLength);
  395.     debug("height %d, position %d, page #%d\n", textInfo[j].paraHeight,
  396.         textInfo[j].position, textInfo[j].pageNum);
  397.     switch(paraHeader.type) {
  398.         case TEXTPARA:
  399.         textHeader = (struct textHeader *) data;
  400.         SWAP(textHeader->textLength)
  401.         debug("%d bytes of text\n", textHeader->textLength);
  402.         /* check for a null or empty paragraph */
  403.         cp = data + 2;
  404.         while( *cp == ' ' || *cp == '\t' )
  405.             cp++;
  406.         if( *cp  == '\r' ) {
  407.             /* null paragraph */
  408.             needSpace++;
  409.             break;
  410.         }
  411.             if(needSpace && !raw) {
  412.             if( needSpace > 1 )
  413.             printf(".sp %d\n", needSpace);
  414.             else
  415.             printf(".sp\n");
  416.             needSpace = 0;
  417.         }
  418.         cp = data + 2 + textHeader->textLength;
  419.         if((int) cp & 0x1) cp++; /* even byte boundary */
  420.         formatRunLength = ntohs(*(short *)cp);
  421.         formatRunLength /= 6;
  422.         debug("%d format items\n", formatRunLength);
  423.         startfp = (struct format *) (cp + 2);
  424.         SWAP(startfp->charPos)
  425.         fp = startfp;
  426.         for(k = 0; k < formatRunLength; k++) {
  427.             SWAP(fp->charPos)
  428.             debug("pos %d, pointsize %d, style 0x%0x, font %d\n",
  429.             fp->charPos, fp->pointSize, fp->style, fp->fontNumber);
  430.             fp++;
  431.         }
  432.         cp = data + 2;
  433.         fp = startfp;
  434.         endfp = fp + (formatRunLength - 1);
  435.         if (*cp == '.') {
  436.             lastWasFormat = 1;
  437.             if ( (cp[1] == 'T' && cp[2] == 'S') ||
  438.                  (cp[1] == 'P' && cp[2] == 'S') ||
  439.                  (cp[1] == 'E' && cp[2] == 'Q') )
  440.             doingTable = 1;
  441.             else if ( (cp[1] == 'T' && cp[2] == 'E') ||
  442.                   (cp[1] == 'P' && cp[2] == 'E') ||
  443.                   (cp[1] == 'E' && cp[2] == 'N') )
  444.             doingTable = 0;
  445.         }
  446.         else {
  447.             if ( !lastWasFormat && !doingTable) {
  448.                 printf(".pp\n");
  449.             }
  450.             lastWasFormat = 0;
  451.         }
  452.  
  453.         /* delete any trailing whitespace */
  454.         i = textHeader->textLength - 1;
  455.         while( cp[i] == ' ' || cp[i] == '\t' )
  456.             i--;
  457.         textHeader->textLength = i;
  458.  
  459.         col = 0;
  460.         for(i = 0; i < textHeader->textLength; i++) {
  461.             if(i == fp->charPos) {
  462.             col += doFormat(fp,i);
  463.             if(fp != endfp) fp++;
  464.             }
  465.             if(wrap && *cp == ' ' && col > 65) {
  466.             skipBlanks = 1;
  467.             putchar('\n');
  468.             col = -1;
  469.             cp++;
  470.             continue;
  471.             }
  472.             if(skipBlanks && *cp == ' ')
  473.             ;
  474.             else {
  475.             col += putcharExtended(*cp);
  476.             skipBlanks = 0;
  477.             }
  478.             cp++;
  479.         }
  480.         /* since we deleted trailing blanks & the final
  481.          * \r, we're guaranteed that we need a newline.
  482.          * But first reset the style since we will get
  483.          * a ".pp" before any text & -me will reset the
  484.          * style on the .pp.
  485.          */
  486.         setStyle( 0 );
  487.         putchar( '\n' );
  488.         break;
  489.  
  490.         case RULERPARA:
  491.         ruler = (struct ruler *) data;
  492.         SWAP(ruler->leftMargin)
  493.         SWAP(ruler->rightMargin)
  494.         SWAP(ruler->paraIndent)
  495.         for(i=0; i<ruler->numTabs; i++) {
  496.             SWAP(ruler->tabs[i])
  497.         }
  498.         debug("leftMargin %d, right %d\n", 
  499.             ruler->leftMargin, ruler->rightMargin);
  500.         debug("just %d, %d tabs, paraIndent %d\n",
  501.             ruler->justify, ruler->numTabs, ruler->paraIndent);
  502.         doRuler(ruler);
  503.         break;
  504.  
  505.         case PICTUREPARA:
  506.         if ( pflag ) {
  507.             printf(".sv %.1fi\n",
  508.                    -textInfo[j].paraHeight/80. );
  509.         }
  510.         break;
  511.     } /* switch */
  512.     free(data);
  513.     } /* for */
  514.     free(textInfo);
  515.     free(headerInfo);
  516.     free(footerInfo);
  517. }
  518.  
  519. doFormat(fp, inParagraph)
  520. struct format *fp;
  521. {
  522.     if(fp->pointSize != curPoint) {
  523.     if(!raw) {
  524.         if ( inParagraph )
  525.         printf( "\\s%d\\&", fp->pointSize - basePoint);
  526.         else {
  527.         printf(".sz %d\n", fp->pointSize - basePoint);
  528.         printf(".nr pp %d\n", fp->pointSize - basePoint);
  529.         }
  530.     }
  531.     curPoint = fp->pointSize;
  532.     }
  533.     setStyle( fp->style );
  534.  
  535.     /* this should be the number of chars taken up by the format
  536.     string, but I'm lazy. */
  537.     return 4;
  538. }
  539.  
  540. setStyle( style )
  541. {
  542.     static int isRaised = 0;
  543.     static int isLowered = 0;
  544.     int font;
  545.  
  546.     if ( style != curStyle ) {
  547.  
  548.     font = style & (BOLD|SHADOW|ITALIC|UNDERLINE);
  549.     if( font != (curStyle & (BOLD|SHADOW|ITALIC|UNDERLINE)) ) {
  550.         if(font & (ITALIC|UNDERLINE))
  551.         printf("\\f2");
  552.         else if(font & (BOLD|SHADOW))
  553.         printf("\\f3");
  554.         else
  555.         printf("\\f1");
  556.     }
  557.  
  558.     if(style & RAISE) {
  559.         printf("\\u");
  560.         isRaised = 1;
  561.     } else if(isRaised) {
  562.         printf("\\d");
  563.         isRaised = 0;
  564.     }
  565.     if(style & LOWER) {
  566.         printf("\\d");
  567.         isLowered = 1;
  568.     } else if(isLowered) {
  569.         printf("\\u");
  570.         isLowered = 0;
  571.     }
  572.     curStyle = style;
  573.     }
  574. }
  575.  
  576. debug(f, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  577. char *f;
  578. {
  579.     if(verbose) fprintf(stdout, f, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  580. }
  581.  
  582. setFlags(argc, argv)
  583. char **argv;
  584. {
  585.  
  586.     if(argc == 1) {
  587.         printf("usage: %s [-r] [-p] [-d] [-w] [-s<pointadj>] files...\n", argv[0]);
  588.     exit(1);
  589.     }
  590.     while(*argv) {
  591.     if(argv[0][0] == '-') {
  592.         switch(argv[0][1]) {
  593.         case 'd':
  594.             verbose = 1;
  595.             break;
  596.         case 'p':
  597.             pflag = 1;
  598.             break;
  599.         case 'w':
  600.             wrap = 0;
  601.             break;
  602.         case 's':
  603.             basePoint = atoi(*argv + 2);
  604.             break;
  605.         case 'r':
  606.             raw = 1;
  607.             break;
  608.         }
  609.     }
  610.     argv++;
  611.     }
  612. }
  613.  
  614. doRuler(ruler)
  615. struct ruler *ruler;
  616. {
  617.     int i;
  618.  
  619.     if(curJust != ruler->justify) {
  620.         curJust = ruler->justify;
  621.     printf(".br\n"); /* need to put out a break or the last bit of text
  622.                 gets munged into the new formatting rules. */
  623.     switch(curJust) {
  624.         case LEFTJUST:
  625.         printf(".ad l\n");
  626.         break;
  627.         case CENTERJUST:
  628.         printf(".ad c\n");
  629.         break;
  630.         case RIGHTJUST:
  631.         printf(".ad r\n");
  632.         break;
  633.         case BOTHJUST:
  634.         printf(".ad b\n");
  635.         break;
  636.     }
  637.     }
  638.     if ( curSpacing != ruler->spacing ) {
  639.     curSpacing = ruler->spacing;
  640.     printf( ".vs %dp\n", (curSpacing+2)*(curPoint - basePoint + 4 )/2 );
  641.     printf( ".nr $r \\n(.v/\\n(.s\n" ); /* isn't -me wonderful? */
  642.     }
  643.     if(curLeft != ruler->leftMargin || curRight != ruler->rightMargin) {
  644.         curLeft = ruler->leftMargin;
  645.     curRight = ruler->rightMargin;
  646.     /* set indent and line length */
  647.     if ( curIndent != curLeft / 80. ) {
  648.         curIndent = curLeft / 80.;
  649.         printf(".ba %.1fi\n", curIndent);
  650.         printf(".nr $i %.1fi\n", curIndent);
  651.     }
  652.     if ( curLinelength != curRight / 80. ) {
  653.         curLinelength = curRight / 80.;
  654.         printf(".ll %.1fi\n", curLinelength);
  655.     }
  656.     if ( curParIndent != (ruler->paraIndent / 80. - curIndent) ) {
  657.         curParIndent = ruler->paraIndent / 80. - curIndent;
  658.         printf(".nr pi %.1fi\n", curParIndent );
  659.     }
  660.     }
  661.     printf(".ta ");
  662.     if ( ruler->numTabs <= 0 && curParIndent < 0 )
  663.     printf("%.1fi", -curParIndent );
  664.     else
  665.     for(i = 0; i < ruler->numTabs; i++) {
  666.         printf("%.1fi ", ruler->tabs[i] / 10.0 / 8.0);
  667.     }
  668.     putchar('\n');
  669. }
  670.  
  671.  
  672. /* standard troff prelude */
  673. doPrelude() {
  674.     printf(".\" this file generated by WtoT version %s\n", 
  675.     VERSION);
  676.     printf(".po 1i\n");
  677.     printf(".nr ps 0\n"); /* kill .pp's interpara spacing */
  678.     printf(".nr pi 0\n");
  679. #ifdef no
  680.     printf(".de pp\n"); /* redefine the .pp macro */
  681.     printf(".br\n.ti \\(pi\n");
  682.     printf("..\n");
  683. #endif
  684. }
  685.  
  686. /* this table maps the Mac's extended character set into troff
  687.  * characters.  It's set up for the standard Geneva font.  (it
  688.  * should really be selected based on the current font)
  689.  */
  690. char *ctrans[] = {
  691.     "\\(sq",    /* 0 */
  692.     "\\(sq",    /* 1 */
  693.     "\\(sq",    /* 2 */
  694.     "\\(sq",    /* 3 */
  695.     "\\(sq",    /* 4 */
  696.     "\\(sq",    /* 5 */
  697.     "\\(sq",    /* 6 */
  698.     "\\(sq",    /* 7 */
  699.     "\b",        /* 8 */
  700.     "\t",        /* 9 */
  701.     "\n",        /* 10 */
  702.     "\\(sq",    /* 11 */
  703.     "\f",        /* 12 */
  704.     "\n",        /* 13 */
  705.     "\\(sq",    /* 14 */
  706.     "\\(sq",    /* 15 */
  707.     "\\(sq",    /* 16 */
  708.     "\\(sq",    /* 17 */
  709.     "\\(sq",    /* 18 */
  710.     "\\(sq",    /* 19 */
  711.     "\\(sq",    /* 20 */
  712.     "\\(sq",    /* 21 */
  713.     "\\(sq",    /* 22 */
  714.     "\\(sq",    /* 23 */
  715.     "\\(sq",    /* 24 */
  716.     "\\(sq",    /* 25 */
  717.     "\\(sq",    /* 26 */
  718.     "\\(sq",    /* 27 */
  719.     "\\(sq",    /* 28 */
  720.     "\\(sq",    /* 29 */
  721.     "\\(sq",    /* 30 */
  722.     "\\(sq",    /* 31 */
  723.     " ",    /* 32 */
  724.     "!",    /* 33 */
  725.     "\"",    /* 34 */
  726.     "#",    /* 35 */
  727.     "$",    /* 36 */
  728.     "%",    /* 37 */
  729.     "&",    /* 38 */
  730.     "'",    /* 39 */
  731.     "(",    /* 40 */
  732.     ")",    /* 41 */
  733.     "*",    /* 42 */
  734.     "+",    /* 43 */
  735.     ",",    /* 44 */
  736.     "-",    /* 45 */
  737.     ".",    /* 46 */
  738.     "/",    /* 47 */
  739.     "0",    /* 48 */
  740.     "1",    /* 49 */
  741.     "2",    /* 50 */
  742.     "3",    /* 51 */
  743.     "4",    /* 52 */
  744.     "5",    /* 53 */
  745.     "6",    /* 54 */
  746.     "7",    /* 55 */
  747.     "8",    /* 56 */
  748.     "9",    /* 57 */
  749.     ":",    /* 58 */
  750.     ";",    /* 59 */
  751.     "<",    /* 60 */
  752.     "=",    /* 61 */
  753.     ">",    /* 62 */
  754.     "?",    /* 63 */
  755.     "@",    /* 64 */
  756.     "A",    /* 65 */
  757.     "B",    /* 66 */
  758.     "C",    /* 67 */
  759.     "D",    /* 68 */
  760.     "E",    /* 69 */
  761.     "F",    /* 70 */
  762.     "G",    /* 71 */
  763.     "H",    /* 72 */
  764.     "I",    /* 73 */
  765.     "J",    /* 74 */
  766.     "K",    /* 75 */
  767.     "L",    /* 76 */
  768.     "M",    /* 77 */
  769.     "N",    /* 78 */
  770.     "O",    /* 79 */
  771.     "P",    /* 80 */
  772.     "Q",    /* 81 */
  773.     "R",    /* 82 */
  774.     "S",    /* 83 */
  775.     "T",    /* 84 */
  776.     "U",    /* 85 */
  777.     "V",    /* 86 */
  778.     "W",    /* 87 */
  779.     "X",    /* 88 */
  780.     "Y",    /* 89 */
  781.     "Z",    /* 90 */
  782.     "[",    /* 91 */
  783.     "\\",    /* 92 */
  784.     "]",    /* 93 */
  785.     "^",    /* 94 -  hat accent */
  786.     "_",    /* 95 */
  787.     "\\(aa",    /* 96 -  acute accent */
  788.     "a",    /* 97 */
  789.     "b",    /* 98 */
  790.     "c",    /* 99 */
  791.     "d",    /* 100 */
  792.     "e",    /* 101 */
  793.     "f",    /* 102 */
  794.     "g",    /* 103 */
  795.     "h",    /* 104 */
  796.     "i",    /* 105 */
  797.     "j",    /* 106 */
  798.     "k",    /* 107 */
  799.     "l",    /* 108 */
  800.     "m",    /* 109 */
  801.     "n",    /* 110 */
  802.     "o",    /* 111 */
  803.     "p",    /* 112 */
  804.     "q",    /* 113 */
  805.     "r",    /* 114 */
  806.     "s",    /* 115 */
  807.     "t",    /* 116 */
  808.     "u",    /* 117 */
  809.     "v",    /* 118 */
  810.     "w",    /* 119 */
  811.     "x",    /* 120 */
  812.     "y",    /* 121 */
  813.     "z",    /* 122 */
  814.     "{",    /* 123 */
  815.     "|",    /* 124 */
  816.     "}",    /* 125 */
  817.     "~",        /* 126 -  circumflex accent */
  818.     "\\(sq",    /* 127 */
  819.     "\\zA\\v'-1m'.\\h'-0.1m'.\\v'+1m'",    /* 128 -  upper A with omlat */
  820.     "\\zA\\u\\(de\\d",    /* 129 -  upper circle A (A) */
  821.     "C",        /* 130 -  upper C with cedilla */
  822.     "\\o.E'.",    /* 131 -  upper E accent grave */
  823.     "\\zN\\u~\\d",    /* 132 -  upper N with circumflex */
  824.     "\\zO\\v'-1m'.\\h'-0.1m'.\\v'+1m'",    /* 133 -  upper O with omlat */
  825.     "\\zU\\v'-1m'.\\h'-0.1m'.\\v'+1m'",    /* 134 -  upper U with omlat */
  826.     "\\o.a'.",    /* 135 -  lower a accent grave */
  827.     "\\o.a`.",    /* 136 -  lower a accent acute */
  828.     "\\o.a^.",    /* 137 -  lower a with hat */
  829.     "\\za\\u.\\h'-0.1m'.\\d",    /* 138 -  lower a with omlat */
  830.     "\\o.a~.",    /* 139 -  lower a with circumflex */
  831.     "\\o'a\\(de'",    /* 140 -  lower a with circle */
  832.     "c",        /* 141 -  c with cedilla */
  833.     "\\o.e'.",    /* 142 -  lower e accent grave */
  834.     "\\o.e`.",    /* 143 -  lower e accent acute */
  835.     "\\o.e^.",    /* 144 -  lower e with hat */
  836.     "\\ze\\u.\\h'-0.1m'.\\d",    /* 145 -  lower e with omlat */
  837.     "\\o.i'.",    /* 146 -  lower i accent grave */
  838.     "\\o.i`.",    /* 147 -  lower i accent acute */
  839.     "\\o.i^.",    /* 148 -  lower i with hat */
  840.     "\\zi\\u.\\h'-0.1m'.\\d",    /* 149 - lower i with omlat */
  841.     "\\o.n~.",    /* 150 -  lower n with circumflex */
  842.     "\\o.o'.",    /* 151 -  lower o accent grave */
  843.     "\\o.o`.",    /* 152 -  lower o accent acute */
  844.     "\\o.o^.",    /* 153 -  lower o with hat */
  845.     "\\zo\\u.\\h'-0.1m'.\\d",    /* 154 -  lower o with omlat */
  846.     "\\o.o~.",    /* 155 -  lower o with circumflex */
  847.     "\\o.u'.",    /* 156 -  lower u accent grave */
  848.     "\\o.u`.",    /* 157 -  lower u accent acute */
  849.     "\\o.u^.",    /* 158 -  lower u with hat */
  850.     "\\zu\\u.\\h'-0.1m'.\\d",    /* 159 -  lower u with omlat */
  851.     "\\(dg",    /* 160 -  dagger */
  852.     "\\(de",    /* 161 -  degrees (shift option 8) */
  853.     "\\o'c/'",    /* 162 -  cents */
  854.     "\\f2\\o'L-'\\fP",    /* 163 -  pounds (currency) */
  855.     "\\(sc",    /* 164 -  section mark */
  856.     "\\(bu",    /* 165 -  bullet */
  857.     "\\(rh",    /* 166 -  paragraph */
  858.     "\\(*b",    /* 167 -  beta (german "ss") */
  859.     "\\(rg",    /* 168 -  registered */
  860.     "\\(co",    /* 169 -  copyright */
  861.     "\\u\\s-4TM\\s0\\d",    /* 170 -  trademark */
  862.     "\\(ag",    /* 171 -  grave accent */
  863.     "\\u.\\h'-0.1m'.\\d",    /* 172 -  oomlat accent */
  864.     "\\(!=",    /* 173 -  not equal */
  865.     "\\f2A\\fP\\h'-0.2m'E",        /* 174 -  upper AE ligature */
  866.     "\\zO/",    /* 175 -  slash upper O (O) */
  867.     "\\(if",    /* 176 -  infinity */
  868.     "\\(+-",    /* 177 -  plus minus (shift option =) */
  869.     "\\(<=",    /* 178 -  <= */
  870.     "\\(>=",    /* 179 -  >= */
  871.     "\\o'Y\\s-2=\\s0'",    /* 180 -  yen */
  872.     "\\(*m",    /* 181 -  lower mu */
  873.     "\\(pd",    /* 182 -  "partial" */
  874.     "\\(*S",    /* 183 -  upper sigma */
  875.     "\\(*P",    /* 184 -  upper PI (P) */
  876.     "\\(*p",    /* 185 -  lower pi */
  877.     "\\(is",    /* 186 -  integral sign */
  878.     "\\u\\za\\(ul\\d'",    /* 187 -  underbar lowercase a */
  879.     "\\u\\zo\\(ul\\d'",    /* 188 -  underbar lowercase o */
  880.     "\\(*W",    /* 189 -  upper omega */
  881.     "a\\h'-0.2m'e",        /* 190 -  lower ae ligature */
  882.     "\\o'o/'",    /* 191 -  slashed lower o */
  883.     "?",        /* 192 -  upside down ? (?) */
  884.     "\\(*i",    /* 193 -  lower case i */
  885.     "\\(no",    /* 194 -  negation */
  886.     "\\(sr",    /* 195 -  square root or check mark */
  887.     "\\z\\(is\\s-2\\(ci\\s0",    /* 196 -  contour integral */
  888.     "\\(~=",    /* 197 -  approx */
  889.     "\\(*D",    /* 198 -  triangle (upper delta) */
  890.     "\\s-2<\\h'-0.3m'<\\s0",    /* 199 -  open double angle brackets */
  891.     "\\s-2>\\h'-0.3m'>\\s0",    /* 200 -  close double angles */
  892.     "...",        /* 201 -  elipses (3 dots) */
  893.     "\\ ",        /* 202 -  unpaddable space */
  894.     "\\o'`A'",    /* 203 -  `A */
  895.     "\\o'~A'",    /* 203 -  A with circumflex */
  896.     "\\o'~O'",    /* 203 -  O with circumflex */
  897.     "O\\h'-0.1m'E",        /* 206 -  upper OE ligature */
  898.     "o\\h'-0.1m'e",        /* 207 -  lower oe ligature */
  899.     "\\(hy",    /* 208 -  hyphen */
  900.     "\\(em",    /* 209 -  m dash (shift option -) */
  901.     "``",        /* 210 -  back double quote */
  902.     "''",        /* 211 -  close double quote */
  903.     "`",        /* 212 -  back single quote */
  904.     "'",        /* 213 -  close single quote */
  905.     "\\(di",    /* 214 -  divide */
  906.     "\\(gr",    /* 215 -  diamond (V) */
  907.     "\\zy\\u.\\h'-0.1m'.\\d",    /* 216 -  y with omlat */
  908.     "\\(sq",    /* 217 */
  909.     "\\(sq",    /* 218 */
  910.     "\\(sq",    /* 219 */
  911.     "\\(sq",    /* 220 */
  912.     "\\(sq",    /* 221 */
  913.     "\\(sq",    /* 222 */
  914.     "\\(sq",    /* 223 */
  915.     "\\(sq",    /* 224 */
  916.     "\\(sq",    /* 225 */
  917.     "\\(sq",    /* 226 */
  918.     "\\(sq",    /* 227 */
  919.     "\\(sq",    /* 228 */
  920.     "\\(sq",    /* 229 */
  921.     "\\(sq",    /* 230 */
  922.     "\\(sq",    /* 231 */
  923.     "\\(sq",    /* 232 */
  924.     "\\(sq",    /* 233 */
  925.     "\\(sq",    /* 234 */
  926.     "\\(sq",    /* 235 */
  927.     "\\(sq",    /* 236 */
  928.     "\\(sq",    /* 237 */
  929.     "\\(sq",    /* 238 */
  930.     "\\(sq",    /* 239 */
  931.     "\\(sq",    /* 240 */
  932.     "\\(sq",    /* 241 */
  933.     "\\(sq",    /* 242 */
  934.     "\\(sq",    /* 243 */
  935.     "\\(sq",    /* 244 */
  936.     "\\(sq",    /* 245 */
  937.     "\\(sq",    /* 246 */
  938.     "\\(sq",    /* 247 */
  939.     "\\(sq",    /* 248 */
  940.     "\\(sq",    /* 249 */
  941.     "\\(sq",    /* 250 -  box (option h) */
  942.     "\\(sq",    /* 251 -  box (option k) */
  943.     "\\(sq",    /* 252 */
  944.     "\\(sq",    /* 253 */
  945.     "\\(sq",    /* 254 */
  946.     "\\(sq",    /* 255 */
  947.     0 };
  948.  
  949. putcharExtended(c)
  950. unsigned char c;
  951. {
  952.     printf("%s", ctrans[c]);
  953.     return( strlen( ctrans[c] ) );
  954. }
  955. 'EOF'
  956. echo -n '         ' ; ls -l oldw2t.c
  957. echo x - w2t.1 '    ' '-rw-r--r--  1 van          3091 May 21 19:53 w2t.1'
  958. sed 's/^X//' > w2t.1 << 'EOF'
  959. .TH write2troff local
  960. .SH NAME
  961. write2troff \- convert MacWrite files to troff input files
  962. .SH SYNOPSIS
  963. .B write2troff
  964. [
  965. .BI \-s pointsize
  966. ] [
  967. .B \-p
  968. ] [
  969. .B \-d
  970. ] [
  971. .B \-w
  972. ] [
  973. .B \-r
  974. ]
  975. file ...
  976. .br
  977. .SH DESCRIPTION
  978. .I write2troff
  979. reads MacWrite file(s) and produces a
  980. .I troff
  981. input file.  The input files to
  982. .I write2troff
  983. should be 
  984. .B .data
  985. files as transferred by
  986. .I macget(1).
  987. .PP
  988. By default, the converted file will contain enough
  989. .I -me
  990. macro commands to make the troff output `strongly resemble' the MacWrite
  991. output.  Currently, this means that justification, spacing, tabs,
  992. paragraphing, and certain kinds of text attributes will be the same.  See
  993. BUGS for a list of things that don't work.
  994. .PP
  995. The usual use of
  996. .I write2troff
  997. is expected to be something like:
  998. .IP
  999. .I
  1000. macget -d - | write2troff | itroff -me
  1001. .PP
  1002. .I Write2troff
  1003. options are:
  1004. .TP
  1005. .B -p
  1006. saves space for pictures.  By default, pictures are ignored completely.
  1007. This option outputs a
  1008. .I `.sv'
  1009. (save space) directive to reserve enough space to hold the picture.
  1010. .TP
  1011. .BI -s pointsize
  1012. is used to scale the document type sizes.
  1013. .I pointsize
  1014. is subtracted from all point sizes in the document.  By default, 
  1015. .I pointsize
  1016. is 2 which will convert documents from 12 point to 10 point.
  1017. .I Pointsize
  1018. can be zero (the MacWrite pointsizes will be used) or negative (the MacWrite
  1019. pointsizes will be scaled up).
  1020. .TP
  1021. .B -r
  1022. inserts far fewer
  1023. .I troff
  1024. commands in the output.  This may be useful when
  1025. the Mac is just being used to draft the text prior to a more rigorous
  1026. formatting.
  1027. .TP
  1028. .B -w
  1029. turns off intraparagraph wrapping.  A MacWrite paragraph is a single
  1030. line of text with no newlines.
  1031. .I Write2troff
  1032. will wrap these lines at about 72 columns by default.  I have never seen an
  1033. application where this wrapping was undesirable, but...
  1034. .TP
  1035. .B -d
  1036. intersperses an immense amount of debugging information
  1037. with the output on stdout.
  1038. .PP
  1039. Since the table & math abilities of MacWrite are limitted,
  1040. .BR tbl , eqn and pic
  1041. commands can be included in the MacWrite document.  I.e., lines
  1042. between .TS/.TE, .EQ/.EN or .PS/.PE will be treated specially.
  1043. Other 
  1044. .I troff
  1045. directives (lines starting with a `.')
  1046. will be passed through but may not do what you expect.
  1047. .PP
  1048. .SH "SEE ALSO"
  1049. macget(l)
  1050. .SH BUGS
  1051. .PP
  1052. Pictures are barely supported (you will need scissors & glue).
  1053. .PP
  1054. Headers and footers are ignored.
  1055. .PP
  1056. Decimal tabs are not handled correctly.
  1057. .PP
  1058. The output is heavily
  1059. .I -me
  1060. macro dependent.
  1061. .PP
  1062. All fonts map into troff's Times Roman.
  1063. .PP
  1064. Text attributes are not quite right.  Bold, italic, subscript, and
  1065. superscript work.  Underlining maps to italic.  Shadow maps to bold.
  1066. Mixed attributes map to either bold or italic.
  1067. .PP
  1068. All the special characters of the standard Mac Geneva font map into
  1069. some (reasonable?) troff character but the mapping is fixed.  Font dependent
  1070. character conversions (e.g., for the Princeton math font) should be supported.
  1071. .SH AUTHOR
  1072. Original version by Michael Caplinger, Rice University (mike@rice.arpa)
  1073. .br
  1074. Additions & changes for MacWrite v3/4 by Van Jacobson, Lawrence
  1075. Berkeley Laboratory (van@lbl-csam.arpa).
  1076. 'EOF'
  1077. echo -n '         ' ; ls -l w2t.1
  1078. echo x - w2t.c '    ' '-rw-r--r--  1 van         22582 May 21 20:25 w2t.c'
  1079. sed 's/^X//' > w2t.c << 'EOF'
  1080. /*
  1081.     MacWrite to troff input converter.
  1082.  
  1083.     version 0.1, Michael Caplinger (mike@rice.arpa), October 1984.
  1084.     version 0.2-4, Van Jacobson (van@lbl-rtsg.arpa), Dec 84
  1085.         added byte swap routines for Vax, added translations
  1086.         for most of Mac's extended characters, added pass-
  1087.         through for tables & equations, changed font cmds
  1088.         from R-I-B-S form to 1-2-3-4 form to allow font
  1089.         changing with ditroff, corrected a couple of minor
  1090.         glitches, add "-p" flag to output space for pictures.
  1091.     version 0.5, vj, Jan 7, 85.  Made text between .PS/.PE be treated
  1092.         like tbl text.
  1093.     version 1.0, vj, Apr 27, 85.  Massive changes to handle MacWrite
  1094.         4.x format files.
  1095. */
  1096.  
  1097. /*
  1098.     copyright (c) 1984, 1985 by Michael Caplinger and Van Jacobson.
  1099.     May be freely redistributed, but this comment must remain in the
  1100.     program or any derivative.
  1101. */
  1102.  
  1103. #define VERSION "1.1"
  1104.  
  1105. #include <stdio.h>
  1106. #include <sys/types.h>
  1107. #include "macwrite.h"
  1108.  
  1109. unsigned short ntohs();
  1110. #define SWAP(s) (s)=ntohs(s);
  1111. unsigned long ntohl();
  1112. #define SWAPL(s) (s)=ntohl(s);
  1113.  
  1114. /*
  1115.  * Current Document Context
  1116.  * The following are all in terms of the troff output, not the MacWrite
  1117.  * input file.  I.e., if the default "-s2" is in effect, 12-point MacWrite
  1118.  * text will make curPoint = 10.
  1119.  */
  1120. int curPoint = 10;
  1121. int curStyle = 0;
  1122. int curFont = -1;
  1123. int curJust = -1;
  1124. int curRight = -1;
  1125. int curLeft = -1;
  1126. int curSpacing = -1;
  1127. int isRaised = 0;
  1128. int isLowered = 0;
  1129. float curIndent = -1.;
  1130. float curLinelength = -1.0;
  1131. float curParIndent = -1.;
  1132.  
  1133. /* Program Option Flags */
  1134. int verbose = 0;
  1135. int wrap = 1;
  1136. int pflag = 0;
  1137. int basePoint = 2;
  1138. int raw = 0;
  1139.  
  1140. char **gargv;        /* orginal 'argv' (in case we have to exec old w2t) */
  1141.  
  1142. struct    textDesc {    /* descriptor for text par returned by read_text_par */
  1143.     byte    *text;        /* text of par */
  1144.     struct format *formats;    /* formats for text */
  1145.     short    nchars;        /* number of chars of text */
  1146.     short    nformats;    /* number of format desc */
  1147. };
  1148.  
  1149. struct    textDesc *read_text_par();
  1150.  
  1151. struct    infoArrayElem *read_par_info();
  1152. struct    ruler *read_ruler_par();
  1153.  
  1154. main(argc, argv)
  1155. char **argv;
  1156. {
  1157.     int f;
  1158.     int gotfile = 0;
  1159.  
  1160.     gargv = argv;
  1161.     argv++;
  1162.     while(*argv)
  1163.     {
  1164.     if(argv[0][0] == '-')
  1165.         {
  1166.         switch(argv[0][1])
  1167.         {
  1168.         case 'd':
  1169.             verbose = 1;
  1170.             break;
  1171.         case 'p':
  1172.             pflag = 1;
  1173.             break;
  1174.         case 'w':
  1175.             wrap = 0;
  1176.             break;
  1177.         case 's':
  1178.             basePoint = atoi(*argv + 2);
  1179.             break;
  1180.         case 'r':
  1181.             raw = 1;
  1182.             break;
  1183.         default:
  1184.             printf("usage: %s [-r] [-p] [-d] [-w] [-s<pointadj>] files...\n",
  1185.                 argv[0]);
  1186.             exit(1);
  1187.         }
  1188.         }
  1189.     else
  1190.         {
  1191.         gotfile++;
  1192.         f = open(argv[0], 0);
  1193.         if(f < 0)
  1194.         {
  1195.         perror( argv[0] );
  1196.         exit(1);
  1197.         }
  1198.         processFile(f);
  1199.         }
  1200.     argv++;
  1201.     }
  1202.     if ( gotfile == 0 )
  1203.     processFile( 0 );
  1204. }
  1205.  
  1206. processFile(f)
  1207. int f;
  1208. {
  1209.     struct MWGlobals global;
  1210.     struct infoArrayElem *textInfo;
  1211.     struct textDesc *td;
  1212.     byte *cp;
  1213.     int i, j, col;
  1214.     struct format *fp;
  1215.     struct ruler *ruler;
  1216.     int needSpace = 0;
  1217.     int skipBlanks = 0;
  1218.     int lastWasFormat = 0;
  1219.     int doingTable = 0;
  1220.  
  1221.     read_doc_info( f, &global );
  1222.     textInfo = read_par_info( f, (off_t)TEXT_PAR_INFO, global.paraCount );
  1223.  
  1224.     doPrelude();
  1225.     for(j = 0; j < global.paraCount; j++) {
  1226.     debug("height %d, position %d, page #%d\n", textInfo[j].paraHeight,
  1227.         textInfo[j].position, textInfo[j].pageNum);
  1228.     switch(textInfo[j].type) {
  1229.  
  1230.         case TEXTPARA:
  1231.         td = read_text_par( f, &textInfo[j] );
  1232.         cp = td->text;
  1233.         fp = td->formats;
  1234.  
  1235.         /* check for a null or empty paragraph */
  1236.         while( *cp == ' ' || *cp == '\t' )
  1237.             cp++;
  1238.         if( *cp  == '\r' ) {
  1239.             /* null paragraph */
  1240.             needSpace++;
  1241.             break;
  1242.         }
  1243.             if(needSpace && !raw) {
  1244.             if( needSpace > 1 )
  1245.             printf(".sp %d\n", needSpace);
  1246.             else
  1247.             printf(".sp\n");
  1248.             needSpace = 0;
  1249.         }
  1250.         if (*cp == '.') {
  1251.             lastWasFormat = 1;
  1252.             if ( (cp[1] == 'T' && cp[2] == 'S') ||
  1253.                  (cp[1] == 'P' && cp[2] == 'S') ||
  1254.                  (cp[1] == 'E' && cp[2] == 'Q') )
  1255.             doingTable = 1;
  1256.             else if ( (cp[1] == 'T' && cp[2] == 'E') ||
  1257.                   (cp[1] == 'P' && cp[2] == 'E') ||
  1258.                   (cp[1] == 'E' && cp[2] == 'N') )
  1259.             doingTable = 0;
  1260.         }
  1261.         else {
  1262.             if ( !lastWasFormat && !doingTable) {
  1263.                 printf(".pp\n");
  1264.             }
  1265.             lastWasFormat = 0;
  1266.         }
  1267.  
  1268.         if ( textInfo[j].parFlags & PF_LOCALJUST )
  1269.             setJust( textInfo[j].parFlags & 0x3 );
  1270.  
  1271.         /* delete any trailing whitespace */
  1272.         cp = td->text;
  1273.         i = td->nchars - 1;
  1274.         while( cp[i] == ' ' || cp[i] == '\t' )
  1275.             i--;
  1276.         td->nchars = i;
  1277.  
  1278.         col = 0;
  1279.         for(i = 0; i < td->nchars; i++) {
  1280.             if(i == fp->charPos) {
  1281.             col += doFormat(fp,i);
  1282.             if(td->nformats > 0)
  1283.                 fp++;
  1284.             }
  1285.             /* (the reason for this "else" is to prevent
  1286.              * a line break immediately following a format
  1287.              * change.
  1288.              */
  1289.             else if(wrap && *cp == ' ' && col > 65) {
  1290.             skipBlanks = 1;
  1291.             putchar('\n');
  1292.             col = -1;
  1293.             cp++;
  1294.             continue;
  1295.             }
  1296.             if(skipBlanks && *cp == ' ')
  1297.             ;
  1298.             else {
  1299.             col += putcharExtended(*cp);
  1300.             skipBlanks = 0;
  1301.             }
  1302.             cp++;
  1303.         }
  1304.         /* since we deleted trailing blanks & the final
  1305.          * \r, we're guaranteed that we need a newline.
  1306.          * But first reset the style since we will get
  1307.          * a ".pp" before any new text & -me will reset the
  1308.          * style on the .pp.
  1309.          */
  1310.         (void) setStyle( 0 );
  1311.         putchar( '\n' );
  1312.  
  1313.         if ( textInfo[j].parFlags & PF_LOCALJUST )
  1314.             setJust( ruler->justify );
  1315.  
  1316.         break;
  1317.  
  1318.         case RULERPARA:
  1319.         ruler = read_ruler_par( f, &textInfo[j] );
  1320.         doRuler(ruler);
  1321.         break;
  1322.  
  1323.         case PICTUREPARA:
  1324.         if ( pflag ) {
  1325.             printf(".sv %.1fi\n",
  1326.                    -textInfo[j].paraHeight/80. );
  1327.         }
  1328.         break;
  1329.     } /* switch */
  1330.     } /* for */
  1331.     free(textInfo);
  1332. }
  1333.  
  1334. doFormat(fp, inParagraph)
  1335. struct format *fp;
  1336. {
  1337.     register int size = 0;
  1338.  
  1339.     /* if we're doing super- or sub-scripts, change the style before
  1340.      * changing the size (otherwise the vertical motions won't be
  1341.      * calculated correctly).
  1342.      */
  1343.     if( isRaised || isLowered )
  1344.     size = setStyle( fp->style );
  1345.  
  1346.     if((fp->pointSize - basePoint) != curPoint)
  1347.     {
  1348.     curPoint = fp->pointSize - basePoint;
  1349.     if(!raw)
  1350.         {
  1351.         if ( inParagraph )
  1352.         {
  1353.         size += 5;
  1354.         printf( "\\s%d\\&", curPoint);
  1355.         }
  1356.         else
  1357.         {
  1358.         printf(".sz %d\n", curPoint);
  1359.         printf(".nr pp %d\n", curPoint);
  1360.         size = 0;
  1361.         }
  1362.         }
  1363.     }
  1364.  
  1365.     size += setStyle( fp->style );
  1366.  
  1367.     return size;
  1368. }
  1369.  
  1370. setStyle( style )
  1371.     register byte    style;
  1372. {
  1373.     register int    font;
  1374.     register int    size = 0;
  1375.  
  1376.     if ( style != curStyle )
  1377.     {
  1378.     font = style & (BOLD|SHADOW|ITALIC|UNDERLINE);
  1379.     if( font != (curStyle & (BOLD|SHADOW|ITALIC|UNDERLINE)) )
  1380.         {
  1381.         size += 3;
  1382.         if(font & (ITALIC|UNDERLINE))
  1383.         printf("\\f2");
  1384.         else if(font & (BOLD|SHADOW))
  1385.         printf("\\f3");
  1386.         else
  1387.         printf("\\f1");
  1388.         }
  1389.  
  1390.     if(style & RAISE)
  1391.         {
  1392.         size += 2;
  1393.         printf("\\u");
  1394.         isRaised = 1;
  1395.         }
  1396.     else if(isRaised)
  1397.         {
  1398.         size += 2;
  1399.         printf("\\d");
  1400.         isRaised = 0;
  1401.         }
  1402.  
  1403.     if(style & LOWER)
  1404.         {
  1405.         size += 2;
  1406.         printf("\\d");
  1407.         isLowered = 1;
  1408.         }
  1409.     else if(isLowered)
  1410.         {
  1411.         size += 2;
  1412.         printf("\\u");
  1413.         isLowered = 0;
  1414.         }
  1415.  
  1416.     curStyle = style;
  1417.     }
  1418.     return( size );
  1419. }
  1420.  
  1421. setJust( justify )
  1422.     byte    justify;
  1423. {
  1424.     justify &= (LEFTJUST|CENTERJUST|RIGHTJUST|BOTHJUST);
  1425.     if(curJust != justify)
  1426.     {
  1427.         curJust = justify;
  1428.     printf(".br\n"); /* need to put out a break or the last bit of text
  1429.                 gets munged into the new formatting rules. */
  1430.     switch(curJust)
  1431.         {
  1432.         case LEFTJUST:
  1433.         printf(".ad l\n");
  1434.         break;
  1435.         case CENTERJUST:
  1436.         printf(".ad c\n");
  1437.         break;
  1438.         case RIGHTJUST:
  1439.         printf(".ad r\n");
  1440.         break;
  1441.         case BOTHJUST:
  1442.         printf(".ad b\n");
  1443.         break;
  1444.         }
  1445.     }
  1446. }
  1447.  
  1448. /*VARARGS1*/
  1449. debug(f, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  1450. char *f;
  1451. {
  1452.     if(verbose)
  1453.     fprintf(stdout, f, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  1454. }
  1455.  
  1456. doRuler(ruler)
  1457. struct ruler *ruler;
  1458. {
  1459.     int i;
  1460.     int    newSpacing,
  1461.     newLeft,
  1462.     newRight,
  1463.     newIndent,
  1464.     newLinelength;
  1465.  
  1466.     setJust( ruler->justify );
  1467.  
  1468.     /* we use 4 point leading for normal rulers, 1 point leading for "6lpi"
  1469.      * rulers.  The actual spacing is the leading times the ruler's 1/1.5/2
  1470.      * space factor.  Note that the order of evaluation of the following
  1471.      * expression is important (to avoid truncation errors).
  1472.      */
  1473.     newSpacing = ((ruler->flags & RF_6LPI? 1 : 4) * (ruler->spacing + 2)) / 2;
  1474.     if ( curSpacing != newSpacing ) {
  1475.     curSpacing = newSpacing;
  1476.     printf( ".vs %dp\n", curSpacing + curPoint );
  1477.     printf( ".nr r$ %d\n", curSpacing );  /* see comments in doPrelude */
  1478.     printf( ".nr $r \\n(.v/\\n(.s\n" );
  1479.     }
  1480.     if(curLeft != ruler->leftMargin || curRight != ruler->rightMargin) {
  1481.         curLeft = ruler->leftMargin;
  1482.     curRight = ruler->rightMargin;
  1483.     /* set indent and line length */
  1484.     if ( curIndent != curLeft / 80. ) {
  1485.         curIndent = curLeft / 80.;
  1486.         printf(".ba %.1fi\n", curIndent);
  1487.         printf(".nr $i %.1fi\n", curIndent);
  1488.     }
  1489.     if ( curLinelength != curRight / 80. ) {
  1490.         curLinelength = curRight / 80.;
  1491.         printf(".ll %.1fi\n", curLinelength);
  1492.     }
  1493.     if ( curParIndent != (ruler->paraIndent / 80. - curIndent) ) {
  1494.         curParIndent = ruler->paraIndent / 80. - curIndent;
  1495.         printf(".nr pi %.1fi\n", curParIndent );
  1496.     }
  1497.     }
  1498.     printf(".ta ");
  1499.     if ( ruler->numTabs == 0 && curParIndent < 0 )
  1500.     printf("%.1fi", -curParIndent );
  1501.     else
  1502.     for(i = 0; i < ruler->numTabs; i++) {
  1503.         if ( ruler->tabs[i] > 0 )
  1504.         printf("%.1fi ", ruler->tabs[i] / 10.0 / 8.0);
  1505.         else
  1506.         printf("%.1fiR ", ruler->tabs[i] / 10.0 / 8.0);
  1507.     }
  1508.     putchar('\n');
  1509. }
  1510.  
  1511.  
  1512. /* standard troff prelude */
  1513. doPrelude() {
  1514.     printf(".\" this file generated by WtoT version %s\n", 
  1515.     VERSION);
  1516.     printf(".po 1i\n");
  1517.     printf(".nr ps 0\n"); /* kill .pp's interpara spacing */
  1518.     printf(".nr pi 0\n");
  1519.     /*
  1520.      * The -me ".sz" macro is wrong.  We redefine .sz to be
  1521.      * more nearly correct (so we can adjust the vertical spacing
  1522.      * when we see a ruler).  This new macro assumes that the
  1523.      * current leading (in points) is in the register 'r$'.
  1524.      */
  1525.     printf(".de sz\n");
  1526.     printf(".ps \\\\$1\n");
  1527.     printf(".vs \\\\n(.sp+\\\\n(r$p\n");
  1528.     printf(".bd S B \\\\n(.su/3u\n");
  1529.     printf("..\n");
  1530. }
  1531.  
  1532.  
  1533. /* read the global document description info from file f into "global" */
  1534.  
  1535. #define GET(x)    if(read(f, &(x), sizeof(x)) != sizeof(x))\
  1536.             error("EOF reading document globals");\
  1537.         SWAP(x)
  1538.  
  1539. read_doc_info( f, global )
  1540.     struct MWGlobals *global;
  1541. {
  1542.     GET(global->versionNumber);
  1543.     debug("version %d\n", global->versionNumber);
  1544.     if ( global->versionNumber != MW_VERSION )
  1545.     {
  1546. #ifdef OLDMACWRITE
  1547.     if ( global->versionNumber == OLD_MW_VERSION )
  1548.         {
  1549.         if ( f == 0 )
  1550.         error( "can't handle old macwrite file if taking input from stdin.");
  1551.         close( f );
  1552.         execvp( OLDMACWRITE, gargv );
  1553.         perror( OLDMACWRITE );
  1554.         }
  1555. #endif
  1556.     error( "input file not in MacWrite v4 format" );
  1557.     }
  1558.     GET(global->paraCount)
  1559.     GET(global->headerParaCount)
  1560.     GET(global->footerParaCount)
  1561.     debug("%d paragraphs in main text\n", global->paraCount);
  1562.     debug("%d paragraphs in header text\n", global->headerParaCount);
  1563.     debug("%d paragraphs in footer text\n", global->footerParaCount);
  1564. }
  1565.  
  1566. /* read "count" paragraphs worth of paragraph descriptors from file "f"
  1567.  * starting at the location *pointed to* by "info_ptr".
  1568.  */
  1569. struct infoArrayElem *
  1570. read_par_info( f, info_ptr, count )
  1571.     int        f;
  1572.     off_t    info_ptr;
  1573.     short    count;
  1574. {
  1575.     struct infoArrayElem *textInfo;
  1576.     off_t    info_start;
  1577.     int        i;
  1578.  
  1579.     textInfo = (struct infoArrayElem *) malloc(count * sizeof(*textInfo));
  1580.  
  1581.     lseek( f, info_ptr, 0 );
  1582.     if ( read( f, &info_start, sizeof(info_start) ) != sizeof(info_start))
  1583.     error( "error reading paragraph desc. pointer" );
  1584.     SWAPL( info_start );
  1585.     info_start &= 0xffffff;
  1586.  
  1587.     lseek( f, info_start, 0 );
  1588.     if ( read(f, textInfo, count * sizeof(*textInfo)) != 
  1589.      (count * sizeof(*textInfo)))
  1590.     error( "error reading paragraph descriptors" );
  1591.     for(i=0; i < count; i++)
  1592.     {
  1593.     SWAP(textInfo[i].paraHeight)
  1594.     SWAP(textInfo[i].position)
  1595.     SWAP(textInfo[i].pageNum)
  1596.     SWAP(textInfo[i].parBytes)
  1597.     SWAPL(textInfo[i].dataPtr)
  1598.     textInfo[i].parFlags = (textInfo[i].dataPtr >> 24) & 0xff;
  1599.     textInfo[i].dataPtr &= 0xffffff;
  1600.     if ( textInfo[i].paraHeight < 0 )
  1601.         {
  1602.         textInfo[i].paraHeight = -textInfo[i].paraHeight;
  1603.         textInfo[i].type = PICTUREPARA;
  1604.         }
  1605.     else if ( textInfo[i].paraHeight == 0 )
  1606.         textInfo[i].type = RULERPARA;
  1607.     else
  1608.         textInfo[i].type = TEXTPARA;
  1609.     }
  1610.     return (textInfo);
  1611.     }
  1612.  
  1613.  
  1614. /* round a number up to next block "s" boundary (s must be a power
  1615.  * of 2)
  1616.  */
  1617. #define round(x,s) (((x - 1) & (s - 1)) + s)
  1618.  
  1619.  
  1620. /* read the text & format info for the text paragraph given by paragraph
  1621.  * descriptor "par".
  1622.  */
  1623.  
  1624. struct textDesc *
  1625. read_text_par( f, par )
  1626.     int        f;
  1627.     struct infoArrayElem *par;
  1628. {
  1629.     register    byte    *cp;
  1630.     register    byte    *fp;
  1631.     register    byte    last;
  1632.     register    byte    c;
  1633.     register    int    top;
  1634.     register    int    i;
  1635.     register    struct format    *formp;
  1636.     short    nchars;
  1637.     short    nformats;
  1638.     static struct textDesc    td;
  1639.     static int    textBufSize = 0;
  1640.     static int    dataBufSize = 0;
  1641.     static byte    *textBuf = NULL;
  1642.     static byte    *dataBuf = NULL;
  1643.  
  1644.     /* get enough space for the paragraph data then read the data */
  1645.  
  1646.     if ( par->parBytes > dataBufSize )
  1647.     {
  1648.     if ( dataBuf )
  1649.         free( dataBuf );
  1650.  
  1651.     dataBufSize = round( par->parBytes, 1024 );
  1652.     dataBuf = (byte *)malloc( dataBufSize );
  1653.     }
  1654.     
  1655.     lseek( f, par->dataPtr, 0 );
  1656.     if (read( f, dataBuf, par->parBytes ) != par->parBytes)
  1657.     error( "error reading paragraph text" );
  1658.  
  1659.     /* if the text is compressed, unpack it into the text buffer */
  1660.  
  1661.     nchars = *(short *)dataBuf;
  1662.     SWAP(nchars);
  1663.     td.nchars = nchars;
  1664.  
  1665.     if ( par->parFlags & PF_COMPRESSED )
  1666.     {
  1667.     /* get enough space for the paragraph text then unpack the text */
  1668.  
  1669.     if ( nchars > textBufSize )
  1670.         {
  1671.         if ( textBuf )
  1672.         free( textBuf );
  1673.  
  1674.         textBufSize = round( par->parBytes, 1024 );
  1675.         textBuf = (byte *)malloc( textBufSize );
  1676.         }
  1677.     
  1678.     cp = textBuf;
  1679.     fp = dataBuf + 2;
  1680.     top = !0;
  1681.     for ( i = nchars; i-- > 0; )
  1682.         {
  1683.         if ( top )
  1684.         {
  1685.         last = *fp++;
  1686.         c = last >> 4;
  1687.         }
  1688.         else
  1689.         c = last;
  1690.  
  1691.         top = !top;
  1692.         c &= 0xf;
  1693.         if ( c != 0xf )
  1694.         *cp++ = COMPRESSION_STRING[c];
  1695.         else
  1696.         {
  1697.         if ( top )
  1698.             *cp++ = *fp++;
  1699.         else
  1700.             {
  1701.             c = (last & 0xf) << 4;
  1702.             last = *fp++;
  1703.             *cp++ = c | ((last >> 4) & 0xf);
  1704.             }
  1705.         }
  1706.         }
  1707.     td.text = textBuf;
  1708.     }
  1709.     else  /* not compressed */
  1710.     {
  1711.     td.text = dataBuf + 2;
  1712.     fp = td.text + nchars;
  1713.     }
  1714.  
  1715.     /* at this point, fp points to the start
  1716.      * of the format runs (a short giving the number of bytes
  1717.      * of format info).
  1718.      */
  1719.     if ( (int)fp & 1 )
  1720.     fp++;
  1721.  
  1722.     nformats = *(short *)fp;
  1723.     SWAP(nformats);
  1724.     formp = (struct format *)(fp + 2);
  1725.     td.formats = formp;
  1726.     td.nformats = nformats / sizeof(*formp);
  1727.  
  1728.     for ( i = nformats; i-- > 0; formp++ )
  1729.     SWAP( formp->charPos );
  1730.  
  1731.     return &td;
  1732. }
  1733.  
  1734. struct ruler *
  1735. read_ruler_par( f, par )
  1736.     struct infoArrayElem *par;
  1737. {
  1738.     static struct ruler ruler;
  1739.     register int i;
  1740.  
  1741.     lseek( f, par->dataPtr, 0 );
  1742.     if (read( f, &ruler, sizeof(ruler) ) != sizeof(ruler))
  1743.     error( "error reading ruler info" );
  1744.     SWAP( ruler.leftMargin );
  1745.     SWAP( ruler.rightMargin );
  1746.     SWAP( ruler.paraIndent );
  1747.     for ( i = 0; i < ruler.numTabs; i++ )
  1748.     SWAP( ruler.tabs[i] );
  1749.  
  1750.     return &ruler;
  1751. }
  1752.  
  1753.  
  1754.  
  1755. /* this table maps the Mac's extended character set into troff
  1756.  * characters.  It's set up for the standard Geneva font.  (it
  1757.  * should really be selected based on the current font)
  1758.  */
  1759. char *ctrans[] = {
  1760.     "\\(sq",    /* 0 */
  1761.     "\\(sq",    /* 1 */
  1762.     "\\(sq",    /* 2 */
  1763.     "\\(sq",    /* 3 */
  1764.     "\\(sq",    /* 4 */
  1765.     "\\(sq",    /* 5 */
  1766.     "\\(sq",    /* 6 */
  1767.     "\\(sq",    /* 7 */
  1768.     "\b",        /* 8 */
  1769.     "\t",        /* 9 */
  1770.     "\n",        /* 10 */
  1771.     "\\(sq",    /* 11 */
  1772.     "\f",        /* 12 */
  1773.     "\n",        /* 13 */
  1774.     "\\(sq",    /* 14 */
  1775.     "\\(sq",    /* 15 */
  1776.     "\\(sq",    /* 16 */
  1777.     "\\(sq",    /* 17 */
  1778.     "\\(sq",    /* 18 */
  1779.     "\\(sq",    /* 19 */
  1780.     "\\(sq",    /* 20 */
  1781.     "\\(sq",    /* 21 */
  1782.     "\\(sq",    /* 22 */
  1783.     "\\(sq",    /* 23 */
  1784.     "\\(sq",    /* 24 */
  1785.     "\\(sq",    /* 25 */
  1786.     "\\(sq",    /* 26 */
  1787.     "\\(sq",    /* 27 */
  1788.     "\\(sq",    /* 28 */
  1789.     "\\(sq",    /* 29 */
  1790.     "\\(sq",    /* 30 */
  1791.     "\\(sq",    /* 31 */
  1792.     " ",    /* 32 */
  1793.     "!",    /* 33 */
  1794.     "\"",    /* 34 */
  1795.     "#",    /* 35 */
  1796.     "$",    /* 36 */
  1797.     "%",    /* 37 */
  1798.     "&",    /* 38 */
  1799.     "'",    /* 39 */
  1800.     "(",    /* 40 */
  1801.     ")",    /* 41 */
  1802.     "*",    /* 42 */
  1803.     "+",    /* 43 */
  1804.     ",",    /* 44 */
  1805.     "-",    /* 45 */
  1806.     ".",    /* 46 */
  1807.     "/",    /* 47 */
  1808.     "0",    /* 48 */
  1809.     "1",    /* 49 */
  1810.     "2",    /* 50 */
  1811.     "3",    /* 51 */
  1812.     "4",    /* 52 */
  1813.     "5",    /* 53 */
  1814.     "6",    /* 54 */
  1815.     "7",    /* 55 */
  1816.     "8",    /* 56 */
  1817.     "9",    /* 57 */
  1818.     ":",    /* 58 */
  1819.     ";",    /* 59 */
  1820.     "<",    /* 60 */
  1821.     "=",    /* 61 */
  1822.     ">",    /* 62 */
  1823.     "?",    /* 63 */
  1824.     "@",    /* 64 */
  1825.     "A",    /* 65 */
  1826.     "B",    /* 66 */
  1827.     "C",    /* 67 */
  1828.     "D",    /* 68 */
  1829.     "E",    /* 69 */
  1830.     "F",    /* 70 */
  1831.     "G",    /* 71 */
  1832.     "H",    /* 72 */
  1833.     "I",    /* 73 */
  1834.     "J",    /* 74 */
  1835.     "K",    /* 75 */
  1836.     "L",    /* 76 */
  1837.     "M",    /* 77 */
  1838.     "N",    /* 78 */
  1839.     "O",    /* 79 */
  1840.     "P",    /* 80 */
  1841.     "Q",    /* 81 */
  1842.     "R",    /* 82 */
  1843.     "S",    /* 83 */
  1844.     "T",    /* 84 */
  1845.     "U",    /* 85 */
  1846.     "V",    /* 86 */
  1847.     "W",    /* 87 */
  1848.     "X",    /* 88 */
  1849.     "Y",    /* 89 */
  1850.     "Z",    /* 90 */
  1851.     "[",    /* 91 */
  1852.     "\\",    /* 92 */
  1853.     "]",    /* 93 */
  1854.     "^",    /* 94 -  hat accent */
  1855.     "_",    /* 95 */
  1856.     "\\(aa",    /* 96 -  acute accent */
  1857.     "a",    /* 97 */
  1858.     "b",    /* 98 */
  1859.     "c",    /* 99 */
  1860.     "d",    /* 100 */
  1861.     "e",    /* 101 */
  1862.     "f",    /* 102 */
  1863.     "g",    /* 103 */
  1864.     "h",    /* 104 */
  1865.     "i",    /* 105 */
  1866.     "j",    /* 106 */
  1867.     "k",    /* 107 */
  1868.     "l",    /* 108 */
  1869.     "m",    /* 109 */
  1870.     "n",    /* 110 */
  1871.     "o",    /* 111 */
  1872.     "p",    /* 112 */
  1873.     "q",    /* 113 */
  1874.     "r",    /* 114 */
  1875.     "s",    /* 115 */
  1876.     "t",    /* 116 */
  1877.     "u",    /* 117 */
  1878.     "v",    /* 118 */
  1879.     "w",    /* 119 */
  1880.     "x",    /* 120 */
  1881.     "y",    /* 121 */
  1882.     "z",    /* 122 */
  1883.     "{",    /* 123 */
  1884.     "|",    /* 124 */
  1885.     "}",    /* 125 */
  1886.     "~",        /* 126 -  circumflex accent */
  1887.     "\\(sq",    /* 127 */
  1888.     "\\zA\\v'-1m'.\\h'-0.1m'.\\v'+1m'",    /* 128 -  upper A with omlat */
  1889.     "\\zA\\u\\(de\\d",    /* 129 -  upper circle A (A) */
  1890.     "C",        /* 130 -  upper C with cedilla */
  1891.     "\\o.E'.",    /* 131 -  upper E accent grave */
  1892.     "\\zN\\u~\\d",    /* 132 -  upper N with circumflex */
  1893.     "\\zO\\v'-1m'.\\h'-0.1m'.\\v'+1m'",    /* 133 -  upper O with omlat */
  1894.     "\\zU\\v'-1m'.\\h'-0.1m'.\\v'+1m'",    /* 134 -  upper U with omlat */
  1895.     "\\o.a'.",    /* 135 -  lower a accent grave */
  1896.     "\\o.a`.",    /* 136 -  lower a accent acute */
  1897.     "\\o.a^.",    /* 137 -  lower a with hat */
  1898.     "\\za\\u.\\h'-0.1m'.\\d",    /* 138 -  lower a with omlat */
  1899.     "\\o.a~.",    /* 139 -  lower a with circumflex */
  1900.     "\\o'a\\(de'",    /* 140 -  lower a with circle */
  1901.     "c",        /* 141 -  c with cedilla */
  1902.     "\\o.e'.",    /* 142 -  lower e accent grave */
  1903.     "\\o.e`.",    /* 143 -  lower e accent acute */
  1904.     "\\o.e^.",    /* 144 -  lower e with hat */
  1905.     "\\ze\\u.\\h'-0.1m'.\\d",    /* 145 -  lower e with omlat */
  1906.     "\\o.i'.",    /* 146 -  lower i accent grave */
  1907.     "\\o.i`.",    /* 147 -  lower i accent acute */
  1908.     "\\o.i^.",    /* 148 -  lower i with hat */
  1909.     "\\zi\\u.\\h'-0.1m'.\\d",    /* 149 - lower i with omlat */
  1910.     "\\o.n~.",    /* 150 -  lower n with circumflex */
  1911.     "\\o.o'.",    /* 151 -  lower o accent grave */
  1912.     "\\o.o`.",    /* 152 -  lower o accent acute */
  1913.     "\\o.o^.",    /* 153 -  lower o with hat */
  1914.     "\\zo\\u.\\h'-0.1m'.\\d",    /* 154 -  lower o with omlat */
  1915.     "\\o.o~.",    /* 155 -  lower o with circumflex */
  1916.     "\\o.u'.",    /* 156 -  lower u accent grave */
  1917.     "\\o.u`.",    /* 157 -  lower u accent acute */
  1918.     "\\o.u^.",    /* 158 -  lower u with hat */
  1919.     "\\zu\\u.\\h'-0.1m'.\\d",    /* 159 -  lower u with omlat */
  1920.     "\\(dg",    /* 160 -  dagger */
  1921.     "\\(de",    /* 161 -  degrees (shift option 8) */
  1922.     "\\o'c/'",    /* 162 -  cents */
  1923.     "\\f2\\o'L-'\\fP",    /* 163 -  pounds (currency) */
  1924.     "\\(sc",    /* 164 -  section mark */
  1925.     "\\(bu",    /* 165 -  bullet */
  1926.     "\\(rh",    /* 166 -  paragraph */
  1927.     "\\(*b",    /* 167 -  beta (german "ss") */
  1928.     "\\(rg",    /* 168 -  registered */
  1929.     "\\(co",    /* 169 -  copyright */
  1930.     "\\u\\s-4TM\\s0\\d",    /* 170 -  trademark */
  1931.     "\\(ag",    /* 171 -  grave accent */
  1932.     "\\u.\\h'-0.1m'.\\d",    /* 172 -  oomlat accent */
  1933.     "\\(!=",    /* 173 -  not equal */
  1934.     "\\f2A\\fP\\h'-0.2m'E",        /* 174 -  upper AE ligature */
  1935.     "\\zO/",    /* 175 -  slash upper O (O) */
  1936.     "\\(if",    /* 176 -  infinity */
  1937.     "\\(+-",    /* 177 -  plus minus (shift option =) */
  1938.     "\\(<=",    /* 178 -  <= */
  1939.     "\\(>=",    /* 179 -  >= */
  1940.     "\\o'Y\\s-2=\\s0'",    /* 180 -  yen */
  1941.     "\\(*m",    /* 181 -  lower mu */
  1942.     "\\(pd",    /* 182 -  "partial" */
  1943.     "\\(*S",    /* 183 -  upper sigma */
  1944.     "\\(*P",    /* 184 -  upper PI (P) */
  1945.     "\\(*p",    /* 185 -  lower pi */
  1946.     "\\(is",    /* 186 -  integral sign */
  1947.     "\\u\\za\\(ul\\d'",    /* 187 -  underbar lowercase a */
  1948.     "\\u\\zo\\(ul\\d'",    /* 188 -  underbar lowercase o */
  1949.     "\\(*W",    /* 189 -  upper omega */
  1950.     "a\\h'-0.2m'e",        /* 190 -  lower ae ligature */
  1951.     "\\o'o/'",    /* 191 -  slashed lower o */
  1952.     "?",        /* 192 -  upside down ? (?) */
  1953.     "\\(*i",    /* 193 -  lower case i */
  1954.     "\\(no",    /* 194 -  negation */
  1955.     "\\(sr",    /* 195 -  square root or check mark */
  1956.     "\\z\\(is\\s-2\\(ci\\s0",    /* 196 -  contour integral */
  1957.     "\\(~=",    /* 197 -  approx */
  1958.     "\\(*D",    /* 198 -  triangle (upper delta) */
  1959.     "\\s-2<\\h'-0.3m'<\\s0",    /* 199 -  open double angle brackets */
  1960.     "\\s-2>\\h'-0.3m'>\\s0",    /* 200 -  close double angles */
  1961.     "...",        /* 201 -  elipses (3 dots) */
  1962.     "\\ ",        /* 202 -  unpaddable space */
  1963.     "\\o'`A'",    /* 203 -  `A */
  1964.     "\\o'~A'",    /* 203 -  A with circumflex */
  1965.     "\\o'~O'",    /* 203 -  O with circumflex */
  1966.     "O\\h'-0.1m'E",        /* 206 -  upper OE ligature */
  1967.     "o\\h'-0.1m'e",        /* 207 -  lower oe ligature */
  1968.     "\\(hy",    /* 208 -  hyphen */
  1969.     "\\(em",    /* 209 -  m dash (shift option -) */
  1970.     "``",        /* 210 -  back double quote */
  1971.     "''",        /* 211 -  close double quote */
  1972.     "`",        /* 212 -  back single quote */
  1973.     "'",        /* 213 -  close single quote */
  1974.     "\\(di",    /* 214 -  divide */
  1975.     "\\(gr",    /* 215 -  diamond (V) */
  1976.     "\\zy\\u.\\h'-0.1m'.\\d",    /* 216 -  y with omlat */
  1977.     "\\(sq",    /* 217 */
  1978.     "\\(sq",    /* 218 */
  1979.     "\\(sq",    /* 219 */
  1980.     "\\(sq",    /* 220 */
  1981.     "\\(sq",    /* 221 */
  1982.     "\\(sq",    /* 222 */
  1983.     "\\(sq",    /* 223 */
  1984.     "\\(sq",    /* 224 */
  1985.     "\\(sq",    /* 225 */
  1986.     "\\(sq",    /* 226 */
  1987.     "\\(sq",    /* 227 */
  1988.     "\\(sq",    /* 228 */
  1989.     "\\(sq",    /* 229 */
  1990.     "\\(sq",    /* 230 */
  1991.     "\\(sq",    /* 231 */
  1992.     "\\(sq",    /* 232 */
  1993.     "\\(sq",    /* 233 */
  1994.     "\\(sq",    /* 234 */
  1995.     "\\(sq",    /* 235 */
  1996.     "\\(sq",    /* 236 */
  1997.     "\\(sq",    /* 237 */
  1998.     "\\(sq",    /* 238 */
  1999.     "\\(sq",    /* 239 */
  2000.     "\\(sq",    /* 240 */
  2001.     "\\(sq",    /* 241 */
  2002.     "\\(sq",    /* 242 */
  2003.     "\\(sq",    /* 243 */
  2004.     "\\(sq",    /* 244 */
  2005.     "\\(sq",    /* 245 */
  2006.     "\\(sq",    /* 246 */
  2007.     "\\(sq",    /* 247 */
  2008.     "\\(sq",    /* 248 */
  2009.     "\\(sq",    /* 249 */
  2010.     "\\(sq",    /* 250 -  box (option h) */
  2011.     "\\(sq",    /* 251 -  box (option k) */
  2012.     "\\(sq",    /* 252 */
  2013.     "\\(sq",    /* 253 */
  2014.     "\\(sq",    /* 254 */
  2015.     "\\(sq",    /* 255 */
  2016.     0 };
  2017.  
  2018. putcharExtended(c)
  2019. unsigned char c;
  2020. {
  2021.     printf("%s", ctrans[c]);
  2022.     return( strlen( ctrans[c] ) );
  2023. }
  2024.  
  2025. error( str )
  2026.     char    *str;
  2027. {
  2028.     fprintf( stderr, "-w2t: %s.\n", str );
  2029.     exit(1);
  2030. }
  2031. 'EOF'
  2032. echo -n '         ' ; ls -l w
  2033.