1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <tools/diagnose_ex.h>
23 #include <rtl/tencinfo.h>
24 #include <svl/itemiter.hxx>
25 #include <svl/whiter.hxx>
26 #include <svtools/rtftoken.h>
27 #include <svl/itempool.hxx>
28 #include <i18nlangtag/languagetag.hxx>
29 #include <tools/debug.hxx>
31 #include <comphelper/string.hxx>
33 #include <com/sun/star/lang/Locale.hpp>
34 #include <editeng/scriptspaceitem.hxx>
35 #include <editeng/fontitem.hxx>
36 #include <editeng/colritem.hxx>
37 #include <editeng/svxrtf.hxx>
38 #include <editeng/editids.hrc>
39 #include <vcl/font.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/settings.hxx>
43 #include <com/sun/star/document/XDocumentProperties.hpp>
46 using namespace ::com::sun::star
;
49 static rtl_TextEncoding
lcl_GetDefaultTextEncodingForRTF()
52 OUString
aLangString( Application::GetSettings().GetLanguageTag().getLanguage());
54 if ( aLangString
== "ru" || aLangString
== "uk" )
55 return RTL_TEXTENCODING_MS_1251
;
56 if ( aLangString
== "tr" )
57 return RTL_TEXTENCODING_MS_1254
;
59 return RTL_TEXTENCODING_MS_1252
;
62 // -------------- Methods --------------------
64 SvxRTFParser::SvxRTFParser( SfxItemPool
& rPool
, SvStream
& rIn
)
65 : SvRTFParser( rIn
, 5 )
72 , bIsSetDfltTab( false)
73 , bChkStyleAttr( false )
75 , bIsLeftToRightDef( true)
76 , bIsInReadStyleTab( false)
78 pDfltFont
.reset( new vcl::Font
);
79 pDfltColor
.reset( new Color
);
82 SvxRTFParser::~SvxRTFParser()
84 if( !aColorTbl
.empty() )
86 if( !aAttrStack
.empty() )
90 void SvxRTFParser::SetInsPos( const EditPosition
& rNew
)
92 pInsPos
= rNew
.Clone();
95 SvParserState
SvxRTFParser::CallParser()
97 DBG_ASSERT( pInsPos
, "no insertion position");
100 return SvParserState::Error
;
102 if( !aColorTbl
.empty() )
105 m_StyleTable
.clear();
106 if( !aAttrStack
.empty() )
109 bIsSetDfltTab
= false;
113 // generate the correct WhichId table from the set WhichIds.
116 return SvRTFParser::CallParser();
119 void SvxRTFParser::Continue( int nToken
)
121 SvRTFParser::Continue( nToken
);
123 SvParserState eStatus
= GetStatus();
124 if (eStatus
!= SvParserState::Pending
&& eStatus
!= SvParserState::Error
)
127 //Regardless of what "color 0" is, word defaults to auto as the default colour.
133 // is called for each token that is recognized in CallParser
134 void SvxRTFParser::NextToken( int nToken
)
139 case RTF_COLORTBL
: ReadColorTable(); break;
140 case RTF_FONTTBL
: ReadFontTable(); break;
141 case RTF_STYLESHEET
: ReadStyleTable(); break;
146 if (!m_FontTable
.empty())
147 // Can immediately be set
148 SetDefault( nToken
, nTokenValue
);
150 // is set after reading the font table
151 nDfltFont
= int(nTokenValue
);
158 SetDefault( nToken
, nTokenValue
);
162 case RTF_PICT
: ReadBitmapData(); break;
164 case RTF_LINE
: cCh
= '\n'; goto INSINGLECHAR
;
165 case RTF_TAB
: cCh
= '\t'; goto INSINGLECHAR
;
166 case RTF_SUBENTRYINDEX
: cCh
= ':'; goto INSINGLECHAR
;
168 case RTF_EMDASH
: cCh
= 0x2014; goto INSINGLECHAR
;
169 case RTF_ENDASH
: cCh
= 0x2013; goto INSINGLECHAR
;
170 case RTF_BULLET
: cCh
= 0x2022; goto INSINGLECHAR
;
171 case RTF_LQUOTE
: cCh
= 0x2018; goto INSINGLECHAR
;
172 case RTF_RQUOTE
: cCh
= 0x2019; goto INSINGLECHAR
;
173 case RTF_LDBLQUOTE
: cCh
= 0x201C; goto INSINGLECHAR
;
174 case RTF_RDBLQUOTE
: cCh
= 0x201D; goto INSINGLECHAR
;
176 aToken
= OUString(cCh
);
177 [[fallthrough
]]; // aToken is set as Text
181 // all collected Attributes are set
182 for (size_t n
= m_AttrSetList
.size(); n
; )
184 auto const& pStkSet
= m_AttrSetList
[--n
];
185 SetAttrSet( *pStkSet
);
186 m_AttrSetList
.pop_back();
196 if (bNewGroup
) // Nesting!
201 if( !bNewGroup
) // Empty Group ??
209 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
210 // First overwrite all (all have to be in one group!!)
211 // Could also appear in the RTF-file without the IGNORE-Flag; all Groups
212 // with the IGNORE-Flag are overwritten in the default branch.
214 case RTF_SWG_PRTDATA
:
226 // RTF_SHPRSLT disabled for #i19718#
229 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
234 if( RTF_IGNOREFLAG
!= GetStackPtr( -1 )->nTokenId
)
236 nToken
= SkipToken();
237 if( '{' == GetStackPtr( -1 )->nTokenId
)
238 nToken
= SkipToken();
240 ReadAttr( nToken
, &GetAttrSet() );
244 switch( nToken
& ~(0xff | RTF_SWGDEFS
) )
246 case RTF_PARFMT
: // here are no SWGDEFS
247 ReadAttr( nToken
, &GetAttrSet() );
254 if( RTF_SWGDEFS
& nToken
)
256 if( RTF_IGNOREFLAG
!= GetStackPtr( -1 )->nTokenId
)
258 nToken
= SkipToken();
259 if( '{' == GetStackPtr( -1 )->nTokenId
)
261 nToken
= SkipToken();
264 ReadAttr( nToken
, &GetAttrSet() );
268 if( RTF_IGNOREFLAG
== GetStackPtr( -1 )->nTokenId
&&
269 '{' == GetStackPtr( -2 )->nTokenId
)
278 void SvxRTFParser::ReadStyleTable()
280 int bSaveChkStyleAttr
= bChkStyleAttr
? 1 : 0;
281 sal_uInt16 nStyleNo
= 0;
282 bool bHasStyleNo
= false;
283 int _nOpenBrakets
= 1; // the first was already detected earlier!!
284 std::unique_ptr
<SvxRTFStyleType
> pStyle(
285 new SvxRTFStyleType( *pAttrPool
, aWhichMap
.data() ));
286 pStyle
->aAttrSet
.Put( GetRTFDefaults() );
288 bIsInReadStyleTab
= true;
289 bChkStyleAttr
= false; // Do not check Attribute against the Styles
291 while( _nOpenBrakets
&& IsParserWorking() )
293 int nToken
= GetNextToken();
296 case '}': if( --_nOpenBrakets
&& IsParserWorking() )
297 // Style has been completely read,
298 // so this is still a stable status
299 SaveState( RTF_STYLESHEET
);
303 if( RTF_IGNOREFLAG
!= GetNextToken() )
305 else if( RTF_UNKNOWNCONTROL
!= ( nToken
= GetNextToken() ) &&
310 // filter out at once
312 nToken
= GetNextToken();
314 eState
= SvParserState::Error
;
321 case RTF_SBASEDON
: pStyle
->nBasedOn
= sal_uInt16(nTokenValue
); break;
322 case RTF_SNEXT
: break;
323 case RTF_OUTLINELEVEL
:
324 case RTF_SOUTLVL
: pStyle
->nOutlineNo
= sal_uInt8(nTokenValue
); break;
325 case RTF_S
: nStyleNo
= static_cast<short>(nTokenValue
);
328 case RTF_CS
: nStyleNo
= static_cast<short>(nTokenValue
);
335 pStyle
->sName
= DelCharAtEnd( aToken
, ';' );
337 if (!m_StyleTable
.empty())
339 m_StyleTable
.erase(nStyleNo
);
341 // All data from the font is available, so off to the table
342 m_StyleTable
.insert(std::make_pair(nStyleNo
, std::move(pStyle
)));
343 pStyle
.reset(new SvxRTFStyleType( *pAttrPool
, aWhichMap
.data() ));
344 pStyle
->aAttrSet
.Put( GetRTFDefaults() );
350 switch( nToken
& ~(0xff | RTF_SWGDEFS
) )
352 case RTF_PARFMT
: // here are no SWGDEFS
353 ReadAttr( nToken
, &pStyle
->aAttrSet
);
360 auto nEnteringToken
= nToken
;
362 auto nEnteringIndex
= m_nTokenIndex
;
363 int nSkippedTokens
= 0;
364 if( RTF_SWGDEFS
& nToken
)
366 if( RTF_IGNOREFLAG
!= GetStackPtr( -1 )->nTokenId
)
368 nToken
= SkipToken();
370 if( '{' == GetStackPtr( -1 )->nTokenId
)
372 nToken
= SkipToken();
376 ReadAttr( nToken
, &pStyle
->aAttrSet
);
377 if (nSkippedTokens
&& m_nTokenIndex
== nEnteringIndex
- nSkippedTokens
)
379 // we called SkipToken to go back one or two, but ReadAttrs
380 // read nothing, so on next loop of the outer while we
381 // would end up in the same state again (assert that)
382 assert(nEnteringToken
== GetNextToken());
383 // and loop endlessly, skip format a token
384 // instead to avoid that
385 SkipToken(nSkippedTokens
);
392 pStyle
.reset(); // Delete the Last Style
393 SkipToken(); // the closing brace is evaluated "above"
395 // Flag back to old state
396 bChkStyleAttr
= bSaveChkStyleAttr
;
397 bIsInReadStyleTab
= false;
400 void SvxRTFParser::ReadColorTable()
403 sal_uInt8 nRed
= 0xff, nGreen
= 0xff, nBlue
= 0xff;
405 while( '}' != ( nToken
= GetNextToken() ) && IsParserWorking() )
409 case RTF_RED
: nRed
= sal_uInt8(nTokenValue
); break;
410 case RTF_GREEN
: nGreen
= sal_uInt8(nTokenValue
); break;
411 case RTF_BLUE
: nBlue
= sal_uInt8(nTokenValue
); break;
414 if( 1 == aToken
.getLength()
416 : -1 == aToken
.indexOf( ";" ) )
417 break; // At least the ';' must be found
422 if( IsParserWorking() )
424 // one color is finished, fill in the table
425 // try to map the values to SV internal names
426 Color
* pColor
= new Color( nRed
, nGreen
, nBlue
);
427 if( aColorTbl
.empty() &&
428 sal_uInt8(-1) == nRed
&& sal_uInt8(-1) == nGreen
&& sal_uInt8(-1) == nBlue
)
430 aColorTbl
.push_back( pColor
);
435 // Color has been completely read,
436 // so this is still a stable status
437 SaveState( RTF_COLORTBL
);
442 SkipToken(); // the closing brace is evaluated "above"
445 void SvxRTFParser::ReadFontTable()
447 int _nOpenBrakets
= 1; // the first was already detected earlier!!
448 std::unique_ptr
<vcl::Font
> pFont(new vcl::Font
);
449 short nFontNo(0), nInsFontNo (0);
450 OUString sAltNm
, sFntNm
;
451 bool bIsAltFntNm
= false;
453 rtl_TextEncoding nSystemChar
= lcl_GetDefaultTextEncodingForRTF();
454 pFont
->SetCharSet( nSystemChar
);
455 SetEncoding( nSystemChar
);
457 while( _nOpenBrakets
&& IsParserWorking() )
459 bool bCheckNewFont
= false;
460 int nToken
= GetNextToken();
465 // Style has been completely read,
466 // so this is still a stable status
467 if( --_nOpenBrakets
<= 1 && IsParserWorking() )
468 SaveState( RTF_FONTTBL
);
469 bCheckNewFont
= true;
470 nInsFontNo
= nFontNo
;
473 if( RTF_IGNOREFLAG
!= GetNextToken() )
475 // immediately skip unknown and all known but non-evaluated
477 else if( RTF_UNKNOWNCONTROL
!= ( nToken
= GetNextToken() ) &&
478 RTF_PANOSE
!= nToken
&& RTF_FNAME
!= nToken
&&
479 RTF_FONTEMB
!= nToken
&& RTF_FONTFILE
!= nToken
)
483 // filter out at once
485 nToken
= GetNextToken();
487 eState
= SvParserState::Error
;
493 pFont
->SetFamily( FAMILY_ROMAN
);
496 pFont
->SetFamily( FAMILY_SWISS
);
499 pFont
->SetFamily( FAMILY_MODERN
);
502 pFont
->SetFamily( FAMILY_SCRIPT
);
505 pFont
->SetFamily( FAMILY_DECORATIVE
);
507 // for technical/symbolic font of the rtl_TextEncoding is changed!
509 pFont
->SetCharSet( RTL_TEXTENCODING_SYMBOL
);
512 pFont
->SetFamily( FAMILY_DONTKNOW
);
515 if (-1 != nTokenValue
)
517 rtl_TextEncoding nrtl_TextEncoding
= rtl_getTextEncodingFromWindowsCharset(
518 static_cast<sal_uInt8
>(nTokenValue
));
519 pFont
->SetCharSet(nrtl_TextEncoding
);
520 //When we're in a font, the fontname is in the font
521 //charset, except for symbol fonts I believe
522 if (nrtl_TextEncoding
== RTL_TEXTENCODING_SYMBOL
)
523 nrtl_TextEncoding
= RTL_TEXTENCODING_DONTKNOW
;
524 SetEncoding(nrtl_TextEncoding
);
528 switch( nTokenValue
)
531 pFont
->SetPitch( PITCH_FIXED
);
534 pFont
->SetPitch( PITCH_VARIABLE
);
539 bCheckNewFont
= true;
540 nInsFontNo
= nFontNo
;
541 nFontNo
= static_cast<short>(nTokenValue
);
547 DelCharAtEnd( aToken
, ';' );
548 if ( !aToken
.isEmpty() )
558 if( bCheckNewFont
&& 1 >= _nOpenBrakets
&& !sFntNm
.isEmpty() ) // one font is ready
560 // All data from the font is available, so off to the table
561 if (!sAltNm
.isEmpty())
562 sFntNm
+= ";" + sAltNm
;
564 pFont
->SetFamilyName( sFntNm
);
565 m_FontTable
.insert(std::make_pair(nInsFontNo
, std::move(pFont
)));
566 pFont
.reset(new vcl::Font
);
567 pFont
->SetCharSet( nSystemChar
);
572 // the last one we have to delete manually
574 SkipToken(); // the closing brace is evaluated "above"
576 // set the default font in the Document
577 if( bNewDoc
&& IsParserWorking() )
578 SetDefault( RTF_DEFF
, nDfltFont
);
581 void SvxRTFParser::ClearColorTbl()
583 while ( !aColorTbl
.empty() )
585 delete aColorTbl
.back();
586 aColorTbl
.pop_back();
590 void SvxRTFParser::ClearAttrStack()
595 OUString
& SvxRTFParser::DelCharAtEnd( OUString
& rStr
, const sal_Unicode cDel
)
597 if( !rStr
.isEmpty() && ' ' == rStr
[ 0 ])
598 rStr
= comphelper::string::stripStart(rStr
, ' ');
599 if( !rStr
.isEmpty() && ' ' == rStr
[ rStr
.getLength()-1 ])
600 rStr
= comphelper::string::stripEnd(rStr
, ' ');
601 if( !rStr
.isEmpty() && cDel
== rStr
[ rStr
.getLength()-1 ])
602 rStr
= rStr
.copy( 0, rStr
.getLength()-1 );
607 const vcl::Font
& SvxRTFParser::GetFont( sal_uInt16 nId
)
609 SvxRTFFontTbl::const_iterator it
= m_FontTable
.find( nId
);
610 if (it
!= m_FontTable
.end())
614 const SvxFontItem
& rDfltFont
= static_cast<const SvxFontItem
&>(
615 pAttrPool
->GetDefaultItem( aPlainMap
.nFont
));
616 pDfltFont
->SetFamilyName( rDfltFont
.GetStyleName() );
617 pDfltFont
->SetFamily( rDfltFont
.GetFamily() );
621 SvxRTFItemStackType
* SvxRTFParser::GetAttrSet_()
623 SvxRTFItemStackType
* pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get();
624 std::unique_ptr
<SvxRTFItemStackType
> pNew
;
626 pNew
.reset(new SvxRTFItemStackType( *pCurrent
, *pInsPos
, false/*bCopyAttr*/ ));
628 pNew
.reset(new SvxRTFItemStackType( *pAttrPool
, aWhichMap
.data(),
630 pNew
->SetRTFDefaults( GetRTFDefaults() );
632 aAttrStack
.push_back( std::move(pNew
) );
634 return aAttrStack
.back().get();
638 void SvxRTFParser::ClearStyleAttr_( SvxRTFItemStackType
& rStkType
)
640 // check attributes to the attributes of the stylesheet or to
641 // the default attrs of the document
642 SfxItemSet
&rSet
= rStkType
.GetAttrSet();
643 const SfxItemPool
& rPool
= *rSet
.GetPool();
644 const SfxPoolItem
* pItem
;
645 SfxWhichIter
aIter( rSet
);
647 if( !IsChkStyleAttr() ||
648 !rStkType
.GetAttrSet().Count() ||
649 m_StyleTable
.count( rStkType
.nStyleNo
) == 0 )
651 for( sal_uInt16 nWhich
= aIter
.GetCurWhich(); nWhich
; nWhich
= aIter
.NextWhich() )
653 if (SfxItemPool::IsWhich(nWhich
) &&
654 SfxItemState::SET
== rSet
.GetItemState( nWhich
, false, &pItem
) &&
655 rPool
.GetDefaultItem( nWhich
) == *pItem
)
656 rSet
.ClearItem( nWhich
); // delete
661 // Delete all Attributes, which are already defined in the Style,
662 // from the current AttrSet.
663 auto const& pStyle
= m_StyleTable
.find(rStkType
.nStyleNo
)->second
;
664 SfxItemSet
&rStyleSet
= pStyle
->aAttrSet
;
665 const SfxPoolItem
* pSItem
;
666 for( sal_uInt16 nWhich
= aIter
.GetCurWhich(); nWhich
; nWhich
= aIter
.NextWhich() )
668 if( SfxItemState::SET
== rStyleSet
.GetItemState( nWhich
, true, &pSItem
))
670 if( SfxItemState::SET
== rSet
.GetItemState( nWhich
, false, &pItem
)
671 && *pItem
== *pSItem
)
672 rSet
.ClearItem( nWhich
); // delete
674 else if (SfxItemPool::IsWhich(nWhich
) &&
675 SfxItemState::SET
== rSet
.GetItemState( nWhich
, false, &pItem
) &&
676 rPool
.GetDefaultItem( nWhich
) == *pItem
)
677 rSet
.ClearItem( nWhich
); // delete
682 void SvxRTFParser::AttrGroupEnd() // process the current, delete from Stack
684 if( !aAttrStack
.empty() )
686 std::unique_ptr
<SvxRTFItemStackType
> pOld
= std::move(aAttrStack
.back());
687 aAttrStack
.pop_back();
688 SvxRTFItemStackType
*pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get();
690 do { // middle check loop
691 sal_Int32 nOldSttNdIdx
= pOld
->pSttNd
->GetIdx();
692 if (!pOld
->m_pChildList
&&
693 ((!pOld
->aAttrSet
.Count() && !pOld
->nStyleNo
) ||
694 (nOldSttNdIdx
== pInsPos
->GetNodeIdx() &&
695 pOld
->nSttCnt
== pInsPos
->GetCntIdx() )))
696 break; // no attributes or Area
698 // set only the attributes that are different from the parent
699 if( pCurrent
&& pOld
->aAttrSet
.Count() )
701 SfxItemIter
aIter( pOld
->aAttrSet
);
702 const SfxPoolItem
* pItem
= aIter
.GetCurItem(), *pGet
;
705 if( SfxItemState::SET
== pCurrent
->aAttrSet
.GetItemState(
706 pItem
->Which(), false, &pGet
) &&
708 pOld
->aAttrSet
.ClearItem( pItem
->Which() );
710 pItem
= aIter
.NextItem();
713 if (!pOld
->aAttrSet
.Count() && !pOld
->m_pChildList
&&
718 // Set all attributes which have been defined from start until here
719 bool bCrsrBack
= !pInsPos
->GetCntIdx();
722 // at the beginning of a paragraph? Move back one position
723 sal_Int32 nNd
= pInsPos
->GetNodeIdx();
725 // if can not move backward then later don't move forward !
726 bCrsrBack
= nNd
!= pInsPos
->GetNodeIdx();
729 if( pOld
->pSttNd
->GetIdx() < pInsPos
->GetNodeIdx() ||
730 ( pOld
->pSttNd
->GetIdx() == pInsPos
->GetNodeIdx() &&
731 pOld
->nSttCnt
<= pInsPos
->GetCntIdx() ) )
735 // all pard attributes are only valid until the previous
737 if( nOldSttNdIdx
== pInsPos
->GetNodeIdx() )
742 // Now it gets complicated:
743 // - all character attributes sre keep the area
744 // - all paragraph attributes to get the area
745 // up to the previous paragraph
746 std::unique_ptr
<SvxRTFItemStackType
> pNew(
747 new SvxRTFItemStackType(*pOld
, *pInsPos
, true));
748 pNew
->aAttrSet
.SetParent( pOld
->aAttrSet
.GetParent() );
750 // Delete all paragraph attributes from pNew
751 for( sal_uInt16 n
= 0; n
< (sizeof(aPardMap
) / sizeof(sal_uInt16
)) &&
752 pNew
->aAttrSet
.Count(); ++n
)
753 if( reinterpret_cast<sal_uInt16
*>(&aPardMap
)[n
] )
754 pNew
->aAttrSet
.ClearItem( reinterpret_cast<sal_uInt16
*>(&aPardMap
)[n
] );
755 pNew
->SetRTFDefaults( GetRTFDefaults() );
758 if( pNew
->aAttrSet
.Count() == pOld
->aAttrSet
.Count() )
766 // Now span the real area of pNew from old
767 SetEndPrevPara( pOld
->pEndNd
, pOld
->nEndCnt
);
770 if( IsChkStyleAttr() )
772 ClearStyleAttr_( *pOld
);
773 ClearStyleAttr_( *pNew
); //#i10381#, methinks.
778 pCurrent
->Add(std::move(pOld
));
779 pCurrent
->Add(std::move(pNew
));
783 // Last off the stack, thus cache it until the next text was
784 // read. (Span no attributes!)
786 m_AttrSetList
.push_back(std::move(pOld
));
787 m_AttrSetList
.push_back(std::move(pNew
));
794 pOld
->pEndNd
= pInsPos
->MakeNodeIdx().release();
795 pOld
->nEndCnt
= pInsPos
->GetCntIdx();
799 If the parent (pCurrent) sets something e.g. , and the child (pOld)
800 unsets it and the style both are based on has it unset then
801 clearing the pOld by looking at the style is clearly a disaster
802 as the text ends up with pCurrents bold and not pOlds no bold, this
803 should be rethought out. For the moment its safest to just do
804 the clean if we have no parent, all we suffer is too many
805 redundant properties.
807 if (IsChkStyleAttr() && !pCurrent
)
808 ClearStyleAttr_( *pOld
);
812 pCurrent
->Add(std::move(pOld
));
813 // split up and create new entry, because it makes no sense
814 // to create a "so long" depend list. Bug 95010
815 if (bCrsrBack
&& 50 < pCurrent
->m_pChildList
->size())
817 // at the beginning of a paragraph? Move back one position
822 std::unique_ptr
<SvxRTFItemStackType
> pNew(new SvxRTFItemStackType(
823 *pCurrent
, *pInsPos
, true ));
824 pNew
->SetRTFDefaults( GetRTFDefaults() );
826 // Set all until here valid Attributes
828 pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get(); // can be changed after AttrGroupEnd!
829 pNew
->aAttrSet
.SetParent( pCurrent
? &pCurrent
->aAttrSet
: nullptr );
830 aAttrStack
.push_back( std::move(pNew
) );
834 // Last off the stack, thus cache it until the next text was
835 // read. (Span no attributes!)
836 m_AttrSetList
.push_back(std::move(pOld
));
840 // at the beginning of a paragraph? Move back one position
849 void SvxRTFParser::SetAllAttrOfStk() // end all Attr. and set it into doc
851 // repeat until all attributes will be taken from stack
852 while( !aAttrStack
.empty() )
855 for (size_t n
= m_AttrSetList
.size(); n
; )
857 auto const& pStkSet
= m_AttrSetList
[--n
];
858 SetAttrSet( *pStkSet
);
859 pStkSet
->DropChildList();
860 m_AttrSetList
.pop_back();
864 // sets all the attributes that are different from the current
865 void SvxRTFParser::SetAttrSet( SvxRTFItemStackType
&rSet
)
867 // Was DefTab never read? then set to default
869 SetDefault( RTF_DEFTAB
, 720 );
871 if (rSet
.m_pChildList
)
872 rSet
.Compress( *this );
873 if( rSet
.aAttrSet
.Count() || rSet
.nStyleNo
)
874 SetAttrInDoc( rSet
);
876 // then process all the children
877 if (rSet
.m_pChildList
)
878 for (size_t n
= 0; n
< rSet
.m_pChildList
->size(); ++n
)
879 SetAttrSet( *(*rSet
.m_pChildList
)[ n
] );
882 // Has no text been inserted yet? (SttPos from the top Stack entry!)
883 bool SvxRTFParser::IsAttrSttPos()
885 SvxRTFItemStackType
* pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get();
886 return !pCurrent
|| (pCurrent
->pSttNd
->GetIdx() == pInsPos
->GetNodeIdx() &&
887 pCurrent
->nSttCnt
== pInsPos
->GetCntIdx());
891 void SvxRTFParser::SetAttrInDoc( SvxRTFItemStackType
& )
895 void SvxRTFParser::BuildWhichTable()
898 aWhichMap
.push_back( 0 );
900 // Building a Which-Map 'rWhichMap' from an array of
901 // 'pWhichIds' from Which-Ids. It has the long 'nWhichIds'.
902 // The Which-Map is not going to be deleted.
903 ::BuildWhichTable( aWhichMap
, reinterpret_cast<sal_uInt16
*>(&aPardMap
), sizeof(aPardMap
) / sizeof(sal_uInt16
) );
904 ::BuildWhichTable( aWhichMap
, reinterpret_cast<sal_uInt16
*>(&aPlainMap
), sizeof(aPlainMap
) / sizeof(sal_uInt16
) );
907 const SfxItemSet
& SvxRTFParser::GetRTFDefaults()
911 pRTFDefaults
.reset( new SfxItemSet( *pAttrPool
, aWhichMap
.data() ) );
913 if( 0 != ( nId
= aPardMap
.nScriptSpace
))
915 SvxScriptSpaceItem
aItem( false, nId
);
917 pAttrPool
->SetPoolDefaultItem( aItem
);
919 pRTFDefaults
->Put( aItem
);
922 return *pRTFDefaults
;
926 SvxRTFStyleType::SvxRTFStyleType( SfxItemPool
& rPool
, const sal_uInt16
* pWhichRange
)
927 : aAttrSet( rPool
, pWhichRange
)
929 nOutlineNo
= sal_uInt8(-1); // not set
934 SvxRTFItemStackType::SvxRTFItemStackType(
935 SfxItemPool
& rPool
, const sal_uInt16
* pWhichRange
,
936 const EditPosition
& rPos
)
937 : aAttrSet( rPool
, pWhichRange
)
940 pSttNd
= rPos
.MakeNodeIdx();
941 nSttCnt
= rPos
.GetCntIdx();
942 pEndNd
= pSttNd
.get();
946 SvxRTFItemStackType::SvxRTFItemStackType(
947 const SvxRTFItemStackType
& rCpy
,
948 const EditPosition
& rPos
,
949 bool const bCopyAttr
)
950 : aAttrSet( *rCpy
.aAttrSet
.GetPool(), rCpy
.aAttrSet
.GetRanges() )
951 , nStyleNo( rCpy
.nStyleNo
)
953 pSttNd
= rPos
.MakeNodeIdx();
954 nSttCnt
= rPos
.GetCntIdx();
955 pEndNd
= pSttNd
.get();
958 aAttrSet
.SetParent( &rCpy
.aAttrSet
);
960 aAttrSet
.Put( rCpy
.aAttrSet
);
963 /* ofz#13491 SvxRTFItemStackType dtor recursively
964 calls the dtor of its m_pChildList. The recurse
965 depth can grow sufficiently to trigger asan.
967 So breadth-first iterate through the nodes
968 and make a flat vector of them which can
969 be iterated through in order of most
970 distant from root first and release
971 their children linearly
973 void SvxRTFItemStackType::DropChildList()
975 if (!m_pChildList
|| m_pChildList
->empty())
978 std::vector
<SvxRTFItemStackType
*> bfs
;
979 std::queue
<SvxRTFItemStackType
*> aQueue
;
982 while (!aQueue
.empty())
984 auto* front
= aQueue
.front();
986 if (front
->m_pChildList
)
988 for (const auto& a
: *front
->m_pChildList
)
989 aQueue
.push(a
.get());
990 bfs
.push_back(front
);
994 for (auto it
= bfs
.rbegin(); it
!= bfs
.rend(); ++it
)
996 SvxRTFItemStackType
* pNode
= *it
;
997 pNode
->m_pChildList
.reset();
1001 SvxRTFItemStackType::~SvxRTFItemStackType()
1003 if( pSttNd
.get() != pEndNd
)
1007 void SvxRTFItemStackType::Add(std::unique_ptr
<SvxRTFItemStackType
> pIns
)
1010 m_pChildList
.reset( new SvxRTFItemStackList
);
1011 m_pChildList
->push_back(std::move(pIns
));
1014 void SvxRTFItemStackType::SetStartPos( const EditPosition
& rPos
)
1016 if (pSttNd
.get() != pEndNd
)
1018 pSttNd
= rPos
.MakeNodeIdx();
1019 pEndNd
= pSttNd
.get();
1020 nSttCnt
= rPos
.GetCntIdx();
1023 void SvxRTFItemStackType::Compress( const SvxRTFParser
& rParser
)
1025 ENSURE_OR_RETURN_VOID(m_pChildList
, "Compress: no ChildList" );
1026 ENSURE_OR_RETURN_VOID(!m_pChildList
->empty(), "Compress: ChildList empty");
1028 SvxRTFItemStackType
* pTmp
= (*m_pChildList
)[0].get();
1030 if( !pTmp
->aAttrSet
.Count() ||
1031 pSttNd
->GetIdx() != pTmp
->pSttNd
->GetIdx() ||
1032 nSttCnt
!= pTmp
->nSttCnt
)
1035 EditNodeIdx
* pLastNd
= pTmp
->pEndNd
;
1036 sal_Int32 nLastCnt
= pTmp
->nEndCnt
;
1038 SfxItemSet
aMrgSet( pTmp
->aAttrSet
);
1039 for (size_t n
= 1; n
< m_pChildList
->size(); ++n
)
1041 pTmp
= (*m_pChildList
)[n
].get();
1042 if (pTmp
->m_pChildList
)
1043 pTmp
->Compress( rParser
);
1046 ? (pLastNd
->GetIdx()+1 != pTmp
->pSttNd
->GetIdx() ||
1047 !rParser
.IsEndPara( pLastNd
, nLastCnt
) )
1048 : ( pTmp
->nSttCnt
!= nLastCnt
||
1049 pLastNd
->GetIdx() != pTmp
->pSttNd
->GetIdx() ))
1051 while (++n
< m_pChildList
->size())
1053 pTmp
= (*m_pChildList
)[n
].get();
1054 if (pTmp
->m_pChildList
)
1055 pTmp
->Compress( rParser
);
1062 // Search for all which are set over the whole area
1063 SfxItemIter
aIter( aMrgSet
);
1064 const SfxPoolItem
* pItem
;
1065 const SfxPoolItem
* pIterItem
= aIter
.GetCurItem();
1067 sal_uInt16 nWhich
= pIterItem
->Which();
1068 if( SfxItemState::SET
!= pTmp
->aAttrSet
.GetItemState( nWhich
,
1069 false, &pItem
) || *pItem
!= *pIterItem
)
1070 aMrgSet
.ClearItem( nWhich
);
1072 pIterItem
= aIter
.NextItem();
1075 if( !aMrgSet
.Count() )
1079 pLastNd
= pTmp
->pEndNd
;
1080 nLastCnt
= pTmp
->nEndCnt
;
1083 if( pEndNd
->GetIdx() != pLastNd
->GetIdx() || nEndCnt
!= nLastCnt
)
1087 aAttrSet
.Put( aMrgSet
);
1089 for (size_t n
= 0; n
< m_pChildList
->size(); ++n
)
1091 pTmp
= (*m_pChildList
)[n
].get();
1092 pTmp
->aAttrSet
.Differentiate( aMrgSet
);
1094 if (!pTmp
->m_pChildList
&& !pTmp
->aAttrSet
.Count() && !pTmp
->nStyleNo
)
1096 m_pChildList
->erase( m_pChildList
->begin() + n
);
1100 if (m_pChildList
->empty())
1102 m_pChildList
.reset();
1105 void SvxRTFItemStackType::SetRTFDefaults( const SfxItemSet
& rDefaults
)
1107 if( rDefaults
.Count() )
1109 SfxItemIter
aIter( rDefaults
);
1110 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1112 sal_uInt16 nWhich
= pItem
->Which();
1113 if( SfxItemState::SET
!= aAttrSet
.GetItemState( nWhich
, false ))
1114 aAttrSet
.Put(*pItem
);
1116 pItem
= aIter
.NextItem();
1122 RTFPlainAttrMapIds::RTFPlainAttrMapIds( const SfxItemPool
& rPool
)
1124 nCaseMap
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CASEMAP
, false );
1125 nBgColor
= rPool
.GetTrueWhich( SID_ATTR_BRUSH_CHAR
, false );
1126 nColor
= rPool
.GetTrueWhich( SID_ATTR_CHAR_COLOR
, false );
1127 nContour
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CONTOUR
, false );
1128 nCrossedOut
= rPool
.GetTrueWhich( SID_ATTR_CHAR_STRIKEOUT
, false );
1129 nEscapement
= rPool
.GetTrueWhich( SID_ATTR_CHAR_ESCAPEMENT
, false );
1130 nFont
= rPool
.GetTrueWhich( SID_ATTR_CHAR_FONT
, false );
1131 nFontHeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_FONTHEIGHT
, false );
1132 nKering
= rPool
.GetTrueWhich( SID_ATTR_CHAR_KERNING
, false );
1133 nLanguage
= rPool
.GetTrueWhich( SID_ATTR_CHAR_LANGUAGE
, false );
1134 nPosture
= rPool
.GetTrueWhich( SID_ATTR_CHAR_POSTURE
, false );
1135 nShadowed
= rPool
.GetTrueWhich( SID_ATTR_CHAR_SHADOWED
, false );
1136 nUnderline
= rPool
.GetTrueWhich( SID_ATTR_CHAR_UNDERLINE
, false );
1137 nOverline
= rPool
.GetTrueWhich( SID_ATTR_CHAR_OVERLINE
, false );
1138 nWeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_WEIGHT
, false );
1139 nWordlineMode
= rPool
.GetTrueWhich( SID_ATTR_CHAR_WORDLINEMODE
, false );
1140 nAutoKerning
= rPool
.GetTrueWhich( SID_ATTR_CHAR_AUTOKERN
, false );
1142 nCJKFont
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_FONT
, false );
1143 nCJKFontHeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT
, false );
1144 nCJKLanguage
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE
, false );
1145 nCJKPosture
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_POSTURE
, false );
1146 nCJKWeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT
, false );
1147 nCTLFont
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_FONT
, false );
1148 nCTLFontHeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT
, false );
1149 nCTLLanguage
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE
, false );
1150 nCTLPosture
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_POSTURE
, false );
1151 nCTLWeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT
, false );
1152 nEmphasis
= rPool
.GetTrueWhich( SID_ATTR_CHAR_EMPHASISMARK
, false );
1153 nTwoLines
= rPool
.GetTrueWhich( SID_ATTR_CHAR_TWO_LINES
, false );
1154 nCharScaleX
= rPool
.GetTrueWhich( SID_ATTR_CHAR_SCALEWIDTH
, false );
1155 nHorzVert
= rPool
.GetTrueWhich( SID_ATTR_CHAR_ROTATED
, false );
1156 nRelief
= rPool
.GetTrueWhich( SID_ATTR_CHAR_RELIEF
, false );
1157 nHidden
= rPool
.GetTrueWhich( SID_ATTR_CHAR_HIDDEN
, false );
1160 RTFPardAttrMapIds ::RTFPardAttrMapIds ( const SfxItemPool
& rPool
)
1162 nLinespacing
= rPool
.GetTrueWhich( SID_ATTR_PARA_LINESPACE
, false );
1163 nAdjust
= rPool
.GetTrueWhich( SID_ATTR_PARA_ADJUST
, false );
1164 nTabStop
= rPool
.GetTrueWhich( SID_ATTR_TABSTOP
, false );
1165 nHyphenzone
= rPool
.GetTrueWhich( SID_ATTR_PARA_HYPHENZONE
, false );
1166 nLRSpace
= rPool
.GetTrueWhich( SID_ATTR_LRSPACE
, false );
1167 nULSpace
= rPool
.GetTrueWhich( SID_ATTR_ULSPACE
, false );
1168 nBrush
= rPool
.GetTrueWhich( SID_ATTR_BRUSH
, false );
1169 nBox
= rPool
.GetTrueWhich( SID_ATTR_BORDER_OUTER
, false );
1170 nShadow
= rPool
.GetTrueWhich( SID_ATTR_BORDER_SHADOW
, false );
1171 nOutlineLvl
= rPool
.GetTrueWhich( SID_ATTR_PARA_OUTLLEVEL
, false );
1172 nSplit
= rPool
.GetTrueWhich( SID_ATTR_PARA_SPLIT
, false );
1173 nKeep
= rPool
.GetTrueWhich( SID_ATTR_PARA_KEEP
, false );
1174 nFontAlign
= rPool
.GetTrueWhich( SID_PARA_VERTALIGN
, false );
1175 nScriptSpace
= rPool
.GetTrueWhich( SID_ATTR_PARA_SCRIPTSPACE
, false );
1176 nHangPunct
= rPool
.GetTrueWhich( SID_ATTR_PARA_HANGPUNCTUATION
, false );
1177 nForbRule
= rPool
.GetTrueWhich( SID_ATTR_PARA_FORBIDDEN_RULES
, false );
1178 nDirection
= rPool
.GetTrueWhich( SID_ATTR_FRAMEDIRECTION
, false );
1181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */