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 <editeng/scriptspaceitem.hxx>
34 #include <editeng/fontitem.hxx>
35 #include <editeng/svxrtf.hxx>
36 #include <editeng/editids.hrc>
37 #include <vcl/font.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/settings.hxx>
42 using namespace ::com::sun::star
;
45 static rtl_TextEncoding
lcl_GetDefaultTextEncodingForRTF()
48 OUString
aLangString( Application::GetSettings().GetLanguageTag().getLanguage());
50 if ( aLangString
== "ru" || aLangString
== "uk" )
51 return RTL_TEXTENCODING_MS_1251
;
52 if ( aLangString
== "tr" )
53 return RTL_TEXTENCODING_MS_1254
;
55 return RTL_TEXTENCODING_MS_1252
;
58 // -------------- Methods --------------------
60 SvxRTFParser::SvxRTFParser( SfxItemPool
& rPool
, SvStream
& rIn
)
61 : SvRTFParser( rIn
, 5 )
68 , bIsSetDfltTab( false)
69 , bChkStyleAttr( false )
71 , bIsLeftToRightDef( true)
72 , bIsInReadStyleTab( false)
74 pDfltFont
.reset( new vcl::Font
);
75 mxDefaultColor
= Color();
78 SvxRTFParser::~SvxRTFParser()
80 if( !aAttrStack
.empty() )
84 void SvxRTFParser::SetInsPos( const EditPosition
& rNew
)
86 pInsPos
= rNew
.Clone();
89 SvParserState
SvxRTFParser::CallParser()
91 DBG_ASSERT( pInsPos
, "no insertion position");
94 return SvParserState::Error
;
96 if( !maColorTable
.empty() )
100 if( !aAttrStack
.empty() )
103 bIsSetDfltTab
= false;
107 // generate the correct WhichId table from the set WhichIds.
110 return SvRTFParser::CallParser();
113 void SvxRTFParser::Continue( int nToken
)
115 SvRTFParser::Continue( nToken
);
117 SvParserState eStatus
= GetStatus();
118 if (eStatus
!= SvParserState::Pending
&& eStatus
!= SvParserState::Error
)
121 //Regardless of what "color 0" is, word defaults to auto as the default colour.
127 // is called for each token that is recognized in CallParser
128 void SvxRTFParser::NextToken( int nToken
)
133 case RTF_COLORTBL
: ReadColorTable(); break;
134 case RTF_FONTTBL
: ReadFontTable(); break;
135 case RTF_STYLESHEET
: ReadStyleTable(); break;
140 if (!m_FontTable
.empty())
141 // Can immediately be set
142 SetDefault( nToken
, nTokenValue
);
144 // is set after reading the font table
145 nDfltFont
= int(nTokenValue
);
152 SetDefault( nToken
, nTokenValue
);
156 case RTF_PICT
: ReadBitmapData(); break;
158 case RTF_LINE
: cCh
= '\n'; goto INSINGLECHAR
;
159 case RTF_TAB
: cCh
= '\t'; goto INSINGLECHAR
;
160 case RTF_SUBENTRYINDEX
: cCh
= ':'; goto INSINGLECHAR
;
162 case RTF_EMDASH
: cCh
= 0x2014; goto INSINGLECHAR
;
163 case RTF_ENDASH
: cCh
= 0x2013; goto INSINGLECHAR
;
164 case RTF_BULLET
: cCh
= 0x2022; goto INSINGLECHAR
;
165 case RTF_LQUOTE
: cCh
= 0x2018; goto INSINGLECHAR
;
166 case RTF_RQUOTE
: cCh
= 0x2019; goto INSINGLECHAR
;
167 case RTF_LDBLQUOTE
: cCh
= 0x201C; goto INSINGLECHAR
;
168 case RTF_RDBLQUOTE
: cCh
= 0x201D; goto INSINGLECHAR
;
170 aToken
= OUString(cCh
);
171 [[fallthrough
]]; // aToken is set as Text
175 // all collected Attributes are set
176 for (size_t n
= m_AttrSetList
.size(); n
; )
178 auto const& pStkSet
= m_AttrSetList
[--n
];
179 SetAttrSet( *pStkSet
);
180 m_AttrSetList
.pop_back();
190 if (bNewGroup
) // Nesting!
195 if( !bNewGroup
) // Empty Group ??
203 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
204 // First overwrite all (all have to be in one group!!)
205 // Could also appear in the RTF-file without the IGNORE-Flag; all Groups
206 // with the IGNORE-Flag are overwritten in the default branch.
208 case RTF_SWG_PRTDATA
:
220 // RTF_SHPRSLT disabled for #i19718#
223 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
228 if( RTF_IGNOREFLAG
!= GetStackPtr( -1 )->nTokenId
)
230 nToken
= SkipToken();
231 if( '{' == GetStackPtr( -1 )->nTokenId
)
232 nToken
= SkipToken();
234 ReadAttr( nToken
, &GetAttrSet() );
238 switch( nToken
& ~(0xff | RTF_SWGDEFS
) )
240 case RTF_PARFMT
: // here are no SWGDEFS
241 ReadAttr( nToken
, &GetAttrSet() );
248 if( RTF_SWGDEFS
& nToken
)
250 if( RTF_IGNOREFLAG
!= GetStackPtr( -1 )->nTokenId
)
252 nToken
= SkipToken();
253 if( '{' == GetStackPtr( -1 )->nTokenId
)
255 nToken
= SkipToken();
258 ReadAttr( nToken
, &GetAttrSet() );
262 if( RTF_IGNOREFLAG
== GetStackPtr( -1 )->nTokenId
&&
263 '{' == GetStackPtr( -2 )->nTokenId
)
272 void SvxRTFParser::ReadStyleTable()
274 int bSaveChkStyleAttr
= bChkStyleAttr
? 1 : 0;
275 sal_uInt16 nStyleNo
= 0;
276 bool bHasStyleNo
= false;
277 int _nOpenBrakets
= 1; // the first was already detected earlier!!
278 std::unique_ptr
<SvxRTFStyleType
> pStyle(
279 new SvxRTFStyleType( *pAttrPool
, aWhichMap
.data() ));
280 pStyle
->aAttrSet
.Put( GetRTFDefaults() );
282 bIsInReadStyleTab
= true;
283 bChkStyleAttr
= false; // Do not check Attribute against the Styles
285 while( _nOpenBrakets
&& IsParserWorking() )
287 int nToken
= GetNextToken();
290 case '}': if( --_nOpenBrakets
&& IsParserWorking() )
291 // Style has been completely read,
292 // so this is still a stable status
293 SaveState( RTF_STYLESHEET
);
297 if( RTF_IGNOREFLAG
!= GetNextToken() )
299 else if( RTF_UNKNOWNCONTROL
!= ( nToken
= GetNextToken() ) &&
304 // filter out at once
306 nToken
= GetNextToken();
308 eState
= SvParserState::Error
;
315 case RTF_SBASEDON
: pStyle
->nBasedOn
= sal_uInt16(nTokenValue
); break;
316 case RTF_SNEXT
: break;
317 case RTF_OUTLINELEVEL
:
318 case RTF_SOUTLVL
: pStyle
->nOutlineNo
= sal_uInt8(nTokenValue
); break;
319 case RTF_S
: nStyleNo
= static_cast<short>(nTokenValue
);
322 case RTF_CS
: nStyleNo
= static_cast<short>(nTokenValue
);
329 pStyle
->sName
= DelCharAtEnd( aToken
, ';' );
331 if (!m_StyleTable
.empty())
333 m_StyleTable
.erase(nStyleNo
);
335 // All data from the font is available, so off to the table
336 m_StyleTable
.insert(std::make_pair(nStyleNo
, std::move(pStyle
)));
337 pStyle
.reset(new SvxRTFStyleType( *pAttrPool
, aWhichMap
.data() ));
338 pStyle
->aAttrSet
.Put( GetRTFDefaults() );
344 switch( nToken
& ~(0xff | RTF_SWGDEFS
) )
346 case RTF_PARFMT
: // here are no SWGDEFS
347 ReadAttr( nToken
, &pStyle
->aAttrSet
);
354 auto nEnteringToken
= nToken
;
356 auto nEnteringIndex
= m_nTokenIndex
;
357 int nSkippedTokens
= 0;
358 if( RTF_SWGDEFS
& nToken
)
360 if( RTF_IGNOREFLAG
!= GetStackPtr( -1 )->nTokenId
)
362 nToken
= SkipToken();
364 if( '{' == GetStackPtr( -1 )->nTokenId
)
366 nToken
= SkipToken();
370 ReadAttr( nToken
, &pStyle
->aAttrSet
);
371 if (nSkippedTokens
&& m_nTokenIndex
== nEnteringIndex
- nSkippedTokens
)
373 // we called SkipToken to go back one or two, but ReadAttrs
374 // read nothing, so on next loop of the outer while we
375 // would end up in the same state again (assert that)
376 assert(nEnteringToken
== GetNextToken());
377 // and loop endlessly, skip format a token
378 // instead to avoid that
379 SkipToken(nSkippedTokens
);
386 pStyle
.reset(); // Delete the Last Style
387 SkipToken(); // the closing brace is evaluated "above"
389 // Flag back to old state
390 bChkStyleAttr
= bSaveChkStyleAttr
;
391 bIsInReadStyleTab
= false;
394 void SvxRTFParser::ReadColorTable()
397 sal_uInt8 nRed
= 0xff, nGreen
= 0xff, nBlue
= 0xff;
401 nToken
= GetNextToken();
402 if ( '}' == nToken
|| !IsParserWorking() )
406 case RTF_RED
: nRed
= sal_uInt8(nTokenValue
); break;
407 case RTF_GREEN
: nGreen
= sal_uInt8(nTokenValue
); break;
408 case RTF_BLUE
: nBlue
= sal_uInt8(nTokenValue
); break;
411 if( 1 == aToken
.getLength()
413 : -1 == aToken
.indexOf( ";" ) )
414 break; // At least the ';' must be found
419 if( IsParserWorking() )
421 // one color is finished, fill in the table
422 // try to map the values to SV internal names
423 Color
aColor( nRed
, nGreen
, nBlue
);
424 if( maColorTable
.empty() &&
425 sal_uInt8(-1) == nRed
&& sal_uInt8(-1) == nGreen
&& sal_uInt8(-1) == nBlue
)
427 maColorTable
.push_back( aColor
);
432 // Color has been completely read,
433 // so this is still a stable status
434 SaveState( RTF_COLORTBL
);
439 SkipToken(); // the closing brace is evaluated "above"
442 void SvxRTFParser::ReadFontTable()
444 int _nOpenBrakets
= 1; // the first was already detected earlier!!
445 std::unique_ptr
<vcl::Font
> pFont(new vcl::Font
);
446 short nFontNo(0), nInsFontNo (0);
447 OUString sAltNm
, sFntNm
;
448 bool bIsAltFntNm
= false;
450 rtl_TextEncoding nSystemChar
= lcl_GetDefaultTextEncodingForRTF();
451 pFont
->SetCharSet( nSystemChar
);
452 SetEncoding( nSystemChar
);
454 while( _nOpenBrakets
&& IsParserWorking() )
456 bool bCheckNewFont
= false;
457 int nToken
= GetNextToken();
462 // Style has been completely read,
463 // so this is still a stable status
464 if( --_nOpenBrakets
<= 1 && IsParserWorking() )
465 SaveState( RTF_FONTTBL
);
466 bCheckNewFont
= true;
467 nInsFontNo
= nFontNo
;
470 if( RTF_IGNOREFLAG
!= GetNextToken() )
472 // immediately skip unknown and all known but non-evaluated
474 else if( RTF_UNKNOWNCONTROL
!= ( nToken
= GetNextToken() ) &&
475 RTF_PANOSE
!= nToken
&& RTF_FNAME
!= nToken
&&
476 RTF_FONTEMB
!= nToken
&& RTF_FONTFILE
!= nToken
)
480 // filter out at once
482 nToken
= GetNextToken();
484 eState
= SvParserState::Error
;
490 pFont
->SetFamily( FAMILY_ROMAN
);
493 pFont
->SetFamily( FAMILY_SWISS
);
496 pFont
->SetFamily( FAMILY_MODERN
);
499 pFont
->SetFamily( FAMILY_SCRIPT
);
502 pFont
->SetFamily( FAMILY_DECORATIVE
);
504 // for technical/symbolic font of the rtl_TextEncoding is changed!
506 pFont
->SetCharSet( RTL_TEXTENCODING_SYMBOL
);
509 pFont
->SetFamily( FAMILY_DONTKNOW
);
512 if (-1 != nTokenValue
)
514 rtl_TextEncoding nrtl_TextEncoding
= rtl_getTextEncodingFromWindowsCharset(
515 static_cast<sal_uInt8
>(nTokenValue
));
516 pFont
->SetCharSet(nrtl_TextEncoding
);
517 //When we're in a font, the fontname is in the font
518 //charset, except for symbol fonts I believe
519 if (nrtl_TextEncoding
== RTL_TEXTENCODING_SYMBOL
)
520 nrtl_TextEncoding
= RTL_TEXTENCODING_DONTKNOW
;
521 SetEncoding(nrtl_TextEncoding
);
525 switch( nTokenValue
)
528 pFont
->SetPitch( PITCH_FIXED
);
531 pFont
->SetPitch( PITCH_VARIABLE
);
536 bCheckNewFont
= true;
537 nInsFontNo
= nFontNo
;
538 nFontNo
= static_cast<short>(nTokenValue
);
544 DelCharAtEnd( aToken
, ';' );
545 if ( !aToken
.isEmpty() )
555 if( bCheckNewFont
&& 1 >= _nOpenBrakets
&& !sFntNm
.isEmpty() ) // one font is ready
557 // All data from the font is available, so off to the table
558 if (!sAltNm
.isEmpty())
559 sFntNm
+= ";" + sAltNm
;
561 pFont
->SetFamilyName( sFntNm
);
562 m_FontTable
.insert(std::make_pair(nInsFontNo
, std::move(pFont
)));
563 pFont
.reset(new vcl::Font
);
564 pFont
->SetCharSet( nSystemChar
);
569 // the last one we have to delete manually
571 SkipToken(); // the closing brace is evaluated "above"
573 // set the default font in the Document
574 if( bNewDoc
&& IsParserWorking() )
575 SetDefault( RTF_DEFF
, nDfltFont
);
578 void SvxRTFParser::ClearColorTbl()
580 maColorTable
.clear();
583 void SvxRTFParser::ClearAttrStack()
588 OUString
& SvxRTFParser::DelCharAtEnd( OUString
& rStr
, const sal_Unicode cDel
)
590 if( !rStr
.isEmpty() && ' ' == rStr
[ 0 ])
591 rStr
= comphelper::string::stripStart(rStr
, ' ');
592 if( !rStr
.isEmpty() && ' ' == rStr
[ rStr
.getLength()-1 ])
593 rStr
= comphelper::string::stripEnd(rStr
, ' ');
594 if( !rStr
.isEmpty() && cDel
== rStr
[ rStr
.getLength()-1 ])
595 rStr
= rStr
.copy( 0, rStr
.getLength()-1 );
600 const vcl::Font
& SvxRTFParser::GetFont( sal_uInt16 nId
)
602 SvxRTFFontTbl::const_iterator it
= m_FontTable
.find( nId
);
603 if (it
!= m_FontTable
.end())
607 const SvxFontItem
& rDfltFont
= static_cast<const SvxFontItem
&>(
608 pAttrPool
->GetDefaultItem( aPlainMap
.nFont
));
609 pDfltFont
->SetFamilyName( rDfltFont
.GetStyleName() );
610 pDfltFont
->SetFamily( rDfltFont
.GetFamily() );
614 SvxRTFItemStackType
* SvxRTFParser::GetAttrSet_()
616 SvxRTFItemStackType
* pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get();
617 std::unique_ptr
<SvxRTFItemStackType
> pNew
;
619 pNew
.reset(new SvxRTFItemStackType( *pCurrent
, *pInsPos
, false/*bCopyAttr*/ ));
621 pNew
.reset(new SvxRTFItemStackType( *pAttrPool
, aWhichMap
.data(),
623 pNew
->SetRTFDefaults( GetRTFDefaults() );
625 aAttrStack
.push_back( std::move(pNew
) );
627 return aAttrStack
.back().get();
631 void SvxRTFParser::ClearStyleAttr_( SvxRTFItemStackType
& rStkType
)
633 // check attributes to the attributes of the stylesheet or to
634 // the default attrs of the document
635 SfxItemSet
&rSet
= rStkType
.GetAttrSet();
636 const SfxItemPool
& rPool
= *rSet
.GetPool();
637 const SfxPoolItem
* pItem
;
638 SfxWhichIter
aIter( rSet
);
640 if( !IsChkStyleAttr() ||
641 !rStkType
.GetAttrSet().Count() ||
642 m_StyleTable
.count( rStkType
.nStyleNo
) == 0 )
644 for( sal_uInt16 nWhich
= aIter
.GetCurWhich(); nWhich
; nWhich
= aIter
.NextWhich() )
646 if (SfxItemPool::IsWhich(nWhich
) &&
647 SfxItemState::SET
== rSet
.GetItemState( nWhich
, false, &pItem
) &&
648 rPool
.GetDefaultItem( nWhich
) == *pItem
)
649 rSet
.ClearItem( nWhich
); // delete
654 // Delete all Attributes, which are already defined in the Style,
655 // from the current AttrSet.
656 auto const& pStyle
= m_StyleTable
.find(rStkType
.nStyleNo
)->second
;
657 SfxItemSet
&rStyleSet
= pStyle
->aAttrSet
;
658 const SfxPoolItem
* pSItem
;
659 for( sal_uInt16 nWhich
= aIter
.GetCurWhich(); nWhich
; nWhich
= aIter
.NextWhich() )
661 if( SfxItemState::SET
== rStyleSet
.GetItemState( nWhich
, true, &pSItem
))
663 if( SfxItemState::SET
== rSet
.GetItemState( nWhich
, false, &pItem
)
664 && *pItem
== *pSItem
)
665 rSet
.ClearItem( nWhich
); // delete
667 else if (SfxItemPool::IsWhich(nWhich
) &&
668 SfxItemState::SET
== rSet
.GetItemState( nWhich
, false, &pItem
) &&
669 rPool
.GetDefaultItem( nWhich
) == *pItem
)
670 rSet
.ClearItem( nWhich
); // delete
675 void SvxRTFParser::AttrGroupEnd() // process the current, delete from Stack
677 if( aAttrStack
.empty() )
680 std::unique_ptr
<SvxRTFItemStackType
> pOld
= std::move(aAttrStack
.back());
681 aAttrStack
.pop_back();
682 SvxRTFItemStackType
*pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get();
684 do { // middle check loop
685 sal_Int32 nOldSttNdIdx
= pOld
->pSttNd
->GetIdx();
686 if (!pOld
->m_pChildList
&&
687 ((!pOld
->aAttrSet
.Count() && !pOld
->nStyleNo
) ||
688 (nOldSttNdIdx
== pInsPos
->GetNodeIdx() &&
689 pOld
->nSttCnt
== pInsPos
->GetCntIdx() )))
690 break; // no attributes or Area
692 // set only the attributes that are different from the parent
693 if( pCurrent
&& pOld
->aAttrSet
.Count() )
695 SfxItemIter
aIter( pOld
->aAttrSet
);
696 const SfxPoolItem
* pItem
= aIter
.GetCurItem(), *pGet
;
699 if( SfxItemState::SET
== pCurrent
->aAttrSet
.GetItemState(
700 pItem
->Which(), false, &pGet
) &&
702 pOld
->aAttrSet
.ClearItem( pItem
->Which() );
704 pItem
= aIter
.NextItem();
707 if (!pOld
->aAttrSet
.Count() && !pOld
->m_pChildList
&&
712 // Set all attributes which have been defined from start until here
713 bool bCrsrBack
= !pInsPos
->GetCntIdx();
716 // at the beginning of a paragraph? Move back one position
717 sal_Int32 nNd
= pInsPos
->GetNodeIdx();
719 // if can not move backward then later don't move forward !
720 bCrsrBack
= nNd
!= pInsPos
->GetNodeIdx();
723 if( pOld
->pSttNd
->GetIdx() < pInsPos
->GetNodeIdx() ||
724 ( pOld
->pSttNd
->GetIdx() == pInsPos
->GetNodeIdx() &&
725 pOld
->nSttCnt
<= pInsPos
->GetCntIdx() ) )
729 // all pard attributes are only valid until the previous
731 if( nOldSttNdIdx
== pInsPos
->GetNodeIdx() )
736 // Now it gets complicated:
737 // - all character attributes sre keep the area
738 // - all paragraph attributes to get the area
739 // up to the previous paragraph
740 std::unique_ptr
<SvxRTFItemStackType
> pNew(
741 new SvxRTFItemStackType(*pOld
, *pInsPos
, true));
742 pNew
->aAttrSet
.SetParent( pOld
->aAttrSet
.GetParent() );
744 // Delete all paragraph attributes from pNew
745 for( sal_uInt16 n
= 0; n
< (sizeof(aPardMap
) / sizeof(sal_uInt16
)) &&
746 pNew
->aAttrSet
.Count(); ++n
)
747 if( reinterpret_cast<sal_uInt16
*>(&aPardMap
)[n
] )
748 pNew
->aAttrSet
.ClearItem( reinterpret_cast<sal_uInt16
*>(&aPardMap
)[n
] );
749 pNew
->SetRTFDefaults( GetRTFDefaults() );
752 if( pNew
->aAttrSet
.Count() == pOld
->aAttrSet
.Count() )
760 // Now span the real area of pNew from old
761 SetEndPrevPara( pOld
->pEndNd
, pOld
->nEndCnt
);
764 if( IsChkStyleAttr() )
766 ClearStyleAttr_( *pOld
);
767 ClearStyleAttr_( *pNew
); //#i10381#, methinks.
772 pCurrent
->Add(std::move(pOld
));
773 pCurrent
->Add(std::move(pNew
));
777 // Last off the stack, thus cache it until the next text was
778 // read. (Span no attributes!)
780 m_AttrSetList
.push_back(std::move(pOld
));
781 m_AttrSetList
.push_back(std::move(pNew
));
788 pOld
->pEndNd
= pInsPos
->MakeNodeIdx().release();
789 pOld
->nEndCnt
= pInsPos
->GetCntIdx();
793 If the parent (pCurrent) sets something e.g. , and the child (pOld)
794 unsets it and the style both are based on has it unset then
795 clearing the pOld by looking at the style is clearly a disaster
796 as the text ends up with pCurrents bold and not pOlds no bold, this
797 should be rethought out. For the moment its safest to just do
798 the clean if we have no parent, all we suffer is too many
799 redundant properties.
801 if (IsChkStyleAttr() && !pCurrent
)
802 ClearStyleAttr_( *pOld
);
806 pCurrent
->Add(std::move(pOld
));
807 // split up and create new entry, because it makes no sense
808 // to create a "so long" depend list. Bug 95010
809 if (bCrsrBack
&& 50 < pCurrent
->m_pChildList
->size())
811 // at the beginning of a paragraph? Move back one position
816 std::unique_ptr
<SvxRTFItemStackType
> pNew(new SvxRTFItemStackType(
817 *pCurrent
, *pInsPos
, true ));
818 pNew
->SetRTFDefaults( GetRTFDefaults() );
820 // Set all until here valid Attributes
822 pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get(); // can be changed after AttrGroupEnd!
823 pNew
->aAttrSet
.SetParent( pCurrent
? &pCurrent
->aAttrSet
: nullptr );
824 aAttrStack
.push_back( std::move(pNew
) );
828 // Last off the stack, thus cache it until the next text was
829 // read. (Span no attributes!)
830 m_AttrSetList
.push_back(std::move(pOld
));
834 // at the beginning of a paragraph? Move back one position
842 void SvxRTFParser::SetAllAttrOfStk() // end all Attr. and set it into doc
844 // repeat until all attributes will be taken from stack
845 while( !aAttrStack
.empty() )
848 for (size_t n
= m_AttrSetList
.size(); n
; )
850 auto const& pStkSet
= m_AttrSetList
[--n
];
851 SetAttrSet( *pStkSet
);
852 pStkSet
->DropChildList();
853 m_AttrSetList
.pop_back();
857 // sets all the attributes that are different from the current
858 void SvxRTFParser::SetAttrSet( SvxRTFItemStackType
&rSet
)
860 // Was DefTab never read? then set to default
862 SetDefault( RTF_DEFTAB
, 720 );
864 if (rSet
.m_pChildList
)
865 rSet
.Compress( *this );
866 if( rSet
.aAttrSet
.Count() || rSet
.nStyleNo
)
867 SetAttrInDoc( rSet
);
869 // then process all the children
870 if (rSet
.m_pChildList
)
871 for (size_t n
= 0; n
< rSet
.m_pChildList
->size(); ++n
)
872 SetAttrSet( *(*rSet
.m_pChildList
)[ n
] );
875 // Has no text been inserted yet? (SttPos from the top Stack entry!)
876 bool SvxRTFParser::IsAttrSttPos()
878 SvxRTFItemStackType
* pCurrent
= aAttrStack
.empty() ? nullptr : aAttrStack
.back().get();
879 return !pCurrent
|| (pCurrent
->pSttNd
->GetIdx() == pInsPos
->GetNodeIdx() &&
880 pCurrent
->nSttCnt
== pInsPos
->GetCntIdx());
884 void SvxRTFParser::SetAttrInDoc( SvxRTFItemStackType
& )
888 void SvxRTFParser::BuildWhichTable()
891 aWhichMap
.push_back( 0 );
893 // Building a Which-Map 'rWhichMap' from an array of
894 // 'pWhichIds' from Which-Ids. It has the long 'nWhichIds'.
895 // The Which-Map is not going to be deleted.
896 ::BuildWhichTable( aWhichMap
, reinterpret_cast<sal_uInt16
*>(&aPardMap
), sizeof(aPardMap
) / sizeof(sal_uInt16
) );
897 ::BuildWhichTable( aWhichMap
, reinterpret_cast<sal_uInt16
*>(&aPlainMap
), sizeof(aPlainMap
) / sizeof(sal_uInt16
) );
900 const SfxItemSet
& SvxRTFParser::GetRTFDefaults()
904 pRTFDefaults
.reset( new SfxItemSet( *pAttrPool
, aWhichMap
.data() ) );
906 if( 0 != ( nId
= aPardMap
.nScriptSpace
))
908 SvxScriptSpaceItem
aItem( false, nId
);
910 pAttrPool
->SetPoolDefaultItem( aItem
);
912 pRTFDefaults
->Put( aItem
);
915 return *pRTFDefaults
;
919 SvxRTFStyleType::SvxRTFStyleType( SfxItemPool
& rPool
, const sal_uInt16
* pWhichRange
)
920 : aAttrSet( rPool
, pWhichRange
)
922 nOutlineNo
= sal_uInt8(-1); // not set
927 SvxRTFItemStackType::SvxRTFItemStackType(
928 SfxItemPool
& rPool
, const sal_uInt16
* pWhichRange
,
929 const EditPosition
& rPos
)
930 : aAttrSet( rPool
, pWhichRange
)
933 pSttNd
= rPos
.MakeNodeIdx();
934 nSttCnt
= rPos
.GetCntIdx();
935 pEndNd
= pSttNd
.get();
939 SvxRTFItemStackType::SvxRTFItemStackType(
940 const SvxRTFItemStackType
& rCpy
,
941 const EditPosition
& rPos
,
942 bool const bCopyAttr
)
943 : aAttrSet( *rCpy
.aAttrSet
.GetPool(), rCpy
.aAttrSet
.GetRanges() )
944 , nStyleNo( rCpy
.nStyleNo
)
946 pSttNd
= rPos
.MakeNodeIdx();
947 nSttCnt
= rPos
.GetCntIdx();
948 pEndNd
= pSttNd
.get();
951 aAttrSet
.SetParent( &rCpy
.aAttrSet
);
953 aAttrSet
.Put( rCpy
.aAttrSet
);
956 /* ofz#13491 SvxRTFItemStackType dtor recursively
957 calls the dtor of its m_pChildList. The recurse
958 depth can grow sufficiently to trigger asan.
960 So breadth-first iterate through the nodes
961 and make a flat vector of them which can
962 be iterated through in order of most
963 distant from root first and release
964 their children linearly
966 void SvxRTFItemStackType::DropChildList()
968 if (!m_pChildList
|| m_pChildList
->empty())
971 std::vector
<SvxRTFItemStackType
*> bfs
;
972 std::queue
<SvxRTFItemStackType
*> aQueue
;
975 while (!aQueue
.empty())
977 auto* front
= aQueue
.front();
979 if (front
->m_pChildList
)
981 for (const auto& a
: *front
->m_pChildList
)
982 aQueue
.push(a
.get());
983 bfs
.push_back(front
);
987 for (auto it
= bfs
.rbegin(); it
!= bfs
.rend(); ++it
)
989 SvxRTFItemStackType
* pNode
= *it
;
990 pNode
->m_pChildList
.reset();
994 SvxRTFItemStackType::~SvxRTFItemStackType()
996 if( pSttNd
.get() != pEndNd
)
1000 void SvxRTFItemStackType::Add(std::unique_ptr
<SvxRTFItemStackType
> pIns
)
1003 m_pChildList
.reset( new SvxRTFItemStackList
);
1004 m_pChildList
->push_back(std::move(pIns
));
1007 void SvxRTFItemStackType::SetStartPos( const EditPosition
& rPos
)
1009 if (pSttNd
.get() != pEndNd
)
1011 pSttNd
= rPos
.MakeNodeIdx();
1012 pEndNd
= pSttNd
.get();
1013 nSttCnt
= rPos
.GetCntIdx();
1016 void SvxRTFItemStackType::Compress( const SvxRTFParser
& rParser
)
1018 ENSURE_OR_RETURN_VOID(m_pChildList
, "Compress: no ChildList" );
1019 ENSURE_OR_RETURN_VOID(!m_pChildList
->empty(), "Compress: ChildList empty");
1021 SvxRTFItemStackType
* pTmp
= (*m_pChildList
)[0].get();
1023 if( !pTmp
->aAttrSet
.Count() ||
1024 pSttNd
->GetIdx() != pTmp
->pSttNd
->GetIdx() ||
1025 nSttCnt
!= pTmp
->nSttCnt
)
1028 EditNodeIdx
* pLastNd
= pTmp
->pEndNd
;
1029 sal_Int32 nLastCnt
= pTmp
->nEndCnt
;
1031 SfxItemSet
aMrgSet( pTmp
->aAttrSet
);
1032 for (size_t n
= 1; n
< m_pChildList
->size(); ++n
)
1034 pTmp
= (*m_pChildList
)[n
].get();
1035 if (pTmp
->m_pChildList
)
1036 pTmp
->Compress( rParser
);
1039 ? (pLastNd
->GetIdx()+1 != pTmp
->pSttNd
->GetIdx() ||
1040 !rParser
.IsEndPara( pLastNd
, nLastCnt
) )
1041 : ( pTmp
->nSttCnt
!= nLastCnt
||
1042 pLastNd
->GetIdx() != pTmp
->pSttNd
->GetIdx() ))
1044 while (++n
< m_pChildList
->size())
1046 pTmp
= (*m_pChildList
)[n
].get();
1047 if (pTmp
->m_pChildList
)
1048 pTmp
->Compress( rParser
);
1055 // Search for all which are set over the whole area
1056 SfxItemIter
aIter( aMrgSet
);
1057 const SfxPoolItem
* pItem
;
1058 const SfxPoolItem
* pIterItem
= aIter
.GetCurItem();
1060 sal_uInt16 nWhich
= pIterItem
->Which();
1061 if( SfxItemState::SET
!= pTmp
->aAttrSet
.GetItemState( nWhich
,
1062 false, &pItem
) || *pItem
!= *pIterItem
)
1063 aMrgSet
.ClearItem( nWhich
);
1065 pIterItem
= aIter
.NextItem();
1068 if( !aMrgSet
.Count() )
1072 pLastNd
= pTmp
->pEndNd
;
1073 nLastCnt
= pTmp
->nEndCnt
;
1076 if( pEndNd
->GetIdx() != pLastNd
->GetIdx() || nEndCnt
!= nLastCnt
)
1080 aAttrSet
.Put( aMrgSet
);
1082 size_t n
= 0, nChildLen
= m_pChildList
->size();
1083 while (n
< nChildLen
)
1085 pTmp
= (*m_pChildList
)[n
].get();
1086 pTmp
->aAttrSet
.Differentiate( aMrgSet
);
1088 if (!pTmp
->m_pChildList
&& !pTmp
->aAttrSet
.Count() && !pTmp
->nStyleNo
)
1090 m_pChildList
->erase( m_pChildList
->begin() + n
);
1096 if (m_pChildList
->empty())
1098 m_pChildList
.reset();
1101 void SvxRTFItemStackType::SetRTFDefaults( const SfxItemSet
& rDefaults
)
1103 if( rDefaults
.Count() )
1105 SfxItemIter
aIter( rDefaults
);
1106 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1108 sal_uInt16 nWhich
= pItem
->Which();
1109 if( SfxItemState::SET
!= aAttrSet
.GetItemState( nWhich
, false ))
1110 aAttrSet
.Put(*pItem
);
1112 pItem
= aIter
.NextItem();
1118 RTFPlainAttrMapIds::RTFPlainAttrMapIds( const SfxItemPool
& rPool
)
1120 nCaseMap
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CASEMAP
, false );
1121 nBgColor
= rPool
.GetTrueWhich( SID_ATTR_BRUSH_CHAR
, false );
1122 nColor
= rPool
.GetTrueWhich( SID_ATTR_CHAR_COLOR
, false );
1123 nContour
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CONTOUR
, false );
1124 nCrossedOut
= rPool
.GetTrueWhich( SID_ATTR_CHAR_STRIKEOUT
, false );
1125 nEscapement
= rPool
.GetTrueWhich( SID_ATTR_CHAR_ESCAPEMENT
, false );
1126 nFont
= rPool
.GetTrueWhich( SID_ATTR_CHAR_FONT
, false );
1127 nFontHeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_FONTHEIGHT
, false );
1128 nKering
= rPool
.GetTrueWhich( SID_ATTR_CHAR_KERNING
, false );
1129 nLanguage
= rPool
.GetTrueWhich( SID_ATTR_CHAR_LANGUAGE
, false );
1130 nPosture
= rPool
.GetTrueWhich( SID_ATTR_CHAR_POSTURE
, false );
1131 nShadowed
= rPool
.GetTrueWhich( SID_ATTR_CHAR_SHADOWED
, false );
1132 nUnderline
= rPool
.GetTrueWhich( SID_ATTR_CHAR_UNDERLINE
, false );
1133 nOverline
= rPool
.GetTrueWhich( SID_ATTR_CHAR_OVERLINE
, false );
1134 nWeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_WEIGHT
, false );
1135 nWordlineMode
= rPool
.GetTrueWhich( SID_ATTR_CHAR_WORDLINEMODE
, false );
1136 nAutoKerning
= rPool
.GetTrueWhich( SID_ATTR_CHAR_AUTOKERN
, false );
1138 nCJKFont
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_FONT
, false );
1139 nCJKFontHeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT
, false );
1140 nCJKLanguage
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE
, false );
1141 nCJKPosture
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_POSTURE
, false );
1142 nCJKWeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT
, false );
1143 nCTLFont
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_FONT
, false );
1144 nCTLFontHeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT
, false );
1145 nCTLLanguage
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE
, false );
1146 nCTLPosture
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_POSTURE
, false );
1147 nCTLWeight
= rPool
.GetTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT
, false );
1148 nEmphasis
= rPool
.GetTrueWhich( SID_ATTR_CHAR_EMPHASISMARK
, false );
1149 nTwoLines
= rPool
.GetTrueWhich( SID_ATTR_CHAR_TWO_LINES
, false );
1150 nCharScaleX
= rPool
.GetTrueWhich( SID_ATTR_CHAR_SCALEWIDTH
, false );
1151 nHorzVert
= rPool
.GetTrueWhich( SID_ATTR_CHAR_ROTATED
, false );
1152 nRelief
= rPool
.GetTrueWhich( SID_ATTR_CHAR_RELIEF
, false );
1153 nHidden
= rPool
.GetTrueWhich( SID_ATTR_CHAR_HIDDEN
, false );
1156 RTFPardAttrMapIds ::RTFPardAttrMapIds ( const SfxItemPool
& rPool
)
1158 nLinespacing
= rPool
.GetTrueWhich( SID_ATTR_PARA_LINESPACE
, false );
1159 nAdjust
= rPool
.GetTrueWhich( SID_ATTR_PARA_ADJUST
, false );
1160 nTabStop
= rPool
.GetTrueWhich( SID_ATTR_TABSTOP
, false );
1161 nHyphenzone
= rPool
.GetTrueWhich( SID_ATTR_PARA_HYPHENZONE
, false );
1162 nLRSpace
= rPool
.GetTrueWhich( SID_ATTR_LRSPACE
, false );
1163 nULSpace
= rPool
.GetTrueWhich( SID_ATTR_ULSPACE
, false );
1164 nBrush
= rPool
.GetTrueWhich( SID_ATTR_BRUSH
, false );
1165 nBox
= rPool
.GetTrueWhich( SID_ATTR_BORDER_OUTER
, false );
1166 nShadow
= rPool
.GetTrueWhich( SID_ATTR_BORDER_SHADOW
, false );
1167 nOutlineLvl
= rPool
.GetTrueWhich( SID_ATTR_PARA_OUTLLEVEL
, false );
1168 nSplit
= rPool
.GetTrueWhich( SID_ATTR_PARA_SPLIT
, false );
1169 nKeep
= rPool
.GetTrueWhich( SID_ATTR_PARA_KEEP
, false );
1170 nFontAlign
= rPool
.GetTrueWhich( SID_PARA_VERTALIGN
, false );
1171 nScriptSpace
= rPool
.GetTrueWhich( SID_ATTR_PARA_SCRIPTSPACE
, false );
1172 nHangPunct
= rPool
.GetTrueWhich( SID_ATTR_PARA_HANGPUNCTUATION
, false );
1173 nForbRule
= rPool
.GetTrueWhich( SID_ATTR_PARA_FORBIDDEN_RULES
, false );
1174 nDirection
= rPool
.GetTrueWhich( SID_ATTR_FRAMEDIRECTION
, false );
1177 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */