build fix
[LibreOffice.git] / sw / source / filter / html / htmlsect.cxx
blobcbcfce1458ca500a39b75d3b3a878454a8dafd57
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <rtl/uri.hxx>
22 #include <svl/urihelper.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/wrkwin.hxx>
25 #include <editeng/adjustitem.hxx>
26 #include <editeng/ulspitem.hxx>
27 #include <editeng/formatbreakitem.hxx>
28 #include <svtools/htmltokn.h>
29 #include <svtools/htmlkywd.hxx>
30 #include <sfx2/linkmgr.hxx>
32 #include "hintids.hxx"
33 #include <fmtornt.hxx>
34 #include <fmthdft.hxx>
35 #include <fmtcntnt.hxx>
36 #include <fmtfsize.hxx>
37 #include <fmtclds.hxx>
38 #include <fmtanchr.hxx>
39 #include <fmtpdsc.hxx>
40 #include <fmtsrnd.hxx>
41 #include <fmtflcnt.hxx>
42 #include "frmatr.hxx"
43 #include "doc.hxx"
44 #include "pam.hxx"
45 #include "ndtxt.hxx"
46 #include "shellio.hxx"
47 #include "section.hxx"
48 #include "poolfmt.hxx"
49 #include "pagedesc.hxx"
50 #include "swtable.hxx"
51 #include "viewsh.hxx"
52 #include "swcss1.hxx"
53 #include "swhtml.hxx"
56 using namespace ::com::sun::star;
58 void SwHTMLParser::NewDivision( int nToken )
60 OUString aId, aHRef;
61 OUString aStyle, aLang, aDir;
62 OUString aClass;
63 SvxAdjust eAdjust = HTML_CENTER_ON==nToken ? SVX_ADJUST_CENTER
64 : SVX_ADJUST_END;
66 bool bHeader=false, bFooter=false;
67 const HTMLOptions& rHTMLOptions = GetOptions();
68 for (size_t i = rHTMLOptions.size(); i; )
70 const HTMLOption& rOption = rHTMLOptions[--i];
71 switch( rOption.GetToken() )
73 case HTML_O_ID:
74 aId = rOption.GetString();
75 break;
76 case HTML_O_ALIGN:
77 if( HTML_DIVISION_ON==nToken )
78 eAdjust = (SvxAdjust)rOption.GetEnum( aHTMLPAlignTable,
79 static_cast< sal_uInt16 >(eAdjust) );
80 break;
81 case HTML_O_STYLE:
82 aStyle = rOption.GetString();
83 break;
84 case HTML_O_CLASS:
85 aClass = rOption.GetString();
86 break;
87 case HTML_O_LANG:
88 aLang = rOption.GetString();
89 break;
90 case HTML_O_DIR:
91 aDir = rOption.GetString();
92 break;
93 case HTML_O_HREF:
94 aHRef = rOption.GetString();
95 break;
96 case HTML_O_TITLE:
98 const OUString& rType = rOption.GetString();
99 if( rType.equalsIgnoreAsciiCase("header") )
100 bHeader = true;
101 else if( rType.equalsIgnoreAsciiCase("footer") )
102 bFooter = true;
107 bool bAppended = false;
108 if( m_pPam->GetPoint()->nContent.GetIndex() )
110 AppendTextNode( bHeader||bFooter||!aId.isEmpty()|| !aHRef.isEmpty() ? AM_NORMAL
111 : AM_NOSPACE );
112 bAppended = true;
115 HTMLAttrContext *pCntxt = new HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
117 bool bStyleParsed = false, bPositioned = false;
118 SfxItemSet aItemSet( m_pDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
119 SvxCSS1PropertyInfo aPropInfo;
120 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
122 bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
123 aItemSet, aPropInfo, &aLang, &aDir );
124 if( bStyleParsed )
126 if ( aPropInfo.m_nColumnCount >= 2 )
128 delete pCntxt;
129 NewMultiCol( aPropInfo.m_nColumnCount );
130 return;
132 bPositioned = HTML_DIVISION_ON == nToken && !aClass.isEmpty() &&
133 CreateContainer( aClass, aItemSet, aPropInfo,
134 pCntxt );
135 if( !bPositioned )
136 bPositioned = DoPositioning( aItemSet, aPropInfo, pCntxt );
140 if( !bPositioned && (bHeader || bFooter) && IsNewDoc() )
142 SwPageDesc *pPageDesc = m_pCSS1Parser->GetMasterPageDesc();
143 SwFrameFormat& rPageFormat = pPageDesc->GetMaster();
145 SwFrameFormat *pHdFtFormat;
146 bool bNew = false;
147 HtmlContextFlags nFlags = HtmlContextFlags::MultiColMask;
148 if( bHeader )
150 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetHeader().GetHeaderFormat());
151 if( !pHdFtFormat )
153 // noch keine Header, dann erzeuge einen.
154 rPageFormat.SetFormatAttr( SwFormatHeader( true ));
155 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetHeader().GetHeaderFormat());
156 bNew = true;
158 nFlags |= HtmlContextFlags::HeaderDist;
160 else
162 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetFooter().GetFooterFormat());
163 if( !pHdFtFormat )
165 // noch keine Footer, dann erzeuge einen.
166 rPageFormat.SetFormatAttr( SwFormatFooter( true ));
167 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetFooter().GetFooterFormat());
168 bNew = true;
170 nFlags |= HtmlContextFlags::FooterDist;
173 const SwFormatContent& rFlyContent = pHdFtFormat->GetContent();
174 const SwNodeIndex& rContentStIdx = *rFlyContent.GetContentIdx();
175 SwContentNode *pCNd;
177 if( bNew )
179 pCNd = m_pDoc->GetNodes()[rContentStIdx.GetIndex()+1]
180 ->GetContentNode();
182 else
184 // Einen neuen Node zu Beginn der Section anlegen
185 SwNodeIndex aSttIdx( rContentStIdx, 1 );
186 pCNd = m_pDoc->GetNodes().MakeTextNode( aSttIdx,
187 m_pCSS1Parser->GetTextCollFromPool(RES_POOLCOLL_TEXT));
189 // Den bisherigen Inhalt der Section loeschen
190 SwPaM aDelPam( aSttIdx );
191 aDelPam.SetMark();
193 const SwStartNode *pStNd =
194 static_cast<const SwStartNode *>( &rContentStIdx.GetNode() );
195 aDelPam.GetPoint()->nNode = pStNd->EndOfSectionIndex() - 1;
197 m_pDoc->getIDocumentContentOperations().DelFullPara( aDelPam );
199 // Die Seitenvorlage aktualisieren
200 for( size_t i=0; i < m_pDoc->GetPageDescCnt(); i++ )
202 if( RES_POOLPAGE_HTML == m_pDoc->GetPageDesc(i).GetPoolFormatId() )
204 m_pDoc->ChgPageDesc( i, *pPageDesc );
205 break;
210 SwPosition aNewPos( SwNodeIndex( rContentStIdx, 1 ), SwIndex( pCNd, 0 ) );
211 SaveDocContext( pCntxt, nFlags, &aNewPos );
213 else if( !bPositioned && aId.getLength() > 9 &&
214 (aId[0] == 's' || aId[0] == 'S' ) &&
215 (aId[1] == 'd' || aId[1] == 'D' ) )
217 bool bEndNote = false, bFootNote = false;
218 if( aId.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote ) )
219 bEndNote = true;
220 else if( aId.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote ) )
221 bFootNote = true;
222 if( bFootNote || bEndNote )
224 SwNodeIndex *pStartNdIdx = GetFootEndNoteSection( aId );
225 if( pStartNdIdx )
227 SwContentNode *pCNd =
228 m_pDoc->GetNodes()[pStartNdIdx->GetIndex()+1]->GetContentNode();
229 SwNodeIndex aTmpSwNodeIndex = SwNodeIndex(*pCNd);
230 SwPosition aNewPos( aTmpSwNodeIndex, SwIndex( pCNd, 0 ) );
231 SaveDocContext( pCntxt, HtmlContextFlags::MultiColMask, &aNewPos );
232 aId.clear();
233 aPropInfo.m_aId.clear();
238 // Bereiche fuegen wir in Rahmen nur dann ein, wenn der Bereich gelinkt ist.
239 if( (!aId.isEmpty() && !bPositioned) || !aHRef.isEmpty() )
241 // Bereich einfuegen (muss vor dem Setzten von Attributen erfolgen,
242 // weil die Section vor der PaM-Position eingefuegt.
244 // wenn wir im ersten Node einer Section stehen, wir die neue
245 // Section nicht in der aktuellen, sondern vor der aktuellen
246 // Section eingefuegt. Deshalb muessen wir dann einen Node
247 // einfuegen. UND IN LOESCHEN!!!
248 if( !bAppended )
250 SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->nNode, -1 );
251 if (aPrvNdIdx.GetNode().IsSectionNode())
253 AppendTextNode();
254 bAppended = true;
257 HTMLAttrs *pPostIts = bAppended ? nullptr : new HTMLAttrs;
258 SetAttr( true, true, pPostIts );
260 // Namen der Section eindeutig machen
261 const OUString aName( m_pDoc->GetUniqueSectionName( !aId.isEmpty() ? &aId : nullptr ) );
263 if( !aHRef.isEmpty() )
265 sal_Unicode cDelim = 255U;
266 sal_Int32 nPos = aHRef.lastIndexOf( cDelim );
267 sal_Int32 nPos2 = -1;
268 if( nPos != -1 )
270 nPos2 = aHRef.lastIndexOf( cDelim, nPos );
271 if( nPos2 != -1 )
273 sal_Int32 nTmp = nPos;
274 nPos = nPos2;
275 nPos2 = nTmp;
278 OUString aURL;
279 if( nPos == -1 )
281 aURL = URIHelper::SmartRel2Abs(INetURLObject( m_sBaseURL ), aHRef, Link<OUString *, bool>(), false);
283 else
285 aURL = URIHelper::SmartRel2Abs(INetURLObject( m_sBaseURL ), aHRef.copy( 0, nPos ), Link<OUString *, bool>(), false )
286 + OUStringLiteral1(sfx2::cTokenSeparator);
287 if( nPos2 == -1 )
289 aURL += aHRef.copy( nPos+1 );
291 else
293 aURL += aHRef.copy( nPos+1, nPos2 - (nPos+1) )
294 + OUStringLiteral1(sfx2::cTokenSeparator)
295 + rtl::Uri::decode( aHRef.copy( nPos2+1 ),
296 rtl_UriDecodeWithCharset,
297 RTL_TEXTENCODING_ISO_8859_1 );
300 aHRef = aURL;
303 SwSectionData aSection( (!aHRef.isEmpty()) ? FILE_LINK_SECTION
304 : CONTENT_SECTION, aName );
305 if( !aHRef.isEmpty() )
307 aSection.SetLinkFileName( aHRef );
308 aSection.SetProtectFlag(true);
311 SfxItemSet aFrameItemSet( m_pDoc->GetAttrPool(),
312 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
313 if( !IsNewDoc() )
314 Reader::ResetFrameFormatAttrs(aFrameItemSet );
316 const SfxPoolItem *pItem;
317 if( SfxItemState::SET == aItemSet.GetItemState( RES_BACKGROUND, false,
318 &pItem ) )
320 aFrameItemSet.Put( *pItem );
321 aItemSet.ClearItem( RES_BACKGROUND );
323 if( SfxItemState::SET == aItemSet.GetItemState( RES_FRAMEDIR, false,
324 &pItem ) )
326 aFrameItemSet.Put( *pItem );
327 aItemSet.ClearItem( RES_FRAMEDIR );
330 m_pDoc->InsertSwSection( *m_pPam, aSection, nullptr, &aFrameItemSet, false );
332 // ggfs. einen Bereich anspringen
333 if( JUMPTO_REGION == m_eJumpTo && aName == m_sJmpMark )
335 m_bChkJumpMark = true;
336 m_eJumpTo = JUMPTO_NONE;
339 SwTextNode* pOldTextNd =
340 (bAppended) ? nullptr : m_pPam->GetPoint()->nNode.GetNode().GetTextNode();
342 m_pPam->Move( fnMoveBackward );
344 // PageDesc- und SwFormatBreak Attribute vom aktuellen Node in den
345 // (ersten) Node des Bereich verschieben.
346 if( pOldTextNd )
347 MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->nNode.GetIndex(),
348 true );
350 if( pPostIts )
352 // noch vorhandene PostIts in den ersten Absatz
353 // der Tabelle setzen
354 InsertAttrs( *pPostIts );
355 delete pPostIts;
356 pPostIts = nullptr;
359 pCntxt->SetSpansSection( true );
361 // keine text::Bookmarks mit dem gleichen Namen wie Bereiche einfuegen
362 if( !aPropInfo.m_aId.isEmpty() && aPropInfo.m_aId==aName )
363 aPropInfo.m_aId.clear();
365 else
367 pCntxt->SetAppendMode( AM_NOSPACE );
370 if( SVX_ADJUST_END != eAdjust )
372 InsertAttr( &m_aAttrTab.pAdjust, SvxAdjustItem(eAdjust, RES_PARATR_ADJUST), pCntxt );
375 // Style parsen
376 if( bStyleParsed )
377 InsertAttrs( aItemSet, aPropInfo, pCntxt, true );
379 PushContext( pCntxt );
382 void SwHTMLParser::EndDivision( int /*nToken*/ )
384 // Stack-Eintrag zu dem Token suchen (weil wir noch den Div-Stack
385 // haben unterscheiden wir erst einmal nicht zwischen DIV und CENTER
386 HTMLAttrContext *pCntxt = nullptr;
387 auto nPos = m_aContexts.size();
388 while( !pCntxt && nPos>m_nContextStMin )
390 switch( m_aContexts[--nPos]->GetToken() )
392 case HTML_CENTER_ON:
393 case HTML_DIVISION_ON:
394 pCntxt = m_aContexts[nPos];
395 m_aContexts.erase( m_aContexts.begin() + nPos );
396 break;
400 if( pCntxt )
402 // Attribute beenden
403 EndContext( pCntxt );
404 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
406 delete pCntxt;
410 void SwHTMLParser::FixHeaderFooterDistance( bool bHeader,
411 const SwPosition *pOldPos )
413 SwPageDesc *pPageDesc = m_pCSS1Parser->GetMasterPageDesc();
414 SwFrameFormat& rPageFormat = pPageDesc->GetMaster();
416 SwFrameFormat *pHdFtFormat =
417 bHeader ? const_cast<SwFrameFormat*>(rPageFormat.GetHeader().GetHeaderFormat())
418 : const_cast<SwFrameFormat*>(rPageFormat.GetFooter().GetFooterFormat());
419 OSL_ENSURE( pHdFtFormat, "Doch keine Kopf- oder Fusszeile" );
421 const SwFormatContent& rFlyContent = pHdFtFormat->GetContent();
422 const SwNodeIndex& rContentStIdx = *rFlyContent.GetContentIdx();
424 sal_uLong nPrvNxtIdx;
425 if( bHeader )
427 nPrvNxtIdx = rContentStIdx.GetNode().EndOfSectionIndex()-1;
429 else
431 nPrvNxtIdx = pOldPos->nNode.GetIndex() - 1;
434 sal_uInt16 nSpace = 0;
435 SwTextNode *pTextNode = m_pDoc->GetNodes()[nPrvNxtIdx]->GetTextNode();
436 if( pTextNode )
438 const SvxULSpaceItem& rULSpace =
439 static_cast<const SvxULSpaceItem&>(pTextNode
440 ->SwContentNode::GetAttr( RES_UL_SPACE ));
442 // Der untere Absatz-Abstand wird zum Abstand zur
443 // Kopf- oder Fusszeile
444 nSpace = rULSpace.GetLower();
446 // und anschliessend auf einen vernuenftigen Wert
447 // gesetzt
448 const SvxULSpaceItem& rCollULSpace =
449 pTextNode->GetAnyFormatColl().GetULSpace();
450 if( rCollULSpace.GetUpper() == rULSpace.GetUpper() )
451 pTextNode->ResetAttr( RES_UL_SPACE );
452 else
453 pTextNode->SetAttr(
454 SvxULSpaceItem( rULSpace.GetUpper(),
455 rCollULSpace.GetLower(), RES_UL_SPACE ) );
458 if( bHeader )
460 nPrvNxtIdx = pOldPos->nNode.GetIndex();
462 else
464 nPrvNxtIdx = rContentStIdx.GetIndex() + 1;
467 pTextNode = m_pDoc->GetNodes()[nPrvNxtIdx]
468 ->GetTextNode();
469 if( pTextNode )
471 const SvxULSpaceItem& rULSpace =
472 static_cast<const SvxULSpaceItem&>(pTextNode
473 ->SwContentNode::GetAttr( RES_UL_SPACE ));
475 // Der obere Absatz-Abstand wird zum Abstand zur
476 // Kopf- oder Fusszeile, wenn er groesser ist als
477 // der untere vom Absatz davor
478 if( rULSpace.GetUpper() > nSpace )
479 nSpace = rULSpace.GetUpper();
481 // und anschliessend auf einen vernuenftigen Wert gesetzt
482 const SvxULSpaceItem& rCollULSpace =
483 pTextNode->GetAnyFormatColl().GetULSpace();
484 if( rCollULSpace.GetLower() == rULSpace.GetLower() )
485 pTextNode->ResetAttr( RES_UL_SPACE );
486 else
487 pTextNode->SetAttr(
488 SvxULSpaceItem( rCollULSpace.GetUpper(),
489 rULSpace.GetLower(), RES_UL_SPACE ) );
492 SvxULSpaceItem aULSpace( RES_UL_SPACE );
493 if( bHeader )
494 aULSpace.SetLower( nSpace );
495 else
496 aULSpace.SetUpper( nSpace );
498 pHdFtFormat->SetFormatAttr( aULSpace );
501 bool SwHTMLParser::EndSection( bool bLFStripped )
503 SwEndNode *pEndNd = m_pDoc->GetNodes()[m_pPam->GetPoint()->nNode.GetIndex()+1]
504 ->GetEndNode();
505 if( pEndNd && pEndNd->StartOfSectionNode()->IsSectionNode() )
507 // den Bereich beenden
508 if( !bLFStripped )
509 StripTrailingPara();
510 m_pPam->Move( fnMoveForward );
511 return true;
514 OSL_ENSURE( false, "Falsche PaM Position Beenden eines Bereichs" );
516 return false;
519 bool SwHTMLParser::EndSections( bool bLFStripped )
521 bool bSectionClosed = false;
522 auto nPos = m_aContexts.size();
523 while( nPos>m_nContextStMin )
525 HTMLAttrContext *pCntxt = m_aContexts[--nPos];
526 if( pCntxt->GetSpansSection() && EndSection( bLFStripped ) )
528 bSectionClosed = true;
529 pCntxt->SetSpansSection( false );
530 bLFStripped = false;
534 return bSectionClosed;
537 void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss )
539 OUString aId;
540 OUString aStyle, aClass, aLang, aDir;
541 long nWidth = 100;
542 sal_uInt16 nCols = columnsFromCss, nGutter = 10;
543 bool bPrcWidth = true;
545 const HTMLOptions& rHTMLOptions = GetOptions();
546 for (size_t i = rHTMLOptions.size(); i; )
548 const HTMLOption& rOption = rHTMLOptions[--i];
549 switch( rOption.GetToken() )
551 case HTML_O_ID:
552 aId = rOption.GetString();
553 break;
554 case HTML_O_STYLE:
555 aStyle = rOption.GetString();
556 break;
557 case HTML_O_CLASS:
558 aClass = rOption.GetString();
559 break;
560 case HTML_O_LANG:
561 aLang = rOption.GetString();
562 break;
563 case HTML_O_DIR:
564 aDir = rOption.GetString();
565 break;
566 case HTML_O_COLS:
567 nCols = (sal_uInt16)rOption.GetNumber();
568 break;
569 case HTML_O_WIDTH:
570 nWidth = rOption.GetNumber();
571 bPrcWidth = (rOption.GetString().indexOf('%') != -1);
572 if( bPrcWidth && nWidth>100 )
573 nWidth = 100;
574 break;
575 case HTML_O_GUTTER:
576 nGutter = (sal_uInt16)rOption.GetNumber();
577 break;
582 HTMLAttrContext *pCntxt = new HTMLAttrContext( HTML_MULTICOL_ON );
584 //.is the multicol element contained in a container? That may be the
585 // case for 5.0 documents.
586 bool bInCntnr = false;
587 auto i = m_aContexts.size();
588 while( !bInCntnr && i > m_nContextStMin )
589 bInCntnr = nullptr != m_aContexts[--i]->GetFrameItemSet();
591 // Parse style sheets, but don't position anything by now.
592 bool bStyleParsed = false;
593 SfxItemSet aItemSet( m_pDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
594 SvxCSS1PropertyInfo aPropInfo;
595 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
596 bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
597 aItemSet, aPropInfo, &aLang, &aDir );
599 // Calculate width.
600 sal_uInt8 nPrcWidth = bPrcWidth ? (sal_uInt8)nWidth : 0;
601 SwTwips nTwipWidth = 0;
602 if( !bPrcWidth && nWidth && Application::GetDefaultDevice() )
604 nTwipWidth = Application::GetDefaultDevice()
605 ->PixelToLogic( Size(nWidth, 0),
606 MapMode(MapUnit::MapTwip) ).Width();
609 if( !nPrcWidth && nTwipWidth < MINFLY )
610 nTwipWidth = MINFLY;
612 // Do positioning.
613 bool bPositioned = false;
614 if( bInCntnr || SwCSS1Parser::MayBePositioned( aPropInfo, true ) )
616 SfxItemSet aFrameItemSet( m_pDoc->GetAttrPool(),
617 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
618 if( !IsNewDoc() )
619 Reader::ResetFrameFormatAttrs(aFrameItemSet );
621 SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, aItemSet, aPropInfo,
622 aFrameItemSet );
624 // The width is either the WIDTH attribute's value or contained
625 // in some style option.
626 SetVarSize( aItemSet, aPropInfo, aFrameItemSet, nTwipWidth, nPrcWidth );
628 SetSpace( Size(0,0), aItemSet, aPropInfo, aFrameItemSet );
630 // Set some other frame attributes. If the background is set, its
631 // it will be cleared here. That for, it won't be set at the section,
632 // too.
633 SetFrameFormatAttrs( aItemSet, aPropInfo,
634 HtmlFrameFormatFlags::Box|HtmlFrameFormatFlags::Background|HtmlFrameFormatFlags::Padding|HtmlFrameFormatFlags::Direction,
635 aFrameItemSet );
637 // Insert fly frame. If the are columns, the fly frame's name is not
638 // the sections name but a generated one.
639 OUString aFlyName( aEmptyOUStr );
640 if( nCols < 2 )
642 aFlyName = aId;
643 aPropInfo.m_aId.clear();
646 InsertFlyFrame(aFrameItemSet, pCntxt, aFlyName);
648 pCntxt->SetPopStack( true );
649 bPositioned = true;
652 bool bAppended = false;
653 if( !bPositioned )
655 if( m_pPam->GetPoint()->nContent.GetIndex() )
657 AppendTextNode( AM_SPACE );
658 bAppended = true;
660 else
662 AddParSpace();
666 // If there are less then 2 columns, no section is inserted.
667 if( nCols >= 2 )
669 if( !bAppended )
671 // If the pam is at the start of a section, a additional text
672 // node must be inserted. Otherwise, the new section will be
673 // inserted in front of the old one.
674 SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->nNode, -1 );
675 if (aPrvNdIdx.GetNode().IsSectionNode())
677 AppendTextNode();
678 bAppended = true;
681 HTMLAttrs *pPostIts = bAppended ? nullptr : new HTMLAttrs;
682 SetAttr( true, true, pPostIts );
684 // Make section name unique.
685 OUString aName( m_pDoc->GetUniqueSectionName( !aId.isEmpty() ? &aId : nullptr ) );
686 SwSectionData aSection( CONTENT_SECTION, aName );
688 SfxItemSet aFrameItemSet( m_pDoc->GetAttrPool(),
689 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
690 if( !IsNewDoc() )
691 Reader::ResetFrameFormatAttrs(aFrameItemSet );
693 if( nGutter && Application::GetDefaultDevice() )
695 nGutter = (sal_uInt16)Application::GetDefaultDevice()
696 ->PixelToLogic( Size(nGutter, 0),
697 MapMode(MapUnit::MapTwip) ).Width();
700 SwFormatCol aFormatCol;
702 aFormatCol.Init( nCols, nGutter, USHRT_MAX );
703 aFrameItemSet.Put( aFormatCol );
705 const SfxPoolItem *pItem;
706 if( SfxItemState::SET == aItemSet.GetItemState( RES_BACKGROUND, false,
707 &pItem ) )
709 aFrameItemSet.Put( *pItem );
710 aItemSet.ClearItem( RES_BACKGROUND );
712 if( SfxItemState::SET == aItemSet.GetItemState( RES_FRAMEDIR, false,
713 &pItem ) )
715 aFrameItemSet.Put( *pItem );
716 aItemSet.ClearItem( RES_FRAMEDIR );
718 m_pDoc->InsertSwSection( *m_pPam, aSection, nullptr, &aFrameItemSet, false );
720 // Jump to section, if this is requested.
721 if( JUMPTO_REGION == m_eJumpTo && aName == m_sJmpMark )
723 m_bChkJumpMark = true;
724 m_eJumpTo = JUMPTO_NONE;
727 SwTextNode* pOldTextNd =
728 (bAppended) ? nullptr : m_pPam->GetPoint()->nNode.GetNode().GetTextNode();
730 m_pPam->Move( fnMoveBackward );
732 // Move PageDesc and SwFormatBreak attributes of the current node
733 // to the section's first node.
734 if( pOldTextNd )
735 MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->nNode.GetIndex(),
736 true );
738 if( pPostIts )
740 // Move pending PostIts into the section.
741 InsertAttrs( *pPostIts );
742 delete pPostIts;
743 pPostIts = nullptr;
746 pCntxt->SetSpansSection( true );
748 // Insert a bookmark if its name differs from the section's name only.
749 if( !aPropInfo.m_aId.isEmpty() && aPropInfo.m_aId==aName )
750 aPropInfo.m_aId.clear();
753 // Additional attributes must be set as hard ones.
754 if( bStyleParsed )
755 InsertAttrs( aItemSet, aPropInfo, pCntxt, true );
757 PushContext( pCntxt );
760 void SwHTMLParser::InsertFlyFrame( const SfxItemSet& rItemSet,
761 HTMLAttrContext *pCntxt,
762 const OUString& rName )
764 RndStdIds eAnchorId =
765 static_cast<const SwFormatAnchor&>(rItemSet.Get( RES_ANCHOR )).GetAnchorId();
767 // Den Rahmen anlegen
768 SwFlyFrameFormat* pFlyFormat = m_pDoc->MakeFlySection( eAnchorId, m_pPam->GetPoint(),
769 &rItemSet );
770 // Ggf. den Namen setzen
771 if( !rName.isEmpty() )
772 pFlyFormat->SetName( rName );
774 RegisterFlyFrame( pFlyFormat );
776 const SwFormatContent& rFlyContent = pFlyFormat->GetContent();
777 const SwNodeIndex& rFlyCntIdx = *rFlyContent.GetContentIdx();
778 SwContentNode *pCNd = m_pDoc->GetNodes()[rFlyCntIdx.GetIndex()+1]
779 ->GetContentNode();
781 SwPosition aNewPos( SwNodeIndex( rFlyCntIdx, 1 ), SwIndex( pCNd, 0 ) );
782 const HtmlContextFlags nFlags = (HtmlContextFlags::ProtectStack|HtmlContextFlags::StripPara);
783 SaveDocContext( pCntxt, nFlags, &aNewPos );
786 void SwHTMLParser::MovePageDescAttrs( SwNode *pSrcNd,
787 sal_uLong nDestIdx,
788 bool bFormatBreak )
790 SwContentNode* pDestContentNd =
791 m_pDoc->GetNodes()[nDestIdx]->GetContentNode();
793 OSL_ENSURE( pDestContentNd, "Wieso ist das Ziel kein Content-Node?" );
795 if( pSrcNd->IsContentNode() )
797 SwContentNode* pSrcContentNd = pSrcNd->GetContentNode();
799 const SfxPoolItem* pItem;
800 if( SfxItemState::SET == pSrcContentNd->GetSwAttrSet()
801 .GetItemState( RES_PAGEDESC, false, &pItem ) &&
802 static_cast<const SwFormatPageDesc *>(pItem)->GetPageDesc() )
804 pDestContentNd->SetAttr( *pItem );
805 pSrcContentNd->ResetAttr( RES_PAGEDESC );
807 if( SfxItemState::SET == pSrcContentNd->GetSwAttrSet()
808 .GetItemState( RES_BREAK, false, &pItem ) )
810 switch( static_cast<const SvxFormatBreakItem *>(pItem)->GetBreak() )
812 case SvxBreak::PageBefore:
813 case SvxBreak::PageAfter:
814 case SvxBreak::PageBoth:
815 if( bFormatBreak )
816 pDestContentNd->SetAttr( *pItem );
817 pSrcContentNd->ResetAttr( RES_BREAK );
818 break;
819 default:
820 break;
824 else if( pSrcNd->IsTableNode() )
826 SwFrameFormat *pFrameFormat = pSrcNd->GetTableNode()->GetTable().GetFrameFormat();
828 const SfxPoolItem* pItem;
829 if( SfxItemState::SET == pFrameFormat->GetAttrSet().
830 GetItemState( RES_PAGEDESC, false, &pItem ) )
832 pDestContentNd->SetAttr( *pItem );
833 pFrameFormat->ResetFormatAttr( RES_PAGEDESC );
838 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */