home *** CD-ROM | disk | FTP | other *** search
- /*
- 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)))
-
-
- # define index strchr
-
- 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 (int class, RTFFuncPtr callback)
- {
- if (class >= 0 && class < rtfMaxClass)
- ccb[class] = callback;
- }
-
-
- RTFFuncPtr RTFGetClassCallback (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 (int dest, RTFFuncPtr callback)
- {
- if (dest >= 0 && dest < rtfMaxDestination)
- dcb[dest] = callback;
- }
-
-
- RTFFuncPtr RTFGetDestinationCallback (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 (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 (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 (int class, int major, int minor, int 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 (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 (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 (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 (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 (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 (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_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 ( char *fmt, char *a1, char *a2, char *a3, char *a4,
- char *a5, char *a6, char *a7, char *a8, char *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 (int size)
- {
- return ((char *) malloc (size));
- }
-
-
- /*
- Saves a string on the heap and returns a pointer to it.
- */
-
-
- char *RTFStrSave (char *s)
- {
- char *p;
-
- if ((p = RTFAlloc (strlen (s) + 1)) == (char *) NULL)
- return ((char *) NULL);
- return (strcpy (p, s));
- }
-
-
- void RTFFree (char *p)
- {
- if (p != (char *) NULL)
- free (p);
- }
-
-
- /* ---------------------------------------------------------------------- */
-
-
- /*
- Token comparison routines
- */
-
- int RTFCheckCM (int class, int major)
- {
- return (rtfClass == class && rtfMajor == major);
- }
-
-
- int RTFCheckCMM ( int class, int major, int minor)
- {
- return (rtfClass == class && rtfMajor == major && rtfMinor == minor);
- }
-
-
- int RTFCheckMM (int major, int minor)
- {
- return (rtfMajor == major && rtfMinor == minor);
- }
-