📄 reader.c
字号:
/* * - Need to document error code meanings. * - Need to do something with \* on destinations. * - Make the parameter a long? * * reader.c - RTF file reader. Release 1.11. * * ASCII 10 (\n) and 13 (\r) are ignored and silently discarded. * Nulls are also discarded. * (although the read hook will still get a look at them.) * * "\:" is not a ":", it's a control symbol. But some versions of * Word seem to write "\:" for ":". This reader treats "\:" as a * plain text ":" * * 19 Mar 93 * - Add hack to skip "{\*\keycode ... }" group in stylesheet. * This is probably the wrong thing to do, but it's simple. * 13 Jul 93 * - Add THINK C awareness to malloc() declaration. Necessary so * compiler knows the malloc argument is 4 bytes. Ugh. * 07 Sep 93 * - Text characters are mapped onto standard codes, which are placed * in rtfMinor. * - Eliminated use of index() function. * 05 Mar 94 * - Added zillions of new symbols (those defined in RTF spec 1.2). * 14 Mar 94 * - Public functions RTFMsg() and RTFPanic() now take variable arguments. * This means RTFPanic() now is used in place of what was formerly the * internal function Error(). * - 8-bit characters are now legal, so they're not converted to \'xx * hex char representation now. * 01 Apr 94 * - Added public variables rtfLineNum and rtfLinePos. * - #include string.h or strings.h, avoiding strncmp() problem where * last argument is treated as zero when prototype isn't available. * 04 Apr 94 * - Treat style numbers 222 and 0 properly as "no style" and "normal". * 08 Apr 94 * - Control symbol table is no longer compiled in. It's read in the * first time that RTFInit() is called from the library file rtf-ctrl. * This shrinks all the translator binaries. rtf-ctrl is built by * mkrtf-ctrl.c. */# ifndef STRING_H# define STRING_H <string.h># endif# include <stdio.h># include <ctype.h># include STRING_H# ifdef STDARG# include <stdarg.h># else# ifdef VARARGS# include <varargs.h># endif /* VARARGS */# endif /* STDARG */# include "tokenscan.h"# define rtfInternal# include "rtf.h"# undef rtfInternal/* * Return pointer to new element of type t, or NULL * if no memory available. */# define New(t) ((t *) RTFAlloc (sizeof (t)))/* maximum number of character values representable in a byte */# define charSetSize 256/* charset stack size */# define maxCSStack 40#ifndef THINK_Cextern char *malloc ();#elseextern void *malloc(size_t);#endifstatic void _RTFGetToken (); void _RTFGetToken2 ();static int GetChar ();static void ReadFontTbl ();static void ReadColorTbl ();static void ReadStyleSheet ();static void ReadInfoGroup ();static void ReadPictGroup ();static void ReadObjGroup ();static void LookupInit ();static void Lookup ();static int Hash ();static void CharSetInit ();static void ReadCharSetMaps ();/* * Public variables (listed in rtf.h) */int rtfClass;int rtfMajor;int rtfMinor;int rtfParam;char *rtfTextBuf = (char *) NULL;int rtfTextLen;long rtfLineNum;int rtfLinePos;/* * Private stuff */static int pushedChar; /* pushback char if read too far */static int pushedClass; /* pushed token info for RTFUngetToken() */static int pushedMajor;static int pushedMinor;static int pushedParam;static char *pushedTextBuf = (char *) NULL;static int prevChar;static int bumpLine;static RTFFont *fontList = (RTFFont *) NULL; /* these lists MUST be */static RTFColor *colorList = (RTFColor *) NULL; /* initialized to NULL */static RTFStyle *styleList = (RTFStyle *) NULL;static FILE *rtffp = stdin;static char *inputName = (char *) NULL;static char *outputName = (char *) NULL;/* * This array is used to map standard character names onto their numeric codes. * The position of the name within the array is the code. * stdcharnames.h is generated in the ../h directory. */static char *stdCharName[] ={# include "stdcharnames.h" (char *) NULL};/* * These arrays are used to map RTF input character values onto the standard * character names represented by the values. Input character values are * used as indices into the arrays to produce standard character codes. */static char *genCharSetFile = (char *) NULL;static int genCharCode[charSetSize]; /* general */static int haveGenCharSet = 0;static char *symCharSetFile = (char *) NULL;static int symCharCode[charSetSize]; /* symbol */static int haveSymCharSet = 0;static int curCharSet = rtfCSGeneral;static int *curCharCode = genCharCode;/* * By default, the reader is configured to handle charset mapping invisibly, * including reading the charset files and switching charset maps as necessary * for Symbol font. */static int autoCharSetFlags;/* * Stack for keeping track of charset map on group begin/end. This is * necessary because group termination reverts the font to the previous * value, which may implicitly change it. */static int csStack[maxCSStack];int csTop = 0;/* * Initialize the reader. This may be called multiple times, * to read multiple files. The only thing not reset is the input * stream; that must be done with RTFSetStream(). */voidRTFInit (){int i;RTFColor *cp;RTFFont *fp;RTFStyle *sp;RTFStyleElt *eltList, *ep; rtfClass = -1; pushedClass = -1; pushedChar = EOF; rtfLineNum = 0; rtfLinePos = 0; prevChar = EOF; bumpLine = 0; if (rtfTextBuf == (char *) NULL) /* initialize text buffers */ { rtfTextBuf = RTFAlloc (rtfBufSiz); pushedTextBuf = RTFAlloc (rtfBufSiz); if (rtfTextBuf == (char *) NULL || pushedTextBuf == (char *) NULL) RTFPanic ("Cannot allocate text buffers."); rtfTextBuf[0] = pushedTextBuf[0] = '\0'; } RTFFree (inputName); RTFFree (outputName); inputName = outputName = (char *) NULL; /* initialize control symbol lookup table */ LookupInit (); for (i = 0; i < rtfMaxClass; i++) RTFSetClassCallback (i, (RTFFuncPtr) NULL); for (i = 0; i < rtfMaxDestination; i++) RTFSetDestinationCallback (i, (RTFFuncPtr) NULL); /* install built-in destination readers */ RTFSetDestinationCallback (rtfFontTbl, ReadFontTbl); RTFSetDestinationCallback (rtfColorTbl, ReadColorTbl); RTFSetDestinationCallback (rtfStyleSheet, ReadStyleSheet); RTFSetDestinationCallback (rtfInfo, ReadInfoGroup); RTFSetDestinationCallback (rtfPict, ReadPictGroup); RTFSetDestinationCallback (rtfObject, ReadObjGroup); RTFSetReadHook ((RTFFuncPtr) NULL); /* dump old lists if necessary */ while (fontList != (RTFFont *) NULL) { fp = fontList->rtfNextFont; RTFFree (fontList->rtfFName); RTFFree ((char *) fontList); fontList = fp; } while (colorList != (RTFColor *) NULL) { cp = colorList->rtfNextColor; RTFFree ((char *) colorList); colorList = cp; } while (styleList != (RTFStyle *) NULL) { sp = styleList->rtfNextStyle; eltList = styleList->rtfSSEList; while (eltList != (RTFStyleElt *) NULL) { ep = eltList->rtfNextSE; RTFFree (eltList->rtfSEText); RTFFree ((char *) eltList); eltList = ep; } RTFFree (styleList->rtfSName); RTFFree ((char *) styleList); styleList = sp; } CharSetInit (); csTop = 0;}/* * Set the reader's input stream to the given stream. Can * be used to redirect to other than the default (stdin). */voidRTFSetStream (stream)FILE *stream;{ rtffp = stream;}/* * Set or get the input or output file name. These are never guaranteed * to be accurate, only insofar as the calling program makes them so. */voidRTFSetInputName (name)char *name;{ if ((inputName = RTFStrSave (name)) == (char *) NULL) RTFPanic ("RTFSetInputName: out of memory");}char *RTFGetInputName (){ return (inputName);}voidRTFSetOutputName (name)char *name;{ if ((outputName = RTFStrSave (name)) == (char *) NULL) RTFPanic ("RTFSetOutputName: out of memory");}char *RTFGetOutputName (){ return (outputName);}/* ---------------------------------------------------------------------- *//* * Callback table manipulation routines *//* * Install or return a writer callback for a token class */static RTFFuncPtr ccb[rtfMaxClass]; /* class callbacks */voidRTFSetClassCallback (class, callback)int class;RTFFuncPtr callback;{ if (class >= 0 && class < rtfMaxClass) ccb[class] = callback;}RTFFuncPtrRTFGetClassCallback (class)int class;{ if (class >= 0 && class < rtfMaxClass) return (ccb[class]); return ((RTFFuncPtr) NULL);}/* * Install or return a writer callback for a destination type */static RTFFuncPtr dcb[rtfMaxDestination]; /* destination callbacks */voidRTFSetDestinationCallback (dest, callback)int dest;RTFFuncPtr callback;{ if (dest >= 0 && dest < rtfMaxDestination) dcb[dest] = callback;}RTFFuncPtrRTFGetDestinationCallback (dest)int dest;{ if (dest >= 0 && dest < rtfMaxDestination) return (dcb[dest]); return ((RTFFuncPtr) NULL);}/* ---------------------------------------------------------------------- *//* * Token reading routines *//* * Read the input stream, invoking the writer's callbacks * where appropriate. */voidRTFRead (){ while (RTFGetToken () != rtfEOF) RTFRouteToken ();}/* * Route a token. If it's a destination for which a reader is * installed, process the destination internally, otherwise * pass the token to the writer's class callback. */voidRTFRouteToken (){RTFFuncPtr p; if (rtfClass < 0 || rtfClass >= rtfMaxClass) /* watchdog */ { RTFPanic ("Unknown class %d: %s (reader malfunction)", rtfClass, rtfTextBuf); } if (RTFCheckCM (rtfControl, rtfDestination)) { /* invoke destination-specific callback if there is one */ if ((p = RTFGetDestinationCallback (rtfMinor)) != (RTFFuncPtr) NULL) { (*p) (); return; } } /* invoke class callback if there is one */ if ((p = RTFGetClassCallback (rtfClass)) != (RTFFuncPtr) NULL) (*p) ();}/* * Skip to the end of the current group. When this returns, * writers that maintain a state stack may want to call their * state unstacker; global vars will still be set to the group's * closing brace. */voidRTFSkipGroup (){int level = 1;int savecsTop; if(csTop>0)savecsTop=csTop-1; else savecsTop=0; RTFGetToken (); while (1) { if (rtfClass == rtfEOF) break; if (rtfClass == rtfGroup) { if (rtfMajor == rtfBeginGroup) ++level; else if (rtfMajor == rtfEndGroup) { if (--level < 1) break; /* end of initial group */ } } _RTFGetToken2(); } csTop=savecsTop;}/* * Read one token. Call the read hook if there is one. The * token class is the return value. Returns rtfEOF when there * are no more tokens. */intRTFGetToken (){RTFFuncPtr p; for (;;) { _RTFGetToken (); if ((p = RTFGetReadHook ()) != (RTFFuncPtr) NULL) (*p) (); /* give read hook a look at token */ /* Silently discard newlines, carriage returns, nulls. */ if (!(rtfClass == rtfText && (rtfMajor == '\n' || rtfMajor == '\r' || rtfMajor == '\0'))) break; } return (rtfClass);}/* * Install or return a token reader hook. */static RTFFuncPtr readHook;voidRTFSetReadHook (f)RTFFuncPtr f;{ readHook = f;}RTFFuncPtrRTFGetReadHook (){ return (readHook);}voidRTFUngetToken (){ if (pushedClass >= 0) /* there's already an ungotten token */ RTFPanic ("cannot unget two tokens"); if (rtfClass < 0) RTFPanic ("no token to unget"); pushedClass = rtfClass; pushedMajor = rtfMajor; pushedMinor = rtfMinor; pushedParam = rtfParam; (void) strcpy (pushedTextBuf, rtfTextBuf);}intRTFPeekToken (){ _RTFGetToken (); RTFUngetToken (); return (rtfClass);}static void_RTFGetToken (){RTFFont *fp; /* first check for pushed token from RTFUngetToken() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -