LibreOffice Module sw (master) 1
htmlsect.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <com/sun/star/text/HoriOrientation.hpp>
21#include <com/sun/star/text/VertOrientation.hpp>
22#include <rtl/uri.hxx>
23
24#include <svl/urihelper.hxx>
25#include <vcl/svapp.hxx>
27#include <editeng/ulspitem.hxx>
29#include <svtools/htmltokn.h>
30#include <svtools/htmlkywd.hxx>
31#include <sfx2/linkmgr.hxx>
32#include <osl/diagnose.h>
33
34#include <hintids.hxx>
35#include <fmthdft.hxx>
36#include <fmtcntnt.hxx>
37#include <fmtclds.hxx>
38#include <fmtanchr.hxx>
39#include <fmtpdsc.hxx>
40#include <frmatr.hxx>
41#include <doc.hxx>
42#include <pam.hxx>
43#include <ndtxt.hxx>
44#include <shellio.hxx>
45#include <section.hxx>
46#include <poolfmt.hxx>
47#include <pagedesc.hxx>
48#include <swtable.hxx>
49#include "swcss1.hxx"
50#include "swhtml.hxx"
51
52
53using namespace ::com::sun::star;
54
56{
57 OUString aId, aHRef;
58 OUString aStyle, aLang, aDir;
59 OUString aClass;
60 SvxAdjust eAdjust = HtmlTokenId::CENTER_ON==nToken ? SvxAdjust::Center
61 : SvxAdjust::End;
62
63 bool bHeader=false, bFooter=false;
64 const HTMLOptions& rHTMLOptions = GetOptions();
65 for (size_t i = rHTMLOptions.size(); i; )
66 {
67 const HTMLOption& rOption = rHTMLOptions[--i];
68 switch( rOption.GetToken() )
69 {
70 case HtmlOptionId::ID:
71 aId = rOption.GetString();
72 break;
73 case HtmlOptionId::ALIGN:
74 if( HtmlTokenId::DIVISION_ON==nToken )
75 eAdjust = rOption.GetEnum( aHTMLPAlignTable, eAdjust );
76 break;
77 case HtmlOptionId::STYLE:
78 aStyle = rOption.GetString();
79 break;
80 case HtmlOptionId::CLASS:
81 aClass = rOption.GetString();
82 break;
83 case HtmlOptionId::LANG:
84 aLang = rOption.GetString();
85 break;
86 case HtmlOptionId::DIR:
87 aDir = rOption.GetString();
88 break;
89 case HtmlOptionId::HREF:
90 aHRef = rOption.GetString();
91 break;
92 case HtmlOptionId::TITLE:
93 {
94 const OUString& rType = rOption.GetString();
95 if( rType.equalsIgnoreAsciiCase("header") )
96 bHeader = true;
97 else if( rType.equalsIgnoreAsciiCase("footer") )
98 bFooter = true;
99 }
100 break;
101 default: break;
102 }
103 }
104
105 bool bAppended = false;
107 {
108 AppendTextNode( bHeader||bFooter||!aId.isEmpty()|| !aHRef.isEmpty() ? AM_NORMAL
109 : AM_NOSPACE );
110 bAppended = true;
111 }
112
113 std::unique_ptr<HTMLAttrContext> xCntxt(new HTMLAttrContext(nToken));
114
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 ) )
119 {
120 bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
121 aItemSet, aPropInfo, &aLang, &aDir );
122 if( bStyleParsed )
123 {
124 if ( aPropInfo.m_nColumnCount >= 2 )
125 {
126 xCntxt.reset();
127 NewMultiCol( aPropInfo.m_nColumnCount );
128 return;
129 }
130 bPositioned = HtmlTokenId::DIVISION_ON == nToken && !aClass.isEmpty() &&
131 CreateContainer(aClass, aItemSet, aPropInfo,
132 xCntxt.get());
133 if( !bPositioned )
134 {
135 if (aPropInfo.m_bVisible && m_aContexts.size())
136 {
137 const std::unique_ptr<HTMLAttrContext>& pParent
138 = m_aContexts[m_aContexts.size() - 1];
139 if (!pParent->IsVisible())
140 {
141 // If the parent context is hidden, we are not visible, either.
142 aPropInfo.m_bVisible = false;
143 }
144 }
145 bPositioned = DoPositioning(aItemSet, aPropInfo, xCntxt.get());
146 }
147 }
148 }
149
150 if (!bPositioned && (bHeader || bFooter) && IsNewDoc() && !m_bReadingHeaderOrFooter)
151 {
153 xCntxt->SetHeaderOrFooter(true);
154
155 SwPageDesc *pPageDesc = m_pCSS1Parser->GetMasterPageDesc();
156 SwFrameFormat& rPageFormat = pPageDesc->GetMaster();
157
158 SwFrameFormat *pHdFtFormat;
159 bool bNew = false;
161 if( bHeader )
162 {
163 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetHeader().GetHeaderFormat());
164 if( !pHdFtFormat )
165 {
166 // still no header, then create one
167 rPageFormat.SetFormatAttr( SwFormatHeader( true ));
168 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetHeader().GetHeaderFormat());
169 bNew = true;
170 }
172 }
173 else
174 {
175 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetFooter().GetFooterFormat());
176 if( !pHdFtFormat )
177 {
178 // still no footer, then create one
179 rPageFormat.SetFormatAttr( SwFormatFooter( true ));
180 pHdFtFormat = const_cast<SwFrameFormat*>(rPageFormat.GetFooter().GetFooterFormat());
181 bNew = true;
182 }
184 }
185
186 const SwFormatContent& rFlyContent = pHdFtFormat->GetContent();
187 const SwNodeIndex& rContentStIdx = *rFlyContent.GetContentIdx();
188
189 if( !bNew )
190 {
191 // Our own html export only exports one "header" at most (and one "footer")
192
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));
199
200 // delete the current content of the section
201 SwPaM aDelPam( aSttIdx );
202 aDelPam.SetMark();
203
204 const SwStartNode *pStNd =
205 static_cast<const SwStartNode *>( &rContentStIdx.GetNode() );
206 aDelPam.GetPoint()->Assign( pStNd->EndOfSectionIndex() );
207
208 SwSectionData aSection(SectionType::Content, m_xDoc->GetUniqueSectionName());
209 if (SwSection* pOldContent = m_xDoc->InsertSwSection(aDelPam, aSection, nullptr, nullptr, false))
210 pOldContent->SetHidden(true);
211
212 // update page style
213 for( size_t i=0; i < m_xDoc->GetPageDescCnt(); i++ )
214 {
215 if( RES_POOLPAGE_HTML == m_xDoc->GetPageDesc(i).GetPoolFormatId() )
216 {
217 m_xDoc->ChgPageDesc( i, *pPageDesc );
218 break;
219 }
220 }
221 }
222
223 SwPosition aNewPos( rContentStIdx, SwNodeOffset(1) );
224 SaveDocContext(xCntxt.get(), nFlags, &aNewPos);
225 }
226 else if( !bPositioned && aId.getLength() > 9 &&
227 (aId[0] == 's' || aId[0] == 'S' ) &&
228 (aId[1] == 'd' || aId[1] == 'D' ) )
229 {
230 bool bEndNote = false, bFootNote = false;
231 if( aId.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote ) )
232 bEndNote = true;
233 else if( aId.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote ) )
234 bFootNote = true;
235 if( bFootNote || bEndNote )
236 {
237 SwNodeIndex *pStartNdIdx = GetFootEndNoteSection( aId );
238 if( pStartNdIdx )
239 {
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);
245 aId.clear();
246 aPropInfo.m_aId.clear();
247 }
248 }
249 }
250
251 // We only insert sections into frames if the section is linked.
252 if( (!aId.isEmpty() && !bPositioned) || !aHRef.isEmpty() )
253 {
254 // Insert section (has to be done before setting of attributes,
255 // because the section is inserted before the PaM position.
256
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!
260 if( !bAppended )
261 {
262 SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->GetNode(), -1 );
263 if (aPrvNdIdx.GetNode().IsSectionNode())
264 {
266 bAppended = true;
267 }
268 }
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() );
271
272 // make name of section unique
273 const OUString aName( m_xDoc->GetUniqueSectionName( !aId.isEmpty() ? &aId : nullptr ) );
274
275 if( !aHRef.isEmpty() )
276 {
277 sal_Unicode cDelim = 255U;
278 sal_Int32 nPos = aHRef.lastIndexOf( cDelim );
279 sal_Int32 nPos2 = -1;
280 if( nPos != -1 )
281 {
282 nPos2 = aHRef.lastIndexOf( cDelim, nPos );
283 if( nPos2 != -1 )
284 std::swap( nPos, nPos2 );
285 }
286 OUString aURL;
287 if( nPos == -1 )
288 {
290 }
291 else
292 {
294 + OUStringChar(sfx2::cTokenSeparator);
295 if( nPos2 == -1 )
296 {
297 aURL += aHRef.subView( nPos+1 );
298 }
299 else
300 {
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 );
306 }
307 }
308 aHRef = aURL;
309 }
310
311 SwSectionData aSection( (!aHRef.isEmpty()) ? SectionType::FileLink
313 if( !aHRef.isEmpty() )
314 {
315 aSection.SetLinkFileName( aHRef );
316 aSection.SetProtectFlag(true);
317 }
318
319 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() );
320 if( !IsNewDoc() )
321 Reader::ResetFrameFormatAttrs(aFrameItemSet );
322
323 if( const SvxBrushItem* pItem = aItemSet.GetItemIfSet( RES_BACKGROUND, false ) )
324 {
325 aFrameItemSet.Put( *pItem );
326 aItemSet.ClearItem( RES_BACKGROUND );
327 }
328 if( const SvxFrameDirectionItem* pItem = aItemSet.GetItemIfSet( RES_FRAMEDIR, false ) )
329 {
330 aFrameItemSet.Put( *pItem );
331 aItemSet.ClearItem( RES_FRAMEDIR );
332 }
333
334 m_xDoc->InsertSwSection( *m_pPam, aSection, nullptr, &aFrameItemSet, false );
335
336 // maybe jump to section
338 {
339 m_bChkJumpMark = true;
341 }
342
343 SwTextNode* pOldTextNd =
344 bAppended ? nullptr : m_pPam->GetPoint()->GetNode().GetTextNode();
345
347
348 // move PageDesc and SwFormatBreak attribute from current node into
349 // (first) node of the section
350 if( pOldTextNd )
352 true );
353
354 if( pPostIts )
355 {
356 // move still existing PostIts in the first paragraph of the table
357 InsertAttrs( std::move(*pPostIts) );
358 pPostIts.reset();
359 }
360
361 xCntxt->SetSpansSection( true );
362
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();
366 }
367 else
368 {
369 xCntxt->SetAppendMode( AM_NOSPACE );
370 }
371
372 if( SvxAdjust::End != eAdjust )
373 {
374 InsertAttr(&m_xAttrTab->pAdjust, SvxAdjustItem(eAdjust, RES_PARATR_ADJUST), xCntxt.get());
375 }
376
377 // parse style
378 if( bStyleParsed )
379 InsertAttrs( aItemSet, aPropInfo, xCntxt.get(), true );
380
381 xCntxt->SetVisible(aPropInfo.m_bVisible);
382 PushContext(xCntxt);
383}
384
386{
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)
392 {
393 switch( m_aContexts[--nPos]->GetToken() )
394 {
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 );
399 break;
400 default: break;
401 }
402 }
403
404 if (xCntxt)
405 {
406 // close attribute
407 EndContext(xCntxt.get());
408 SetAttr(); // set paragraph attributes really fast because of JavaScript
409 if (xCntxt->IsHeaderOrFooter())
411 }
412}
413
415 const SwPosition *pOldPos )
416{
417 SwPageDesc *pPageDesc = m_pCSS1Parser->GetMasterPageDesc();
418 SwFrameFormat& rPageFormat = pPageDesc->GetMaster();
419
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" );
424
425 const SwFormatContent& rFlyContent = pHdFtFormat->GetContent();
426 const SwNodeIndex& rContentStIdx = *rFlyContent.GetContentIdx();
427
428 SwNodeOffset nPrvNxtIdx;
429 if( bHeader )
430 {
431 nPrvNxtIdx = rContentStIdx.GetNode().EndOfSectionIndex()-1;
432 }
433 else
434 {
435 nPrvNxtIdx = pOldPos->GetNodeIndex() - 1;
436 }
437
438 sal_uInt16 nSpace = 0;
439 SwTextNode *pTextNode = m_xDoc->GetNodes()[nPrvNxtIdx]->GetTextNode();
440 if( pTextNode )
441 {
442 const SvxULSpaceItem& rULSpace =
443 pTextNode->SwContentNode::GetAttr( RES_UL_SPACE );
444
445 // The bottom paragraph padding becomes the padding
446 // to header or footer
447 nSpace = rULSpace.GetLower();
448
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 );
454 else
455 pTextNode->SetAttr(
456 SvxULSpaceItem( rULSpace.GetUpper(),
457 rCollULSpace.GetLower(), RES_UL_SPACE ) );
458 }
459
460 if( bHeader )
461 {
462 nPrvNxtIdx = pOldPos->GetNodeIndex();
463 }
464 else
465 {
466 nPrvNxtIdx = rContentStIdx.GetIndex() + 1;
467 }
468
469 pTextNode = m_xDoc->GetNodes()[nPrvNxtIdx]
470 ->GetTextNode();
471 if( pTextNode )
472 {
473 const SvxULSpaceItem& rULSpace =
474 pTextNode->SwContentNode::GetAttr( RES_UL_SPACE );
475
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();
481
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 );
487 else
488 pTextNode->SetAttr(
489 SvxULSpaceItem( rCollULSpace.GetUpper(),
490 rULSpace.GetLower(), RES_UL_SPACE ) );
491 }
492
493 SvxULSpaceItem aULSpace( RES_UL_SPACE );
494 if( bHeader )
495 aULSpace.SetLower( nSpace );
496 else
497 aULSpace.SetUpper( nSpace );
498
499 pHdFtFormat->SetFormatAttr( aULSpace );
500}
501
502bool SwHTMLParser::EndSection( bool bLFStripped )
503{
504 SwEndNode *pEndNd = m_xDoc->GetNodes()[m_pPam->GetPoint()->GetNodeIndex()+1]
505 ->GetEndNode();
506 if( pEndNd && pEndNd->StartOfSectionNode()->IsSectionNode() )
507 {
508 // close the section
509 if( !bLFStripped )
512 return true;
513 }
514
515 OSL_ENSURE( false, "Wrong PaM position at end of section" );
516
517 return false;
518}
519
520bool SwHTMLParser::EndSections( bool bLFStripped )
521{
522 bool bSectionClosed = false;
523 auto nPos = m_aContexts.size();
524 while( nPos>m_nContextStMin )
525 {
526 HTMLAttrContext *pCntxt = m_aContexts[--nPos].get();
527 if( pCntxt->GetSpansSection() && EndSection( bLFStripped ) )
528 {
529 bSectionClosed = true;
530 pCntxt->SetSpansSection( false );
531 bLFStripped = false;
532 }
533 }
534
535 return bSectionClosed;
536}
537
538void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss )
539{
540 OUString aId;
541 OUString aStyle, aClass, aLang, aDir;
542 tools::Long nWidth = 100;
543 sal_uInt16 nCols = columnsFromCss, nGutter = 10;
544 bool bPercentWidth = true;
545
546 const HTMLOptions& rHTMLOptions = GetOptions();
547 for (size_t i = rHTMLOptions.size(); i; )
548 {
549 const HTMLOption& rOption = rHTMLOptions[--i];
550 switch( rOption.GetToken() )
551 {
552 case HtmlOptionId::ID:
553 aId = rOption.GetString();
554 break;
555 case HtmlOptionId::STYLE:
556 aStyle = rOption.GetString();
557 break;
558 case HtmlOptionId::CLASS:
559 aClass = rOption.GetString();
560 break;
561 case HtmlOptionId::LANG:
562 aLang = rOption.GetString();
563 break;
564 case HtmlOptionId::DIR:
565 aDir = rOption.GetString();
566 break;
567 case HtmlOptionId::COLS:
568 nCols = o3tl::narrowing<sal_uInt16>(rOption.GetNumber());
569 break;
570 case HtmlOptionId::WIDTH:
571 nWidth = rOption.GetNumber();
572 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
573 if( bPercentWidth && nWidth>100 )
574 nWidth = 100;
575 break;
576 case HtmlOptionId::GUTTER:
577 nGutter = o3tl::narrowing<sal_uInt16>(rOption.GetNumber());
578 break;
579 default: break;
580 }
581 }
582
583 std::unique_ptr<HTMLAttrContext> xCntxt(new HTMLAttrContext(HtmlTokenId::MULTICOL_ON));
584
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();
591
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 );
599
600 // Calculate width.
601 sal_uInt8 nPercentWidth = bPercentWidth ? static_cast<sal_uInt8>(nWidth) : 0;
602 SwTwips nTwipWidth = 0;
603 if( !bPercentWidth && nWidth && Application::GetDefaultDevice() )
604 {
605 nTwipWidth = Application::GetDefaultDevice()
606 ->PixelToLogic( Size(nWidth, 0),
607 MapMode(MapUnit::MapTwip) ).Width();
608 }
609
610 if( !nPercentWidth && nTwipWidth < MINFLY )
611 nTwipWidth = MINFLY;
612
613 // Do positioning.
614 bool bPositioned = false;
615 if( bInCntnr || SwCSS1Parser::MayBePositioned( aPropInfo, true ) )
616 {
617 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() );
618 if( !IsNewDoc() )
619 Reader::ResetFrameFormatAttrs(aFrameItemSet );
620
622 aFrameItemSet );
623
624 // The width is either the WIDTH attribute's value or contained
625 // in some style option.
626 SetVarSize( aPropInfo, aFrameItemSet, nTwipWidth, nPercentWidth );
627
628 SetSpace( Size(0,0), aItemSet, aPropInfo, aFrameItemSet );
629
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,
635 aFrameItemSet );
636
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;
640 if( nCols < 2 )
641 {
642 aFlyName = aId;
643 aPropInfo.m_aId.clear();
644 }
645
646 InsertFlyFrame(aFrameItemSet, xCntxt.get(), aFlyName);
647
648 xCntxt->SetPopStack( true );
649 bPositioned = true;
650 }
651
652 bool bAppended = false;
653 if( !bPositioned )
654 {
656 {
658 bAppended = true;
659 }
660 else
661 {
662 AddParSpace();
663 }
664 }
665
666 // If there are less than 2 columns, no section is inserted.
667 if( nCols >= 2 )
668 {
669 if( !bAppended )
670 {
671 // If the pam is at the start of a section, an 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()->GetNode(), -1 );
675 if (aPrvNdIdx.GetNode().IsSectionNode())
676 {
678 bAppended = true;
679 }
680 }
681 std::unique_ptr<std::deque<std::unique_ptr<HTMLAttr>>> pPostIts(bAppended ? nullptr : new std::deque<std::unique_ptr<HTMLAttr>>);
682 SetAttr( true, true, pPostIts.get() );
683
684 // Make section name unique.
685 OUString aName( m_xDoc->GetUniqueSectionName( !aId.isEmpty() ? &aId : nullptr ) );
687
688 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() );
689 if( !IsNewDoc() )
690 Reader::ResetFrameFormatAttrs(aFrameItemSet );
691
692 if( nGutter && Application::GetDefaultDevice() )
693 {
694 nGutter = o3tl::narrowing<sal_uInt16>(Application::GetDefaultDevice()
695 ->PixelToLogic( Size(nGutter, 0),
696 MapMode(MapUnit::MapTwip) ).Width());
697 }
698
699 SwFormatCol aFormatCol;
700
701 aFormatCol.Init( nCols, nGutter, USHRT_MAX );
702 aFrameItemSet.Put( aFormatCol );
703
704 if( const SvxBrushItem* pItem = aItemSet.GetItemIfSet( RES_BACKGROUND, false) )
705 {
706 aFrameItemSet.Put( *pItem );
707 aItemSet.ClearItem( RES_BACKGROUND );
708 }
709 if( const SvxFrameDirectionItem* pItem = aItemSet.GetItemIfSet( RES_FRAMEDIR, false ) )
710 {
711 aFrameItemSet.Put( *pItem );
712 aItemSet.ClearItem( RES_FRAMEDIR );
713 }
714 m_xDoc->InsertSwSection( *m_pPam, aSection, nullptr, &aFrameItemSet, false );
715
716 // Jump to section, if this is requested.
718 {
719 m_bChkJumpMark = true;
721 }
722
723 SwTextNode* pOldTextNd =
724 bAppended ? nullptr : m_pPam->GetPoint()->GetNode().GetTextNode();
725
727
728 // Move PageDesc and SwFormatBreak attributes of the current node
729 // to the section's first node.
730 if( pOldTextNd )
732 true );
733
734 if( pPostIts )
735 {
736 // Move pending PostIts into the section.
737 InsertAttrs( std::move(*pPostIts) );
738 pPostIts.reset();
739 }
740
741 xCntxt->SetSpansSection( true );
742
743 // Insert a bookmark if its name differs from the section's name only.
744 if( !aPropInfo.m_aId.isEmpty() && aPropInfo.m_aId==aName )
745 aPropInfo.m_aId.clear();
746 }
747
748 // Additional attributes must be set as hard ones.
749 if( bStyleParsed )
750 InsertAttrs( aItemSet, aPropInfo, xCntxt.get(), true );
751
752 PushContext(xCntxt);
753}
754
756 HTMLAttrContext *pCntxt,
757 const OUString& rName )
758{
759 RndStdIds eAnchorId =
760 rItemSet.Get( RES_ANCHOR ).GetAnchorId();
761
762 // create frame
763 SwFlyFrameFormat* pFlyFormat = m_xDoc->MakeFlySection( eAnchorId, m_pPam->GetPoint(),
764 &rItemSet );
765 if( !rName.isEmpty() )
766 pFlyFormat->SetFormatName( rName );
767
768 RegisterFlyFrame( pFlyFormat );
769
770 const SwFormatContent& rFlyContent = pFlyFormat->GetContent();
771 const SwNodeIndex& rFlyCntIdx = *rFlyContent.GetContentIdx();
772
773 SwPosition aNewPos( rFlyCntIdx, SwNodeOffset(1) );
775 SaveDocContext( pCntxt, nFlags, &aNewPos );
776}
777
779 SwNodeOffset nDestIdx,
780 bool bFormatBreak )
781{
782 SwContentNode* pDestContentNd =
783 m_xDoc->GetNodes()[nDestIdx]->GetContentNode();
784
785 OSL_ENSURE( pDestContentNd, "Why is the target not a Content-Node?" );
786
787 if( pSrcNd->IsContentNode() )
788 {
789 SwContentNode* pSrcContentNd = pSrcNd->GetContentNode();
790
791 const SwFormatPageDesc* pFormatPageDesc =
792 pSrcContentNd->GetSwAttrSet().GetItemIfSet( RES_PAGEDESC, false );
793 if( pFormatPageDesc && pFormatPageDesc->GetPageDesc() )
794 {
795 pDestContentNd->SetAttr( *pFormatPageDesc );
796 pSrcContentNd->ResetAttr( RES_PAGEDESC );
797 }
798 if( const SvxFormatBreakItem* pItem = pSrcContentNd->GetSwAttrSet()
799 .GetItemIfSet( RES_BREAK, false ) )
800 {
801 switch( pItem->GetBreak() )
802 {
803 case SvxBreak::PageBefore:
804 case SvxBreak::PageAfter:
805 case SvxBreak::PageBoth:
806 if( bFormatBreak )
807 pDestContentNd->SetAttr( *pItem );
808 pSrcContentNd->ResetAttr( RES_BREAK );
809 break;
810 default:
811 break;
812 }
813 }
814 }
815 else if( pSrcNd->IsTableNode() )
816 {
817 SwFrameFormat *pFrameFormat = pSrcNd->GetTableNode()->GetTable().GetFrameFormat();
818
819 if( const SwFormatPageDesc* pItem = pFrameFormat->GetAttrSet().
820 GetItemIfSet( RES_PAGEDESC, false ) )
821 {
822 if (pDestContentNd)
823 pDestContentNd->SetAttr(*pItem);
824 pFrameFormat->ResetFormatAttr( RES_PAGEDESC );
825 }
826 }
827}
828
829/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OutputDevice * GetDefaultDevice()
bool GetSpansSection() const
Definition: swhtml.hxx:276
void SetSpansSection(bool bSet)
Definition: swhtml.hxx:275
HtmlOptionId GetToken() const
const OUString & GetString() const
EnumT GetEnum(const HTMLOptionEnum< EnumT > *pOptEnums, EnumT nDflt=static_cast< EnumT >(0)) const
sal_uInt32 GetNumber() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
static void ResetFrameFormatAttrs(SfxItemSet &rFrameSet)
Definition: shellio.cxx:621
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
sal_uInt16 m_nColumnCount
Definition: svxcss1.hxx:131
void SetLower(const sal_uInt16 nL, const sal_uInt16 nProp=100)
sal_uInt16 GetUpper() const
void SetUpper(const sal_uInt16 nU, const sal_uInt16 nProp=100)
sal_uInt16 GetLower() const
static bool MayBePositioned(const SvxCSS1PropertyInfo &rPropInfo, bool bAutoWidth=false)
Definition: htmlcss1.cxx:1417
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:727
virtual bool SetAttr(const SfxPoolItem &)
made virtual
Definition: node.cxx:1586
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: node.cxx:1679
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:720
Ends a section of nodes in the document model.
Definition: node.hxx:378
void Init(sal_uInt16 nNumCols, sal_uInt16 nGutterWidth, sal_uInt16 nAct)
This function allows to (repeatedly) initialize the columns.
Definition: atrfrm.cxx:969
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:32
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
Footer, for pageformats Client of FrameFormat describing the footer.
Definition: fmthdft.hxx:65
const SwFrameFormat * GetFooterFormat() const
Definition: fmthdft.hxx:85
Header, for PageFormats Client of FrameFormat describing the header.
Definition: fmthdft.hxx:34
const SwFrameFormat * GetHeaderFormat() const
Definition: fmthdft.hxx:54
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:36
SwPageDesc * GetPageDesc()
Definition: fmtpdsc.hxx:61
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:618
const SwFormatFooter & GetFooter(bool=true) const
Definition: fmthdft.hxx:99
const SwFormatHeader & GetHeader(bool=true) const
Definition: fmthdft.hxx:97
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:447
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:100
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
Style of a layout element.
Definition: frmfmt.hxx:72
virtual void SetFormatName(const OUString &rNewName, bool bBroadcast=false) override
Definition: atrfrm.cxx:2608
void PushContext(std::unique_ptr< HTMLAttrContext > &rCntxt)
Definition: swhtml.hxx:580
OUString m_sJmpMark
Definition: swhtml.hxx:374
void NewDivision(HtmlTokenId nToken)
Definition: htmlsect.cxx:55
bool EndSection(bool bLFStripped=false)
Definition: htmlsect.cxx:502
void SetAnchorAndAdjustment(sal_Int16 eVertOri, sal_Int16 eHoriOri, const SvxCSS1PropertyInfo &rPropInfo, SfxItemSet &rFrameSet)
Definition: htmlgrin.cxx:151
void InsertAttrs(std::deque< std::unique_ptr< HTMLAttr > > rAttrs)
Definition: swhtml.cxx:3483
JumpToMarks m_eJumpTo
Definition: swhtml.hxx:430
bool CreateContainer(std::u16string_view rClass, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, HTMLAttrContext *pContext)
Definition: htmlctxt.cxx:505
HTMLAttrContexts m_aContexts
Definition: swhtml.hxx:385
void InsertAttr(const SfxPoolItem &rItem, bool bInsAtStart)
Definition: swhtml.cxx:3474
static void SetSpace(const Size &rPixSpace, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, SfxItemSet &rFlyItemSet)
Definition: htmlplug.cxx:243
void NewMultiCol(sal_uInt16 columnsFromCss=0)
Definition: htmlsect.cxx:538
std::shared_ptr< HTMLAttrTable > m_xAttrTab
Definition: swhtml.hxx:384
void SetAttr(bool bChkEnd=true, bool bBeforeTable=false, std::deque< std::unique_ptr< HTMLAttr > > *pPostIts=nullptr)
Definition: swhtml.hxx:516
void SaveDocContext(HTMLAttrContext *pCntxt, HtmlContextFlags nFlags, const SwPosition *pNewPos)
Definition: htmlctxt.cxx:273
void StripTrailingPara()
Definition: htmlgrin.cxx:1448
bool DoPositioning(SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, HTMLAttrContext *pContext)
Definition: htmlctxt.cxx:468
static bool HasStyleOptions(std::u16string_view rStyle, std::u16string_view rId, std::u16string_view rClass, const OUString *pLang=nullptr, const OUString *pDir=nullptr)
Definition: swhtml.hxx:1020
void InsertFlyFrame(const SfxItemSet &rItemSet, HTMLAttrContext *pCntxt, const OUString &rId)
Definition: htmlsect.cxx:755
bool m_bChkJumpMark
Definition: swhtml.hxx:464
SwPaM * m_pPam
Definition: swhtml.hxx:399
void EndDivision()
Definition: htmlsect.cxx:385
rtl::Reference< SwDoc > m_xDoc
Definition: swhtml.hxx:398
bool ParseStyleOptions(const OUString &rStyle, const OUString &rId, const OUString &rClass, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, const OUString *pLang=nullptr, const OUString *pDir=nullptr)
Definition: htmlcss1.cxx:1853
bool EndSections(bool bLFStripped)
Definition: htmlsect.cxx:520
std::unique_ptr< SwCSS1Parser > m_pCSS1Parser
Definition: swhtml.hxx:394
void AddParSpace()
Definition: swhtml.cxx:2492
bool m_bReadingHeaderOrFooter
Definition: swhtml.hxx:476
bool AppendTextNode(SwHTMLAppendMode eMode=AM_NORMAL, bool bUpdateNum=true)
Definition: swhtml.cxx:2190
void RegisterFlyFrame(SwFrameFormat *pFlyFrame)
Definition: htmlgrin.cxx:278
void EndContext(HTMLAttrContext *pContext)
Definition: htmlctxt.cxx:372
void MovePageDescAttrs(SwNode *pSrcNd, SwNodeOffset nDestIdx, bool bFormatBreak)
Definition: htmlsect.cxx:778
void FixHeaderFooterDistance(bool bHeader, const SwPosition *pOldPos)
Definition: htmlsect.cxx:414
static void SetFrameFormatAttrs(SfxItemSet &rItemSet, HtmlFrameFormatFlags nFlags, SfxItemSet &rFrameItemSet)
Definition: htmlcss1.cxx:2076
OUString m_sBaseURL
Definition: swhtml.hxx:363
size_t m_nContextStMin
Definition: swhtml.hxx:424
SwNodeIndex * GetFootEndNoteSection(const OUString &rName)
Definition: htmlftn.cxx:220
static void SetVarSize(SvxCSS1PropertyInfo const &rPropInfo, SfxItemSet &rFlyItemSet, SwTwips nDfltWidth=MINLAY, sal_uInt8 nDefaultPercentWidth=0)
Definition: htmlcss1.cxx:2037
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
bool IsContentNode() const
Definition: node.hxx:188
bool IsSectionNode() const
Definition: node.hxx:192
bool IsTableNode() const
Definition: node.hxx:191
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
SwContentNode * GetContentNode()
Definition: node.hxx:666
SwTableNode * GetTableNode()
Definition: node.hxx:650
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:643
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:657
const SwPosition * GetPoint() const
Definition: pam.hxx:253
SwFrameFormat & GetMaster()
Definition: pagedesc.hxx:238
SAL_DLLPRIVATE void SetProtectFlag(bool const bFlag)
Definition: section.hxx:106
void SetLinkFileName(OUString const &rNew)
Definition: section.hxx:118
Starts a section of nodes in the document model.
Definition: node.hxx:348
const SwTable & GetTable() const
Definition: node.hxx:542
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:209
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:5066
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0) override
Definition: ndtxt.cxx:5293
URL aURL
constexpr TypedWhichId< SvxFrameDirectionItem > RES_FRAMEDIR(126)
constexpr sal_uInt16 RES_FRMATR_BEGIN(RES_PARATR_LIST_END)
constexpr sal_uInt16 RES_FRMATR_END(141)
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(99)
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(111)
constexpr TypedWhichId< SvxAdjustItem > RES_PARATR_ADJUST(64)
constexpr TypedWhichId< SwFormatAnchor > RES_ANCHOR(110)
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(100)
constexpr TypedWhichId< SvxULSpaceItem > RES_UL_SPACE(98)
#define OOO_STRING_SVTOOLS_HTML_sdendnote
#define OOO_STRING_SVTOOLS_HTML_sdfootnote
HtmlTokenId
OUString aName
sal_uInt16 nPos
SVL_DLLPUBLIC OUString SmartRel2Abs(INetURLObject const &rTheBaseURIRef, OUString const &rTheRelURIRef, Link< OUString *, bool > const &rMaybeFileHdl=Link< OUString *, bool >(), bool bCheckFileExists=true, bool bIgnoreFragment=false, INetURLObject::EncodeMechanism eEncodeMechanism=INetURLObject::EncodeMechanism::WasEncoded, INetURLObject::DecodeMechanism eDecodeMechanism=INetURLObject::DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8, FSysStyle eStyle=FSysStyle::Detect)
int i
const sal_Unicode cTokenSeparator
long Long
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:60
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:61
::std::vector< HTMLOption > HTMLOptions
@ RES_POOLCOLL_TEXT
Text body.
Definition: poolfmt.hxx:251
@ RES_POOLPAGE_HTML
HTML.
Definition: poolfmt.hxx:176
DefTokenId nToken
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:231
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
SvxAdjust
RndStdIds
HTMLOptionEnum< SvxAdjust > const aHTMLPAlignTable[]
Definition: swhtml.cxx:141
@ AM_SPACE
Definition: swhtml.hxx:206
@ AM_NORMAL
Definition: swhtml.hxx:204
@ AM_NOSPACE
Definition: swhtml.hxx:205
HtmlContextFlags
Definition: swhtml.hxx:317
tools::Long SwTwips
Definition: swtypes.hxx:51
#define MINFLY
Definition: swtypes.hxx:61
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
const sal_Unicode cDelim