📄 rtfread.cpp
字号:
break;
case tokenColorForeground: // \cf
PARSERCOVERAGE_CASE();
_CF.crTextColor = GetColor(CFM_COLOR);
// V-GUYB: Table cell backgrounds (\clcbpat) are not handled in Richedit 2.0.
// This means all table cells will have a white background. Therefore change
// any white text to black here.
if (_pstateStackTop->fInTable && _CF.crTextColor == RGB(0xFF, 0xFF, 0xFF))
{
_CF.crTextColor = RGB(0x00, 0x00, 0x00);
}
break;
case tokenColorBackground: // \highlight
PARSERCOVERAGE_CASE();
_CF.crBackColor = GetColor(CFM_BACKCOLOR);
break;
case tokenExpand: // \expndtw N
PARSERCOVERAGE_CASE();
_CF.sSpacing = (SHORT) iParam;
_CF.dwMask |= CFM_SPACING;
break;
case tokenCharStyle: // \cs N
PARSERCOVERAGE_CASE();
/* FUTURE (alexgo): we may want to support character styles
in some future version.
_CF.sStyle = (SHORT)iParam;
_CF.dwMask |= CFM_STYLE; */
if(pstate->sDest == destStyleSheet)
goto skip_group;
break;
case tokenAnimText: // \animtext N
PARSERCOVERAGE_CASE();
_CF.bAnimation = (BYTE)iParam;
_CF.dwMask |= CFM_ANIMATION;
break;
case tokenKerning: // \kerning N
PARSERCOVERAGE_CASE();
_CF.wKerning = (WORD)(10 * iParam); // Convert to twips
_CF.dwMask |= CFM_KERNING;
break;
case tokenFollowingPunct: // \*\fchars
PARSERCOVERAGE_CASE();
pstate->sDest = destFollowingPunct;
break;
case tokenLeadingPunct: // \*\lchars
PARSERCOVERAGE_CASE();
pstate->sDest = destLeadingPunct;
break;
case tokenDocumentArea: // \info
PARSERCOVERAGE_CASE();
pstate->sDest = destDocumentArea;
break;
#ifdef FE
USHORT usPunct; // Used for FE word breaking
case tokenNoOverflow: // \nooverflow
PARSERCOVERAGE_CASE();
TRACEINFOSZ("No Overflow");
usPunct = ~WBF_OVERFLOW;
goto setBrkOp;
case tokenNoWordBreak: // \nocwrap
PARSERCOVERAGE_CASE();
TRACEINFOSZ("No Word Break" );
usPunct = ~WBF_WORDBREAK;
goto setBrkOp;
case tokenNoWordWrap: // \nowwrap
PARSERCOVERAGE_CASE();
TRACEINFOSZ("No Word Word Wrap" );
usPunct = ~WBF_WORDWRAP;
setBrkOp:
if (!(_dwFlags & fRTFFE))
{
usPunct &= UsVGetBreakOption(_ped->lpPunctObj);
UsVSetBreakOption(_ped->lpPunctObj, usPunct);
}
break;
case tokenVerticalRender: // \vertdoc
PARSERCOVERAGE_CASE();
TRACEINFOSZ("Vertical" );
if (pstate->sDest == destDocumentArea && !(_dwFlags & fRTFFE))
_ped->fModeDefer = TRUE;
break;
case tokenHorizontalRender: // \horzdoc
PARSERCOVERAGE_CASE();
TRACEINFOSZ("Horizontal" );
if (pstate->sDest == destDocumentArea && !(_dwFlags & fRTFFE))
_ped->fModeDefer = FALSE;
break;
#endif
//-------------------- Character Format Control Words -----------------------------
case tokenUnderlineHairline: // \ulhair [10]
case tokenUnderlineThick: // \ulth [9]
case tokenUnderlineWave: // \ulwave [8]
case tokenUnderlineDashDotDotted: // \uldashdd [7]
case tokenUnderlineDashDotted: // \uldashd [6]
case tokenUnderlineDash: // \uldash [5]
case tokenUnderlineDotted: // \uld [4]
case tokenUnderlineDouble: // \uldb [3]
case tokenUnderlineWord: // \ulw [2]
PARSERCOVERAGE_CASE();
_CF.bUnderlineType = _token - tokenUnderlineWord + 2;
_token = tokenUnderline; // Except for their type, these
goto under; // control words behave like
// \ul (try them with Word)
case tokenUnderline: // \ul [Effect 4]
PARSERCOVERAGE_CASE(); // (see handleCF)
_CF.bUnderlineType = CFU_UNDERLINE; // Fall thru to \b
under: _CF.dwMask |= CFM_UNDERLINETYPE;
goto handleCF;
// These effects are turned on if their control word parameter is missing
// or nonzero. They are turned off if the parameter is zero. This
// behavior is usually identified by an asterisk (*) in the RTF spec.
// The code uses fact that CFE_xxx = CFM_xxx
case tokenDeleted: // \deleted
PARSERCOVERAGE_CASE();
_token = tokenStrikeOut; // fall through and handle
// this as a tokenStrikeOut
handleCF:
case tokenRevised: // \revised [4000]
case tokenDisabled: // \disabled [2000]
case tokenImprint: // \impr [1000]
case tokenEmboss: // \embo [800]
case tokenShadow: // \shad [400]
case tokenOutline: // \outl [200]
case tokenHiddenText: // \v [100]
case tokenCaps: // \caps [80]
case tokenSmallCaps: // \scaps [40]
case tokenLink: // \link [20]
case tokenProtect: // \protect [10]
case tokenStrikeOut: // \strike [8]
case tokenItalic: // \i [2]
case tokenBold: // \b [1]
PARSERCOVERAGE_CASE();
dwT = 1 << (_token - tokenBold); // Generate effect mask
_CF.dwEffects &= ~dwT; // Default attribute off
if (!*_szParam || _iParam) // Effect is on
_CF.dwEffects |= dwT;
_CF.dwMask |= dwT; // In either case, the effect
break; // is defined
case tokenStopUnderline: // \ulnone
PARSERCOVERAGE_CASE();
_CF.dwEffects &= ~CFE_UNDERLINE; // Kill all underlining
_CF.dwMask |= CFM_UNDERLINE;
break;
case tokenRevAuthor: // \revauth
PARSERCOVERAGE_CASE();
/* FUTURE: (alexgo) this doesn't work well now since we don't support
revision tables. We may want to support this better in the future.
So what we do now is the 1.0 technique of using a color for the
author */
if( iParam > 0 )
{
_CF.dwEffects &= ~CFE_AUTOCOLOR;
_CF.dwMask |= CFM_COLOR;
_CF.crTextColor = rgcrRevisions[(iParam - 1) & REVMASK];
}
break;
case tokenUp: // \up
PARSERCOVERAGE_CASE();
dy = 10;
goto StoreOffset;
case tokenDown: // \down
PARSERCOVERAGE_CASE();
dy = -10;
StoreOffset:
if (!*_szParam)
iParam = dyDefaultSuperscript;
_CF.yOffset = iParam * dy; // Half points->twips
_CF.dwMask |= CFM_OFFSET;
break;
case tokenSuperscript: // \super
PARSERCOVERAGE_CASE();
dwT = CFE_SUPERSCRIPT;
goto SetSubSuperScript;
case tokenSubscript: // \sub
PARSERCOVERAGE_CASE();
dwT = CFE_SUBSCRIPT;
goto SetSubSuperScript;
case tokenNoSuperSub: // \nosupersub
PARSERCOVERAGE_CASE();
dwT = 0;
SetSubSuperScript:
_CF.dwMask |= (CFE_SUPERSCRIPT | CFE_SUBSCRIPT);
_CF.dwEffects &= ~(CFE_SUPERSCRIPT | CFE_SUBSCRIPT);
_CF.dwEffects |= dwT;
break;
//--------------------- Paragraph Control Words -----------------------------
case tokenStyleSheet: // \stylesheet
PARSERCOVERAGE_CASE();
pstate->sDest = destStyleSheet;
_Style = 0; // Default normal style
break;
case tokenTabBar: // \tb
PARSERCOVERAGE_CASE();
_bTabType = PFT_BAR; // Fall thru to \tx
case tokenTabPosition: // \tx
PARSERCOVERAGE_CASE();
if(!pstate->fInTable)
{
_PF.AddTab(iParam, _bTabType, _bTabLeader, FALSE);
_PF.dwMask |= PFM_TABSTOPS;
}
break;
case tokenDecimalTab: // \tqdec
case tokenFlushRightTab: // \tqr
case tokenCenterTab: // \tqc
PARSERCOVERAGE_CASE();
_bTabType = _token - tokenCenterTab + PFT_CENTER;
break;
case tokenTabLeaderEqual: // \tleq
case tokenTabLeaderThick: // \tlth
case tokenTabLeaderUnderline: // \tlul
case tokenTabLeaderHyphen: // \tlhyph
case tokenTabLeaderDots: // \tldot
PARSERCOVERAGE_CASE();
_bTabLeader = _token - tokenTabLeaderDots + PFTL_DOTS;
break;
// The following need to be kept in sync with PFE_xxx
case tokenCollapsed: // \collapsed
#ifdef PWD_JUPITER
// GuyBark Jupiter 31960: Make a note we've found some collapsed text.
_fFoundCollapsedText = TRUE;
#endif // PWD_JUPITER
case tokenSideBySide: // \sbys
case tokenHyphPar: // \hyphpar
case tokenNoWidCtlPar: // \nowidctlpar
case tokenNoLineNumber: // \noline
case tokenPageBreakBefore: // \pagebb
case tokenKeepNext: // \keepn
case tokenKeep: // \keep
case tokenRToLPara: // \rtlpar
PARSERCOVERAGE_CASE();
wT = 1 << (_token - tokenRToLPara);
_PF.wEffects |= wT;
_PF.dwMask |= (wT << 16);
break;
case tokenLToRPara: // \ltrpar
PARSERCOVERAGE_CASE();
_PF.wEffects &= ~PFE_RTLPARA;
_PF.dwMask |= PFM_RTLPARA;
break;
case tokenLineSpacing: // \sl N
PARSERCOVERAGE_CASE();
_PF.dyLineSpacing = abs(iParam);
_PF.bLineSpacingRule // Handle nonmultiple rules
= (!iParam || iParam == 1000) ? 0
: tomLineSpaceAtLeast;
/* FUTURE (joseogl): we don't handle exact linespacing correctly in
some situations (e.g. dropped caps cause partial lines). It seems
wise to treat these as "at least" line space requests */
//old code : (iParam > 0) ? tomLineSpaceAtLeast
//old code : tomLineSpaceExactly;
// \slmult can change (has to
// follow if it appears)
_PF.dwMask |= PFM_LINESPACING;
break;
case tokenLineSpacingRule: // \slmult N
PARSERCOVERAGE_CASE();
if(iParam)
{ // It's multiple line spacing
_PF.bLineSpacingRule = tomLineSpaceMultiple;
_PF.dyLineSpacing /= 12; // RE line spacing multiple is
_PF.dwMask |= PFM_LINESPACING; // given in 20ths of a line,
} // while RTF uses 240ths
break;
case tokenSpaceBefore: // \sb N
PARSERCOVERAGE_CASE();
_PF.dySpaceBefore = iParam;
_PF.dwMask |= PFM_SPACEBEFORE;
break;
case tokenSpaceAfter: // \sa N
PARSERCOVERAGE_CASE();
_PF.dySpaceAfter = iParam;
_PF.dwMask |= PFM_SPACEAFTER;
break;
case tokenStyle: // \s N
PARSERCOVERAGE_CASE();
_Style = iParam; // Save it in case in StyleSheet
if(pstate->sDest != destStyleSheet)
{ // Select possible heading level
_PF.sStyle = STYLE_NORMAL; // Default Normal style
_PF.bOutlineLevel |= 1;
for(i = 0; i < NSTYLES && iParam != _rgStyles[i]; i++)
; // Check for heading style
if(i < NSTYLES) // Found one
{
_PF.sStyle = -i - 1; // Store desired heading level
_PF.bOutlineLevel = 2*(i-1); // Update outline level for
} // nonheading styles
_PF.dwMask |= PFM_ALLRTF;
}
break;
case tokenIndentFirst: // \fi N
PARSERCOVERAGE_CASE();
_PF.dxStartIndent += _PF.dxOffset // Cancel current offset
+ iParam; // and add in new one
_PF.dxOffset = -iParam; // Offset for all but 1st line
// = -RTF_FirstLineIndent
_PF.dwMask |= (PFM_STARTINDENT | PFM_OFFSET);
break;
case tokenIndentLeft: // \li N
case tokenIndentRight: // \ri N
PARSERCOVERAGE_CASE();
// AymanA: For RtL para indents has to be flipped.
Assert(PFE_RTLPARA == 0x0001);
if((_token == tokenIndentLeft) ^ (_PF.wEffects & PFE_RTLPARA))
{
_PF.dxStartIndent = iParam - _PF.dxOffset;
_PF.dwMask |= PFM_STARTINDENT;
}
else
{
_PF.dxRightIndent = iParam;
_PF.dwMask |= PFM_RIGHTINDENT;
}
break;
case tokenAlignLeft: // \ql
case tokenAlignRight: // \qr
case tokenAlignCenter: // \qc
case tokenAlignJustify: // \qj
PARSERCOVERAGE_CASE();
_PF.wAlignment = _token - tokenAlignLeft + PFA_LEFT;
_PF.dwMask |= PFM_ALIGNMENT;
break;
case tokenParaNum: // \pn
PARSERCOVERAGE_CASE();
pstate->sDest = destParaNumbering;
pstate->fBullet = FALSE;
_PF.wNumberingStart = 1;
_PF.dwMask |= PFM_NUMBERINGSTART;
break;
case tokenParaNumCont: // \pnlvlcont
PARSERCOVERAGE_CASE(); // Ignore if margins changed
_prg->_rpPF.AdjustBackward();
i = pstate->pPF->dxStartIndent - _prg->GetPF()->dxStartIndent;
_prg->_rpPF.AdjustForward();
if(i)
goto skip_group;
_wNumberingStyle = PFNS_NONUMBER;
break;
case tokenBorderOutside: // \brdrbar
case tokenBorderBetween: // \brdrbtw
case tokenBorderShadow: // \brdrsh
PARSERCOVERAGE_CASE();
_PF.dwBorderColor |= 1 << (_token - tokenBorderShadow + 20);
_dwBorderColor = _PF.dwBorderColor;
break;
// Paragraph and cell border segments
case tokenBox: // \box
PARSERCOVERAGE_CASE();
_PF.wEffects |= PFE_BOX;
_PF.dwMask |= PFM_BOX;
_bBorder = 0; // Store parms as if for
break; // \brdrt
case tokenCellBorderRight: // \clbrdrr
case tokenCellBorderBottom: // \clbrdrb
case tokenCellBorderLeft: // \clbrdrl
case tokenCellBorderTop: // \clbrdrt
case tokenBorderRight: // \brdrr
case tokenBorderBottom: // \brdrb
case tokenBorderLeft: // \brdrl
case tokenBorderTop: // \brdrt
PARSERCOVERAGE_CASE();
_bBorder = _token - tokenBorderTop;
break;
// Paragraph border styles
case tokenBorderTriple: // \brdrtriple
case tokenBorderDoubleThick: // \brdrth
case tokenBorderSingleThick: // \brdrs
case tokenBorderHairline: // \brdrhair
case tokenBorderDot: // \brdrdot
case tokenBorderDouble: // \brdrdb
case tokenBorderDashSmall: // \brdrdashsm
case tokenBorderDash: // \brdrdash
PARSERCOVERAGE_CASE();
if(_bBorder < 4) // Only for paragraphs
SetBorderParm(_PF.wBorders, _token - tokenBorderDash);
break;
case tokenBorderColor: // \brdrcf
PARSERCOVERAGE_CASE();
if(_bBorder < 4) // Only for paragraphs
{
iParam = GetStandardColorIndex();
_PF.dwBorderColor &= ~(0x1F << (5*_bBorder));
_PF.dwBorderColor |= iParam << (5*_bBorder);
_dwBorderColor = _PF.dwBorderColor;
}
break;
case tokenBorder
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -