/* ** ** mwxlate ** ** This program interprets a MacWrite document and translates it to a batch ** document format like troff, script, tex or scribe, depending upon the backend ** functions ** ** Norman Meyrowitz ** IRIS (Institute for Research in Information and Scholarship) ** Brown University ** Box 1946 ** Providence, RI 02912 ** ** August, 1984 ** ** (c) 1984 Brown University ** ** ** REVISION HISTORY ** ** Version Date Author Description ** ** 0.8 8/29/84 nkm Translates from MacWrite to WSCRIPT ** Headers and footers disabled ** ** 0.9 11/28/84 nkm TROFF enhancements added ** 12/4/84 tep added switch for imagen output for TROFF ** ** 0.95 1/2/85 nkm Cleaned up FilterText, fixed tabs, added Greek ** ** 0.97 1/26/85 nkm Fixed terminal .br bug, added TM sign in Script ** ** 1.00 1/29/85 nkm FIRST RELEASE ** ** 1.01 2/4/85 nkm Fixed Subscript/Superscript bug in SCRIPT ** ** KNOWN BUGS/FEATURES NOT IMPLEMENTED ** ** - Headers and footers (including date and time) not implemented ** ** - Tabs not guaranteed to work after first line of paragraph (TROFF ** only) ** ** - Decimal tabs are treated as right-aligned tabs (TROFF only, TROFF ** imposed limitation) ** ** - Tabs may not work on lines with font changes (TROFF only) ** ** - Pictures are always treated as a page advance ** ** */ #include #include #include #include /* ** ** C O N S T A N T D E F I N I T I O N S ** */ #define VALIDVERSION 3 /* ID of valid document from MacWrite 2.2 */ #define TEMPFILE "/tmp/#mwxXXXXXX" /* Template for filename of xlated file */ #define MAIN 0 /* Document Types */ #define HEADER 1 #define FOOTER 2 #define RULER 0 /* Paragraph Types */ #define TEXT 1 #define PICTURE 2 #ifdef WSCRIPT # define SPOOLPATH "/a/mac/mwspool" /* Pathname of pgm that sends to 9700 */ # define SPOOLNAME "mwspool" #endif #ifdef TROFF # define SPOOLPATH "/a/mac/mwtoip" /* Pathname of pgm to send to Imagen */ # define SPOOLNAME "mwtoip" #endif /* Error Codes */ #define TOOMANYARGS -1 #define CANTOPENINPUT -2 #define CANTOPENOUTPUT -3 #define CANTWRITETEMP -4 #define CANTFINDHEADER -5 #define INVALIDVERSION -6 /* ** ** T Y P E D E F I N I T I O N S ** */ typedef unsigned char BYTE; /* An 8-bit, unsigned quantity */ typedef short WORD; /* A 16-bit, unsigned quantity */ typedef struct { /* Holds paragraph number, character */ WORD paragraphNumber; /* num of one end of a selection */ WORD characterPosition; } SELECTION; typedef struct { /* Holds y,x QuickDraw coordinates */ WORD vertical; WORD horizontal; } POSITION; typedef struct { /* Holds information pertaining to */ SELECTION startOfSelection; /* document state when document */ SELECTION endOfSelection; /* was last stored (not used) */ WORD verticalOffset; WORD needToRedraw; POSITION pageNumberPosition; POSITION datePosition; POSITION timePosition; POSITION timeCoordinates; BYTE iconRedraw; BYTE iconFlag; WORD activeFontNumber; WORD activeStyleNumber; } DOCUMENTVARIABLES; typedef struct { /* One entry for each paragraph */ WORD height; /* the document to specify page */ WORD position; /* it falls on and its position on */ BYTE pageNumber; /* that page in QuickDraw coords */ BYTE unused[3]; /* (not used) */ } INFOARRAYELEMENT; typedef struct { /* Each time an attribute (font, */ WORD characterPosition; /* type size, type style) changes */ BYTE pointSize; /* a format element is created. It */ BYTE style; /* contains the character position */ WORD fontNumber; /* in the paragraph where the */ } FORMATELEMENT; /* change occurs & the new attribs */ typedef struct { /* Created for each RULER in the doc */ WORD leftMargin; /* - In 1/80ths of an inch, with an */ WORD rightMargin; /* offset of 1", e.g. 30 => 1 3/8" */ BYTE justification; /* - 0=left, 1=ctr, 2=right, 3=full */ BYTE numberOfTabs; /* - Number between 1 and 10 */ BYTE unused1; /* - Unused */ BYTE spacing; /* - 0=single, 1 = 1 1/2, 2=double */ WORD indentMargin; /* - 1st line, same measures as abv */ WORD tabs[10]; /* - Up to 10, measured as above, */ WORD unused2[2]; /* negative for decimal tabs */ } RULERRECORD; typedef struct { /* Variables used to hold status */ WORD versionNumber; /* info while MacWrite is running */ WORD paragraphOffset; /* (not used) */ WORD paragraphCount[3]; BYTE titlePageFlag; BYTE scrapShowFlag; BYTE footerDisplayedFlag; BYTE headerDisplayedFlag; BYTE rulersShowingFlag; BYTE spareByte; WORD activeDocumentNumber; WORD startingPageNumber; } GLOBALVARIABLES; typedef struct { /* Precedes paras stored on disk */ WORD type; /* - 0=ruler, 1=text, 2=bitmap */ WORD length; /* - Number of bytes in entire para */ } PARAGRAPHDATAHEADER; typedef struct { /* For text paragraphs... */ WORD length; /* - Number of bytes of text */ BYTE *ascii; /* -> To that text */ WORD formatRunLength; /* - Number of bytes of format info */ } PARAGRAPHTEXTRECORD; typedef struct { /* Printing variables (not used) */ BYTE vars[120] } PRINTINGVARIABLES; /* ** ** G L O B A L V A R I A B L E S ** */ char *versionString = "1.01 2/4/85 15:50";/* Used by DocProlog for comment */ INFOARRAYELEMENT infoArray; /* Used to pass over info in data */ GLOBALVARIABLES globVar; /* Used to pass over global doc vars */ DOCUMENTVARIABLES docs[3]; /* 1 for main, 1 for hdr, 1 for foot */ PARAGRAPHDATAHEADER pDataHead; /* Holds current paragraph info */ PARAGRAPHTEXTRECORD pTextRec; /* Holds current info for text para */ PRINTINGVARIABLES printVar; /* Used to pass over print vars */ RULERRECORD rulerRec; /* Holds current ruler information */ BYTE buffer[2048]; /* Temporary buffer */ int bufferPtr; /* Index into buffer */ BYTE *textBuf; /* Pointer to buffer */ /* ** ** main(argc,argv) ** */ main(argc,argv) int argc; /* Number of arguments */ char **argv; /* Array of pointers to arg strings */ { register int j, k; /* Loop counters */ register int spool; /* True if -s option is used */ register int fdIn; /* Holds file desc of input file */ static char *tempFile = TEMPFILE; /* File to write xlated version to */ struct stat statBuf; /* Holds result of file status query */ char string[96]; /* Used to prepare "system" call */ /* In spooling mode, *arg[1] is the MacWrite file to be translated and */ /* *arg[2] is a header file containing filename and accounting info. In */ /* regular mode, if there is an arg[1] and arg[2] (i.e. if file */ /* indirection isn't being used), *arg[1] is the MacWrite file and */ /* *arg[2] is the name of the file to be written. */ /* If there are four args (including the command name) and the last is */ /* "-s", then turn spooling on. */ if (argc == 4) { if (argv[3][0] == '-' && argv[3][1] == 's') spool = 1; } else spool = 0; /* If more than four args, or four args but last isn't "-s", error */ if ((argc > 4) || (argc == 4 && !spool)) { fprintf(stderr, "Usage: mwxlate [file1 file2 [-s]]\n"); exit(TOOMANYARGS); } /* start out with std input and output coming from indirected files */ /* and change if arguments specify explicit files */ if (spool) { /* if we're spooling, open temp file as std output in stream mode */ if (freopen(mktemp(tempFile),"w",stdout) == NULL) { fprintf(stderr,"mwxlate: can't open temp file%s\n",tempFile); exit(CANTWRITETEMP); } if (stat(argv[2],&statBuf)) { fprintf(stderr,"mwxlate: cannot find spool header file %s\n",argv[2]); exit(CANTFINDHEADER); } } else if (argc == 3) { /* both in and out files have been specified */ /* open file2 as std output, in stream mode for printf */ if (freopen(argv[2],"w",stdout) == NULL) { fprintf(stderr,"mwxlate: invalid output filename %s\n",argv[2]); exit(CANTOPENOUTPUT); } } if (argc >= 2) { /* the input file has been specified explictly */ /* open file1 as std input, in low-level read mode */ if ((fdIn = open(argv[1],O_RDONLY,0644)) < 0) { fprintf(stderr,"mwxlate: invalid input filename %s\n",argv[1]); exit(CANTOPENINPUT); } dup2(fdIn,0); /* force std input to point to this file */ close(fdIn); } GetGlobalVars(); GetPrintingVars(); GetDocumentVars(MAIN); GetDocumentVars(HEADER); GetDocumentVars(FOOTER); GetInfoArray(MAIN); GetInfoArray(HEADER); GetInfoArray(FOOTER); DocProlog(versionString); /* Put initial information in output file */ GetParagraphs(MAIN); /* Routine to read & process all para in main */ /* DocHeaderProlog(); GetParagraphs(HEADER); DocHeaderEpilog(); */ /* GetParagraphs(FOOTER); */ DocEpilog(); /* Put terminating information in output file */ /* Cleanup files, if spooling, send result on down the pipeline */ close(0); fclose(stdout); if (spool) { /* remove MacWrite file */ if (unlink(argv[1]) != NULL) fprintf(stderr,"mwxlate: Can't remove macwrite file %s\n",argv[1]); /* send the translated file (tempfile) and the header file (argv[2]) */ /* to the spooler programe for printing */ execl(SPOOLPATH,SPOOLNAME,tempFile,argv[2],0); _exit(1); /* exec failed */ } } /* ** ** U T I L I T Y R O U T I N E S ** */ /* ** ** BYTE getByte() ** ** getByte is a utility routine that maintains a current pointer into the ** global "buffer" array. When called, getByte returns the byte currently ** pointed at by bufferPtr and then increments that pointer. ** */ BYTE getByte() { return(buffer[bufferPtr++]); } /* ** ** WORD getWord() ** ** getWord is a utility routine that maintains a current pointer into the ** global "buffer" array and returns the 16-bit integer stored at that ** location. In MacWrite, these integers are stored with byte 0 (the left ** byte) holding the most significant bits and byte 1 (the right byte) ** holding the least significant bits. This routine reads byte 0, ** shifts it left 8 bits and masks it with 0xff00 to have it become ** the high-order byte and then takes byte one masked with 0xff and ** ors the two together to make a 16-bit integer. This process assures ** that regardless of the byte order of machine storage, the appropriate ** 16-bit value will be returned. The bufferPtr is moved past the word. ** */ WORD getWord() { WORD retVal; retVal = (((buffer[bufferPtr]<<8)&0xFF00) | ((buffer[bufferPtr+1])&0xFF)); bufferPtr += 2; return(retVal); } /* ** ** BYTE peekByte() ** ** Provides same functionality as getByte, but does not increment bufferPtr. ** */ BYTE peekByte() { return(buffer[bufferPtr]); } /* ** ** WORD peekWord() ** ** Provides same functionality as getWord, but does not increment bufferPtr. ** */ WORD peekWord() { return(((buffer[bufferPtr]<<8)&0xFF00) | ((buffer[bufferPtr+1])&0xFF)); } /* ** ** readBuf(size) ** ** readBuf fills the global "buffer" array with size bytes read directly ** from the MacWrite document on disk. After reading, the master pointer ** to that buffer -- bufferPtr -- is set to point to the byte 0 of the buffer ** */ readBuf(size) int size; { read(0,buffer,size); bufferPtr = 0; } /* ** ** getNextType() ** ** A frequent necessity in the translation process is to determine the type ** of the next paragraph. getNextType fills the global buffer with the 16-bit ** integer that specifies the paragraph type. ** */ getNextType() { readBuf(2); pDataHead.type = getWord(); } /* ** ** getNextLength() ** ** A frequent necessity in the translation process is to determine the length ** of the data for the next paragraph. getNextLength fills the global buffer ** with the 16-bit integer that specifies that length. ** */ getNextLength() { readBuf(2); pDataHead.length = getWord(); } /* ** ** S U B R O U T I N E S ** */ /* ** ** GetGlobalVars() ** ** GetGlobalVars reads in the 20 bytes of information expected in the ** global area section of the stored MacWrite document. None of these ** are used except the versionNumber, which must be equal to 3 if this ** is a valid MacWrite 2.2 document. This test fairly adequately weeds ** out non-MacWrite documents that are passed to the program for ** translation (there is a 1 in 65536 chance that a bad document will ** have a 3 in this slot, but those are small odds). The other variables ** are read in but never used. If compiled with the DEBUG flag, the ** routine will print out the values of all these variables on stderr. ** ** Called by: main ** Calls: readbuf ** getByte, getWord ** Parms: ** Returns: ** */ GetGlobalVars() { readBuf(20); globVar.versionNumber = getWord(); if (globVar.versionNumber != VALIDVERSION) { fprintf(stderr,"mwxlate: macwrite version # %d wrong, should be %d\n", globVar.versionNumber,VALIDVERSION); exit(INVALIDVERSION); } globVar.paragraphOffset = getWord(); globVar.paragraphCount[MAIN] = getWord(); globVar.paragraphCount[HEADER] = getWord(); globVar.paragraphCount[FOOTER] = getWord(); globVar.titlePageFlag = getByte(); globVar.scrapShowFlag = getByte(); globVar.footerDisplayedFlag = getByte(); globVar.headerDisplayedFlag = getByte(); globVar.rulersShowingFlag = getByte(); globVar.spareByte = getByte(); globVar.activeDocumentNumber = getWord(); globVar.startingPageNumber = getWord(); #ifdef DEBUG fprintf(stderr,"versionNumber = %d\n",globVar.versionNumber); fprintf(stderr,"paragraphOffset = %d\n",globVar.paragraphOffset); fprintf(stderr,"paragraphCount[MAIN] = %d\n", globVar.paragraphCount[MAIN]); fprintf(stderr,"paragraphCount[HEADER] = %d\n", globVar.paragraphCount[HEADER]); fprintf(stderr,"paragraphCount[FOOTER] = %d\n", globVar.paragraphCount[FOOTER]); fprintf(stderr,"titlePageFlag = %d\n",globVar.titlePageFlag); fprintf(stderr,"scrapShowFlag = %d\n",globVar.scrapShowFlag); fprintf(stderr,"footerDisplayedFlag = %d\n",globVar.footerDisplayedFlag); fprintf(stderr,"headerDisplayedFlag = %d\n",globVar.headerDisplayedFlag); fprintf(stderr,"rulersShowingFlag = %d\n",globVar.rulersShowingFlag); fprintf(stderr,"spareByte = %d\n",globVar.spareByte); fprintf(stderr,"activeDocumentNumber = %d\n",globVar.activeDocumentNumber); fprintf(stderr,"startingPageNumber = %d\n",globVar.startingPageNumber); #endif } /* ** ** GetPrintingVars() ** ** This routine simply reads in the 120 bytes of printing variables ** stored in the MacWrite document for purposes of flushing them. ** ** Called by: main ** Calls: readBuf ** Parms: ** Returns: ** */ GetPrintingVars() { readBuf(120); /* throw away printing variables for time being */ } /* ** ** GetDocumentVars(j) ** ** GetDocumentVars reads in the document variables associated with ** each of the the three types of documents stored in the MacWrite file ** and stores them in the appropriate entry in the global array "docs." ** These currently aren't used, but the date and time values will be of ** use in trying to implement the date and time tags for full headers ** (currently not implemented). Compiled with the DEBUG flag, the values ** of the variables are printed on stderr. ** ** Called by: main ** Calls: readBuf ** Parms: int -- 0 for main doc, 1 for hdr doc, 2 for footer doc ** Returns: ** */ GetDocumentVars(j) int j; /* 0 = main, 1 = header, 2 = footer */ { readBuf(34); docs[j].startOfSelection.paragraphNumber = getWord(); docs[j].startOfSelection.characterPosition = getWord(); docs[j].endOfSelection.paragraphNumber = getWord(); docs[j].endOfSelection.characterPosition = getWord(); docs[j].verticalOffset = getWord(); docs[j].needToRedraw = getWord(); docs[j].pageNumberPosition.vertical = getWord(); docs[j].pageNumberPosition.horizontal = getWord(); docs[j].datePosition.vertical = getWord(); docs[j].datePosition.horizontal = getWord(); docs[j].timePosition.vertical = getWord(); docs[j].timePosition.horizontal = getWord(); docs[j].timeCoordinates.vertical = getWord(); docs[j].timeCoordinates.horizontal = getWord(); docs[j].iconRedraw = getByte(); docs[j].iconFlag = getByte(); docs[j].activeFontNumber = getWord(); docs[j].activeStyleNumber = getWord(); #ifdef DEBUG fprintf(stderr,"docs[%d].startOfSelection.paragraphNumber = %d\n",j,docs[j].startOfSelection.paragraphNumber); fprintf(stderr,"docs[%d].startOfSelection.characterPosition = %d\n",j,docs[j].startOfSelection.characterPosition); fprintf(stderr,"docs[%d].endOfSelection.paragraphNumber = %d\n",j,docs[j].endOfSelection.paragraphNumber); fprintf(stderr,"docs[%d].endOfSelection.characterPosition = %d\n",j,docs[j].endOfSelection.characterPosition); fprintf(stderr,"docs[%d].verticalOffset = %d\n",j,docs[j].verticalOffset); fprintf(stderr,"docs[%d].needToRedraw = %d\n",j,docs[j].needToRedraw); fprintf(stderr,"docs[%d].pageNumberPosition.vertical = %d\n",j,docs[j].pageNumberPosition.vertical); fprintf(stderr,"docs[%d].pageNumberPosition.horizontal = %d\n",j,docs[j].pageNumberPosition.horizontal); fprintf(stderr,"docs[%d].datePosition.vertical = %d\n",j,docs[j].datePosition.vertical); fprintf(stderr,"docs[%d].datePosition.horizontal = %d\n",j,docs[j].datePosition.horizontal); fprintf(stderr,"docs[%d].timePosition.vertical = %d\n",j,docs[j].timePosition.vertical); fprintf(stderr,"docs[%d].timePosition.horizontal = %d\n",j,docs[j].timePosition.horizontal); fprintf(stderr,"docs[%d].timeCoordinates.vertical = %d\n",j,docs[j].timeCoordinates.vertical); fprintf(stderr,"docs[%d].timeCoordinates.horizontal = %d\n",j,docs[j].timeCoordinates.horizontal); fprintf(stderr,"docs[%d].iconRedraw = %d\n",j,docs[j].iconRedraw); fprintf(stderr,"docs[%d].iconFlag = %d\n",j,docs[j].iconFlag); fprintf(stderr,"docs[%d].activeFontNumber = %d\n",j,docs[j].activeFontNumber); fprintf(stderr,"docs[%d].activeStyleNumber = %d\n",j,docs[j].activeStyleNumber); #endif } /* ** ** GetInfoArray(which) ** ** GetInfoArray, depending on the which parameter -- which selects ** whether to look at the main document (0), the header (1), or the ** footer (2) -- reads the page layout information for each paragraph ** in that document. This consists of reading 8 bytes for each paragraph ** and putting a 16-bit value in the height slot, a 16-bit value in the ** position slot, and an 8-bit value in the pageNumber slot. The ** remaining two bytes that were read are disregarded. If compiled with ** the DEBUG flag, the information for each paragraph is printed on ** stderr. Currently, this information is not used in the translator ** and is simply flushed. ** ** Called by: main ** Calls: readBuf ** getByte, getWord ** Parms: int -- identifies which doc (main,hdr,footer) ** Returns: ** */ GetInfoArray(which) int which; { register int k; for (k = 0; k < globVar.paragraphCount[which]; k++) { readBuf(8); infoArray.height = getWord(); infoArray.position = getWord(); infoArray.pageNumber = getByte(); #ifdef DEBUG fprintf(stderr,"%d, Paragraph %d, height = %d\n",which,k,infoArray.height); fprintf(stderr,"%d, Paragraph %d, position = %d\n",which,k,infoArray.position); fprintf(stderr,"%d, Paragraph %d, pageNumber = %d\n",which,k,infoArray.pageNumber); #endif } } /* ** GetParagraphs(which) ** ** Depending upon the which parameter (which distinguishs the main, header, ** and footer documents) this routine dispatches the appropriate routines ** to handle ruler paragraphs, text paragraphs, and picture paragraphs. ** It loops for the number of paragraphs in the "which" document, getting ** the paragraph type and the length of that paragraph each time through ** the loop. It then cases on the type and calls the appropriate routines ** to handle that type. For rulers, GetRulerData reads in the paragraph ** data in ruler format and translates it, for text, GetTextData reads in ** the users's ascii data and GetFormatData reads in the formatting data, ** combines it with the text data, and translates both. For pictures, ** GetPictureData is meant to read in the picture data and translate it. ** (Currently it only uses GetPictureData to skip over the picture data ** and generate new pages). ** ** Called by: main ** Calls: GetRulerData ** GetTextData ** GetFormatData ** GetPictureData ** getNextType ** getNextLength ** Parms: int -- which document to select ** Returns: */ GetParagraphs(which) int which; { register int k; /* loop counter */ for (k = 0; k < globVar.paragraphCount[which]; k++) { getNextType(); getNextLength(); switch(pDataHead.type) { case RULER: GetRulerData(); break; case TEXT: GetTextData(); GetFormatData(); break; case PICTURE: GetPictureData(); break; default: fprintf(stderr, "Erroneous type %d\n",pDataHead.type); /* should never be reached */ } } } /* ** ** GetRulerData() ** ** GetRulerData reads the information about a ruler paragraph into the ** global "rulerRec" structure. First the routine uses readBuf to read ** in the number of bytes specified in the pDataHead.length global ** variable (which was filled in the GetParagraphData routine using ** the getNextLength utility routine). Next, it reads the information ** into the appropriate structure slots, using getWord and getByte. ** LeftMargin, rightMargin, indentMargin, and tabs are specified in ** 1/80ths of an inch, with an offset of 1", such that a value of ** 60 corresponds to 1 3/4" on the MacWrite ruler. In tabs, a negative ** value means that is a decimal tab; the absolute value specifies the ** position. If the DEBUG flag is set, than the contents of each slot ** is printed on stderr. When all is read, this routine calls ** ProcessRulerData to invoke the translation for the rulers. ** ** Called by: GetParagraphData ** Calls: readBuf ** getByte, getWord ** ProcessRulerData ** Parms: ** Returns: ** */ GetRulerData() { register int j; readBuf(pDataHead.length); rulerRec.leftMargin = getWord(); rulerRec.rightMargin = getWord(); rulerRec.justification = getByte(); rulerRec.numberOfTabs = getByte(); rulerRec.unused1 = getByte(); rulerRec.spacing = getByte(); rulerRec.indentMargin = getWord(); for (j = 0; j < 10; j++) rulerRec.tabs[j] = getWord(); for (j = 0; j < 2; j++) { rulerRec.unused2[j] = getWord(); } #ifdef DEBUG fprintf(stderr,"rulerRec.leftMargin = %d\n",rulerRec.leftMargin); fprintf(stderr,"rulerRec.rightMargin = %d\n",rulerRec.rightMargin); fprintf(stderr,"rulerRec.spacing = %d\n",rulerRec.spacing); fprintf(stderr,"rulerRec.numberOfTabs = %d\n",rulerRec.numberOfTabs); fprintf(stderr,"rulerRec.unused1 = %d\n",rulerRec.unused1); fprintf(stderr,"rulerRec.justification = %d\n",rulerRec.justification); fprintf(stderr,"rulerRec.indentMargin = %d\n",rulerRec.indentMargin); for (j = 0; j < 10; j++) fprintf(stderr,"rulerRec.tabs[j] = %d\n",rulerRec.tabs[j]); for (j = 0; j < 2; j++) fprintf(stderr,"rulerRec.unused2[j] = %d\n",rulerRec.unused2[j]); #endif ProcessRulerData(); /* invoke the translation process */ } /* ** ** GetTextData() ** ** GetTextData reads in the ascii text of a text paragraph. The first ** two bytes of a text paragraph hold the number of characters to read, ** and as such, the first action in this routine is to use readBuf to ** read those bytes in and getWord to assign them to pTextRec.length. ** ** Next, malloc is used to generate dynamic storage to hold text of this ** length (+1 for an ending null) and the global text pointer "textBuf" ** is set to point to this storage. Next, using a system read, the ascii ** text is actually read into textBuf, and the last character of textBuf ** is assigned a terminating null. Since MacWrite starts the next significant ** data on a word boundary, the routine realigns if the number of bytes ** read was odd. Finally, DocParaProlog is called to tell the backend that ** we are ready to start translation for a text paragraph. If VERBOSEDEBUG ** is set, the full text is printed out. ** ** Called by: GetParagraphData ** Calls: readBuf ** getWord ** DocParaProlog ** Parms: ** Returns: ** */ GetTextData() { readBuf(2); pTextRec.length = getWord(); #ifdef VERBOSEDEBUG fprintf(stderr,"pTextRec.length = %d\n", pTextRec.length); #endif textBuf = (BYTE *) malloc(pTextRec.length+1); read(0,textBuf,pTextRec.length); textBuf[pTextRec.length] = 0; #ifdef VERBOSEDEBUG fprintf(stderr,"Text is: %s\n",textBuf); #endif if (pTextRec.length % 2) readBuf(1); /* if str len was odd, need to word align */ DocParaProlog((rulerRec.indentMargin - rulerRec.leftMargin)/80.0); } /* ** ** GetFormatData() ** ** GetFormatData is one of the workhorses of the translator. After a ** text paragraph's text data is read in, GetFormatData is called to ** read in the corresponding format data, which is stored as a sequence ** of FORMATELEMENT structures, one for each change in formatting in the ** paragraph. Initially the routine readBufs in 2 bytes and assigns it ** to pTextRec.formatRunLength; this holds the size in bytes of the ** set of FORMATELEMENT structures for this paragraph. Next numRuns (the ** number of FORMATELEMENTs) is computed by dividing this byte size by ** the number of bytes in a single FORMATELEMENT. Then, an array of ** numRuns FORMATELEMENTs is dynamically created using calloc and the ** local variable "fmt" is set to point at it. Similarly, an array of ** numRuns BYTEs is dynamically created using calloc and the local ** variable saveChar is set to point at it. After this, the routine ** loops numRuns times -- once for each FORMATELEMENT, reading the ** information into the slots in the FORMATELEMENT record. Once all ** these have been read in it again loops numRuns times. At the top of ** this loop, it calls the backend three times to send font number, ** font size, and font style information. Since the FORMATELEMENTS ** only specify at what character the new formatting STARTS, the next part ** of the loop splits up the text in textBuf based upon the runs. When running ** through the loop for run k (except when k is the last run), the first ** character of the text for run k+1 (which directly follows the last ** character of the text for k) is saved in array savechar[k+1] and a null ** (x00) is substituted in its place. In this way, run k now constitutes ** a full string, as it is terminated by a null, without having to do ** any string copying. In the case of k being the last run, we know ** it already ends in a null, so we needn't do this. After each run is ** temporarily null-terminated, the routine calls WrapText, a procedure ** that will take the string of the run along with its formatting ** information, break it into strings short enough for most target ** batch text process, and filter it to effect appropriate character ** translation. After this is called, the character saved in the ** savechar array is replaced back into the global textBuf. When the loop ** is completed, the dynamic storage is freed. Next, an appropriate ** number of unused bytes at the end of the format runs are flushed. ** Finally, the backend is called with DocParaEpilog to mark the end ** of processing for this paragraph. ** ** Called by: GetParagraphData ** Calls: readBuf ** getByte, getWord ** WrapText ** DocParaEpilog ** Parms: ** Returns: ** */ GetFormatData() { register int k; /* loop counter */ FORMATELEMENT *fmt; /* -> current format element */ register BYTE *saveChar; /* -> loc in which to save a char */ register int numRuns; /* number of runs in this paragraph */ register WORD extraBytes; /* padding at end of the paragraph */ readBuf(2); /* this is the format run length */ pTextRec.formatRunLength = getWord(); readBuf(pTextRec.formatRunLength); numRuns = pTextRec.formatRunLength/sizeof(FORMATELEMENT); fmt = (FORMATELEMENT *) calloc(numRuns, sizeof(FORMATELEMENT)); saveChar = (BYTE *) calloc(numRuns, sizeof(BYTE)); for (k = 0; k < numRuns; k++) { fmt[k].characterPosition = getWord(); fmt[k].pointSize = getByte(); fmt[k].style = getByte(); fmt[k].fontNumber = getWord(); } for (k = 0; k < numRuns; k++) { #ifdef DEBUG fprintf(stderr,"charPos = %d\n",fmt[k].characterPosition); fprintf(stderr,"pointSize = %d\n",fmt[k].pointSize); fprintf(stderr,"style = %d\n",fmt[k].style); fprintf(stderr,"fontNumber = %d\n",fmt[k].fontNumber); #endif DocTypeFace(fmt[k].fontNumber); /* call backend with curr font # */ DocTypeSize(fmt[k].pointSize); /* call backend with curr pt size */ DocTypeStyle(fmt[k].style); /* call backend with curr typestyle */ if (k + 1 < numRuns) { /* for all but last run */ saveChar[k+1] = textBuf[fmt[k+1].characterPosition]; textBuf[fmt[k+1].characterPosition] = 0; WrapText(textBuf+fmt[k].characterPosition,fmt[k].fontNumber, fmt[k].style,0); } else { /* for last run only */ WrapText(textBuf+fmt[k].characterPosition, fmt[k].fontNumber,fmt[k].style,1); } if (k + 1 < numRuns) /* for all but last run */ textBuf[fmt[k+1].characterPosition] = saveChar[k+1]; } free(textBuf); free(saveChar); free(fmt); extraBytes = sizeof(pTextRec.length) + pTextRec.length + sizeof(pTextRec.formatRunLength) + pTextRec.formatRunLength; if (pTextRec.length % 2) extraBytes++; if (extraBytes < pDataHead.length) readBuf(pDataHead.length - extraBytes); DocParaEpilog(); /* call to backend to mark completion of paragraph */ } /* ** ** WrapText(strg, fontNum,fontStyle,lastLine) ** ** WrapText takes from the runlength decoding routine ** a string, a font number and style, and a flag indicating ** whether the string contains the last line of the paragraph. ** Upon receipt of this, WrapText simply breaks the string into ** manageable pieces defined by the constant DOCLINELEN, making sure ** to break lines on word boundaries, and passes them on to FilterText ** for character translation. The character pointer p is initially set to ** point to the passed string. While p points to a string that is greater ** than the desired DOCLINELEN, a loop is executed. Inside that loop, chase ** is set to be DOCLINELEN characters past p, and is decremented until ** chase points to either a space or meets up with p. If chase is less than ** or equal to p, then a line the length of DOCLINELEN is put out and ** chase is set to point to the character after this line. If chase has ** found a space, it is incremented to point directly after the space. At ** this point, the character that chase is pointing at is changed to be a ** string terminator (null) while the old char is saved, the line is ** written out, and the old character is restored. p is then set equal to ** the new value of chase ** ** Called by: GetParagraphData ** Calls: FilterText ** Parms: BYTE *strg -> string to wrap ** WORD fontNum -- number of font for runLength ** BYTE fontStyle -- style of typeface ** int lastLine -- true if strg contains last line of para ** Returns: ** */ WrapText(strg, fontNum,fontStyle,lastLine) BYTE *strg; WORD fontNum; BYTE fontStyle; int lastLine; { #define DOCLINELEN 50 register BYTE *p, *chase; register BYTE saveChar; p = strg; while (strlen(p) > DOCLINELEN) { for (chase = p + DOCLINELEN; chase > p && *chase != ' '; chase--); if (chase <= p) chase = p + DOCLINELEN; else chase++; saveChar = *chase; *chase = 0; FilterText(p,fontNum,fontStyle,0); *chase = saveChar; p = chase; } FilterText(p,fontNum,fontStyle,lastLine); /* if lastline of para, no cont. char */ } /* ** FilterText(p,fontNum,fontStyle,lastLine) ** ** FilterText takes the same type of parameters as WrapText (though the ** string pointer p now points to a string of DOCLINELEN or less because ** of WrapText. FilterText is the workhorse of the program, in that it ** it does the translation of each character in the string into the ** appropriate backend character codes. FilterText has two pointers to ** character translation tables, with each translation table being an array ** of 128 strings. xFormBot is dynamically assigned to point to the table ** that represents characters 0x00 - 0x7f; xFormTop is assigned to point to ** desired table for charas 0x80 - 0xff. For example, xFormTop[0xAF] ** is the pointer to the character translation string for the character 0xAF. ** For the default, a table called stdTop is set up with the appropriate ** translations for the standard Macintosh character set between 0x80 and ** 0xFF, and xFormTop is set to point to this. Sine 0x00 - 0x7f is standard ** ASCII, there is no stdBot, and xFormBot is set to 0 to indicate that ** no translation need be done. ** ** In the main loop, each character in string p is sent through a ** cascading if-then-else to check backend specific conditions that ** might necessitate a non-standard translation (capturing special ** characters like a "." in troff). Backend-specific documentation is ** provided below. ** ** Called by: WrapText ** Calls: DocSubSuper ** ** Parms: BYTE -> shortend string from WrapText ** WORD -- font number of typeface for this run ** BYTE -- style for this run ** int -- true if this line is last line of paragraph ** Returns: ** */ FilterText(p,fontNum,fontStyle,lastLine) BYTE *p; WORD fontNum; BYTE fontStyle; int lastLine; #ifdef TROFF { register BYTE *strg; static BYTE xBuf[1024]; /* holds translated string */ BYTE *xBufPtr; char **xFormTop, **xFormBot; static char *stdBot[] = { "\000","\001","\002","\003","\004","\005","\006","\007", "\010","\011","\012","\013","\014","\n", "\016","\017", /* CR -> \n */ "\020","\021","\022","\023","\024","\025","\026","\027", "\030","\031","\032","\033","\034","\035","\036","\037", " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\\\","]", "^", "_", /* \ */ "\\(ga","a", "b", "c", "d", "e", "f", "g", /* ` */ "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "\177"}; static char *stdTop[] = { /* Std Mac characters 0x80 - 0xff */ "\\*(UDA", /* 80 A diaeresis */ "\\*(ANA", /* 81 A angstrom */ "\\*(CEC", /* 82 C cedilla */ "\\*(UAE", /* 83 E acute */ "\\*(UCN", /* 84 N tilde */ "\\*(UDO", /* 85 O diaeresis */ "\\*(UDU", /* 86 U diaeresis */ "\\*Aa", /* 87 a acute */ "\\*Ga", /* 88 a grave */ "\\*Ha", /* 89 a circumflex */ "\\*Da", /* 8A a diaeresis */ "\\*Ca", /* 8B a tilde */ "\\*(ANa", /* 8C a angstrom */ "\\*(CEc", /* 8D c cedilla */ "\\*Ae", /* 8E e acute */ "\\*Ge", /* 8F e grave */ "\\*He", /* 90 e circumflex */ "\\*De", /* 91 e diaeresis */ "\\*Ai", /* 92 i acute */ "\\*Gi", /* 93 i grave */ "\\*Hi", /* 94 i circumflex */ "\\*Di", /* 95 i diaeresis */ "\\*Cn", /* 96 n tilde */ "\\*Ao", /* 97 o acute */ "\\*Go", /* 98 o grave */ "\\*Ho", /* 99 o circumflex */ "\\*Do", /* 9A o diaeresis */ "\\*Co", /* 9B o tilde */ "\\*Au", /* 9C u acute */ "\\*Gu", /* 9D u grave */ "\\*Hu", /* 9E u circumflex */ "\\*Du", /* 9F u diaeresis */ "\\(dg", /* A0 |t dagger */ "\\(de", /* A1 |* degree */ "\\(ct", /* A2 |4 cent sign */ "\\(bu", /* A3 |3 british pound sign*/ "\\(sc", /* A4 |6 section */ "\\(bu", /* A5 |8 bullet */ "\\(bu", /* A6 |7 paragraph */ "\\(*b", /* A7 |s beta */ "\\o'\\(ci\\R'", /* A8 |r registered */ "\\(co", /* A9 |g copyright */ "\\*[TM\\*]", /* AA |2 TM */ "\\*A\\&", /* AB |E accent acute */ "\\*D\\&", /* AC |U diaeresis */ "\\(!=", /* AD |= not equals */ "A\\h'-0.3m'E", /* AE |" AE */ "\\o'O/'", /* AF |O O slash */ "\\(if", /* B0 |5 infinity */ "\\(+-", /* B1 |+ plus minus */ "\\(<=", /* B2 |, <= */ "\\(>=", /* B3 |. >= */ "\\o'Y='", /* B4 |y yen sign */ "\\(*m", /* B5 |[ mu */ "\\(pd", /* B6 |d partial deriv */ "\\(*S", /* B7 |w sigma */ "\\(*P", /* B8 |P uppercase pi */ "\\(*p", /* B9 |p lowercase pi */ "\\(is", /* BA |b integral */ "\\o'a_'", /* BB |9 a underscore */ "\\o'o_'", /* BC |0 o underscore */ "\\(*W", /* BD |z omega */ "a\\h'-0.2m'e", /* BE |' ae */ "\\o'o/'", /* BF |o o slash */ "\\(bu", /* C0 |? spanish ? */ "\\(bu", /* C1 |! spanish ! */ "\\(no", /* C2 |l not sign */ "\\(sr", /* C3 |v square root */ "\\fIf\\fP", /* C4 |f script f */ "\\*(AP", /* C5 |x approximately */ "\\(*D", /* C6 |j uppercase delta */ ">\\h'-0.5m'>", /* C7 |\ >> (|| illegal) */ "<\\h'-0.5m'<", /* C8 |< << (|\ illegal) */ "...", /* C9 ellipsis */ "\\ ", /* CA |S nonbreaking space */ "\\*(UGA", /* CB A grave */ "\\*(UCA", /* CC A tilde */ "\\*(UCO", /* CD O tilde */ "O\\h'-0.3m'E", /* CE |Q OE */ "o\\h'-0.2m'e", /* CF |q oe */ "\\(hy", /* D0 |- small dash */ "\\-", /* D1 |_ large dash */ "``", /* D2 |[ open " */ "''", /* D3 |{ close " */ "`", /* D4 |] open ' */ "'", /* D5 |} close ' */ "\\(di", /* D6 |/ division sign */ "\\(gr", /* D7 |V diamond */ "\\*Dy", /* D8 y umlaut */ "\\(bu", /* D9 MISSING CHAR */ "\\(bu", /* DA MISSING CHAR */ "\\(bu", /* DB MISSING CHAR */ "\\(bu", /* DC MISSING CHAR */ "\\(bu", /* DD MISSING CHAR */ "\\(bu", /* DE MISSING CHAR */ "\\(bu", /* DF MISSING CHAR */ "\\(bu", /* E0 MISSING CHAR */ "\\(bu", /* E1 MISSING CHAR */ "\\(bu", /* E2 MISSING CHAR */ "\\(bu", /* E3 MISSING CHAR */ "\\(bu", /* E4 MISSING CHAR */ "\\(bu", /* E5 MISSING CHAR */ "\\(bu", /* E6 MISSING CHAR */ "\\(bu", /* E7 MISSING CHAR */ "\\(bu", /* E8 MISSING CHAR */ "\\(bu", /* E9 MISSING CHAR */ "\\(bu", /* EA MISSING CHAR */ "\\(bu", /* EB MISSING CHAR */ "\\(bu", /* EC MISSING CHAR */ "\\(bu", /* ED MISSING CHAR */ "\\(bu", /* EE MISSING CHAR */ "\\(bu", /* EF MISSING CHAR */ "\\(bu", /* F0 MISSING CHAR */ "\\(bu", /* F1 MISSING CHAR */ "\\(bu", /* F2 MISSING CHAR */ "\\(bu", /* F3 MISSING CHAR */ "\\(bu", /* F4 MISSING CHAR */ "\\(bu", /* F5 MISSING CHAR */ "\\(bu", /* F6 MISSING CHAR */ "\\(bu", /* F7 MISSING CHAR */ "\\(bu", /* F8 MISSING CHAR */ "\\(bu", /* F9 MISSING CHAR */ "\\(bu", /* FA MISSING CHAR */ "\\(bu", /* FB MISSING CHAR */ "\\(bu", /* FC MISSING CHAR */ "\\(bu", /* FD MISSING CHAR */ "\\(bu", /* FE MISSING CHAR */ "\\(bu" /* FF MISSING CHAR */ }; /* greekBot and greekTop are xlate tables for a special Brown Greek */ /* font. Contact us for availability. */ /* x00 - x7f translation codes */ static char *greekBot[] = { "\000","\001","\002","\003","\004","\005","\006","\007", "\010","\011","\012","\013","\014","\n", "\016","\017", /* CR -> \n */ "\020","\021","\022","\023","\024","\025","\026","\027", "\030","\031","\032","\033","\034","\035","\036","\037", " ", /* 20 space */ "!", /* 21 ! */ "\"", /* 22 " */ "\\*(SC\\*(IS\\(*a", /* 23 alpha/smooth/circ/iotasub */ "\\*(RC\\*(IS\\(*a", /* 24 alpha/rough/circ/iotasub */ "\\*C\\*(IS\\(*a", /* 25 alpha/circ/iotasub */ "\\*(RA\\*(IS\\(*a", /* 26 alpha/rough/acute/iotasub */ "\\*(SA\\*(IS\\(*a", /* 27 alpha/smooth/acute/iotasub*/ "\\*(RG\\*(IS\\(*a", /* 28 alpha/rough/grave/iotasub */ "\\*(SG\\*(IS\\(*a", /* 29 alpha/smooth/grave/iotasub*/ "\\*G\\*(IS\\(*a", /* 2A alpha/grave/iotasub */ "\\*A\\*(IS\\(*a", /* 2B alpha/acute/iotasub */ ",", /* 2C */ "-", /* 2D */ ".", /* 2E */ "/", /* 2F */ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "\\*R\\*(IS\\(*a", /* 3A alpha/rough/iotasub */ ".", "\\*S\\*(IS\\(*a", /* 3C alpha/smooth/iotasub */ "\\*(SC\\*(IS\\(*y", /* 3D eta/smooth/circ/iotasub */ "\\*(RC\\*(IS\\*y", /* 3E eta/rough/circ/iotasub */ ";", /* 3F */ "\\*S\\*(IS\\(*y", /* 40 eta/smooth/iotasub */ "\\(*A", /* 41 Alpha */ "\\(*B", /* 42 Beta */ "\\(*Q", /* 43 Psi */ "\\(*D", /* 44 Delta */ "\\(*E", /* 45 Epsilon */ "\\(*F", /* 46 Phi */ "\\(*G", /* 47 Gamma */ "\\(*Y", /* 48 Eta */ "\\(*I", /* 49 Iota */ "\\(*C", /* 4A Xi */ "\\(*K", /* 4B Kappa */ "\\(*L", /* 4C Lambda */ "\\(*M", /* 4D Mu */ "\\(*N", /* 4E Nu */ "\\(*O", /* 4F Omicron */ "\\(*P", /* 50 Pi */ "\\*R\\*(IS\\(*y", /* 51 eta/rough/iotasub */ "\\(*R", /* 52 Rho */ "\\(*S", /* 53 Sigma */ "\\(*T", /* 54 Tau */ "\\(*H", /* 55 Theta */ "\\(*W", /* 56 Omega */ "\\(*y", /* 57 eta */ "\\(*X", /* 58 Chi */ "\\(*U", /* 59 Upsilon */ "\\(*Z", /* 5A Zeta */ "\\*(RA\\*(IS\\(*y", /* 5B eta/rough/acute/iotasub */ "\\*A\\*(IS\\(*y", /* 5C eta/acute/iotasub */ "\\*(SG\\*(IS\\(*y", /* 5D eta/smooth/grave/iotasub */ "^", /* 5E ^ */ "_", /* 5F _ */ "`", /* 60 grave */ "\\(*a", /* 61 alpha */ "\\(*b", /* 62 beta */ "\\(*w", /* 63 psi */ "\\(*d", /* 64 delta */ "\\(*e", /* 65 epsilon */ "\\(*f", /* 66 phi */ "\\(*g", /* 67 gamma */ "\\(*y", /* 68 eta */ "\\(*i", /* 69 iota */ "\\(*c", /* 6A xi */ "\\(*k", /* 6B kappa */ "\\(*l", /* 6C lambda */ "\\(*m", /* 6D mu */ "\\(*n", /* 6E nu */ "\\(*o", /* 6F omicron */ "\\(*p", /* 70 pi */ "\\*(SG\\*(IS\\(*y", /* 71 eta/smooth/grave/iotasub */ "\\(*r", /* 72 rho */ "\\(*s", /* 73 sigma */ "\\(*t", /* 74 tau */ "\\(*h", /* 75 theta */ "\\(*w", /* 76 omega */ "\\*(TS", /* 77 terminal sigma */ "\\(*x", /* 78 chi */ "\\(*u", /* 79 upsilon */ "\\(*z", /* 7A zeta */ "\\*G\\*(IS\\(*y", /* 7B eta/grave/iotasub */ "|", /* 7C ^ */ "\\*S\\*(IS\\(*w", /* 7D omega/smooth/iotasub */ "~", /* 7E circumflex */ "\\*R\\(*a" /* 7F alpha/rough */ }; static char *greekTop[] = { /* Greek characters 0x80 - 0xff */ "\\*S\\(*a", /* 80 alpha/smooth */ "\\*(SA\\(*a", /* 81 alpha/smooth/acute */ "\\*(SG\\(*a", /* 82 alpha/smooth/grave */ "\\*A\\(*E", /* 83 Epsilon/acute */ "\\*C\\(*y", /* 84 eta/circumflex */ "\\*(RG\\(*a", /* 85 alpha/rough/grave */ "\\*(RA\\(*a", /* 86 alpha/rough/acute */ "\\*A\\(*a", /* 87 alpha/acute */ "\\*G\\(*a", /* 88 alpha/grave */ "\\*R\\(*e", /* 89 epsilon/rough */ "\\*S\\(*e", /* 8A epsilon/smooth */ "\\*C\\(*a", /* 8B alpha/circumflex */ "\\*(IS\\(*a", /* 8C alpha/iota subscript */ "\\*(RA\\(*e", /* 8D epsilon/rough/acute */ "\\*A\\(*e", /* 8E epsilon/acute */ "\\*G\\(*e", /* 8F epsilon/grave */ "\\*(SA\\(*e", /* 90 epsilon/smooth/acute */ "\\*(SG\\(*e", /* 91 epsilon/smooth/grave */ "\\*A\\(*i", /* 92 iota/acute */ "\\*G\\(*i", /* 93 iota/grave */ "\\*R\\(*i", /* 94 iota/rough */ "\\*D\\(*i", /* 95 iota/diaresis */ "\\*S\\(*i", /* 96 iota/smooth */ "\\*A\\(*o", /* 97 ormicron/acute */ "\\*G\\(*o", /* 98 ormicron/grave */ "\\*(RA\\(*i", /* 99 iota/rough/acute */ "\\*D\\(*o", /* 9A ormicron/diaeresis */ "\\*C\\(*o", /* 9B ormicron/circumflex */ "\\*S\\(*o", /* 9C ormicron/smooth */ "\\*(SC\\(*i", /* 9D iota/smooth/circumflex */ "\\*(SA\\(*i", /* 9E iota/smooth/acute */ "\\*D\\(*u", /* 9F upsilon/diaeresis */ "\\*(SG\\(*i", /* A0 iota/smooth/grave */ "\\*R\\(*y", /* A1 eta/rough */ "\\*(SG\\&", /* A2 smooth/grave */ "\\*(RC\\&", /* A3 rough/circumflex */ "\\*(SA\\&", /* A4 smooth/acute */ "\\(bu", /* A5 bullet */ "\\*(RA\\&", /* A6 rough acute */ "\\*(RG\\(*y", /* A7 eta/rough/grave */ "\\*(RA\\(*y", /* A8 eta/rough/acute */ "\\*(SA\\(*y", /* A9 eta/smooth/acute */ "\\*(SC\\&", /* AA smooth/circumflex */ "\\*A\\&", /* AB acute */ "\\*D\\&", /* AC diaeresis */ "\\*(RG\\(*e", /* AD rough/grave/epsilon */ "\\*A\\(*u", /* AE upsilon/acute */ "\\*R\\(*o", /* AF ormicron/rough */ "\\*S\\&", /* B0 smooth */ "\\*(SG\\(*y", /* B1 eta/smooth/grave */ "\\*A\\(*y", /* B2 eta/acute */ "\\*S\\(*y", /* B3 eta/smooth */ "\\*C\\(*i", /* B4 iota/circumflex */ "\\*(RG\\(*i", /* B5 iota/rough/grave */ "\\*A\\(*A", /* B6 Alpha/acute */ "\\*G\\(*y", /* B7 eta/grave */ "\\*(RG\\(*o", /* B8 ormicron/rough/grave */ "\\*(SC\\*(IS\\(*w", /* B9 omega/smooth/circ/iotasub*/ "\\*C\\(*W", /* BA Omega/circumflex */ "\\*R\\&", /* BB rough */ "\\*R\\(*u", /* BC upsilon/rough */ "\\*S\\(*u", /* BD upsilon/smooth */ "\\*C\\(*u", /* BE upsilon/circumflex */ "\\*(RG\\(*u", /* BF upsilon/rough/grave */ "\\*(RA\\(*u", /* C0 upsilon/rough/acute */ "\\*(RG", /* C1 rough/grave */ "\\*(SA\\(*u", /* C2 upsilon/smooth/acute */ "\\*(IS\\(*w", /* C3 omega/iotasub */ "\\*C\\(*O", /* C4 Ormicron/circumflex */ "\\*(RC\\*(IS\\(*w", /* C5 omega/rough/circ/iotasub */ "\\*C\\(*E", /* C6 Eta/circumflex */ "\\*(SG\\(*u", /* C7 upsilon/smooth/grave */ "\\*G\\(*O", /* C8 Ormicron/grave */ "\\*S\\(*w", /* C9 omega/smooth */ "\\*G\\(*U", /* CA Upsilon/grave */ "\\*G\\(*A", /* CB Alpha/grave */ "\\*C\\(*A", /* CC Alpha/circumflex */ "\\*G\\(*W", /* CD Omega/grave */ "\\*C\\*(IS\\(*w", /* CE omega/circ/iotasub */ "\\*C\\(*I", /* CF Iota/circumflex */ "\\-", /* D0 dash */ "\\*(RA\\*(IS\\(*w", /* D1 omega/rough/acute/iotasub*/ "\\*(SA\\*(IS\\(*w", /* D2 omega/smooth/acute/iotas */ "\\*(SG\\*(IS\\(*w", /* D3 omega/smooth/grave/iotas */ "\\*(RG\\*(IS\\(*w", /* D4 omega/rough/grave/iotasub*/ "\\*G\\*(IS\\(*w", /* D5 omega/grave/iotasub */ "\\*A\\*(IS\\(*w", /* D6 omega/acute/iotasub */ "\\*G\\(*Y", /* D7 Eta/grave */ "\\*G\\(*I", /* D8 Iota/grave */ "\\*G\\(*E", /* D9 Epsilon/grave */ "\\*C\\(*U", /* DA Upsilon/circumflex */ "\\*A\\(*W", /* DB Omega/acute */ "\\*A\\(*U", /* DC Upsilon/acute */ "\\*A\\(*O", /* DD Ormicron/acute */ "\\*A\\(*I", /* DE Iota/acute */ "\\*C\\*(IS\\(*e", /* DF eta/circumflex/iotasub */ "\\*R\\*(IS\\(*w", /* E0 omega/rough/iotasub */ "\\*(RC\\(*u", /* E1 upsilon/rough/circumflex */ "\\*(SC\\(*u", /* E2 upsilon/smooth/circumflex*/ "\\*(SG\\(*o", /* E3 ormicron/smooth/grave */ "\\*(SA\\(*o", /* E4 ormicron/smooth/acute */ "\\*(RA\\(*o", /* E5 ormicron/rough/acute */ "\\*(RC\\(*o", /* E6 ormicron/rough/circumflex*/ "\\*(SC\\(*o", /* E7 ormicron/smooth/circum */ "\\*(SC\\(*y", /* E8 eta/smooth/circumflex */ "\\*(RC\\(*y", /* E9 eta/rough/circumflex */ "\\*(RC\\(*i", /* EA iota/rough/circumflex */ "\\*G\\(*u", /* EB upsilon/grave */ "\\*(RC\\(*e", /* EC epsilon/rough/circumflex */ "\\*(SC\\(*e", /* ED epsilon/smooth/circumflex*/ "\\*(RC\\(*a", /* EE alpha/rough/circumflex */ "\\*(SC\\(*a", /* EF alpha/smooth/circumflex */ "\\*R\\(*r", /* F0 rho/rough */ "\\*(RC\\(*w", /* F1 omega/rough/circumflex */ "\\*(SC\\(*w", /* F2 omega/smooth/circumflex */ "\\*(SG\\(*w", /* F3 omega/smooth/grave */ "\\*(SA\\(*w", /* F4 omega/smooth/acute */ "\\*(RG\\(*w", /* F5 omega/rough/grave */ "\\*(RA\\(*w", /* F6 omega/rough/acute */ "\\*C\\(*w", /* F7 omega/circumflex */ "\\*G\\(*w", /* F8 omega/grave */ "\\*A\\(*w", /* F9 omega/acute */ "\\*(IS\\(*y", /* FA eta/iotasub */ "\\*R\\(*w", /* FB omega/rough */ "\\*A\\(*Y", /* FC Eta/acute */ "\\*C\\(*e", /* FD epsilon/circumflex */ "\\*C\\(*E", /* FE Epsilon/circumflex */ "\\(bu" /* FF MISSING CHAR */ }; /* ** FilterText ==> TROFF ** ** In the processing for the TROFF dependent FilterText, we first check ** to see if fontNum is equal to any special fonts, and if so, set the ** appropriate translation tables. If not, then we default to setting ** xFormBot to point to stdBot and xFormTop to point at stdTop. ** We set xBufPtr to point to xBuf, which is a new output buffer in which ** to do our translation. We then loop for each character in the ** string, and send it to the appropriate translation table. After this ** loop, we check to make sure that a . or ' is not in the first column ** (since these are control word indicators in troff). If one is found, ** the troff 0-width character (\&) is prepended. After this, we send ** */ #define tTop 0x80 #define SUPERSCRIPT 0x20 #define SUBSCRIPT 0x40 if (fontNum == 14) { xFormBot = greekBot; xFormTop = greekTop; } else { xFormBot = stdBot; xFormTop = stdTop; } xBufPtr = xBuf; for (strg = p; *strg != 0; strg++) { if (*strg < tTop) { /* 0x00 - 0x7f */ strcpy(xBufPtr,xFormBot[*strg]); xBufPtr += strlen(xFormBot[*strg]); } else { /* 0x80 - 0xff */ strcpy(xBufPtr,xFormTop[*strg - tTop]); xBufPtr += strlen(xFormTop[*strg - tTop]); } } *xBufPtr = 0; /* null terminate the string */ if (xBuf[0] == '.' || xBuf[0] == '\'') /* don't allow . or ' in column 1 to be treated */ printf("\\&"); /* as the control word indicator */ if (fontStyle & SUBSCRIPT) DocPrintSubSuper(xBuf,SUBSCRIPT,lastLine); else if (fontStyle & SUPERSCRIPT) DocPrintSubSuper(xBuf,SUPERSCRIPT,lastLine); else printf("%s",xBuf); if (!lastLine) printf("\\c\n"); } #endif #ifdef WSCRIPT { register BYTE *strg; static BYTE xBuf[1024]; /* holds translated string */ BYTE *xBufPtr; char **xFormTop, **xFormBot; static char *stdBot[] = { "\000","\001","\002","\003","\004","\005","\006","\007", "\010","|T", "\012","\013","\014","\n", "\016","\017",/* TAB, CR */ "\020","\021","\022","\023","\024","\025","\026","\027", "\030","\031","\032","\033","\034","\035","\036","\037", " ", "!", "\"", "#", "$", "%", "|Y", "'", /* & */ "(", ")", "*", "+", ",", "-", "|e", "/", /* . */ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "|I", "_", /* ^ */ "|G", "a", "b", "c", "d", "e", "f", "g", /* ` */ "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "|N", "\177"};/* ~ */ static char *stdTop[] = { /* Std Mac characters 0x80 - 0xff */ "A|B&S'|U.", /* 80 A umlaut */ "A|B&x'A1.", /* 81 A angstrom */ "C|B&x'76.", /* 82 C cedilla */ "E|B&S'|E.", /* 83 E acute */ "N|B&S'|N.", /* 84 N tilde */ "O|B&S'|U.", /* 85 O umlaut */ "U|B&S'|U.", /* 86 U umlaut */ "a|B|E", /* 87 a acute */ "a|B|G", /* 88 a grave */ "a|B|I", /* 89 a circumflex */ "a|B|U", /* 8A a umlaut */ "a|B|N", /* 8B a tilde */ "a|B&x'A1.", /* 8C a angstrom */ "c|B&x'76.", /* 8D c cedilla */ "e|B|E", /* 8E e acute */ "e|B|G", /* 8F e grave */ "e|B|I", /* 90 e circumflex */ "e|B|U", /* 91 e umlaut */ "i|B|U", /* 92 i acute */ "i|B|G", /* 93 i grave */ "i|B|I", /* 94 i circumflex */ "i|B|U", /* 95 i umlaut */ "n|B|N", /* 96 n tilde */ "o|B|E", /* 97 o acute */ "o|B|G", /* 98 o grave */ "o|B|I", /* 99 o circumflex */ "o|B|U", /* 9A o umlaut */ "o|B|N", /* 9B o tilde */ "u|B|E", /* 9C u acute */ "u|B|G", /* 9D u grave */ "u|B|I", /* 9E u circumflex */ "u|B|U", /* 9F u umlaut */ "|t", /* A0 |t dagger */ "|*", /* A1 |* degree */ "|4", /* A2 |4 cent sign */ "|3", /* A3 |3 british pound sign*/ "|6", /* A4 |6 section */ "|8", /* A5 |8 bullet */ "|7", /* A6 |7 paragraph */ "|s", /* A7 |s beta */ "|r", /* A8 |r registered */ "|g", /* A9 |g copyright */ "&S'TM.", /* AA |2 TM (missing) */ "|E", /* AB |E accent acute */ "|U", /* AC |U umlaut */ "|=", /* AD |= not equals */ "|\"", /* AE |" AE */ "O|B/", /* AF |O O slash */ "|5", /* B0 |5 infinity */ "|+", /* B1 |+ plus minus */ "|,", /* B2 |, <= */ "|.", /* B3 |. >= */ "|y", /* B4 |y antenna? */ "|[", /* B5 |[ mu */ "|d", /* B6 |d lowercase delta */ "|w", /* B7 |w sigma */ "|P", /* B8 |P uppercase pi */ "|p", /* B9 |p lowercase pi */ "|b", /* BA |b integral */ "a|B&x'6D.", /* BB |9 a underscore */ "o|B&x'6D.", /* BC |0 o underscore */ "|z", /* BD |z omega */ "|'", /* BE |' ae */ "o|B/", /* BF |o o slash */ "|?", /* C0 |? spanish ? */ "|!", /* C1 |! spanish ! */ "|l", /* C2 |l not sign */ "|v", /* C3 |v square root */ "|f", /* C4 |f script f */ "|x", /* C5 |x equivalent */ "|j", /* C6 |j uppercase delta */ "|>", /* C7 |\ >> (|| illegal) */ "|<", /* C8 |< << (|\ illegal) */ "...", /* C9 ellipsis */ "|S", /* CA |S nonbreaking space */ "A|B&S'|G.", /* CB A grave */ "A|B&S'|N.", /* CC A tilde */ "O|B&S'|N.", /* CD O tilde */ "|Q", /* CE |Q OE */ "|q", /* CF |q oe */ "|-", /* D0 |- small dash */ "|_", /* D1 |_ large dash */ "|[", /* D2 |[ open " */ "|{", /* D3 |{ close " */ "|]", /* D4 |] open ' */ "|}", /* D5 |} close ' */ "|/", /* D6 |/ division sign */ "|V", /* D7 |V diamond */ "\\y\\:", /* D8 y umlaut */ "|M", /* D9 MISSING CHAR */ "|M", /* DA MISSING CHAR */ "|M", /* DB MISSING CHAR */ "|M", /* DC MISSING CHAR */ "|M", /* DD MISSING CHAR */ "|M", /* DE MISSING CHAR */ "|M", /* DF MISSING CHAR */ "|M", /* F0 MISSING CHAR */ "|M", /* E1 MISSING CHAR */ "|M", /* E2 MISSING CHAR */ "|M", /* E3 MISSING CHAR */ "|M", /* E4 MISSING CHAR */ "|M", /* E5 MISSING CHAR */ "|M", /* E6 MISSING CHAR */ "|M", /* E7 MISSING CHAR */ "|M", /* E8 MISSING CHAR */ "|M", /* E9 MISSING CHAR */ "|M", /* EA MISSING CHAR */ "|M", /* EB MISSING CHAR */ "|M", /* EC MISSING CHAR */ "|M", /* ED MISSING CHAR */ "|M", /* EE MISSING CHAR */ "|M", /* EF MISSING CHAR */ "|M", /* F0 MISSING CHAR */ "|M", /* F1 MISSING CHAR */ "|M", /* F2 MISSING CHAR */ "|M", /* F3 MISSING CHAR */ "|M", /* F4 MISSING CHAR */ "|M", /* F5 MISSING CHAR */ "|M", /* F6 MISSING CHAR */ "|M", /* F7 MISSING CHAR */ "|M", /* F8 MISSING CHAR */ "|M", /* F9 MISSING CHAR */ "|M", /* FA MISSING CHAR */ "|M", /* FB MISSING CHAR */ "|M", /* FC MISSING CHAR */ "|M", /* FD MISSING CHAR */ "|M", /* FE MISSING CHAR */ "|M" /* FF MISSING CHAR */ }; #define tTop 0x80 #define SUPERSCRIPT 0x20 #define SUBSCRIPT 0x40 xFormBot = stdBot; /* use standard ASCII for 0x00 - 0x7f */ xFormTop = stdTop; /* use std Mac chars for 0x80 - 0xff */ xBufPtr = xBuf; for (strg = p; *strg != 0; strg++) { if (*strg < tTop) { /* 0x00 - 0x7f */ strcpy(xBufPtr,xFormBot[*strg]); xBufPtr += strlen(xFormBot[*strg]); } else { /* 0x80 - 0xff */ strcpy(xBufPtr,xFormTop[*strg - tTop]); xBufPtr += strlen(xFormTop[*strg - tTop]); } } *xBufPtr = 0; /* null terminate the string */ if (fontStyle & SUBSCRIPT) DocPrintSubSuper(xBuf,SUBSCRIPT,lastLine); else if (fontStyle & SUPERSCRIPT) DocPrintSubSuper(xBuf,SUPERSCRIPT,lastLine); else if (strlen(xBuf) == 1 && xBuf[0] == '\n') printf(" \n"); else printf("%s",xBuf); if (!lastLine) printf("\\\n"); } #endif /* ** GetPictureData() ** ** GetPictureData simply reads in the number of bytes specified in the ** picture's data header. Since MacWrite uses blank pictures for creating ** page advances, all this routine does is call the DocPageAdvance. This means ** that currently, each time a picture is hit (even if it is a bitmap and ** NOT a page advance, a page advance code will be put in). ** ** Called by: GetParagraphData ** Calls: DocPageAdvance [backend] ** Parms: ** Returns: ** */ GetPictureData() { #ifdef DEBUG fprintf(stderr,"This is a PICTURE\n"); #endif readBuf(pDataHead.length); DocPageAdvance(); } /* ** ProcessRulerData ** ** Upon finding RULER paragraph, ProcessRulerData is called to interpret ** the ruler settings and call the appropriate backend functions. It ** calls DocMarginRight and DocMargin left with the ruler settings divided ** by 80, since the data is stored in 1/80ths of an inch and the backend ** expects inches. Line spacing is called with the standard setting (0= ** single spacing, 1 = 1-1/2 spacing, 2 = double spacing. ** */ ProcessRulerData() { register int j; DocMarginRight(rulerRec.rightMargin/80.0); DocMarginLeft(rulerRec.leftMargin/80.0); DocLineSpacing(rulerRec.spacing); DocTabProlog(); /* MacWrite treats l. marg as tab */ if (rulerRec.indentMargin < rulerRec.leftMargin) DocTabReg(rulerRec.leftMargin/80.0,rulerRec.leftMargin/80.0, rulerRec.indentMargin/80.0); for (j = 0; j < rulerRec.numberOfTabs; j++) if (rulerRec.tabs[j] >= 0) DocTabReg(rulerRec.tabs[j]/80.0,rulerRec.leftMargin/80.0, rulerRec.indentMargin/80.0); else DocTabDecimal(-rulerRec.tabs[j]/80.0,rulerRec.leftMargin/80.0, rulerRec.indentMargin/80.0); DocTabEpilog(); DocAdjust(rulerRec.justification); } DocAdjust(adjType) BYTE adjType; { #ifdef TROFF static char *adjString[4] = {"l","c","r","b"}; printf(".ad %s\n", adjString[adjType]); #endif #ifdef WSCRIPT static char *adjString[4] = {"left","center","right","on"}; printf(".ju %s\n", adjString[adjType]); #endif } DocEpilog() { #ifdef TROFF printf("\n"); #endif } DocHeaderEpilog() { #ifdef WSCRIPT printf(".hn end\n"); #endif } DocHeaderProlog() { #ifdef WSCRIPT printf(".hn begin\n"); #endif } /* ** ** DocLineSpacing ** ** Create a line for spacing. MacWrite uses 0 for single spacing, ** 1 for 1 1/2 spacing, 2 for double spacing. ** ** We must add 1 for corresponding troff setting. ** WScript doesn't support 1 1/2 space. We must also ** put in .sp since MacWrite adds the line spacing before any ** lines are output. ** */ DocLineSpacing(spacing) BYTE spacing; { #ifdef TROFF printf(".ls %d\n", spacing); printf(".sp %d\n", spacing); #endif #ifdef WSCRIPT if (spacing > 1) spacing = 1; /* treat 1 1/2 and double space the same */ printf(".ls %d\n", spacing); printf(".sp %d A\n", spacing); #endif } /* ** ** DocMarginLeft ** ** MacWrite calculates all measurements relative to a fixed zero point ** which happens to be located at the 1" mark on the ruler. The left ** margin, therefore, is really an indent from that zero point, and we ** treat is as such here. ** */ DocMarginLeft(left) float left; { #ifdef TROFF printf(".ti 0\n.in %.3fi\n", left); #endif #ifdef WSCRIPT printf(".il 0;.in %.3fi\n", left); #endif } DocMarginRight(right) float right; { #ifdef TROFF printf(".ll %.3fi\n",right); #endif #ifdef WSCRIPT printf(".ll %.3fi\n",right); #endif } DocPageAdvance() { #ifdef TROFF printf(".bp\n"); #endif #ifdef WSCRIPT printf(".pa\n"); #endif } DocParaEpilog() { #ifdef TROFF /* printf(".br\n"); */ #endif #ifdef WSCRIPT /* printf(".br\n"); */ #endif } DocParaProlog(indent) float indent; { #ifdef TROFF if (indent >= 0) printf(".ti +%.3fi\n", indent); /* need to put in + size for relative */ else printf(".ti %.3fi\n", indent); /* minus sign already for relative */ #endif #ifdef WSCRIPT printf(".br;.il 0;.il %.3fi\n", indent); #endif } DocPrintSubSuper(strg,flag,lastLine) char *strg; /* text to print */ unsigned char flag; int lastLine; #ifdef TROFF { char *prefix; /* superscript or subscript prefix */ char *suffix; /* superscript or subscript suffix */ if (flag == SUBSCRIPT) { prefix = "\\*<"; suffix = "\\*>"; } else { prefix = "\\*["; suffix = "\\*]"; } printf("%s%s%s",prefix,strg,suffix); if (lastLine) printf ("\n"); } #endif #ifdef WSCRIPT { register char *chase, *p; char *prefix; /* superscript or subscript prefix */ if (flag == SUBSCRIPT) prefix = "&s'"; else prefix = "&S'"; p = strg; if (strlen(p) < 1) return; /* sub/superscripts of null strgs don't work */ chase = p; while (*p != 0) { while (*chase == ' ') { /* no blanks in superscripts, just write out */ printf("%c",' '); p++; chase++; } while (*chase != 0 && *chase != ' ') chase++; if (*chase != 0) { *chase = 0; printf("%s%s.",prefix,p); *chase = ' '; } else if (*p != 0) /* if *p = 0, then blanking above exhausted the str */ printf("%s%s.",prefix,p); p = chase; } } #endif DocProlog(version) char *version; /* current version string */ { #ifdef TROFF /* The following are troff statements for local motion to generate */ /* diacritics, generously provided by Greg Crane, Dept. of Classics, */ /* Harvard University. */ static char * smoothcirc = "\\v'-.3n'\\z~\\v'.1n'\\h'.2n'\\z'\\v`.2n'\\h'-.2n'"; static char * smoothgrave = "\\v'-.2n'\\z'\\h'.4n'\\z\\(ga\\v'.2n'\\h'-.4n'"; static char * smoothacute = "\\v'-.2n'\\z'\\h'.1n'\\z\\(aa\\v'.2n'\\h'-.1n'"; static char * iotasub = "\\v'.8n'\\s-4\\z\\(*i\\s+4\\v'-.8n'"; static char * roughcirc = "\\v'-.3n'\\z~\\v'.1n'\\h'.2n'\\z`\\v'.2n'\\h'-.2n'"; static char * roughgrave = "\\v'-.2n'\\z`\\h'.3n'\\z\\(ga\\v'.2n'\\h'-.3n'"; static char * roughacute = "\\v'-.2n'\\z`\\h'.1n'\\z\\(aa\\v'.2n'\\h'-.1n'"; static char * acute = "\\v'-.1n'\\z\\(aa\\v'.1n'"; static char * grave = "\\v'-.1n'\\z\\(ga\\v'.1n'"; static char * rough = "\\v'-.2n'\\z`\\v'.2n'"; static char * smooth = "\\v'-.2n'\\z'\\v'.2n'"; static char * circum = "\\v'-.1n'\\z~\\v'.1n'"; static char * upperAcute = "\\v'-.5n'\\h'.1n'\\z\\(aa\\v'.5n'\\h'-.1n'"; static char * upperGrave = "\\v'-.5n'\\h'.1n'\\z\\(ga\\v'.5n'\\h'-.1n'"; static char * upperRough = "\\v'-.6n'\\h'.1n'\\z`\\v'.6n'\\h'-.1n'"; static char * upperSmooth = "\\v'-.6n'\\h'.1n'\\z'\\v'.6n'\\h'-.1n'"; static char * upperCircum = "\\v'-.5n'\\h'.1n'\\z~\\v'.5n'\\h'-.1n'"; static char * upperDiaeresis = "\\v'-1.5n'\\z.\\h'.4n'\\z.\\h'-.4n'\\v'1.5n'"; static char * diaeresis = "\\v'-1n'\\z.\\h'.4n'\\z.\\h'-.4n'\\v'1n'"; static char * diaergrave = "\\v'-1n'\\z.\\h'.1n'\\v'.7n'\\z\\`\\v'-.7n'\\h'.5n'\\z.\\h'-.6n'\\v'1n'"; static char * diaeracute = "\\v'-1n'\\z.\\h'.1n'\\v'.7n'\\z\\'\\v'-.7n'\\h'.5n'\\z.\\h'-.6n'\\v'1n'"; static char * hidot = "\\v'-.7n'.\\v'.7n'"; static char * hat = "\\v'-.1n'\\z^\\v'.1n'"; static char * angstrom = "\\v'-.1n'\\z\\(de\\v'.1n'"; static char * cedilla = "\\v'.1n'\\h'.5n'\\s-4\\z,\\s+4\\h'-.5n'\\v'-.1n'"; static char * terminalSigma = "\\v'.2n'\\h'.5n'\\s-4\\z,\\s+4\\h'-.5n\\v'-.2n'\fIc\fP"; static char * approx = "\\v'-.6n'\\z~\\v'.6n'~"; printf("\\\" mwtroff version %s\n.po .5in\n.tp\n",version); /* margin starts at 1" per MacWrite */ printf(".ds SC %s\n",smoothcirc); printf(".ds SG %s\n",smoothgrave); printf(".ds SA %s\n",smoothacute); printf(".ds IS %s\n",iotasub); printf(".ds RC %s\n", roughcirc); printf(".ds GC %s\n", roughgrave); printf(".ds RA %s\n", roughacute); printf(".ds A %s\n",acute); printf(".ds R %s\n",rough); printf(".ds G %s\n",grave); printf(".ds S %s\n",smooth); printf(".ds C %s\n",circum); printf(".ds D %s\n",diaeresis); printf(".ds DG %s\n",diaergrave); printf(".ds DA %s\n",diaeracute); printf(".ds HI %s\n",hidot); printf(".ds AN %s\n",angstrom); printf(".ds CE %s\n",cedilla); printf(".ds H %s\n",hat); printf(".ds UA %s\n",upperAcute); printf(".ds UR %s\n",upperRough); printf(".ds UG %s\n",upperGrave); printf(".ds US %s\n",upperSmooth); printf(".ds UC %s\n",upperCircum); printf(".ds UD %s\n",upperDiaeresis); printf(".ds TS %s\n",terminalSigma); printf(".ds AP %s\n",approx); #endif #ifdef WSCRIPT printf(".* mwscript version %s\n.im mwprof\n",version); /* file containing script char translations */ #endif } DocTabDecimal(stop,left,indent) float stop; float left; float indent; { #ifdef TROFF if (left == indent) printf("%.3fiR ",stop-left); else printf("%.3fiR ",stop-indent); #endif #ifdef WSCRIPT register int propSpace; /* SCRIPT expects tabs as fixed char offsets */ /* based upon its CPI value (use 32) */ propSpace = stop * 32 + 1; if (propSpace > 0) printf("%d'.' ",propSpace); #endif } DocTabEpilog() { #ifdef TROFF printf("\n"); #endif #ifdef WSCRIPT printf("\n"); #endif } DocTabProlog() { #ifdef TROFF printf(".ta "); #endif #ifdef WSCRIPT printf(".tb "); #endif } DocTabReg(stop,left,indent) float stop; float left; float indent; { #ifdef TROFF if (left == indent) printf("%.3fi ",stop-left); else printf("%.3fi ",stop-indent); #endif #ifdef WSCRIPT register int propSpace; /* SCRIPT expects tabs as fixed char offsets */ /* based upon its CPI value (32) */ propSpace = stop * 32 + 1; if (propSpace > 0) printf("%d ",propSpace); #endif } DocTypeFace(face) WORD face; { } DocTypeSize(size) BYTE size; { #ifdef TROFF printf("'vs %d\n\\s%d",size/9 + size + 1,size); #endif #ifdef WSCRIPT #endif } DocTypeStyle(style) BYTE style; { #ifdef TROFF #define numStyles 7 register int bitPtr; static char *typeStyle[7][2] = {"\\fR","\\fB", /* bold */ "","\\fI", /* italic */ "","", /* unders */ "","", /* outline*/ "","", /* shadow */ "","", /* subscript */ "",""}; /* superscr */ for (bitPtr = 0; bitPtr < numStyles; bitPtr++) printf("%s",typeStyle[bitPtr][(style >> bitPtr) & 0x01]); #endif #ifdef WSCRIPT #define numStyles 7 register int bitPtr; static char *typeStyle[7][2] = {".bd off;",".bd on;", /* bold */ ".us off;",".us on;", /* italic */ "","", /* unders */ "","", /* outline*/ "","", /* shadow */ "","", /* subscript */ "",""}; /* superscr */ for (bitPtr = 0; bitPtr < numStyles; bitPtr++) printf("%s",typeStyle[bitPtr][(style >> bitPtr) & 0x01]); printf("\n"); #endif }