/* rtfactn.c */ #include #include #include #include #include "rtftype.h" #include "rtfdecl.h" // RTF parser tables // Property descriptions PROP rgprop [ipropMax] = { actnByte, propChp, offsetof(CHP, fBold), // ipropBold actnByte, propChp, offsetof(CHP, fItalic), // ipropItalic actnByte, propChp, offsetof(CHP, fUnderline), // ipropUnderline actnWord, propPap, offsetof(PAP, xaLeft), // ipropLeftInd actnWord, propPap, offsetof(PAP, xaRight), // ipropRightInd actnWord, propPap, offsetof(PAP, xaFirst), // ipropFirstInd actnWord, propSep, offsetof(SEP, cCols), // ipropCols actnWord, propSep, offsetof(SEP, xaPgn), // ipropPgnX actnWord, propSep, offsetof(SEP, yaPgn), // ipropPgnY actnWord, propDop, offsetof(DOP, xaPage), // ipropXaPage actnWord, propDop, offsetof(DOP, yaPage), // ipropYaPage actnWord, propDop, offsetof(DOP, xaLeft), // ipropXaLeft actnWord, propDop, offsetof(DOP, xaRight), // ipropXaRight actnWord, propDop, offsetof(DOP, yaTop), // ipropYaTop actnWord, propDop, offsetof(DOP, yaBottom), // ipropYaBottom actnWord, propDop, offsetof(DOP, pgnStart), // ipropPgnStart actnByte, propSep, offsetof(SEP, sbk), // ipropSbk actnByte, propSep, offsetof(SEP, pgnFormat), // ipropPgnFormat actnByte, propDop, offsetof(DOP, fFacingp), // ipropFacingp actnByte, propDop, offsetof(DOP, fLandscape), // ipropLandscape actnByte, propPap, offsetof(PAP, just), // ipropJust actnSpec, propPap, 0, // ipropPard actnSpec, propChp, 0, // ipropPlain actnSpec, propSep, 0, // ipropSectd }; // Keyword descriptions SYM rgsymRtf[] = { // keyword dflt fPassDflt kwd idx "b", 1, fFalse, kwdProp, ipropBold, "u", 1, fFalse, kwdProp, ipropUnderline, "i", 1, fFalse, kwdProp, ipropItalic, "li", 0, fFalse, kwdProp, ipropLeftInd, "ri", 0, fFalse, kwdProp, ipropRightInd, "fi", 0, fFalse, kwdProp, ipropFirstInd, "cols", 1, fFalse, kwdProp, ipropCols, "sbknone", sbkNon, fTrue, kwdProp, ipropSbk, "sbkcol", sbkCol, fTrue, kwdProp, ipropSbk, "sbkeven", sbkEvn, fTrue, kwdProp, ipropSbk, "sbkodd", sbkOdd, fTrue, kwdProp, ipropSbk, "sbkpage", sbkPg, fTrue, kwdProp, ipropSbk, "pgnx", 0, fFalse, kwdProp, ipropPgnX, "pgny", 0, fFalse, kwdProp, ipropPgnY, "pgndec", pgDec, fTrue, kwdProp, ipropPgnFormat, "pgnucrm", pgURom, fTrue, kwdProp, ipropPgnFormat, "pgnlcrm", pgLRom, fTrue, kwdProp, ipropPgnFormat, "pgnucltr", pgULtr, fTrue, kwdProp, ipropPgnFormat, "pgnlcltr", pgLLtr, fTrue, kwdProp, ipropPgnFormat, "qc", justC, fTrue, kwdProp, ipropJust, "ql", justL, fTrue, kwdProp, ipropJust, "qr", justR, fTrue, kwdProp, ipropJust, "qj", justF, fTrue, kwdProp, ipropJust, "paperw", 12240, fFalse, kwdProp, ipropXaPage, "paperh", 15480, fFalse, kwdProp, ipropYaPage, "margl", 1800, fFalse, kwdProp, ipropXaLeft, "margr", 1800, fFalse, kwdProp, ipropXaRight, "margt", 1440, fFalse, kwdProp, ipropYaTop, "margb", 1440, fFalse, kwdProp, ipropYaBottom, "pgnstart", 1, fTrue, kwdProp, ipropPgnStart, "facingp", 1, fTrue, kwdProp, ipropFacingp, "landscape", 1, fTrue, kwdProp, ipropLandscape, "par", 0, fFalse, kwdChar, 0x0a, "\0x0a", 0, fFalse, kwdChar, 0x0a, "\0x0d", 0, fFalse, kwdChar, 0x0a, "tab", 0, fFalse, kwdChar, 0x09, "ldblquote", 0, fFalse, kwdChar, '"', "rdblquote", 0, fFalse, kwdChar, '"', "bin", 0, fFalse, kwdSpec, ipfnBin, "*", 0, fFalse, kwdSpec, ipfnSkipDest, "'", 0, fFalse, kwdSpec, ipfnHex, "author", 0, fFalse, kwdDest, idestSkip, "buptim", 0, fFalse, kwdDest, idestSkip, "colortbl", 0, fFalse, kwdDest, idestSkip, "comment", 0, fFalse, kwdDest, idestSkip, "creatim", 0, fFalse, kwdDest, idestSkip, "doccomm", 0, fFalse, kwdDest, idestSkip, "fonttbl", 0, fFalse, kwdDest, idestSkip, "footer", 0, fFalse, kwdDest, idestSkip, "footerf", 0, fFalse, kwdDest, idestSkip, "footerl", 0, fFalse, kwdDest, idestSkip, "footerr", 0, fFalse, kwdDest, idestSkip, "footnote", 0, fFalse, kwdDest, idestSkip, "ftncn", 0, fFalse, kwdDest, idestSkip, "ftnsep", 0, fFalse, kwdDest, idestSkip, "ftnsepc", 0, fFalse, kwdDest, idestSkip, "header", 0, fFalse, kwdDest, idestSkip, "headerf", 0, fFalse, kwdDest, idestSkip, "headerl", 0, fFalse, kwdDest, idestSkip, "headerr", 0, fFalse, kwdDest, idestSkip, "info", 0, fFalse, kwdDest, idestSkip, "keywords", 0, fFalse, kwdDest, idestSkip, "operator", 0, fFalse, kwdDest, idestSkip, "pict", 0, fFalse, kwdDest, idestSkip, "printim", 0, fFalse, kwdDest, idestSkip, "private1", 0, fFalse, kwdDest, idestSkip, "revtim", 0, fFalse, kwdDest, idestSkip, "rxe", 0, fFalse, kwdDest, idestSkip, "stylesheet", 0, fFalse, kwdDest, idestSkip, "subject", 0, fFalse, kwdDest, idestSkip, "tc", 0, fFalse, kwdDest, idestSkip, "title", 0, fFalse, kwdDest, idestSkip, "txe", 0, fFalse, kwdDest, idestSkip, "xe", 0, fFalse, kwdDest, idestSkip, "{", 0, fFalse, kwdChar, '{', "}", 0, fFalse, kwdChar, '}', "\\", 0, fFalse, kwdChar, '\\' }; int isymMax = sizeof(rgsymRtf) / sizeof(SYM); // // %%Function: ecApplyPropChange // // Set the property identified by _iprop_ to the value _val_. // // int ecApplyPropChange(IPROP iprop, int val) { char *pb; SET(pb); if (rds == rdsSkip) // If we are skipping text, return ecOK; // do not do anything. switch (rgprop[iprop].prop) { case propDop: pb = (char *) & dop; break; case propSep: pb = (char *) & sep; break; case propPap: pb = (char *) & pap; break; case propChp: pb = (char *) & chp; break; default: if (rgprop[iprop].actn != actnSpec) return ecBadTable; break; } switch (rgprop[iprop].actn) { case actnByte: pb[rgprop[iprop].offset] = (unsigned char) val; break; case actnWord: (*(int *) (pb + rgprop[iprop].offset)) = val; break; case actnSpec: return ecParseSpecialProperty(iprop, val); break; default: return ecBadTable; } return ecOK; } // // %%Function: ecParseSpecialProperty // // Set a property that requires code to evaluate. // int ecParseSpecialProperty(IPROP iprop, int val) { USED(val); switch (iprop) { case ipropPard: memset(&pap, 0, sizeof(pap)); return ecOK; case ipropPlain: memset(&chp, 0, sizeof(chp)); return ecOK; case ipropSectd: memset(&sep, 0, sizeof(sep)); return ecOK; } return ecBadTable; } // // %%Function: ecTranslateKeyword. // // Step 3. // Search rgsymRtf for szKeyword and evaluate it appropriately. // // Inputs: // szKeyword: The RTF control to evaluate. // param: The parameter of the RTF control. // fParam: fTrue if the control had a parameter; (that is, if param is valid) // fFalse if it did not. // int ecTranslateKeyword(char *szKeyword, int param, bool fParam) { int isym; // search for szKeyword in rgsymRtf for (isym = 0; isym < isymMax; isym++) if (strcmp(szKeyword, rgsymRtf[isym].szKeyword) == 0) break; if (isym == isymMax){ // control word not found if (fSkipDestIfUnk) // if this is a new destination rds = rdsSkip; // skip the destination // else just discard it fSkipDestIfUnk = fFalse; return ecOK; } // found it! use kwd and idx to determine what to do with it. fSkipDestIfUnk = fFalse; switch (rgsymRtf[isym].kwd) { case kwdProp: if (rgsymRtf[isym].fPassDflt || !fParam) param = rgsymRtf[isym].dflt; return ecApplyPropChange(rgsymRtf[isym].idx, param); case kwdChar: return ecParseChar(rgsymRtf[isym].idx); case kwdDest: return ecChangeDest(rgsymRtf[isym].idx); case kwdSpec: return ecParseSpecialKeyword(rgsymRtf[isym].idx); } return ecBadTable; } // // %%Function: ecChangeDest // // Change to the destination specified by idest. // There is usually more to do here than this... // int ecChangeDest(IDEST idest) { if (rds == rdsSkip) // if we are skipping text, return ecOK; // do not do anything switch (idest) { default: rds = rdsSkip; // when in doubt, skip it... break; } return ecOK; } // // %%Function: ecEndGroupAction // // The destination specified by rds is coming to a close. // If There is any cleanup that needs to be done, do it now. // int ecEndGroupAction(RDS rds) { USED(rds); return ecOK; } // // %%Function: ecParseSpecialKeyword // // Evaluate an RTF control that needs special processing. // int ecParseSpecialKeyword(IPFN ipfn) { if (rds == rdsSkip && ipfn != ipfnBin) // if we are skipping, and it is not return ecOK; // the \bin keyword, ignore it. switch (ipfn) { case ipfnBin: ris = risBin; cbBin = lParam; break; case ipfnSkipDest: fSkipDestIfUnk = fTrue; break; case ipfnHex: ris = risHex; break; default: return ecBadTable; } return ecOK; }