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 .
20 #include <com/sun/star/text/HoriOrientation.hpp>
21 #include <com/sun/star/text/VertOrientation.hpp>
22 #include <rtl/uri.hxx>
24 #include <svl/urihelper.hxx>
25 #include <vcl/svapp.hxx>
26 #include <editeng/adjustitem.hxx>
27 #include <editeng/ulspitem.hxx>
28 #include <editeng/formatbreakitem.hxx>
29 #include <svtools/htmltokn.h>
30 #include <svtools/htmlkywd.hxx>
31 #include <sfx2/linkmgr.hxx>
32 #include <osl/diagnose.h>
34 #include <hintids.hxx>
35 #include <fmthdft.hxx>
36 #include <fmtcntnt.hxx>
37 #include <fmtclds.hxx>
38 #include <fmtanchr.hxx>
39 #include <fmtpdsc.hxx>
44 #include <shellio.hxx>
45 #include <section.hxx>
46 #include <poolfmt.hxx>
47 #include <pagedesc.hxx>
48 #include <swtable.hxx>
53 using namespace ::com::sun::star
;
55 void SwHTMLParser::NewDivision( HtmlTokenId nToken
)
58 OUString aStyle
, aLang
, aDir
;
60 SvxAdjust eAdjust
= HtmlTokenId::CENTER_ON
==nToken
? SvxAdjust::Center
63 bool bHeader
=false, bFooter
=false;
64 const HTMLOptions
& rHTMLOptions
= GetOptions();
65 for (size_t i
= rHTMLOptions
.size(); i
; )
67 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
68 switch( rOption
.GetToken() )
70 case HtmlOptionId::ID
:
71 aId
= rOption
.GetString();
73 case HtmlOptionId::ALIGN
:
74 if( HtmlTokenId::DIVISION_ON
==nToken
)
75 eAdjust
= rOption
.GetEnum( aHTMLPAlignTable
, eAdjust
);
77 case HtmlOptionId::STYLE
:
78 aStyle
= rOption
.GetString();
80 case HtmlOptionId::CLASS
:
81 aClass
= rOption
.GetString();
83 case HtmlOptionId::LANG
:
84 aLang
= rOption
.GetString();
86 case HtmlOptionId::DIR:
87 aDir
= rOption
.GetString();
89 case HtmlOptionId::HREF
:
90 aHRef
= rOption
.GetString();
92 case HtmlOptionId::TITLE
:
94 const OUString
& rType
= rOption
.GetString();
95 if( rType
.equalsIgnoreAsciiCase("header") )
97 else if( rType
.equalsIgnoreAsciiCase("footer") )
105 bool bAppended
= false;
106 if( m_pPam
->GetPoint()->GetContentIndex() )
108 AppendTextNode( bHeader
||bFooter
||!aId
.isEmpty()|| !aHRef
.isEmpty() ? AM_NORMAL
113 std::unique_ptr
<HTMLAttrContext
> xCntxt(new HTMLAttrContext(nToken
));
115 bool bStyleParsed
= false, bPositioned
= false;
116 SfxItemSet
aItemSet( m_xDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
117 SvxCSS1PropertyInfo aPropInfo
;
118 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
120 bStyleParsed
= ParseStyleOptions( aStyle
, aId
, aClass
,
121 aItemSet
, aPropInfo
, &aLang
, &aDir
);
124 if ( aPropInfo
.m_nColumnCount
>= 2 )
127 NewMultiCol( aPropInfo
.m_nColumnCount
);
130 bPositioned
= HtmlTokenId::DIVISION_ON
== nToken
&& !aClass
.isEmpty() &&
131 CreateContainer(aClass
, aItemSet
, aPropInfo
,
135 if (aPropInfo
.m_bVisible
&& m_aContexts
.size())
137 const std::unique_ptr
<HTMLAttrContext
>& pParent
138 = m_aContexts
[m_aContexts
.size() - 1];
139 if (!pParent
->IsVisible())
141 // If the parent context is hidden, we are not visible, either.
142 aPropInfo
.m_bVisible
= false;
145 bPositioned
= DoPositioning(aItemSet
, aPropInfo
, xCntxt
.get());
150 if (!bPositioned
&& (bHeader
|| bFooter
) && IsNewDoc() && !m_bReadingHeaderOrFooter
)
152 m_bReadingHeaderOrFooter
= true;
153 xCntxt
->SetHeaderOrFooter(true);
155 SwPageDesc
*pPageDesc
= m_pCSS1Parser
->GetMasterPageDesc();
156 SwFrameFormat
& rPageFormat
= pPageDesc
->GetMaster();
158 SwFrameFormat
*pHdFtFormat
;
160 HtmlContextFlags nFlags
= HtmlContextFlags::MultiColMask
;
163 pHdFtFormat
= const_cast<SwFrameFormat
*>(rPageFormat
.GetHeader().GetHeaderFormat());
166 // still no header, then create one
167 rPageFormat
.SetFormatAttr( SwFormatHeader( true ));
168 pHdFtFormat
= const_cast<SwFrameFormat
*>(rPageFormat
.GetHeader().GetHeaderFormat());
171 nFlags
|= HtmlContextFlags::HeaderDist
;
175 pHdFtFormat
= const_cast<SwFrameFormat
*>(rPageFormat
.GetFooter().GetFooterFormat());
178 // still no footer, then create one
179 rPageFormat
.SetFormatAttr( SwFormatFooter( true ));
180 pHdFtFormat
= const_cast<SwFrameFormat
*>(rPageFormat
.GetFooter().GetFooterFormat());
183 nFlags
|= HtmlContextFlags::FooterDist
;
186 const SwFormatContent
& rFlyContent
= pHdFtFormat
->GetContent();
187 const SwNodeIndex
& rContentStIdx
= *rFlyContent
.GetContentIdx();
191 // Our own html export only exports one "header" at most (and one "footer")
193 // Create a new node at the beginning of the section if a duplicate arises
194 // and hide the original header/footers content by putting it into a hidden
195 // document-level section
196 SwNodeIndex
aSttIdx( rContentStIdx
, 1 );
197 m_xDoc
->GetNodes().MakeTextNode( aSttIdx
.GetNode(),
198 m_pCSS1Parser
->GetTextCollFromPool(RES_POOLCOLL_TEXT
));
200 // delete the current content of the section
201 SwPaM
aDelPam( aSttIdx
);
204 const SwStartNode
*pStNd
=
205 static_cast<const SwStartNode
*>( &rContentStIdx
.GetNode() );
206 aDelPam
.GetPoint()->Assign( pStNd
->EndOfSectionIndex() );
208 SwSectionData
aSection(SectionType::Content
, m_xDoc
->GetUniqueSectionName());
209 if (SwSection
* pOldContent
= m_xDoc
->InsertSwSection(aDelPam
, aSection
, nullptr, nullptr, false))
210 pOldContent
->SetHidden(true);
213 for( size_t i
=0; i
< m_xDoc
->GetPageDescCnt(); i
++ )
215 if( RES_POOLPAGE_HTML
== m_xDoc
->GetPageDesc(i
).GetPoolFormatId() )
217 m_xDoc
->ChgPageDesc( i
, *pPageDesc
);
223 SwPosition
aNewPos( rContentStIdx
, SwNodeOffset(1) );
224 SaveDocContext(xCntxt
.get(), nFlags
, &aNewPos
);
226 else if( !bPositioned
&& aId
.getLength() > 9 &&
227 (aId
[0] == 's' || aId
[0] == 'S' ) &&
228 (aId
[1] == 'd' || aId
[1] == 'D' ) )
230 bool bEndNote
= false, bFootNote
= false;
231 if( aId
.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote
) )
233 else if( aId
.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote
) )
235 if( bFootNote
|| bEndNote
)
237 SwNodeIndex
*pStartNdIdx
= GetFootEndNoteSection( aId
);
240 SwContentNode
*pCNd
=
241 m_xDoc
->GetNodes()[pStartNdIdx
->GetIndex()+1]->GetContentNode();
242 SwNodeIndex
aTmpSwNodeIndex(*pCNd
);
243 SwPosition
aNewPos( aTmpSwNodeIndex
, pCNd
, 0 );
244 SaveDocContext(xCntxt
.get(), HtmlContextFlags::MultiColMask
, &aNewPos
);
246 aPropInfo
.m_aId
.clear();
251 // We only insert sections into frames if the section is linked.
252 if( (!aId
.isEmpty() && !bPositioned
) || !aHRef
.isEmpty() )
254 // Insert section (has to be done before setting of attributes,
255 // because the section is inserted before the PaM position.
257 // If we are in the first node of a section, we insert the section
258 // before the current section and not in the current section.
259 // Therefore we have to add a node and delete it again!
262 SwNodeIndex
aPrvNdIdx( m_pPam
->GetPoint()->GetNode(), -1 );
263 if (aPrvNdIdx
.GetNode().IsSectionNode())
269 std::unique_ptr
<std::deque
<std::unique_ptr
<HTMLAttr
>>> pPostIts(bAppended
? nullptr : new std::deque
<std::unique_ptr
<HTMLAttr
>>);
270 SetAttr( true, true, pPostIts
.get() );
272 // make name of section unique
273 const OUString
aName( m_xDoc
->GetUniqueSectionName( !aId
.isEmpty() ? &aId
: nullptr ) );
275 if( !aHRef
.isEmpty() )
277 sal_Unicode cDelim
= 255U;
278 sal_Int32 nPos
= aHRef
.lastIndexOf( cDelim
);
279 sal_Int32 nPos2
= -1;
282 nPos2
= aHRef
.lastIndexOf( cDelim
, nPos
);
284 std::swap( nPos
, nPos2
);
289 aURL
= URIHelper::SmartRel2Abs(INetURLObject( m_sBaseURL
), aHRef
, Link
<OUString
*, bool>(), false);
293 aURL
= URIHelper::SmartRel2Abs(INetURLObject( m_sBaseURL
), aHRef
.copy( 0, nPos
), Link
<OUString
*, bool>(), false )
294 + OUStringChar(sfx2::cTokenSeparator
);
297 aURL
+= aHRef
.subView( nPos
+1 );
301 aURL
+= aHRef
.subView( nPos
+1, nPos2
- (nPos
+1) )
302 + OUStringChar(sfx2::cTokenSeparator
)
303 + rtl::Uri::decode( aHRef
.copy( nPos2
+1 ),
304 rtl_UriDecodeWithCharset
,
305 RTL_TEXTENCODING_ISO_8859_1
);
311 SwSectionData
aSection( (!aHRef
.isEmpty()) ? SectionType::FileLink
312 : SectionType::Content
, aName
);
313 if( !aHRef
.isEmpty() )
315 aSection
.SetLinkFileName( aHRef
);
316 aSection
.SetProtectFlag(true);
319 SfxItemSetFixed
<RES_FRMATR_BEGIN
, RES_FRMATR_END
-1> aFrameItemSet( m_xDoc
->GetAttrPool() );
321 Reader::ResetFrameFormatAttrs(aFrameItemSet
);
323 if( const SvxBrushItem
* pItem
= aItemSet
.GetItemIfSet( RES_BACKGROUND
, false ) )
325 aFrameItemSet
.Put( *pItem
);
326 aItemSet
.ClearItem( RES_BACKGROUND
);
328 if( const SvxFrameDirectionItem
* pItem
= aItemSet
.GetItemIfSet( RES_FRAMEDIR
, false ) )
330 aFrameItemSet
.Put( *pItem
);
331 aItemSet
.ClearItem( RES_FRAMEDIR
);
334 m_xDoc
->InsertSwSection( *m_pPam
, aSection
, nullptr, &aFrameItemSet
, false );
336 // maybe jump to section
337 if( JumpToMarks::Region
== m_eJumpTo
&& aName
== m_sJmpMark
)
339 m_bChkJumpMark
= true;
340 m_eJumpTo
= JumpToMarks::NONE
;
343 SwTextNode
* pOldTextNd
=
344 bAppended
? nullptr : m_pPam
->GetPoint()->GetNode().GetTextNode();
346 m_pPam
->Move( fnMoveBackward
);
348 // move PageDesc and SwFormatBreak attribute from current node into
349 // (first) node of the section
351 MovePageDescAttrs( pOldTextNd
, m_pPam
->GetPoint()->GetNodeIndex(),
356 // move still existing PostIts in the first paragraph of the table
357 InsertAttrs( std::move(*pPostIts
) );
361 xCntxt
->SetSpansSection( true );
363 // don't insert Bookmarks with same name as sections
364 if( !aPropInfo
.m_aId
.isEmpty() && aPropInfo
.m_aId
==aName
)
365 aPropInfo
.m_aId
.clear();
369 xCntxt
->SetAppendMode( AM_NOSPACE
);
372 if( SvxAdjust::End
!= eAdjust
)
374 InsertAttr(&m_xAttrTab
->pAdjust
, SvxAdjustItem(eAdjust
, RES_PARATR_ADJUST
), xCntxt
.get());
379 InsertAttrs( aItemSet
, aPropInfo
, xCntxt
.get(), true );
381 xCntxt
->SetVisible(aPropInfo
.m_bVisible
);
385 void SwHTMLParser::EndDivision()
387 // search for the stack entry of the token (because we still have the div stack
388 // we don't make a difference between DIV and CENTER)
389 std::unique_ptr
<HTMLAttrContext
> xCntxt
;
390 auto nPos
= m_aContexts
.size();
391 while (!xCntxt
&& nPos
>m_nContextStMin
)
393 switch( m_aContexts
[--nPos
]->GetToken() )
395 case HtmlTokenId::CENTER_ON
:
396 case HtmlTokenId::DIVISION_ON
:
397 xCntxt
= std::move(m_aContexts
[nPos
]);
398 m_aContexts
.erase( m_aContexts
.begin() + nPos
);
407 EndContext(xCntxt
.get());
408 SetAttr(); // set paragraph attributes really fast because of JavaScript
409 if (xCntxt
->IsHeaderOrFooter())
410 m_bReadingHeaderOrFooter
= false;
414 void SwHTMLParser::FixHeaderFooterDistance( bool bHeader
,
415 const SwPosition
*pOldPos
)
417 SwPageDesc
*pPageDesc
= m_pCSS1Parser
->GetMasterPageDesc();
418 SwFrameFormat
& rPageFormat
= pPageDesc
->GetMaster();
420 SwFrameFormat
*pHdFtFormat
=
421 bHeader
? const_cast<SwFrameFormat
*>(rPageFormat
.GetHeader().GetHeaderFormat())
422 : const_cast<SwFrameFormat
*>(rPageFormat
.GetFooter().GetFooterFormat());
423 OSL_ENSURE( pHdFtFormat
, "No header or footer" );
425 const SwFormatContent
& rFlyContent
= pHdFtFormat
->GetContent();
426 const SwNodeIndex
& rContentStIdx
= *rFlyContent
.GetContentIdx();
428 SwNodeOffset nPrvNxtIdx
;
431 nPrvNxtIdx
= rContentStIdx
.GetNode().EndOfSectionIndex()-1;
435 nPrvNxtIdx
= pOldPos
->GetNodeIndex() - 1;
438 sal_uInt16 nSpace
= 0;
439 SwTextNode
*pTextNode
= m_xDoc
->GetNodes()[nPrvNxtIdx
]->GetTextNode();
442 const SvxULSpaceItem
& rULSpace
=
443 pTextNode
->SwContentNode::GetAttr( RES_UL_SPACE
);
445 // The bottom paragraph padding becomes the padding
446 // to header or footer
447 nSpace
= rULSpace
.GetLower();
449 // and afterwards set to a valid value
450 const SvxULSpaceItem
& rCollULSpace
=
451 pTextNode
->GetAnyFormatColl().GetULSpace();
452 if( rCollULSpace
.GetUpper() == rULSpace
.GetUpper() )
453 pTextNode
->ResetAttr( RES_UL_SPACE
);
456 SvxULSpaceItem( rULSpace
.GetUpper(),
457 rCollULSpace
.GetLower(), RES_UL_SPACE
) );
462 nPrvNxtIdx
= pOldPos
->GetNodeIndex();
466 nPrvNxtIdx
= rContentStIdx
.GetIndex() + 1;
469 pTextNode
= m_xDoc
->GetNodes()[nPrvNxtIdx
]
473 const SvxULSpaceItem
& rULSpace
=
474 pTextNode
->SwContentNode::GetAttr( RES_UL_SPACE
);
476 // The top paragraph padding becomes the padding
477 // to headline or footer if it is greater than the
478 // bottom padding of the paragraph beforehand
479 if( rULSpace
.GetUpper() > nSpace
)
480 nSpace
= rULSpace
.GetUpper();
482 // and afterwards set to a valid value
483 const SvxULSpaceItem
& rCollULSpace
=
484 pTextNode
->GetAnyFormatColl().GetULSpace();
485 if( rCollULSpace
.GetLower() == rULSpace
.GetLower() )
486 pTextNode
->ResetAttr( RES_UL_SPACE
);
489 SvxULSpaceItem( rCollULSpace
.GetUpper(),
490 rULSpace
.GetLower(), RES_UL_SPACE
) );
493 SvxULSpaceItem
aULSpace( RES_UL_SPACE
);
495 aULSpace
.SetLower( nSpace
);
497 aULSpace
.SetUpper( nSpace
);
499 pHdFtFormat
->SetFormatAttr( aULSpace
);
502 bool SwHTMLParser::EndSection( bool bLFStripped
)
504 SwEndNode
*pEndNd
= m_xDoc
->GetNodes()[m_pPam
->GetPoint()->GetNodeIndex()+1]
506 if( pEndNd
&& pEndNd
->StartOfSectionNode()->IsSectionNode() )
511 m_pPam
->Move( fnMoveForward
);
515 OSL_ENSURE( false, "Wrong PaM position at end of section" );
520 bool SwHTMLParser::EndSections( bool bLFStripped
)
522 bool bSectionClosed
= false;
523 auto nPos
= m_aContexts
.size();
524 while( nPos
>m_nContextStMin
)
526 HTMLAttrContext
*pCntxt
= m_aContexts
[--nPos
].get();
527 if( pCntxt
->GetSpansSection() && EndSection( bLFStripped
) )
529 bSectionClosed
= true;
530 pCntxt
->SetSpansSection( false );
535 return bSectionClosed
;
538 void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss
)
541 OUString aStyle
, aClass
, aLang
, aDir
;
542 tools::Long nWidth
= 100;
543 sal_uInt16 nCols
= columnsFromCss
, nGutter
= 10;
544 bool bPercentWidth
= true;
546 const HTMLOptions
& rHTMLOptions
= GetOptions();
547 for (size_t i
= rHTMLOptions
.size(); i
; )
549 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
550 switch( rOption
.GetToken() )
552 case HtmlOptionId::ID
:
553 aId
= rOption
.GetString();
555 case HtmlOptionId::STYLE
:
556 aStyle
= rOption
.GetString();
558 case HtmlOptionId::CLASS
:
559 aClass
= rOption
.GetString();
561 case HtmlOptionId::LANG
:
562 aLang
= rOption
.GetString();
564 case HtmlOptionId::DIR:
565 aDir
= rOption
.GetString();
567 case HtmlOptionId::COLS
:
568 nCols
= o3tl::narrowing
<sal_uInt16
>(rOption
.GetNumber());
570 case HtmlOptionId::WIDTH
:
571 nWidth
= rOption
.GetNumber();
572 bPercentWidth
= (rOption
.GetString().indexOf('%') != -1);
573 if( bPercentWidth
&& nWidth
>100 )
576 case HtmlOptionId::GUTTER
:
577 nGutter
= o3tl::narrowing
<sal_uInt16
>(rOption
.GetNumber());
583 std::unique_ptr
<HTMLAttrContext
> xCntxt(new HTMLAttrContext(HtmlTokenId::MULTICOL_ON
));
585 //.is the multicol element contained in a container? That may be the
586 // case for 5.0 documents.
587 bool bInCntnr
= false;
588 auto i
= m_aContexts
.size();
589 while( !bInCntnr
&& i
> m_nContextStMin
)
590 bInCntnr
= nullptr != m_aContexts
[--i
]->GetFrameItemSet();
592 // Parse style sheets, but don't position anything by now.
593 bool bStyleParsed
= false;
594 SfxItemSet
aItemSet( m_xDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
595 SvxCSS1PropertyInfo aPropInfo
;
596 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
597 bStyleParsed
= ParseStyleOptions( aStyle
, aId
, aClass
,
598 aItemSet
, aPropInfo
, &aLang
, &aDir
);
601 sal_uInt8 nPercentWidth
= bPercentWidth
? static_cast<sal_uInt8
>(nWidth
) : 0;
602 SwTwips nTwipWidth
= 0;
603 if( !bPercentWidth
&& nWidth
)
605 nTwipWidth
= o3tl::convert(nWidth
, o3tl::Length::px
, o3tl::Length::twip
);
608 if( !nPercentWidth
&& nTwipWidth
< MINFLY
)
612 bool bPositioned
= false;
613 if( bInCntnr
|| SwCSS1Parser::MayBePositioned( aPropInfo
, true ) )
615 SfxItemSetFixed
<RES_FRMATR_BEGIN
, RES_FRMATR_END
-1> aFrameItemSet( m_xDoc
->GetAttrPool() );
617 Reader::ResetFrameFormatAttrs(aFrameItemSet
);
619 SetAnchorAndAdjustment( text::VertOrientation::NONE
, text::HoriOrientation::NONE
, aPropInfo
,
622 // The width is either the WIDTH attribute's value or contained
623 // in some style option.
624 SetVarSize( aPropInfo
, aFrameItemSet
, nTwipWidth
, nPercentWidth
);
626 SetSpace( Size(0,0), aItemSet
, aPropInfo
, aFrameItemSet
);
628 // Set some other frame attributes. If the background is set, its
629 // it will be cleared here. That for, it won't be set at the section,
631 SetFrameFormatAttrs( aItemSet
,
632 HtmlFrameFormatFlags::Box
|HtmlFrameFormatFlags::Background
|HtmlFrameFormatFlags::Padding
|HtmlFrameFormatFlags::Direction
,
635 // Insert fly frame. If the are columns, the fly frame's name is not
636 // the sections name but a generated one.
641 aPropInfo
.m_aId
.clear();
644 InsertFlyFrame(aFrameItemSet
, xCntxt
.get(), aFlyName
);
646 xCntxt
->SetPopStack( true );
650 bool bAppended
= false;
653 if( m_pPam
->GetPoint()->GetContentIndex() )
655 AppendTextNode( AM_SPACE
);
664 // If there are less than 2 columns, no section is inserted.
669 // If the pam is at the start of a section, an additional text
670 // node must be inserted. Otherwise, the new section will be
671 // inserted in front of the old one.
672 SwNodeIndex
aPrvNdIdx( m_pPam
->GetPoint()->GetNode(), -1 );
673 if (aPrvNdIdx
.GetNode().IsSectionNode())
679 std::unique_ptr
<std::deque
<std::unique_ptr
<HTMLAttr
>>> pPostIts(bAppended
? nullptr : new std::deque
<std::unique_ptr
<HTMLAttr
>>);
680 SetAttr( true, true, pPostIts
.get() );
682 // Make section name unique.
683 OUString
aName( m_xDoc
->GetUniqueSectionName( !aId
.isEmpty() ? &aId
: nullptr ) );
684 SwSectionData
aSection( SectionType::Content
, aName
);
686 SfxItemSetFixed
<RES_FRMATR_BEGIN
, RES_FRMATR_END
-1> aFrameItemSet( m_xDoc
->GetAttrPool() );
688 Reader::ResetFrameFormatAttrs(aFrameItemSet
);
692 nGutter
= o3tl::convert(nGutter
, o3tl::Length::px
, o3tl::Length::twip
);
695 SwFormatCol aFormatCol
;
697 aFormatCol
.Init( nCols
, nGutter
, USHRT_MAX
);
698 aFrameItemSet
.Put( aFormatCol
);
700 if( const SvxBrushItem
* pItem
= aItemSet
.GetItemIfSet( RES_BACKGROUND
, false) )
702 aFrameItemSet
.Put( *pItem
);
703 aItemSet
.ClearItem( RES_BACKGROUND
);
705 if( const SvxFrameDirectionItem
* pItem
= aItemSet
.GetItemIfSet( RES_FRAMEDIR
, false ) )
707 aFrameItemSet
.Put( *pItem
);
708 aItemSet
.ClearItem( RES_FRAMEDIR
);
710 m_xDoc
->InsertSwSection( *m_pPam
, aSection
, nullptr, &aFrameItemSet
, false );
712 // Jump to section, if this is requested.
713 if( JumpToMarks::Region
== m_eJumpTo
&& aName
== m_sJmpMark
)
715 m_bChkJumpMark
= true;
716 m_eJumpTo
= JumpToMarks::NONE
;
719 SwTextNode
* pOldTextNd
=
720 bAppended
? nullptr : m_pPam
->GetPoint()->GetNode().GetTextNode();
722 m_pPam
->Move( fnMoveBackward
);
724 // Move PageDesc and SwFormatBreak attributes of the current node
725 // to the section's first node.
727 MovePageDescAttrs( pOldTextNd
, m_pPam
->GetPoint()->GetNodeIndex(),
732 // Move pending PostIts into the section.
733 InsertAttrs( std::move(*pPostIts
) );
737 xCntxt
->SetSpansSection( true );
739 // Insert a bookmark if its name differs from the section's name only.
740 if( !aPropInfo
.m_aId
.isEmpty() && aPropInfo
.m_aId
==aName
)
741 aPropInfo
.m_aId
.clear();
744 // Additional attributes must be set as hard ones.
746 InsertAttrs( aItemSet
, aPropInfo
, xCntxt
.get(), true );
751 void SwHTMLParser::InsertFlyFrame( const SfxItemSet
& rItemSet
,
752 HTMLAttrContext
*pCntxt
,
753 const OUString
& rName
)
755 RndStdIds eAnchorId
=
756 rItemSet
.Get( RES_ANCHOR
).GetAnchorId();
759 SwFlyFrameFormat
* pFlyFormat
= m_xDoc
->MakeFlySection( eAnchorId
, m_pPam
->GetPoint(),
761 if( !rName
.isEmpty() )
762 pFlyFormat
->SetFormatName( rName
);
764 RegisterFlyFrame( pFlyFormat
);
766 const SwFormatContent
& rFlyContent
= pFlyFormat
->GetContent();
767 const SwNodeIndex
& rFlyCntIdx
= *rFlyContent
.GetContentIdx();
769 SwPosition
aNewPos( rFlyCntIdx
, SwNodeOffset(1) );
770 const HtmlContextFlags nFlags
= HtmlContextFlags::ProtectStack
|HtmlContextFlags::StripPara
;
771 SaveDocContext( pCntxt
, nFlags
, &aNewPos
);
774 void SwHTMLParser::MovePageDescAttrs( SwNode
*pSrcNd
,
775 SwNodeOffset nDestIdx
,
778 SwContentNode
* pDestContentNd
=
779 m_xDoc
->GetNodes()[nDestIdx
]->GetContentNode();
781 OSL_ENSURE( pDestContentNd
, "Why is the target not a Content-Node?" );
783 if( pSrcNd
->IsContentNode() )
785 SwContentNode
* pSrcContentNd
= pSrcNd
->GetContentNode();
787 const SwFormatPageDesc
* pFormatPageDesc
=
788 pSrcContentNd
->GetSwAttrSet().GetItemIfSet( RES_PAGEDESC
, false );
789 if( pFormatPageDesc
&& pFormatPageDesc
->GetPageDesc() )
791 pDestContentNd
->SetAttr( *pFormatPageDesc
);
792 pSrcContentNd
->ResetAttr( RES_PAGEDESC
);
794 if( const SvxFormatBreakItem
* pItem
= pSrcContentNd
->GetSwAttrSet()
795 .GetItemIfSet( RES_BREAK
, false ) )
797 switch( pItem
->GetBreak() )
799 case SvxBreak::PageBefore
:
800 case SvxBreak::PageAfter
:
801 case SvxBreak::PageBoth
:
803 pDestContentNd
->SetAttr( *pItem
);
804 pSrcContentNd
->ResetAttr( RES_BREAK
);
811 else if( pSrcNd
->IsTableNode() )
813 SwFrameFormat
*pFrameFormat
= pSrcNd
->GetTableNode()->GetTable().GetFrameFormat();
815 if( const SwFormatPageDesc
* pItem
= pFrameFormat
->GetAttrSet().
816 GetItemIfSet( RES_PAGEDESC
, false ) )
819 pDestContentNd
->SetAttr(*pItem
);
820 pFrameFormat
->ResetFormatAttr( RES_PAGEDESC
);
825 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */