📄 reader.c
字号:
* Set the current character set. If csId is illegal, uses general charset. */voidRTFSetCharSet (csId)int csId;{ switch (csId) { default: /* use general if csId unknown */ case rtfCSGeneral: curCharCode = genCharCode; curCharSet = csId; break; case rtfCSSymbol: curCharCode = symCharCode; curCharSet = csId; break; }}intRTFGetCharSet (){ return (curCharSet);}/* ---------------------------------------------------------------------- *//* * 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 destination 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 voidReadFontTbl (){RTFFont *fp;char buf[rtfBufSiz], *bp;int old = -1;char *fn = "ReadFontTbl"; 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! */ RTFPanic ("%s: Cannot determine format", fn); } if (old == 0) /* need to find "{" here */ { if (!RTFCheckCM (rtfGroup, rtfBeginGroup)) RTFPanic ("%s: missing \"{\"", fn); (void) RTFGetToken (); /* yes, skip to next token */ } if ((fp = New (RTFFont)) == (RTFFont *) NULL) RTFPanic ("%s: cannot allocate font entry", fn); fp->rtfNextFont = fontList; fontList = fp; fp->rtfFName = (char *) NULL; fp->rtfFAltName = (char *) NULL; fp->rtfFNum = -1; fp->rtfFFamily = 0; fp->rtfFCharSet = 0; fp->rtfFPitch = 0; fp->rtfFType = 0; fp->rtfFCodePage = 0; while (rtfClass != rtfEOF && !RTFCheckCM (rtfText, ';')) { if (rtfClass == rtfControl) { switch (rtfMajor) { default: /* ignore token but announce it */ RTFMsg ("%s: unknown token \"%s\"\n", fn, rtfTextBuf); case rtfFontFamily: fp->rtfFFamily = rtfMinor; break; case rtfCharAttr: switch (rtfMinor) { default: break; /* ignore unknown? */ case rtfFontNum: fp->rtfFNum = rtfParam; break; } break; case rtfFontAttr: switch (rtfMinor) { default: break; /* ignore unknown? */ case rtfFontCharSet: fp->rtfFCharSet = rtfParam; break; case rtfFontPitch: fp->rtfFPitch = rtfParam; break; case rtfFontCodePage: fp->rtfFCodePage = rtfParam; break; case rtfFTypeNil: case rtfFTypeTrueType: fp->rtfFType = rtfParam; break; } break; } } else if (RTFCheckCM (rtfGroup, rtfBeginGroup)) /* dest */ { RTFSkipGroup (); /* ignore for now */ } else if (rtfClass == rtfText) /* font name */ { bp = buf; while (rtfClass != rtfEOF && !RTFCheckCM (rtfText, ';')) { *bp++ = rtfMajor; (void) RTFGetToken (); } *bp = '\0'; fp->rtfFName = RTFStrSave (buf); if (fp->rtfFName == (char *) NULL) RTFPanic ("%s: cannot allocate font name", fn); /* already have next token; don't read one */ /* at bottom of loop */ continue; } else { /* ignore token but announce it */ RTFMsg ("%s: unknown token \"%s\"\n", fn, rtfTextBuf); } (void) RTFGetToken (); } if (old == 0) /* need to see "}" here */ { (void) RTFGetToken (); if (!RTFCheckCM (rtfGroup, rtfEndGroup)) RTFPanic ("%s: missing \"}\"", fn); } } if (fp->rtfFNum == -1) RTFPanic ("%s: missing font number", fn);/* * Could check other pieces of structure here, too, I suppose. */ 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 voidReadColorTbl (){RTFColor *cp;int cnum = 0;char *fn = "ReadColorTbl"; for (;;) { (void) RTFGetToken (); if (RTFCheckCM (rtfGroup, rtfEndGroup)) break; if ((cp = New (RTFColor)) == (RTFColor *) NULL) RTFPanic ("%s: cannot allocate color entry", fn); cp->rtfCNum = cnum++; cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1; cp->rtfNextColor = colorList; colorList = cp; while (RTFCheckCM (rtfControl, rtfColorName)) { 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) ';')) RTFPanic ("%s: malformed entry", fn); } RTFRouteToken (); /* feed "}" back to router */}/* * The "Normal" style definition doesn't contain any style number, * all others do. Normal style is given style rtfNormalStyleNum. */static voidReadStyleSheet (){RTFStyle *sp;RTFStyleElt *sep, *sepLast;char buf[rtfBufSiz], *bp;char *fn = "ReadStyleSheet"; for (;;) { (void) RTFGetToken (); if (RTFCheckCM (rtfGroup, rtfEndGroup)) break; if ((sp = New (RTFStyle)) == (RTFStyle *) NULL) RTFPanic ("%s: cannot allocate stylesheet entry", fn); sp->rtfSName = (char *) NULL; sp->rtfSNum = -1; sp->rtfSType = rtfParStyle; sp->rtfSAdditive = 0; sp->rtfSBasedOn = rtfNoStyleNum; sp->rtfSNextPar = -1; sp->rtfSSEList = sepLast = (RTFStyleElt *) NULL; sp->rtfNextStyle = styleList; sp->rtfExpanding = 0; styleList = sp; if (!RTFCheckCM (rtfGroup, rtfBeginGroup)) RTFPanic ("%s: missing \"{\"", fn); for (;;) { (void) RTFGetToken (); if (rtfClass == rtfEOF || RTFCheckCM (rtfText, ';')) break; if (rtfClass == rtfControl) { if (RTFCheckMM (rtfSpecialChar, rtfOptDest)) continue; /* ignore "\*" */ if (RTFCheckMM (rtfParAttr, rtfStyleNum)) { sp->rtfSNum = rtfParam; sp->rtfSType = rtfParStyle; continue; } if (RTFCheckMM (rtfCharAttr, rtfCharStyleNum)) { sp->rtfSNum = rtfParam; sp->rtfSType = rtfCharStyle; continue; } if (RTFCheckMM (rtfSectAttr, rtfSectStyleNum)) { sp->rtfSNum = rtfParam; sp->rtfSType = rtfSectStyle; continue; } if (RTFCheckMM (rtfStyleAttr, rtfBasedOn)) { sp->rtfSBasedOn = rtfParam; continue; } if (RTFCheckMM (rtfStyleAttr, rtfAdditive)) { sp->rtfSAdditive = 1; continue; } if (RTFCheckMM (rtfStyleAttr, rtfNext)) { sp->rtfSNextPar = rtfParam; continue; } if ((sep = New (RTFStyleElt)) == (RTFStyleElt *) NULL) RTFPanic ("%s: cannot allocate style element", fn); sep->rtfSEClass = rtfClass; sep->rtfSEMajor = rtfMajor; sep->rtfSEMinor = rtfMinor; sep->rtfSEParam = rtfParam; if ((sep->rtfSEText = RTFStrSave (rtfTextBuf)) == (char *) NULL) RTFPanic ("%s: cannot allocate style element text", fn); if (sepLast == (RTFStyleElt *) NULL) sp->rtfSSEList = sep; /* first element */ else /* add to end */ sepLast->rtfNextSE = sep; sep->rtfNextSE = (RTFStyleElt *) NULL; sepLast = sep; } else if (RTFCheckCM (rtfGroup, rtfBeginGroup)) { /* * This passes over "{\*\keycode ... }, among * other things. A temporary (perhaps) hack. */ RTFSkipGroup (); continue; } else if (rtfClass == rtfText) /* style name */ { bp = buf; while (rtfClass == rtfText) { if (rtfMajor == ';') { /* put back for "for" loop */ (void) RTFUngetToken (); break; } *bp++ = rtfMajor; (void) RTFGetToken (); } *bp = '\0'; if ((sp->rtfSName = RTFStrSave (buf)) == (char *) NULL) RTFPanic ("%s: cannot allocate style name", fn); } else /* unrecognized */ { /* ignore token but announce it */ RTFMsg ("%s: unknown token \"%s\"\n", fn, rtfTextBuf); } } (void) RTFGetToken (); if (!RTFCheckCM (rtfGroup, rtfEndGroup)) RTFPanic ("%s: missing \"}\"", fn); /* * Check over the style structure. A name is a must. * If no style number was specified, check whether it's the * Normal style (in which case it's given style number * rtfNormalStyleNum). Note that some "normal" style names * just begin with "Normal" and can have other stuff following, * e.g., "Normal,Times 10 point". Ugh. * * Some German RTF writers use "Standard" instead of "Normal". */ if (sp->rtfSName == (char *) NULL) RTFPanic ("%s: missing style name", fn); if (sp->rtfSNum < 0) { if (strncmp (buf, "Normal", 6) != 0 && strncmp (buf, "Standard", 8) != 0) RTFPanic ("%s: missing style number", fn); sp->rtfSNum = rtfNormalStyleNum; } if (sp->rtfSNextPar == -1) /* if \snext not given, */ sp->rtfSNextPar = sp->rtfSNum; /* next is itself */ } RTFRouteToken (); /* feed "}" back to router */}static voidReadInfoGroup (){ RTFSkipGroup (); RTFRouteToken (); /* feed "}" back to router */}static voidReadPictGroup (){ RTFSkipGroup (); RTFRouteToken (); /* feed "}" back to router */}static voidReadObjGroup (){ RTFSkipGroup (); RTFRouteToken (); /* feed "}" back to router */}/* ---------------------------------------------------------------------- *//* * Routines to return pieces of stylesheet, or font or color tables. * References to style 0 are mapped onto the Normal style. */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. */voidRTFExpandStyle (n)int n;{RTFStyle *s;RTFStyleElt *se; if (n == -1 || (s = RTFGetStyle (n)) == (RTFStyle *) NULL) return; if (s->rtfExpanding != 0) RTFPanic ("Style expansion loop, style %d", n); s->rtfExpanding = 1; /* set expansion flag for loop detection */ /* * Expand "based-on" style (unless it's the same as the current * style -- Normal style usually gives itself as its own based-on * style). Based-on style expansion 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. */ if (n != s->rtfSBasedOn) { 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 RTFCtrl RTFCtrl;struct RTFCtrl{ int major; /* major number */ int minor; /* minor number */ char *str; /* symbol name */ int hash; /* symbol name hash value */};/* * A minor number of -1 means the token has no minor number * (all valid minor numbers are >= 0). */static RTFCtrl **rtfCtrl = (RTFCtrl **) NULL;static int nKeys;/* * Initialize lookup table hash values. Only need to do this once. */# define ctrlFileName "rtf-ctrl"static voidLookupInit (){FILE *f;RTFCtrl *rp;char buf[rtfBufSiz];int line = 0, i;char *p1, *p2, *p3, c;TSScanner scanner;char *scanEscape;char *fn = "LookupInit"; if (rtfCtrl != (RTFCtrl **) NULL) /* already initialized */ return; if ((f = RTFOpenLibFile (ctrlFileName, "r")) == (FILE *) NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -