diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/rtf2tex/reader.c |
Initial commit
Diffstat (limited to 'support/rtf2tex/reader.c')
-rw-r--r-- | support/rtf2tex/reader.c | 1443 |
1 files changed, 1443 insertions, 0 deletions
diff --git a/support/rtf2tex/reader.c b/support/rtf2tex/reader.c new file mode 100644 index 0000000000..a3f7bab107 --- /dev/null +++ b/support/rtf2tex/reader.c @@ -0,0 +1,1443 @@ +/* + Need to document error code meanings. + Change document to reflect RTFFuncPtr. + + reader.c - RTF file reader. Distribution 1.06a2. + + ASCII 10 (\n) and 13 (\r) are ignored and silently 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 ":" + + This reader needs to catch \cf and \cb in the color table + reader? (Doesn't yet.) +*/ + +# include <stdio.h> +# include <ctype.h> +# ifdef VARARGS +# include <varargs.h> +# endif /* VARARGS */ + +# include "rtf.h" + + +/* + Return pointer to new element of type t, or NULL +*/ + +# define New(t) ((t *) RTFAlloc ((int) sizeof (t))) + + +# ifdef SYSV +# define index strchr +# endif + +extern char *index (); +extern char *strcpy (); +extern char *malloc (); + + +static void _RTFGetToken (); +static int GetChar (); +static int HexVal (); +static void ReadFontTbl (); +static void ReadColorTbl (); +static void ReadStyleSheet (); +static void ReadInfoGroup (); +static void ReadPictGroup (); +static void LookupInit (); +static void Lookup (); +static int Hash (); +static void Error (); + + +/* + Public variables (listed in rtf.h) +*/ + +int rtfClass; +int rtfMajor; +int rtfMinor; +int rtfParam; +char rtfTextBuf[rtfBufSiz]; +int rtfTextLen; + + +/* + 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[rtfBufSiz]; + + +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; + + +/* + 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(). +*/ + +void RTFInit () +{ +int i; +RTFColor *cp; +RTFFont *fp; +RTFStyle *sp; +RTFStyleElt *eltList, *ep; + + /* initialize 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); + + 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; + } + + rtfClass = -1; + pushedClass = -1; + pushedChar = EOF; +} + + +/* + Set the reader's input stream to the given stream. Can + be used to redirect to other than the default (stdin). +*/ + +void RTFSetStream (stream) +FILE *stream; +{ + rtffp = stream; +} + + +/* ---------------------------------------------------------------------- */ + +/* + Callback table manipulation routines +*/ + + +/* + Install or return a writer callback for a token class +*/ + + +static RTFFuncPtr ccb[rtfMaxClass]; /* class callbacks */ + +void RTFSetClassCallback (class, callback) +int class; +RTFFuncPtr callback; +{ + if (class >= 0 && class < rtfMaxClass) + ccb[class] = callback; +} + + +RTFFuncPtr RTFGetClassCallback (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 */ + +void RTFSetDestinationCallback (dest, callback) +int dest; +RTFFuncPtr callback; +{ + if (dest >= 0 && dest < rtfMaxDestination) + dcb[dest] = callback; +} + + +RTFFuncPtr RTFGetDestinationCallback (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. +*/ + +void RTFRead () +{ + 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. +*/ + +void RTFRouteToken () +{ +RTFFuncPtr p; + + if (rtfClass < 0 || rtfClass >= rtfMaxClass) /* watchdog */ + { + Error ("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. +*/ + +void RTFSkipGroup () +{ +int level = 1; + + while (RTFGetToken () != rtfEOF) + { + if (rtfClass == rtfGroup) + { + if (rtfMajor == rtfBeginGroup) + ++level; + else if (rtfMajor == rtfEndGroup) + { + if (--level < 1) + break; /* end of initial group */ + } + } + } +} + + +/* + 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. +*/ + +int RTFGetToken () +{ +RTFFuncPtr p; + + for (;;) + { + _RTFGetToken (); + if ((p = RTFGetReadHook ()) != (RTFFuncPtr) NULL) + (*p) (); /* give read hook a look at token */ + + /* Silently discard newlines and carriage returns. */ + if (!(rtfClass == rtfText + && (rtfMajor == '\n' || rtfMajor == '\r'))) + break; + } + return (rtfClass); +} + + +/* + Install or return a token reader hook. +*/ + +static RTFFuncPtr readHook; + +void RTFSetReadHook (f) +RTFFuncPtr f; +{ + readHook = f; +} + + +RTFFuncPtr RTFGetReadHook () +{ + return (readHook); +} + + +void RTFUngetToken () +{ + if (pushedClass >= 0) /* there's already an ungotten token */ + Error ("cannot unget two tokens"); + if (rtfClass < 0) + Error ("no token to unget"); + pushedClass = rtfClass; + pushedMajor = rtfMajor; + pushedMinor = rtfMinor; + pushedParam = rtfParam; + (void) strcpy (pushedTextBuf, rtfTextBuf); +} + + +int RTFPeekToken () +{ + _RTFGetToken (); + RTFUngetToken (); + return (rtfClass); +} + + +static void _RTFGetToken () +{ +int sign; +int c; + + /* check for pushed token from RTFUngetToken() */ + + if (pushedClass >= 0) + { + rtfClass = pushedClass; + rtfMajor = pushedMajor; + rtfMinor = pushedMinor; + rtfParam = pushedParam; + (void) strcpy (rtfTextBuf, pushedTextBuf); + rtfTextLen = strlen (rtfTextBuf); + pushedClass = -1; + return; + } + + /* initialize token vars */ + + rtfClass = rtfUnknown; + rtfParam = rtfNoParam; + rtfTextBuf[rtfTextLen = 0] = '\0'; + + /* get first character, which may be a pushback from previous token */ + + if (pushedChar != EOF) + { + c = pushedChar; + rtfTextBuf[rtfTextLen] = c; + rtfTextBuf[++rtfTextLen] = '\0'; + pushedChar = EOF; + } + else if ((c = GetChar ()) == EOF) + { + rtfClass = rtfEOF; + return; + } + + if (c == '{') + { + rtfClass = rtfGroup; + rtfMajor = rtfBeginGroup; + return; + } + if (c == '}') + { + rtfClass = rtfGroup; + rtfMajor = rtfEndGroup; + return; + } + if (c != '\\') + { + /* + Two possibilities here: + 1) ASCII 9, effectively like \tab control symbol + 2) literal text char + */ + if (c == '\t') /* ASCII 9 */ + { + rtfClass = rtfControl; + rtfMajor = rtfSpecialChar; + rtfMinor = rtfTab; + } + else + { + rtfClass = rtfText; + rtfMajor = c; + } + return; + } + if ((c = GetChar ()) == EOF) + { + /* early eof, whoops (class is rtfUnknown) */ + return; + } + if (!isalpha (c)) + { + /* + Three possibilities here: + 1) hex encoded text char, e.g., \'d5, \'d3 + 2) special escaped text char, e.g., \{, \} + 3) control symbol, e.g., \_, \-, \|, \<10> + */ + if (c == '\'') /* hex char */ + { + int c2; + + if ((c = GetChar ()) != EOF && (c2 = GetChar ()) != EOF) + { + /* should do isxdigit check! */ + rtfClass = rtfText; + rtfMajor = HexVal (c) * 16 + HexVal (c2); + return; + } + /* early eof, whoops (class is rtfUnknown) */ + return; + } + + if (index (":{}\\", c) != (char *) NULL) /* escaped char */ + { + rtfClass = rtfText; + rtfMajor = c; + return; + } + + /* control symbol */ + Lookup (rtfTextBuf); /* sets class, major, minor */ + return; + } + /* control word */ + while (isalpha (c)) + { + if ((c = GetChar ()) == EOF) + break; + } + + /* + At this point, the control word is all collected, so the + major/minor numbers are determined before the parameter + (if any) is scanned. There will be one too many characters + in the buffer, though, so fix up before and restore after + looking up. + */ + + if (c != EOF) + rtfTextBuf[rtfTextLen-1] = '\0'; + Lookup (rtfTextBuf); /* sets class, major, minor */ + if (c != EOF) + rtfTextBuf[rtfTextLen-1] = c; + + /* + Should be looking at first digit of parameter if there + is one, unless it's negative. In that case, next char + is '-', so need to gobble next char, and remember sign. + */ + + sign = 1; + if (c == '-') + { + sign = -1; + c = GetChar (); + } + if (c != EOF && isdigit (c)) + { + rtfParam = 0; + while (isdigit (c)) /* gobble parameter */ + { + rtfParam = rtfParam * 10 + c - '0'; + if ((c = GetChar ()) == EOF) + break; + } + rtfParam *= sign; + } + /* + If control symbol delimiter was a blank, gobble it. + Otherwise the character is first char of next token, so + push it back for next call. In either case, delete the + delimiter from the token buffer. + */ + if (c != EOF) + { + if (c != ' ') + pushedChar = c; + rtfTextBuf[--rtfTextLen] = '\0'; + } + return; +} + + +/* + Distributions up through 1.04 assumed high bit could be set in + RTF file characters. Beginning with 1.05, that's not true, but + still check and ignore such characters. (Cope with things like + WriteNow on NeXT, which generates bad RTF by writing 8-bit + characters.) +*/ + +static int GetChar () +{ +int c; + + if ((c = getc (rtffp)) != EOF) + { + if (c & 0x80) + { + fprintf (stderr, "Character found with high bit set"); + fprintf (stderr, " (%#x) -> changed to '?'\n", c); + c = '?'; + } + rtfTextBuf[rtfTextLen] = c; + rtfTextBuf[++rtfTextLen] = '\0'; + } + return (c); +} + + +static int HexVal (c) +char c; +{ + if (isupper (c)) + c = tolower (c); + if (isdigit (c)) + return (c - '0'); /* '0'..'9' */ + return (c - 'a' + 10); /* 'a'..'f' */ +} + + +/* + Synthesize a token by setting the global variables to the + values supplied. Typically this is followed with a call + to RTFRouteToken(). + + If param is non-negative, it becomes part of the token text. +*/ + +void RTFSetToken (class, major, minor, param, text) +int class, major, minor, param; +char *text; +{ + rtfClass = class; + rtfMajor = major; + rtfMinor = minor; + rtfParam = param; + if (param == rtfNoParam) + (void) strcpy (rtfTextBuf, text); + else + sprintf (rtfTextBuf, "%s%d", text, param); + rtfTextLen = strlen (rtfTextBuf); +} + + +/* ---------------------------------------------------------------------- */ + +/* + Special destination readers. They gobble the destination so the + writer doesn't have to deal with them. That's wrong for any + translator that wants to process any of these itself. In that + case, these readers should be overridden by installing a different + destination callback. + + NOTE: The last token read by each of these reader will be the + destination's terminating '}', which will then be the current token. + That '}' token is passed to RTFRouteToken() - the writer has already + seen the '{' that began the destination group, and may have pushed a + state; it also needs to know at the end of the group that a state + should be popped. + + It's important that rtf.h and the control token lookup table list + as many symbols as possible, because these readers unfortunately + make strict assumptions about the input they expect, and a token + of class rtfUnknown will throw them off easily. +*/ + + +/* + Read { \fonttbl ... } destination. Old font tables don't have + braces around each table entry; try to adjust for that. +*/ + +static void ReadFontTbl () +{ +RTFFont *fp; +char buf[rtfBufSiz], *bp; +int old = -1; + + for (;;) + { + (void) RTFGetToken (); + if (RTFCheckCM (rtfGroup, rtfEndGroup)) + break; + if (old < 0) /* first entry - determine tbl type */ + { + if (RTFCheckCMM (rtfControl, rtfCharAttr, rtfFontNum)) + old = 1; /* no brace */ + else if (RTFCheckCM (rtfGroup, rtfBeginGroup)) + old = 0; /* brace */ + else /* can't tell! */ + Error ("FTErr - Cannot determine format"); + } + if (old == 0) /* need to find "{" here */ + { + if (!RTFCheckCM (rtfGroup, rtfBeginGroup)) + Error ("FTErr - missing \"{\""); + (void) RTFGetToken (); /* yes, skip to next token */ + } + if ((fp = New (RTFFont)) == (RTFFont *) NULL) + Error ("FTErr - cannot allocate font entry"); + fp->rtfNextFont = fontList; + fontList = fp; + if (!RTFCheckCMM (rtfControl, rtfCharAttr, rtfFontNum)) + Error ("FTErr - missing font number"); + fp->rtfFNum = rtfParam; + (void) RTFGetToken (); + if (!RTFCheckCM (rtfControl, rtfFontFamily)) + Error ("FTErr - missing font family"); + fp->rtfFFamily = rtfMinor; + bp = buf; + while (RTFGetToken () == rtfText) + { + if (rtfMajor == ';') + break; + *bp++ = rtfMajor; + } + *bp = '\0'; + if (buf[0] == '\0') + Error ("FTErr - missing font name"); + if ((fp->rtfFName = RTFStrSave (buf)) == (char *) NULL) + Error ("FTErr - cannot allocate font name"); + if (old == 0) /* need to see "}" here */ + { + (void) RTFGetToken (); + if (!RTFCheckCM (rtfGroup, rtfEndGroup)) + Error ("FTErr - missing \"}\""); + } + } + RTFRouteToken (); /* feed "}" back to router */ +} + + +/* + The color table entries have color values of -1 if + the default color should be used for the entry (only + a semi-colon is given in the definition, no color values). + There will be a problem if a partial entry (1 or 2 but + not 3 color values) is given. The possibility is ignored + here. +*/ + +static void ReadColorTbl () +{ +RTFColor *cp; +int cnum = 0; + + for (;;) + { + (void) RTFGetToken (); + if (RTFCheckCM (rtfGroup, rtfEndGroup)) + break; + if ((cp = New (RTFColor)) == (RTFColor *) NULL) + Error ("CTErr - cannot allocate color entry"); + cp->rtfCNum = cnum++; + cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1; + cp->rtfNextColor = colorList; + colorList = cp; + for (;;) + { + if (!RTFCheckCM (rtfControl, rtfColorName)) + break; + switch (rtfMinor) + { + case rtfRed: cp->rtfCRed = rtfParam; break; + case rtfGreen: cp->rtfCGreen = rtfParam; break; + case rtfBlue: cp->rtfCBlue = rtfParam; break; + } + RTFGetToken (); + } + if (!RTFCheckCM (rtfText, (int) ';')) + Error ("CTErr - malformed entry"); + } + RTFRouteToken (); /* feed "}" back to router */ +} + + +/* + The "Normal" style definition doesn't contain any style number + (why?), all others do. Normal style is given style 0. +*/ + +static void ReadStyleSheet () +{ +RTFStyle *sp; +RTFStyleElt *sep, *sepLast; +char buf[rtfBufSiz], *bp; + + for (;;) + { + (void) RTFGetToken (); + if (RTFCheckCM (rtfGroup, rtfEndGroup)) + break; + if ((sp = New (RTFStyle)) == (RTFStyle *) NULL) + Error ("SSErr - cannot allocate stylesheet entry"); + sp->rtfSNum = -1; + sp->rtfSBasedOn = rtfBasedOnNone; + sp->rtfSNextPar = -1; + sp->rtfSSEList = sepLast = (RTFStyleElt *) NULL; + sp->rtfNextStyle = styleList; + sp->rtfExpanding = 0; + styleList = sp; + if (!RTFCheckCM (rtfGroup, rtfBeginGroup)) + Error ("SSErr - missing \"{\""); + while (RTFGetToken () == rtfControl) + { + if (RTFCheckMM (rtfParAttr, rtfStyleNum)) + { + sp->rtfSNum = rtfParam; + continue; + } + if (RTFCheckMM (rtfStyleAttr, rtfBasedOn)) + { + sp->rtfSBasedOn = rtfParam; + continue; + } + if (RTFCheckMM (rtfStyleAttr, rtfNext)) + { + sp->rtfSNextPar = rtfParam; + continue; + } + if ((sep = New (RTFStyleElt)) == (RTFStyleElt *) NULL) + Error ("SSErr - cannot allocate style element"); + sep->rtfSEClass = rtfClass; + sep->rtfSEMajor = rtfMajor; + sep->rtfSEMinor = rtfMinor; + sep->rtfSEParam = rtfParam; + if ((sep->rtfSEText = RTFStrSave (rtfTextBuf)) + == (char *) NULL) + Error ("SSErr - cannot allocate style element text"); + if (sepLast == (RTFStyleElt *) NULL) + sp->rtfSSEList = sep; /* first element */ + else /* add to end */ + sepLast->rtfNextSE = sep; + sep->rtfNextSE = (RTFStyleElt *) NULL; + sepLast = sep; + } + if (sp->rtfSNextPar == -1) /* \snext not given */ + sp->rtfSNextPar = sp->rtfSNum; /* next is itself */ + if (rtfClass != rtfText) + Error ("SSErr - missing style name"); + bp = buf; + while (rtfClass == rtfText) + { + if (rtfMajor == ';') + { + (void) RTFGetToken (); + break; + } + *bp++ = rtfMajor; + (void) RTFGetToken (); + } + *bp = '\0'; + if (sp->rtfSNum < 0) /* no style number was specified */ + { /* (only legal for Normal style) */ + if (strcmp (buf, "Normal") != 0) + Error ("SSErr - missing style number"); + sp->rtfSNum = 0; + } + if ((sp->rtfSName = RTFStrSave (buf)) == (char *) NULL) + Error ("SSErr - cannot allocate style name"); + if (!RTFCheckCM (rtfGroup, rtfEndGroup)) + Error ("SSErr - missing \"}\""); + } + RTFRouteToken (); /* feed "}" back to router */ +} + + +static void ReadInfoGroup () +{ + RTFSkipGroup (); + RTFRouteToken (); /* feed "}" back to router */ +} + + +static void ReadPictGroup () +{ + RTFSkipGroup (); + RTFRouteToken (); /* feed "}" back to router */ +} + + +/* ---------------------------------------------------------------------- */ + +/* + Routines to return pieces of stylesheet, or font or color tables +*/ + + +RTFStyle *RTFGetStyle (num) +int num; +{ +RTFStyle *s; + + if (num == -1) + return (styleList); + for (s = styleList; s != (RTFStyle *) NULL; s = s->rtfNextStyle) + { + if (s->rtfSNum == num) + break; + } + return (s); /* NULL if not found */ +} + + +RTFFont *RTFGetFont (num) +int num; +{ +RTFFont *f; + + if (num == -1) + return (fontList); + for (f = fontList; f != (RTFFont *) NULL; f = f->rtfNextFont) + { + if (f->rtfFNum == num) + break; + } + return (f); /* NULL if not found */ +} + + +RTFColor *RTFGetColor (num) +int num; +{ +RTFColor *c; + + if (num == -1) + return (colorList); + for (c = colorList; c != (RTFColor *) NULL; c = c->rtfNextColor) + { + if (c->rtfCNum == num) + break; + } + return (c); /* NULL if not found */ +} + + +/* ---------------------------------------------------------------------- */ + + +/* + Expand style n, if there is such a style. +*/ + +void RTFExpandStyle (n) +int n; +{ +RTFStyle *s; +RTFStyleElt *se; + + if (n == -1 || (s = RTFGetStyle (n)) == (RTFStyle *) NULL) + return; + if (s->rtfExpanding != 0) + Error ("Style expansion loop, style %d", n); + s->rtfExpanding = 1; /* set expansion flag for loop detection */ + /* + Expand "based-on" style. This is done by synthesizing + the token that the writer needs to see in order to trigger + another style expansion, and feeding to token back through + the router so the writer sees it. + */ + RTFSetToken (rtfControl, rtfParAttr, rtfStyleNum, s->rtfSBasedOn, "\\s"); + RTFRouteToken (); + /* + Now route the tokens unique to this style. RTFSetToken() + isn't used because it would add the param value to the end + of the token text, which already has it in. + */ + for (se = s->rtfSSEList; se != (RTFStyleElt *) NULL; se = se->rtfNextSE) + { + rtfClass = se->rtfSEClass; + rtfMajor = se->rtfSEMajor; + rtfMinor = se->rtfSEMinor; + rtfParam = se->rtfSEParam; + (void) strcpy (rtfTextBuf, se->rtfSEText); + rtfTextLen = strlen (rtfTextBuf); + RTFRouteToken (); + } + s->rtfExpanding = 0; /* done - clear expansion flag */ +} + + +/* ---------------------------------------------------------------------- */ + +/* + Control symbol lookup routines +*/ + + +typedef struct RTFKey RTFKey; + +struct RTFKey +{ + int rtfKMajor; /* major number */ + int rtfKMinor; /* minor number */ + char *rtfKStr; /* symbol name */ + int rtfKHash; /* symbol name hash value */ +}; + +/* + A minor number of -1 means the token has no minor number + (all valid minor numbers are >= 0). +*/ + +static RTFKey rtfKey[] = +{ + rtfSpecialChar, rtfCurHeadPict, "chpict", 0, /* ?? */ + + rtfSpecialChar, rtfCurHeadDate, "chdate", 0, + rtfSpecialChar, rtfCurHeadTime, "chtime", 0, + rtfSpecialChar, rtfCurHeadPage, "chpgn", 0, + rtfSpecialChar, rtfCurFNote, "chftn", 0, + rtfSpecialChar, rtfCurAnnotRef, "chatn", 0, + rtfSpecialChar, rtfFNoteSep, "chftnsep", 0, + rtfSpecialChar, rtfFNoteCont, "chftnsepc", 0, + rtfSpecialChar, rtfFormula, "|", 0, + rtfSpecialChar, rtfNoBrkSpace, "~", 0, + rtfSpecialChar, rtfNoReqHyphen, "-", 0, + rtfSpecialChar, rtfNoBrkHyphen, "_", 0, + rtfSpecialChar, rtfCell, "cell", 0, + rtfSpecialChar, rtfRow, "row", 0, + rtfSpecialChar, rtfPar, "par", 0, + rtfSpecialChar, rtfPar, "\n", 0, + rtfSpecialChar, rtfPar, "\r", 0, + rtfSpecialChar, rtfSect, "sect", 0, + rtfSpecialChar, rtfPage, "page", 0, + rtfSpecialChar, rtfColumn, "column", 0, + rtfSpecialChar, rtfLine, "line", 0, + rtfSpecialChar, rtfTab, "tab", 0, + rtfSpecialChar, rtfOptDest, "*", 0, + rtfSpecialChar, rtfIIntVersion, "vern", 0, + rtfSpecialChar, rtfICreateTime, "creatim", 0, + rtfSpecialChar, rtfIRevisionTime, "revtim", 0, + rtfSpecialChar, rtfIPrintTime, "printim", 0, + rtfSpecialChar, rtfIBackupTime, "buptim", 0, + rtfSpecialChar, rtfIEditTime, "edmins", 0, + rtfSpecialChar, rtfIYear, "yr", 0, + rtfSpecialChar, rtfIMonth, "mo", 0, + rtfSpecialChar, rtfIDay, "dy", 0, + rtfSpecialChar, rtfIHour, "hr", 0, + rtfSpecialChar, rtfIMinute, "min", 0, + rtfSpecialChar, rtfINPages, "nofpages", 0, + rtfSpecialChar, rtfINWords, "nofwords", 0, + rtfSpecialChar, rtfINChars, "nofchars", 0, + rtfSpecialChar, rtfIIntID, "id", 0, + + rtfCharAttr, rtfPlain, "plain", 0, + rtfCharAttr, rtfBold, "b", 0, + rtfCharAttr, rtfItalic, "i", 0, + rtfCharAttr, rtfStrikeThru, "strike", 0, + rtfCharAttr, rtfOutline, "outl", 0, + rtfCharAttr, rtfShadow, "shad", 0, + rtfCharAttr, rtfSmallCaps, "scaps", 0, + rtfCharAttr, rtfAllCaps, "caps", 0, + rtfCharAttr, rtfInvisible, "v", 0, + rtfCharAttr, rtfFontNum, "f", 0, + rtfCharAttr, rtfFontSize, "fs", 0, + rtfCharAttr, rtfExpand, "expnd", 0, + rtfCharAttr, rtfUnderline, "ul", 0, + rtfCharAttr, rtfWUnderline, "ulw", 0, + rtfCharAttr, rtfDUnderline, "uld", 0, + rtfCharAttr, rtfDbUnderline, "uldb", 0, + rtfCharAttr, rtfNoUnderline, "ulnone", 0, + rtfCharAttr, rtfSuperScript, "up", 0, + rtfCharAttr, rtfSubScript, "dn", 0, + rtfCharAttr, rtfRevised, "revised", 0, + rtfCharAttr, rtfForeColor, "cf", 0, + rtfCharAttr, rtfBackColor, "cb", 0, + rtfCharAttr, rtfGray, "gray", 0, + + rtfParAttr, rtfParDef, "pard", 0, + rtfParAttr, rtfStyleNum, "s", 0, + rtfParAttr, rtfQuadLeft, "ql", 0, + rtfParAttr, rtfQuadRight, "qr", 0, + rtfParAttr, rtfQuadJust, "qj", 0, + rtfParAttr, rtfQuadCenter, "qc", 0, + rtfParAttr, rtfFirstIndent, "fi", 0, + rtfParAttr, rtfLeftIndent, "li", 0, + rtfParAttr, rtfRightIndent, "ri", 0, + rtfParAttr, rtfSpaceBefore, "sb", 0, + rtfParAttr, rtfSpaceAfter, "sa", 0, + rtfParAttr, rtfSpaceBetween, "sl", 0, + rtfParAttr, rtfInTable, "intbl", 0, + rtfParAttr, rtfKeep, "keep", 0, + rtfParAttr, rtfKeepNext, "keepn", 0, + rtfParAttr, rtfSideBySide, "sbys", 0, + rtfParAttr, rtfPBBefore, "pagebb", 0, + rtfParAttr, rtfNoLineNum, "noline", 0, + rtfParAttr, rtfTabPos, "tx", 0, + rtfParAttr, rtfTabRight, "tqr", 0, + rtfParAttr, rtfTabCenter, "tqc", 0, + rtfParAttr, rtfTabDecimal, "tqdec", 0, + rtfParAttr, rtfTabBar, "tb", 0, + rtfParAttr, rtfBorderTop, "brdrt", 0, + rtfParAttr, rtfBorderBottom, "brdrb", 0, + rtfParAttr, rtfBorderLeft, "brdrl", 0, + rtfParAttr, rtfBorderRight, "brdrr", 0, + rtfParAttr, rtfBorderBar, "bar", 0, + rtfParAttr, rtfBorderBox, "box", 0, + rtfParAttr, rtfBorderBetween, "brdrbtw", 0, + rtfParAttr, rtfBorderSingle, "brdrs", 0, + rtfParAttr, rtfBorderThick, "brdrth", 0, + rtfParAttr, rtfBorderShadow, "brdrsh", 0, + rtfParAttr, rtfBorderDouble, "brdrdb", 0, + rtfParAttr, rtfBorderDot, "brdrdot", 0, + rtfParAttr, rtfBorderHair, "brdrhair", 0, + rtfParAttr, rtfLeaderDot, "tldot", 0, + rtfParAttr, rtfLeaderHyphen, "tlhyph", 0, + rtfParAttr, rtfLeaderUnder, "tlul", 0, + rtfParAttr, rtfLeaderThick, "tlth", 0, + rtfParAttr, rtfBorderSpace, "brsp", 0, + + rtfSectAttr, rtfSectDef, "sectd", 0, + /*rtfSectAttr, rtfNoBreak, "nobreak", 0, + rtfSectAttr, rtfColBreak, "colbreak", 0, + rtfSectAttr, rtfPageBreak, "pagebreak", 0, + rtfSectAttr, rtfEvenBreak, "evenbreak", 0, + rtfSectAttr, rtfOddBreak, "oddbreak", 0,*/ + rtfSectAttr, rtfNoBreak, "sbknone", 0, + rtfSectAttr, rtfColBreak, "sbkcol", 0, + rtfSectAttr, rtfPageBreak, "sbkpage", 0, + rtfSectAttr, rtfEvenBreak, "sbkeven", 0, + rtfSectAttr, rtfOddBreak, "sbkodd", 0, + rtfSectAttr, rtfPageCont, "pgncont", 0, + rtfSectAttr, rtfPageStarts, "pgnstarts", 0, + rtfSectAttr, rtfPageRestart, "pgnrestart", 0, + rtfSectAttr, rtfPageDecimal, "pgndec", 0, + rtfSectAttr, rtfPageURoman, "pgnucrm", 0, + rtfSectAttr, rtfPageLRoman, "pgnlcrm", 0, + rtfSectAttr, rtfPageULetter, "pgnucltr", 0, + rtfSectAttr, rtfPageLLetter, "pgnlcltr", 0, + rtfSectAttr, rtfPageNumLeft, "pgnx", 0, + rtfSectAttr, rtfPageNumTop, "pgny", 0, + rtfSectAttr, rtfHeaderY, "headery", 0, + rtfSectAttr, rtfFooterY, "footery", 0, + rtfSectAttr, rtfLineModulus, "linemod", 0, + rtfSectAttr, rtfLineDist, "linex", 0, + rtfSectAttr, rtfLineStarts, "linestarts", 0, + rtfSectAttr, rtfLineRestart, "linerestart", 0, + rtfSectAttr, rtfLineRestartPg, "lineppage", 0, + rtfSectAttr, rtfLineCont, "linecont", 0, + rtfSectAttr, rtfTopVAlign, "vertalt", 0, + rtfSectAttr, rtfBottomVAlign, "vertal", 0, + rtfSectAttr, rtfCenterVAlign, "vertalc", 0, + rtfSectAttr, rtfJustVAlign, "vertalj", 0, + rtfSectAttr, rtfColumns, "cols", 0, + rtfSectAttr, rtfColumnSpace, "colsx", 0, + rtfSectAttr, rtfColumnLine, "linebetcol", 0, + rtfSectAttr, rtfENoteHere, "endnhere", 0, + rtfSectAttr, rtfTitleSpecial, "titlepg", 0, + + rtfDocAttr, rtfPaperWidth, "paperw", 0, + rtfDocAttr, rtfPaperHeight, "paperh", 0, + rtfDocAttr, rtfLeftMargin, "margl", 0, + rtfDocAttr, rtfRightMargin, "margr", 0, + rtfDocAttr, rtfTopMargin, "margt", 0, + rtfDocAttr, rtfBottomMargin, "margb", 0, + rtfDocAttr, rtfFacingPage, "facingp", 0, + rtfDocAttr, rtfGutterWid, "gutter", 0, + rtfDocAttr, rtfDefTab, "deftab", 0, + rtfDocAttr, rtfWidowCtrl, "widowctrl", 0, + rtfDocAttr, rtfHyphHotZone, "hyphhotz", 0, + rtfDocAttr, rtfFNoteEndSect, "endnotes", 0, + rtfDocAttr, rtfFNoteEndDoc, "enddoc", 0, + rtfDocAttr, rtfFNoteBottom, "ftnbj", 0, + rtfDocAttr, rtfFNoteText, "ftntj", 0, + rtfDocAttr, rtfFNoteStart, "ftnstart", 0, + rtfDocAttr, rtfFNoteRestart, "ftnrestart", 0, + rtfDocAttr, rtfPageStart, "pgnstart", 0, + rtfDocAttr, rtfLineStart, "linestart", 0, + rtfDocAttr, rtfLandscape, "landscape", 0, + rtfDocAttr, rtfFracWidth, "fracwidth", 0, + rtfDocAttr, rtfNextFile, "nextfile", 0, + rtfDocAttr, rtfTemplate, "template", 0, + rtfDocAttr, rtfMakeBackup, "makeback", 0, + rtfDocAttr, rtfRTFDefault, "defformat", 0, + rtfDocAttr, rtfRevisions, "revisions", 0, + rtfDocAttr, rtfMirrorMargin, "margmirror", 0, + rtfDocAttr, rtfRevDisplay, "revprop", 0, + rtfDocAttr, rtfRevBar, "revbar", 0, + + rtfStyleAttr, rtfBasedOn, "sbasedon", 0, + rtfStyleAttr, rtfNext, "snext", 0, + + rtfPictAttr, rtfMacQD, "macpict", 0, + rtfPictAttr, rtfWinMetafile, "wmetafile", 0, + rtfPictAttr, rtfWinBitmap, "wbitmap", 0, + rtfPictAttr, rtfPicWid, "picw", 0, + rtfPictAttr, rtfPicHt, "pich", 0, + rtfPictAttr, rtfPicGoalWid, "picwgoal", 0, + rtfPictAttr, rtfPicGoalWid, "picwGoal", 0, + rtfPictAttr, rtfPicGoalHt, "pichgoal", 0, + rtfPictAttr, rtfPicGoalHt, "pichGoal", 0, + rtfPictAttr, rtfPicScaleX, "picscalex", 0, + rtfPictAttr, rtfPicScaleY, "picscaley", 0, + rtfPictAttr, rtfPicScaled, "picscaled", 0, + rtfPictAttr, rtfPicCropTop, "piccropt", 0, + rtfPictAttr, rtfPicCropBottom, "piccropb", 0, + rtfPictAttr, rtfPicCropLeft, "piccropl", 0, + rtfPictAttr, rtfPicCropRight, "piccropr", 0, + rtfPictAttr, rtfPixelBits, "wbmbitspixel", 0, + rtfPictAttr, rtfBitmapPlanes, "wbmplanes", 0, + rtfPictAttr, rtfBitmapWid, "wbmwidthbytes", 0, + rtfPictAttr, rtfPicBinary, "bin", 0, + + rtfNeXTGrAttr, rtfNeXTGWidth, "width", 0, + rtfNeXTGrAttr, rtfNeXTGHeight, "height", 0, + + rtfDestination, rtfPict, "pict", 0, + rtfDestination, rtfNeXTGraphic, "NeXTGraphic", 0, + rtfDestination, rtfFootnote, "footnote", 0, + rtfDestination, rtfHeader, "header", 0, + rtfDestination, rtfHeaderLeft, "headerl", 0, + rtfDestination, rtfHeaderRight, "headerr", 0, + rtfDestination, rtfHeaderFirst, "headerf", 0, + rtfDestination, rtfFooter, "footer", 0, + rtfDestination, rtfFooterLeft, "footerl", 0, + rtfDestination, rtfFooterRight, "footerr", 0, + rtfDestination, rtfFooterFirst, "footerf", 0, + rtfDestination, rtfFNSep, "ftnsep", 0, + rtfDestination, rtfFNContSep, "ftnsepc", 0, + rtfDestination, rtfFNContNotice, "ftncn", 0, + rtfDestination, rtfInfo, "info", 0, + rtfDestination, rtfStyleSheet, "stylesheet", 0, + rtfDestination, rtfFontTbl, "fonttbl", 0, + rtfDestination, rtfColorTbl, "colortbl", 0, + rtfDestination, rtfAnnotation, "annotation", 0, + rtfDestination, rtfAnnotID, "atnid", 0, + rtfDestination, rtfField, "field", 0, + rtfDestination, rtfFieldInst, "fldinst", 0, + rtfDestination, rtfFieldResult, "fldrslt", 0, + rtfDestination, rtfIndex, "xe", 0, + rtfDestination, rtfIndexBold, "bxe", 0, + rtfDestination, rtfIndexItalic, "ixe", 0, + rtfDestination, rtfIndexText, "txe", 0, + rtfDestination, rtfIndexRange, "rxe", 0, + rtfDestination, rtfTOC, "tc", 0, + rtfDestination, rtfBookmarkStart, "bkmkstart", 0, + rtfDestination, rtfBookmarkEnd, "bkmkend", 0, + rtfDestination, rtfITitle, "title", 0, + rtfDestination, rtfISubject, "subject", 0, + rtfDestination, rtfIAuthor, "author", 0, + rtfDestination, rtfIOperator, "operator", 0, + rtfDestination, rtfIKeywords, "keywords", 0, + rtfDestination, rtfIComment, "comment", 0, + rtfDestination, rtfIVersion, "version", 0, + rtfDestination, rtfIDoccomm, "doccomm", 0, + + rtfTOCAttr, rtfTOCType, "tcf", 0, + rtfTOCAttr, rtfTOCLevel, "tcl", 0, + + rtfFontFamily, rtfFFNil, "fnil", 0, + rtfFontFamily, rtfFFRoman, "froman", 0, + rtfFontFamily, rtfFFSwiss, "fswiss", 0, + rtfFontFamily, rtfFFModern, "fmodern", 0, + rtfFontFamily, rtfFFScript, "fscript", 0, + rtfFontFamily, rtfFFDecor, "fdecor", 0, + rtfFontFamily, rtfFFTech, "ftech", 0, + + rtfColorName, rtfRed, "red", 0, + rtfColorName, rtfGreen, "green", 0, + rtfColorName, rtfBlue, "blue", 0, + + rtfCharSet, rtfMacCharSet, "mac", 0, + rtfCharSet, rtfAnsiCharSet, "ansi", 0, + rtfCharSet, rtfPcCharSet, "pc", 0, + rtfCharSet, rtfPcaCharSet, "pca", 0, + + rtfTblAttr, rtfCellBordBottom, "clbrdrb", 0, + rtfTblAttr, rtfCellBordTop, "clbrdrt", 0, + rtfTblAttr, rtfCellBordLeft, "clbrdrl", 0, + rtfTblAttr, rtfCellBordRight, "clbrdrr", 0, + rtfTblAttr, rtfRowDef, "trowd", 0, + rtfTblAttr, rtfRowLeft, "trql", 0, + rtfTblAttr, rtfRowRight, "trqr", 0, + rtfTblAttr, rtfRowCenter, "trqc", 0, + rtfTblAttr, rtfRowGapH, "trgaph", 0, + rtfTblAttr, rtfRowHt, "trrh", 0, + rtfTblAttr, rtfRowLeftEdge, "trleft", 0, + rtfTblAttr, rtfCellPos, "cellx", 0, + rtfTblAttr, rtfMergeRngFirst, "clmgf", 0, + rtfTblAttr, rtfMergePrevious, "clmrg", 0, + + rtfFieldAttr, rtfFieldDirty, "flddirty", 0, + rtfFieldAttr, rtfFieldEdited, "fldedit", 0, + rtfFieldAttr, rtfFieldLocked, "fldlock", 0, + rtfFieldAttr, rtfFieldPrivate, "fldpriv", 0, + + rtfPosAttr, rtfPosX, "posx", 0, + rtfPosAttr, rtfPosXCenter, "posxc", 0, + rtfPosAttr, rtfPosXInside, "posxi", 0, + rtfPosAttr, rtfPosXLeft, "posxl", 0, + rtfPosAttr, rtfPosXOutSide, "posxo", 0, + rtfPosAttr, rtfPosXRight, "posxr", 0, + rtfPosAttr, rtfPosY, "posy", 0, + rtfPosAttr, rtfPosYInline, "posyil", 0, + rtfPosAttr, rtfPosYTop, "posyt", 0, + rtfPosAttr, rtfPosYCenter, "posyc", 0, + rtfPosAttr, rtfPosYBottom, "posyb", 0, + rtfPosAttr, rtfAbsWid, "absw", 0, + rtfPosAttr, rtfTextDist, "dxfrtext", 0, + rtfPosAttr, rtfRPosMargV, "pvmrg", 0, + rtfPosAttr, rtfRPosPageV, "pvpg", 0, + rtfPosAttr, rtfRPosMargH, "phmrg", 0, + rtfPosAttr, rtfRPosPageH, "phpg", 0, + rtfPosAttr, rtfRPosColH, "phcol", 0, + + rtfVersion, -1, "rtf", 0, + rtfDefFont, -1, "deff", 0, + + 0, -1, (char *) NULL, 0 +}; + + +/* + Initialize lookup table hash values. Only need to do this the + first time it's called. +*/ + +static void LookupInit () +{ +static int inited = 0; +RTFKey *rp; + + if (inited == 0) + { + for (rp = rtfKey; rp->rtfKStr != (char *) NULL; rp++) + rp->rtfKHash = Hash (rp->rtfKStr); + ++inited; + } +} + + +/* + Determine major and minor number of control token. If it's + not found, the class turns into rtfUnknown. +*/ + +static void Lookup (s) +char *s; +{ +RTFKey *rp; +int hash; + + ++s; /* skip over the leading \ character */ + hash = Hash (s); + for (rp = rtfKey; rp->rtfKStr != (char *) NULL; rp++) + { + if (hash == rp->rtfKHash && strcmp (s, rp->rtfKStr) == 0) + { + rtfClass = rtfControl; + rtfMajor = rp->rtfKMajor; + rtfMinor = rp->rtfKMinor; + return; + } + } + rtfClass = rtfUnknown; +} + + +/* + Compute hash value of symbol +*/ + +static int Hash (s) +char *s; +{ +char c; +int val = 0; + + while ((c = *s++) != '\0') + val += (int) c; + return (val); +} + + +/* + Print helpful error message and give up +*/ + +# ifdef VARARGS + +/* + This version is for systems that have varargs. +*/ + +static void Error (va_alist) +va_dcl +{ +va_list args; +char *fmt; + + va_start (args); + fmt = va_arg (args, char *); + vfprintf (stderr, fmt, args); + va_end (args); + fprintf (stderr, "\nLast token read was \"%s\"\n", rtfTextBuf); + exit (1); +} + +# else /* !VARARGS */ + +/* + This version is for systems that don't have varargs. +*/ + +static void Error (fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9) +char *fmt; +char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9; +{ + fprintf (stderr, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); + fprintf (stderr, "\nLast token read was \"%s\"\n", rtfTextBuf); + exit (1); +} + +# endif /* VARARGS */ + + +/* ---------------------------------------------------------------------- */ + +/* + Memory allocation routines +*/ + + +/* + Return pointer to block of size bytes, or NULL if there's + not enough memory available. +*/ + +char *RTFAlloc (size) +int size; +{ + return ((char *) malloc (size)); +} + + +/* + Saves a string on the heap and returns a pointer to it. +*/ + + +char *RTFStrSave (s) +char *s; +{ +char *p; + + if ((p = RTFAlloc (strlen (s) + 1)) == (char *) NULL) + return ((char *) NULL); + return (strcpy (p, s)); +} + + +void RTFFree (p) +char *p; +{ + if (p != (char *) NULL) + free (p); +} + + +/* ---------------------------------------------------------------------- */ + + +/* + Token comparison routines +*/ + +int RTFCheckCM (class, major) +int class, major; +{ + return (rtfClass == class && rtfMajor == major); +} + + +int RTFCheckCMM (class, major, minor) +int class, major, minor; +{ + return (rtfClass == class && rtfMajor == major && rtfMinor == minor); +} + + +int RTFCheckMM (major, minor) +int major, minor; +{ + return (rtfMajor == major && rtfMinor == minor); +} |