📄 rtftohtml.c
字号:
/* rtftohtml - RTF to HTML translator Initial Implementation by Chris Hector (cjh@cray.com) (c) 1994 by Chris Hector May be freely distributed. This translator was based on rtfskel. Kudos to Paul DuBois for his work in developing the rtf reader and skeleton code.*/# include <stdio.h># include <stdlib.h># define Edef # include "rtf.h"# include "rtftohtml.h"static void UnknownClass ();static void GroupClass ();static void ControlClass ();static void Destination ();static void SpecialChar ();static void DocAttr ();static void SectAttr ();static void TblAttr ();static void ParAttr ();static void CharAttr ();static void PictAttr ();static void NeXTGrAttr ();static void FieldAttr ();static void TOCAttr ();static void PosAttr ();static void PictAttr();char *outputMapName="html-map";char *TransFile= "html-trans";/* Translator Options */int debug=0;int IMG=0;int ToC=1;int WriteGraf=1;/* Input State Variables */# define PSAtCol1 0# define PSInCol1 1# define PSAtCol2 2# define PSInCol2 3int IStyle_Chg=1; /* Has input style changed? */int lastleft=0;char *ParStyle=""; /* Paragraph Style Name */TStyle_typ TStyle; /* Bitmask of Text Styles */char *TFont=""; /* Points to Font String */int TSize=0; /* Pointsize of Font */int inTable=0; /* In a table? */int cellno=0;int firstcell=0;int lastcell=0;int celldidx; /* index of the cell definition */int ToCLev; /* Table of Contents Level */int CurFNote;int destination=rtfMaxDestination; /* The current input destination */RTFFont *fp; /* Actual Font Pointer */int OptDestFound; /* Set if an optional destination was encountered */InStateStack *ISS=NULL;char PFileExt[16]="gif"; /* extension to be used for links to pictures */char *FPrefix; /* Base name of output files */char *FPrefixR; /* Relative name of output files */char *OutfileName; /* output file name */int linkself; /* set for internal links */char *outMap[rtfSC_MaxChar];char *filename;static void ObjAttr ();/* * Once-only writer initialization */voidWriterInit (){ FPrefix = RTFAlloc (256); FPrefixR = RTFAlloc (256); OutfileName = RTFAlloc (256); filename = RTFAlloc (256); if (FPrefix == (char *) NULL || FPrefixR == (char *) NULL || OutfileName == (char *) NULL || filename == (char *) NULL) RTFPanic ("Cannot allocate filename buffers."); FPrefix[0] = '\0'; FPrefixR[0] = '\0'; OutfileName[0] = '\0'; filename[0] = '\0'; if (RTFReadOutputMap (outputMapName, outMap, 1) == 0) RTFPanic ("Cannot read output map %s", outputMapName); if (TransInit (TransFile) == 0) RTFPanic ("Cannot read Translation File %s", TransFile);}/* * Set up to process a single file */intdo_main(argc, argv)int argc;char **argv;{ int i; char versid[256]; debug=0; IMG=0; ToC=1; ToCLev=0; IStyle_Chg=1; ParStyle=""; TFont=""; WriteGraf=1; TSize=0; cellno=0; inTable=0; firstcell=0; lastcell=0; CurFNote=0; destination=rtfMaxDestination; ISS=NULL; strcpy(PFileExt,"gif"); FPrefix[0]='\0'; OptDestFound=0; --argc; ++argv; while (argc > 0 && **argv == '-') { if (strcmp ("-V", *argv) == 0){ sprintf(versid,"rtftohtml Version %s\n",PVers); RTFMsg(versid); return (0); } else if (strcmp ("-i", *argv) == 0){ IMG=1; } else if (strcmp ("-G", *argv) == 0){ WriteGraf=0; } else if (strcmp ("-T", *argv) == 0){ ToC=0; } else if (strcmp ("-o", *argv) == 0){ if (argc < 2) { return (-1); } --argc; ++argv; strcpy(OutfileName,*argv); /* if the -o option was specified, use the file name as a prefix (stripping off .html or .HTML if present.) */ i=strlen(argv[0]); if(i>5&&(strcmp(&(argv[0][i-5]),".html")==0|| strcmp(&(argv[0][i-5]),".HTML")==0)){ i=i-5; } if(i>256)i=255; strncpy(FPrefix,argv[0],(size_t) i); FPrefix[i]=0; } else if (strcmp ("-P", *argv) == 0){ if (argc < 2) { return (-1); } --argc; ++argv; strncpy(PFileExt,*argv,(size_t) 15); PFileExt[15] = '\0'; } else { RTFMsg ("Don't understand %s option.\n", *argv); return (-1); } --argc; ++argv; } if (argc > 0) { if (freopen (argv[0], "r", stdin) == NULL) { RTFMsg ("Can't open \"%s\"\n", argv[0]); return (0); } /* if the -o option was not specified, use the file name as a prefix (stripping off .rtf or .RTF if present.) */ if(FPrefix[0]==0){ i=strlen(argv[0]); if(i>4&&(strcmp(&(argv[0][i-4]),".rtf")==0|| strcmp(&(argv[0][i-4]),".RTF")==0)){ i=i-4; } if(i>256)i=256; strncpy(FPrefix,argv[0],(size_t) i); FPrefix[i]=0; sprintf(OutfileName,"%s.html",FPrefix); } } else { RTFMsg("No input file given\n"); return (0); } strcpy(FPrefixR, Basename (FPrefix)); HTMLInit(); /* install class callbacks */ RTFSetClassCallback (rtfUnknown, UnknownClass); RTFSetClassCallback (rtfGroup, GroupClass); RTFSetClassCallback (rtfText, PutHTML); RTFSetClassCallback (rtfControl, ControlClass); /* de-install default destination callbacks */ RTFSetDestinationCallback(rtfInfo, NULL); RTFSetDestinationCallback(rtfPict, NULL); RTFSetDestinationCallback(rtfObject, NULL); RTFSetDestinationCallback(rtfColorTbl, NULL); /* Process the input stream. Make sure the first intoken is a "{" so a state push will occur before anything else (need to preserve state 0 intact for section, paragraph, character default restoration). */ (void) RTFGetToken (); if (!RTFCheckCM (rtfGroup, rtfBeginGroup)) { RTFMsg ("malformed rtf file - does not begin with \"{\"\n"); return (0); } RTFRouteToken (); /* send "{" through router */ return (1);}/* Token class callbacks*/static void UnknownClass (){ /* use this to print warnings about unknown tokens */ if(OptDestFound){ /* Weed out optional destinations. No Warning given */ RTFSkipGroup (); PopIState(); return; } RTFMsg ("Unknown symbol \"%s\" near line %ld, position %d.\n", rtfTextBuf, rtfLineNum, rtfLinePos);}static void GroupClass (){ IStyle_Chg=1; switch (rtfMajor) { case rtfBeginGroup: /* push state */ PushIState(); break; case rtfEndGroup: /* pop state */ PopIState(); break; }}/* Process control symbol.*/static void ControlClass (){ switch (rtfMajor) { case rtfVersion: break; case rtfDefFont: /* rtfParam contains the default font number. Beware that there is no guarantee that this font will actually be listed in the font table! */ break; case rtfCharSet: /*CharSet ();*/ break; case rtfDestination: Destination (); break; case rtfFontFamily: /* only occurs within font table - can ignore */ break; case rtfColorName: /* only occurs within color table - can ignore */ break; case rtfSpecialChar: SpecialChar (); break; case rtfStyleAttr: /* only occurs within stylesheet - can ignore */ break; case rtfDocAttr: DocAttr (); break; case rtfSectAttr: SectAttr (); break; case rtfTblAttr: TblAttr (); break; case rtfObjAttr: ObjAttr (); break; case rtfParAttr: ParAttr (); break; case rtfCharAttr: CharAttr (); break; case rtfPictAttr: PictAttr (); break; case rtfNeXTGrAttr: NeXTGrAttr (); break; case rtfFieldAttr: FieldAttr (); break; case rtfTOCAttr: TOCAttr (); break; case rtfPosAttr: PosAttr (); break; }}/* Control class major number handlers. Each one switches on the minor numbers that occur within the major number.*/static void Destination (){ destination=rtfMinor; OptDestFound=0; IStyle_Chg=1; switch (rtfMinor) { case rtfPict: break; case rtfNeXTGraphic: break; case rtfFootnote: firstcell=lastcell; break; case rtfHeader: case rtfHeaderLeft: case rtfHeaderRight: case rtfHeaderFirst: case rtfFooter: case rtfFooterLeft: case rtfFooterRight: case rtfFooterFirst: RTFSkipGroup (); PopIState(); break; case rtfFNSep: RTFSkipGroup (); PopIState(); break; case rtfFNContSep: RTFSkipGroup (); PopIState(); break; case rtfFNContNotice: RTFSkipGroup (); PopIState(); break; case rtfInfo: break; case rtfStyleSheet: /* will never occur because of default destination reader */ break; case rtfFontTbl: /* will never occur because of default destination reader */ break; case rtfColorTbl: RTFSkipGroup (); PopIState(); break; case rtfField: case rtfFieldResult: break; case rtfFieldInst: RTFSkipGroup (); PopIState(); break; case rtfIndex: case rtfIndexBold: case rtfIndexItalic: case rtfIndexText: case rtfIndexRange: break; case rtfTOC: break; case rtfBookmarkStart: break; case rtfBookmarkEnd: break; case rtfITitle: break; case rtfISubject: case rtfIAuthor: case rtfIOperator: case rtfIKeywords: case rtfIComment: case rtfIVerscomm: case rtfIDoccomm: RTFSkipGroup (); PopIState(); break; case rtfObject: linkself=0; break; case rtfObjItem: break; case rtfObjData: case rtfObjClass: case rtfObjName: case rtfObjTopic: RTFSkipGroup (); PopIState(); break; case rtfParNumText: break; case rtfObjResult: break; case rtfAnnotation: break; case rtfAnnotID: break; default: RTFSkipGroup (); PopIState(); break; } HTMLStartDivert();}static void SpecialChar (){ char fnote[8]; switch (rtfMinor) { case rtfCurHeadPage: break; case rtfCurFNote: if(destination!=rtfFootnote)CurFNote++; sprintf(fnote,"%d",CurFNote); PutHTMLString(fnote); break; case rtfCurHeadPict: break; case rtfCurHeadDate: break; case rtfCurHeadTime: break; case rtfFormula: break; case rtfNoBrkSpace: rtfMinor = rtfSC_nobrkspace; PutHTML (); break; case rtfNoReqHyphen: break; case rtfNoBrkHyphen: rtfMinor = rtfSC_nobrkhyphen; PutHTML (); case rtfRow: if(lastcell==0){ lastcell=celldidx; } cellno=firstcell; PutSpecial(rtfRow); break; case rtfSect: break; case rtfPage: break; case rtfLine: rtfMinor = rtfSC_newline; PutHTML (); break; case rtfPar: PutSpecial(rtfPar); break; case rtfBullet: rtfMinor = rtfSC_bullet; PutHTML (); break; case rtfCell: if(cellno++>=CELLMAX){ RTFMsg ("Overflowed the total number of cells %s\n",CELLMAX); cellno--; } break; case rtfTab: PutSpecial(rtfTab); break;/* case rtfCurAnnot: break;*/ case rtfCurAnnotRef: break; case rtfFNoteSep: break; case rtfFNoteCont: break; case rtfColumn: break; case rtfOptDest: OptDestFound=1; break; case rtfIIntVersion: break; case rtfICreateTime: break; case rtfIRevisionTime: break; case rtfIPrintTime: break; case rtfIBackupTime: break; case rtfIEditTime: break; case rtfIYear: break; case rtfIMonth: break; case rtfIDay: break; case rtfIHour: break; case rtfIMinute: break; case rtfINPages: break; case rtfINWords: break; case rtfINChars: break; case rtfIIntID: break; case rtfEmDash: rtfMinor = rtfSC_emdash; PutHTML (); break; case rtfEnDash: rtfMinor = rtfSC_endash; PutHTML (); break; case rtfLQuote: rtfMinor = rtfSC_quoteleft; PutHTML (); break; case rtfRQuote: rtfMinor = rtfSC_quoteright; PutHTML (); break; case rtfLDblQuote: rtfMinor = rtfSC_quotedblleft; PutHTML (); break; case rtfRDblQuote: rtfMinor = rtfSC_quotedblright; PutHTML (); break; }}static void DocAttr (){ switch (rtfMinor) { case rtfPaperWidth: break; case rtfPaperHeight: break; case rtfLeftMargin: break; case rtfRightMargin: break; case rtfTopMargin: break; case rtfBottomMargin: break; case rtfFacingPage: break; case rtfGutterWid: break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -