while( bContinue && IsParserWorking() ) // as long as known Attribute are recognized
{ switch( nToken )
{ case RTF_PARD:
RTFPardPlain( true, &pSet ); break;
case RTF_PLAIN:
RTFPardPlain( false, &pSet ); break;
if (pCurrent->aAttrSet.Count() || !pCurrent->maChildList.empty() ||
pCurrent->nStyleNo )
{ // Open a new Group auto xNew(std::make_unique<SvxRTFItemStackType>(*pCurrent, *mxInsertPosition, true));
xNew->SetRTFDefaults( GetRTFDefaults() );
// "Set" all valid attributes up until this point
AttrGroupEnd();
pCurrent = aAttrStack.empty() ? nullptr : aAttrStack.back().get(); // can be changed after AttrGroupEnd!
xNew->aAttrSet.SetParent( pCurrent ? &pCurrent->aAttrSet : nullptr );
aAttrStack.push_back( std::move(xNew) );
pCurrent = aAttrStack.back().get();
} else // continue to use this entry as a new one
pCurrent->SetStartPos( *mxInsertPosition );
pSet = &pCurrent->aAttrSet;
} while( false );
switch( nToken )
{ case RTF_INTBL: case RTF_PAGEBB: case RTF_SBYS: case RTF_CS: case RTF_LS: case RTF_ILVL:
UnknownAttrToken( nToken ); break;
case RTF_S: if( bIsInReadStyleTab )
{ if( !bFirstToken )
SkipToken();
bContinue = false;
} else
{
sal_uInt16 nStyleNo = -1 == nTokenValue ? 0 : sal_uInt16(nTokenValue); // set StyleNo to the current style on the AttrStack
SvxRTFItemStackType* pCurrent = aAttrStack.empty() ? nullptr : aAttrStack.back().get(); if( !pCurrent ) break;
pCurrent->nStyleNo = nStyleNo;
} break;
case RTF_KEEP: if (const TypedWhichId<SvxFormatSplitItem> wid = aPardMap[SID_ATTR_PARA_SPLIT])
{
pSet->Put(SvxFormatSplitItem(false, wid));
} break;
case RTF_KEEPN: if (const TypedWhichId<SvxFormatKeepItem> wid = aPardMap[SID_ATTR_PARA_KEEP])
{
pSet->Put(SvxFormatKeepItem(true, wid));
} break;
case RTF_LEVEL: if (const TypedWhichId<SfxInt16Item> wid = aPardMap[SID_ATTR_PARA_OUTLLEVEL])
{
pSet->Put(SfxInt16Item(wid, static_cast<sal_uInt16>(nTokenValue)));
} break;
case RTF_QL: if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST])
{
pSet->Put(SvxAdjustItem(SvxAdjust::Left, wid));
} break; case RTF_QR: if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST])
{
pSet->Put(SvxAdjustItem(SvxAdjust::Right, wid));
} break; case RTF_QJ: if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST])
{
pSet->Put(SvxAdjustItem(SvxAdjust::Block, wid));
} break; case RTF_QC: if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST])
{
pSet->Put(SvxAdjustItem(SvxAdjust::Center, wid));
} break;
case RTF_SL: if (const TypedWhichId<SvxLineSpacingItem> wid = aPardMap[SID_ATTR_PARA_LINESPACE])
{ // Calculate the ratio between the default font and the // specified size. The distance consists of the line height // (100%) and the space above the line (20%).
SvxLineSpacingItem aLSpace(0, wid);
case RTF_FS: case RTF_AFS:
{ if( -1 == nTokenValue )
nTokenValue = 240; else
nTokenValue *= 10; // #i66167# // for the SwRTFParser 'IsCalcValue' will be false and for the EditRTFParser // the conversion takes now place in EditRTFParser since for other reasons // the wrong MapUnit might still be use there // if( IsCalcValue() ) // CalcValue();
SvxFontHeightItem aTmpItem( static_cast<sal_uInt16>(nTokenValue), 100,
SID_ATTR_CHAR_FONTHEIGHT );
SetScriptAttr( eCharType, *pSet, aTmpItem );
} break;
case RTF_I: case RTF_AI: if( IsAttrSttPos() ) // not in the text flow?
{
SvxPostureItem aTmpItem(
nTokenValue ? ITALIC_NORMAL : ITALIC_NONE,
SID_ATTR_CHAR_POSTURE );
SetScriptAttr( eCharType, *pSet, aTmpItem );
} break;
case RTF_OUTL: if (const TypedWhichId<SvxContourItem> wid = aPlainMap[SID_ATTR_CHAR_CONTOUR];
wid && IsAttrSttPos()) // not in the text flow?
{
pSet->Put(SvxContourItem(nTokenValue != 0, wid));
} break;
case RTF_SHAD: if (const TypedWhichId<SvxShadowedItem> wid = aPlainMap[SID_ATTR_CHAR_SHADOWED];
wid && IsAttrSttPos()) // not in the text flow?
{
pSet->Put(SvxShadowedItem(nTokenValue != 0, wid));
} break;
case RTF_STRIKE: if (const TypedWhichId<SvxCrossedOutItem> wid = aPlainMap[SID_ATTR_CHAR_STRIKEOUT];
wid && IsAttrSttPos()) // not in the text flow?
{
pSet->Put( SvxCrossedOutItem(
nTokenValue ? STRIKEOUT_SINGLE : STRIKEOUT_NONE,
wid ));
} break;
case RTF_STRIKED: if (const TypedWhichId<SvxCrossedOutItem> wid = aPlainMap[SID_ATTR_CHAR_STRIKEOUT]) // not in the text flow?
{
pSet->Put( SvxCrossedOutItem(
nTokenValue ? STRIKEOUT_DOUBLE : STRIKEOUT_NONE,
wid ));
} break;
case RTF_CF: if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_COLOR])
{
pSet->Put(SvxColorItem(GetColor(sal_uInt16(nTokenValue)), wid));
} break; //#i12501# While cb is clearly documented in the rtf spec, word //doesn't accept it at all #if0 case RTF_CB: if (const sal_uInt16 wid = aPlainMap[SID_ATTR_BRUSH_CHAR])
{
pSet->Put(SvxBrushItem(GetColor(sal_uInt16(nTokenValue)), wid));
} break; #endif
case RTF_LANG: if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_LANGUAGE])
{
pSet->Put(SvxLanguageItem(LanguageType(nTokenValue), wid));
} break;
case RTF_LANGFE: if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_CJK_LANGUAGE])
{
pSet->Put(SvxLanguageItem(LanguageType(nTokenValue), wid));
} break; case RTF_ALANG:
{
SvxLanguageItem aTmpItem( LanguageType(nTokenValue),
SID_ATTR_CHAR_LANGUAGE );
SetScriptAttr( eCharType, *pSet, aTmpItem );
} break;
case RTF_RTLCH:
bIsLeftToRightDef = false; break; case RTF_LTRCH:
bIsLeftToRightDef = true; break; case RTF_RTLPAR: if (const TypedWhichId<SvxFrameDirectionItem> wid = aPardMap[SID_ATTR_FRAMEDIRECTION])
{
pSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_RL_TB, wid));
} break; case RTF_LTRPAR: if (const TypedWhichId<SvxFrameDirectionItem> wid = aPardMap[SID_ATTR_FRAMEDIRECTION])
{
pSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB, wid));
} break; case RTF_LOCH: eCharType = LOW_CHARTYPE; break; case RTF_HICH: eCharType = HIGH_CHARTYPE; break; case RTF_DBCH: eCharType = DOUBLEBYTE_CHARTYPE; break;
case RTF_ACCNONE:
eEmphasis = FontEmphasisMark::NONE; goto ATTR_SETEMPHASIS; case RTF_ACCDOT:
eEmphasis = (FontEmphasisMark::Dot | FontEmphasisMark::PosAbove); goto ATTR_SETEMPHASIS;
case RTF_ACCCOMMA:
eEmphasis = (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove);
ATTR_SETEMPHASIS: if (const TypedWhichId<SvxEmphasisMarkItem> wid = aPlainMap[SID_ATTR_CHAR_EMPHASISMARK])
{
pSet->Put(SvxEmphasisMarkItem(eEmphasis, wid));
} break;
case RTF_CHARSCALEX : if (const TypedWhichId<SvxCharScaleWidthItem> wid = aPlainMap[SID_ATTR_CHAR_SCALEWIDTH])
{ //i21372 if (nTokenValue < 1 || nTokenValue > 600)
nTokenValue = 100;
pSet->Put(SvxCharScaleWidthItem(sal_uInt16(nTokenValue), wid));
} break;
case RTF_HORZVERT: if (const TypedWhichId<SvxCharRotateItem> wid = aPlainMap[SID_ATTR_CHAR_ROTATED])
{ // RTF knows only 90deg
pSet->Put(SvxCharRotateItem(900_deg10, 1 == nTokenValue, wid));
} break;
case RTF_EMBO: if (const TypedWhichId<SvxCharReliefItem> wid = aPlainMap[SID_ATTR_CHAR_RELIEF])
{
pSet->Put(SvxCharReliefItem(FontRelief::Embossed, wid));
} break; case RTF_IMPR: if (const TypedWhichId<SvxCharReliefItem> wid = aPlainMap[SID_ATTR_CHAR_RELIEF])
{
pSet->Put(SvxCharReliefItem(FontRelief::Engraved, wid));
} break; case RTF_V: if (const TypedWhichId<SvxCharHiddenItem> wid = aPlainMap[SID_ATTR_CHAR_HIDDEN])
{
pSet->Put(SvxCharHiddenItem(nTokenValue != 0, wid));
} break; case RTF_CHBGFDIAG: case RTF_CHBGDKVERT: case RTF_CHBGDKHORIZ: case RTF_CHBGVERT: case RTF_CHBGHORIZ: case RTF_CHBGDKFDIAG: case RTF_CHBGDCROSS: case RTF_CHBGCROSS: case RTF_CHBGBDIAG: case RTF_CHBGDKDCROSS: case RTF_CHBGDKCROSS: case RTF_CHBGDKBDIAG: case RTF_CHCBPAT: case RTF_CHCFPAT: case RTF_CHSHDNG: if (aPlainMap[SID_ATTR_BRUSH_CHAR])
ReadBackgroundAttr( nToken, *pSet ); break;
case BRACELEFT:
{ // tests on Swg internal tokens bool bHandled = false; short nSkip = 0; if( RTF_IGNOREFLAG != GetNextToken())
nSkip = -1; elseif( (nToken = GetNextToken() ) & RTF_SWGDEFS )
{
bHandled = true; switch( nToken )
{ case RTF_PGDSCNO: case RTF_PGBRK: case RTF_SOUTLVL:
UnknownAttrToken( nToken ); // overwrite the closing parenthesis break;
case RTF_SWG_ESCPROP:
{ // Store percentage change!
sal_uInt8 nProp = sal_uInt8( nTokenValue / 100 ); short nEsc = 0; if( 1 == ( nTokenValue % 100 )) // Recognize own auto-flags!
nEsc = DFLT_ESC_AUTO_SUPER;
pSet->Put( aHypenZone );
} else
SkipGroup(); // at the end of the group
} break;
// We expect these to be preceded by a RTF_HYPHEN and // so normally are handled by the RTF_HYPHEN case, but // if they appear 'bare' in a document then safely skip // them here case RTF_HYPHLEAD: case RTF_HYPHTRAIL: case RTF_HYPHMAX:
SkipGroup(); break;
do { switch( nToken )
{ case RTF_BOX: case RTF_BRDRT: case RTF_BRDRB: case RTF_BRDRL: case RTF_BRDRR:
nBorderTyp = nToken; break;
case RTF_CLBRDRT: // Cell top border
{ if( bTableDef )
{ if (nBorderTyp != 0)
SetBorderLine( nBorderTyp, *aAttr, aBrd );
nBorderTyp = RTF_BRDRT;
} break;
} case RTF_CLBRDRB: // Cell bottom border
{ if( bTableDef )
{ if (nBorderTyp != 0)
SetBorderLine( nBorderTyp, *aAttr, aBrd );
nBorderTyp = RTF_BRDRB;
} break;
} case RTF_CLBRDRL: // Cell left border
{ if( bTableDef )
{ if (nBorderTyp != 0)
SetBorderLine( nBorderTyp, *aAttr, aBrd );
nBorderTyp = RTF_BRDRL;
} break;
} case RTF_CLBRDRR: // Cell right border
{ if( bTableDef )
{ if (nBorderTyp != 0)
SetBorderLine( nBorderTyp, *aAttr, aBrd );
nBorderTyp = RTF_BRDRR;
} break;
}
case RTF_BRDRDOT: // dotted border
aBrd.SetBorderLineStyle(SvxBorderLineStyle::DOTTED); break; case RTF_BRDRDASH: // dashed border
aBrd.SetBorderLineStyle(SvxBorderLineStyle::DASHED); break; case RTF_BRDRHAIR: // hairline border
{
aBrd.SetBorderLineStyle( SvxBorderLineStyle::SOLID);
aBrd.SetWidth( SvxBorderLineWidth::Hairline );
} break; case RTF_BRDRDB: // Double border
aBrd.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE); break; case RTF_BRDRINSET: // inset border
aBrd.SetBorderLineStyle(SvxBorderLineStyle::INSET); break; case RTF_BRDROUTSET: // outset border
aBrd.SetBorderLineStyle(SvxBorderLineStyle::OUTSET); break; case RTF_BRDRTNTHSG: // ThinThick Small gap
aBrd.SetBorderLineStyle(SvxBorderLineStyle::THINTHICK_SMALLGAP); break; case RTF_BRDRTNTHMG: // ThinThick Medium gap
aBrd.SetBorderLineStyle(SvxBorderLineStyle::THINTHICK_MEDIUMGAP); break; case RTF_BRDRTNTHLG: // ThinThick Large gap
aBrd.SetBorderLineStyle(SvxBorderLineStyle::THINTHICK_LARGEGAP); break; case RTF_BRDRTHTNSG: // ThickThin Small gap
aBrd.SetBorderLineStyle(SvxBorderLineStyle::THICKTHIN_SMALLGAP); break; case RTF_BRDRTHTNMG: // ThickThin Medium gap
aBrd.SetBorderLineStyle(SvxBorderLineStyle::THICKTHIN_MEDIUMGAP); break; case RTF_BRDRTHTNLG: // ThickThin Large gap
aBrd.SetBorderLineStyle(SvxBorderLineStyle::THICKTHIN_LARGEGAP); break; case RTF_BRDREMBOSS: // Embossed border
aBrd.SetBorderLineStyle(SvxBorderLineStyle::EMBOSSED); break; case RTF_BRDRENGRAVE: // Engraved border
aBrd.SetBorderLineStyle(SvxBorderLineStyle::ENGRAVED); break;
case RTF_BRDRS: // single thickness border
bDoubleWidth = false; break; case RTF_BRDRTH: // double thickness border width*2
bDoubleWidth = true; break; case RTF_BRDRW: // border width <255
nWidth = nTokenValue; break;
case RTF_BRDRCF: // Border color
aBrd.SetColor( GetColor( sal_uInt16(nTokenValue) ) ); break;
case RTF_BRSP: // Spacing to content in twip
{ switch( nBorderTyp )
{ case RTF_BRDRB:
aAttr->SetDistance( static_cast<sal_uInt16>(nTokenValue), SvxBoxItemLine::BOTTOM ); break;
case RTF_BRDRT:
aAttr->SetDistance( static_cast<sal_uInt16>(nTokenValue), SvxBoxItemLine::TOP ); break;
case RTF_BRDRL:
aAttr->SetDistance( static_cast<sal_uInt16>(nTokenValue), SvxBoxItemLine::LEFT ); break;
case RTF_BRDRR:
aAttr->SetDistance( static_cast<sal_uInt16>(nTokenValue), SvxBoxItemLine::RIGHT ); break;
case RTF_BOX:
aAttr->SetAllDistances( static_cast<sal_uInt16>(nTokenValue) ); break;
}
} break;
case RTF_BRDRBTW: // Border formatting group case RTF_BRDRBAR: // Border outside // TODO unhandled ATM break;
do { switch( nToken )
{ case RTF_CLCBPAT: case RTF_CHCBPAT: case RTF_CBPAT:
nFillColor = sal_uInt16( nTokenValue ); break;
case RTF_CLCFPAT: case RTF_CHCFPAT: case RTF_CFPAT:
nColor = sal_uInt16( nTokenValue ); break;
case RTF_CLSHDNG: case RTF_CHSHDNG: case RTF_SHADING:
nFillValue = static_cast<sal_uInt8>( nTokenValue / 100 ); break;
case RTF_CLBGDKHOR: case RTF_CHBGDKHORIZ: case RTF_BGDKHORIZ: case RTF_CLBGDKVERT: case RTF_CHBGDKVERT: case RTF_BGDKVERT: case RTF_CLBGDKBDIAG: case RTF_CHBGDKBDIAG: case RTF_BGDKBDIAG: case RTF_CLBGDKFDIAG: case RTF_CHBGDKFDIAG: case RTF_BGDKFDIAG: case RTF_CLBGDKCROSS: case RTF_CHBGDKCROSS: case RTF_BGDKCROSS: case RTF_CLBGDKDCROSS: case RTF_CHBGDKDCROSS: case RTF_BGDKDCROSS: // dark -> 60%
nFillValue = 60; break;
case RTF_CLBGHORIZ: case RTF_CHBGHORIZ: case RTF_BGHORIZ: case RTF_CLBGVERT: case RTF_CHBGVERT: case RTF_BGVERT: case RTF_CLBGBDIAG: case RTF_CHBGBDIAG: case RTF_BGBDIAG: case RTF_CLBGFDIAG: case RTF_CHBGFDIAG: case RTF_BGFDIAG: case RTF_CLBGCROSS: case RTF_CHBGCROSS: case RTF_BGCROSS: case RTF_CLBGDCROSS: case RTF_CHBGDCROSS: case RTF_BGDCROSS: // light -> 20%
nFillValue = 20; break;
// pard / plain handling void SvxRTFParser::RTFPardPlain( boolconst bPard, SfxItemSet** ppSet )
{ if( bNewGroup || aAttrStack.empty() ) // not at the beginning of a new group return;
int nLastToken = GetStackPtr(-1)->nTokenId; bool bNewStkEntry = true; if( RTF_PARD != nLastToken &&
RTF_PLAIN != nLastToken &&
BRACELEFT != nLastToken )
{ if (pCurrent->aAttrSet.Count() || !pCurrent->maChildList.empty() || pCurrent->nStyleNo)
{ // open a new group auto xNew(std::make_unique<SvxRTFItemStackType>(*pCurrent, *mxInsertPosition, true));
xNew->SetRTFDefaults( GetRTFDefaults() );
// Set all until here valid attributes
AttrGroupEnd();
pCurrent = aAttrStack.empty() ? nullptr : aAttrStack.back().get(); // can be changed after AttrGroupEnd!
xNew->aAttrSet.SetParent( pCurrent ? &pCurrent->aAttrSet : nullptr );
aAttrStack.push_back( std::move(xNew) );
pCurrent = aAttrStack.back().get();
} else
{ // continue to use this entry as new
pCurrent->SetStartPos( *mxInsertPosition );
bNewStkEntry = false;
}
}
for (; aIt != aEnd; ++aIt)
{ const sal_uInt16 wid = aIt->second; // Item set and different -> Set the Default Pool if (!wid)
; elseif (SfxItemPool::IsSlot(wid))
pCurrent->aAttrSet.ClearItem(wid); elseif( IsChkStyleAttr() )
pCurrent->aAttrSet.Put(pDfltSet->Get(wid)); elseif( !pCurrent->aAttrSet.GetParent() )
{ if (SfxItemState::SET == pDfltSet->GetItemState(wid, false, &pDef))
pCurrent->aAttrSet.Put( *pDef ); else
pCurrent->aAttrSet.ClearItem(wid);
} elseif( SfxItemState::SET == pCurrent->aAttrSet.GetParent()->
GetItemState(wid, true, &pItem) &&
*( pDef = &pDfltSet->Get(wid)) != *pItem )
pCurrent->aAttrSet.Put( *pDef ); else
{ if (SfxItemState::SET == pDfltSet->GetItemState(wid, false, &pDef))
pCurrent->aAttrSet.Put( *pDef ); else
pCurrent->aAttrSet.ClearItem(wid);
}
}
} elseif( bPard )
pCurrent->nStyleNo = 0; // reset Style number
*ppSet = &pCurrent->aAttrSet;
if (bPard) return;
//Once we have a default font, then any text without a font specifier is //in the default font, and thus has the default font charset, otherwise //we can fall back to the ansicpg set codeset if (nDfltFont != -1)
{ const vcl::Font& rSVFont = GetFont(sal_uInt16(nDfltFont));
SetEncoding(rSVFont.GetCharSet());
} else
SetEncoding(GetCodeSet());
}
void SvxRTFParser::SetDefault( int nToken, int nValue )
{ if( !bNewDoc ) return;
case RTF_ADEFLANG:
bIsLeftToRightDef = false;
[[fallthrough]]; case RTF_DEFLANG: // store default Language if( -1 != nValue )
{
SvxLanguageItem aTmpItem( LanguageType(nValue), SID_ATTR_CHAR_LANGUAGE );
SetScriptAttr( NOTDEF_CHARTYPE, aTmp, aTmpItem );
} break;
case RTF_DEFTAB: if (const sal_uInt16 wid = aPardMap[SID_ATTR_TABSTOP])
{ // RTF defines 720 twips as default
bIsSetDfltTab = true; if( -1 == nValue || !nValue )
nValue = 720;
// who would like to have no twips ... if( IsCalcValue() )
{
nTokenValue = nValue;
CalcValue();
nValue = nTokenValue;
}
// Calculate the ratio of default TabWidth / Tabs and // calculate the corresponding new number. // ?? how did one come up with 13 ??
sal_uInt16 nTabCount = (SVX_TAB_DEFDIST * 13 ) / sal_uInt16(nValue); /* cmc,makesurewehaveatleastone,orallhellbreaksloosein everybodyexporters,#i8247#
*/ if (nTabCount < 1)
nTabCount = 1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.