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>
26 #include <editeng/adjustitem.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 
53 using 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;
106  if( m_pPam->GetPoint()->nContent.GetIndex() )
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  SwContentNode *pCNd;
189 
190  if( bNew )
191  {
192  pCNd = m_xDoc->GetNodes()[rContentStIdx.GetIndex()+1]
193  ->GetContentNode();
194  }
195  else
196  {
197  // Our own html export only exports one "header" at most (and one "footer")
198 
199  // Create a new node at the beginning of the section if a duplicate arises
200  // and hide the original header/footers content by putting it into a hidden
201  // document-level section
202  SwNodeIndex aSttIdx( rContentStIdx, 1 );
203  pCNd = m_xDoc->GetNodes().MakeTextNode( aSttIdx,
204  m_pCSS1Parser->GetTextCollFromPool(RES_POOLCOLL_TEXT));
205 
206  // delete the current content of the section
207  SwPaM aDelPam( aSttIdx );
208  aDelPam.SetMark();
209 
210  const SwStartNode *pStNd =
211  static_cast<const SwStartNode *>( &rContentStIdx.GetNode() );
212  aDelPam.GetPoint()->nNode = pStNd->EndOfSectionIndex();
213 
214  SwSectionData aSection(SectionType::Content, m_xDoc->GetUniqueSectionName());
215  if (SwSection* pOldContent = m_xDoc->InsertSwSection(aDelPam, aSection, nullptr, nullptr, false))
216  pOldContent->SetHidden(true);
217 
218  // update page style
219  for( size_t i=0; i < m_xDoc->GetPageDescCnt(); i++ )
220  {
221  if( RES_POOLPAGE_HTML == m_xDoc->GetPageDesc(i).GetPoolFormatId() )
222  {
223  m_xDoc->ChgPageDesc( i, *pPageDesc );
224  break;
225  }
226  }
227  }
228 
229  SwPosition aNewPos( SwNodeIndex( rContentStIdx, 1 ), SwIndex( pCNd, 0 ) );
230  SaveDocContext(xCntxt.get(), nFlags, &aNewPos);
231  }
232  else if( !bPositioned && aId.getLength() > 9 &&
233  (aId[0] == 's' || aId[0] == 'S' ) &&
234  (aId[1] == 'd' || aId[1] == 'D' ) )
235  {
236  bool bEndNote = false, bFootNote = false;
237  if( aId.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote ) )
238  bEndNote = true;
239  else if( aId.startsWithIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote ) )
240  bFootNote = true;
241  if( bFootNote || bEndNote )
242  {
243  SwNodeIndex *pStartNdIdx = GetFootEndNoteSection( aId );
244  if( pStartNdIdx )
245  {
246  SwContentNode *pCNd =
247  m_xDoc->GetNodes()[pStartNdIdx->GetIndex()+1]->GetContentNode();
248  SwNodeIndex aTmpSwNodeIndex(*pCNd);
249  SwPosition aNewPos( aTmpSwNodeIndex, SwIndex( pCNd, 0 ) );
250  SaveDocContext(xCntxt.get(), HtmlContextFlags::MultiColMask, &aNewPos);
251  aId.clear();
252  aPropInfo.m_aId.clear();
253  }
254  }
255  }
256 
257  // We only insert sections into frames if the section is linked.
258  if( (!aId.isEmpty() && !bPositioned) || !aHRef.isEmpty() )
259  {
260  // Insert section (has to be done before setting of attributes,
261  // because the section is inserted before the PaM position.
262 
263  // If we are in the first node of a section, we insert the section
264  // before the current section and not in the current section.
265  // Therefore we have to add a node and delete it again!
266  if( !bAppended )
267  {
268  SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->nNode, -1 );
269  if (aPrvNdIdx.GetNode().IsSectionNode())
270  {
271  AppendTextNode();
272  bAppended = true;
273  }
274  }
275  std::unique_ptr<std::deque<std::unique_ptr<HTMLAttr>>> pPostIts(bAppended ? nullptr : new std::deque<std::unique_ptr<HTMLAttr>>);
276  SetAttr( true, true, pPostIts.get() );
277 
278  // make name of section unique
279  const OUString aName( m_xDoc->GetUniqueSectionName( !aId.isEmpty() ? &aId : nullptr ) );
280 
281  if( !aHRef.isEmpty() )
282  {
283  sal_Unicode cDelim = 255U;
284  sal_Int32 nPos = aHRef.lastIndexOf( cDelim );
285  sal_Int32 nPos2 = -1;
286  if( nPos != -1 )
287  {
288  nPos2 = aHRef.lastIndexOf( cDelim, nPos );
289  if( nPos2 != -1 )
290  {
291  sal_Int32 nTmp = nPos;
292  nPos = nPos2;
293  nPos2 = nTmp;
294  }
295  }
296  OUString aURL;
297  if( nPos == -1 )
298  {
300  }
301  else
302  {
303  aURL = URIHelper::SmartRel2Abs(INetURLObject( m_sBaseURL ), aHRef.copy( 0, nPos ), Link<OUString *, bool>(), false )
304  + OUStringChar(sfx2::cTokenSeparator);
305  if( nPos2 == -1 )
306  {
307  aURL += aHRef.subView( nPos+1 );
308  }
309  else
310  {
311  aURL += aHRef.subView( nPos+1, nPos2 - (nPos+1) )
312  + OUStringChar(sfx2::cTokenSeparator)
313  + rtl::Uri::decode( aHRef.copy( nPos2+1 ),
314  rtl_UriDecodeWithCharset,
315  RTL_TEXTENCODING_ISO_8859_1 );
316  }
317  }
318  aHRef = aURL;
319  }
320 
321  SwSectionData aSection( (!aHRef.isEmpty()) ? SectionType::FileLink
322  : SectionType::Content, aName );
323  if( !aHRef.isEmpty() )
324  {
325  aSection.SetLinkFileName( aHRef );
326  aSection.SetProtectFlag(true);
327  }
328 
329  SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() );
330  if( !IsNewDoc() )
331  Reader::ResetFrameFormatAttrs(aFrameItemSet );
332 
333  if( const SvxBrushItem* pItem = aItemSet.GetItemIfSet( RES_BACKGROUND, false ) )
334  {
335  aFrameItemSet.Put( *pItem );
336  aItemSet.ClearItem( RES_BACKGROUND );
337  }
338  if( const SvxFrameDirectionItem* pItem = aItemSet.GetItemIfSet( RES_FRAMEDIR, false ) )
339  {
340  aFrameItemSet.Put( *pItem );
341  aItemSet.ClearItem( RES_FRAMEDIR );
342  }
343 
344  m_xDoc->InsertSwSection( *m_pPam, aSection, nullptr, &aFrameItemSet, false );
345 
346  // maybe jump to section
347  if( JumpToMarks::Region == m_eJumpTo && aName == m_sJmpMark )
348  {
349  m_bChkJumpMark = true;
351  }
352 
353  SwTextNode* pOldTextNd =
354  bAppended ? nullptr : m_pPam->GetPoint()->nNode.GetNode().GetTextNode();
355 
357 
358  // move PageDesc and SwFormatBreak attribute from current node into
359  // (first) node of the section
360  if( pOldTextNd )
361  MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->nNode.GetIndex(),
362  true );
363 
364  if( pPostIts )
365  {
366  // move still existing PostIts in the first paragraph of the table
367  InsertAttrs( std::move(*pPostIts) );
368  pPostIts.reset();
369  }
370 
371  xCntxt->SetSpansSection( true );
372 
373  // don't insert Bookmarks with same name as sections
374  if( !aPropInfo.m_aId.isEmpty() && aPropInfo.m_aId==aName )
375  aPropInfo.m_aId.clear();
376  }
377  else
378  {
379  xCntxt->SetAppendMode( AM_NOSPACE );
380  }
381 
382  if( SvxAdjust::End != eAdjust )
383  {
384  InsertAttr(&m_xAttrTab->pAdjust, SvxAdjustItem(eAdjust, RES_PARATR_ADJUST), xCntxt.get());
385  }
386 
387  // parse style
388  if( bStyleParsed )
389  InsertAttrs( aItemSet, aPropInfo, xCntxt.get(), true );
390 
391  xCntxt->SetVisible(aPropInfo.m_bVisible);
392  PushContext(xCntxt);
393 }
394 
396 {
397  // search for the stack entry of the token (because we still have the div stack
398  // we don't make a difference between DIV and CENTER)
399  std::unique_ptr<HTMLAttrContext> xCntxt;
400  auto nPos = m_aContexts.size();
401  while (!xCntxt && nPos>m_nContextStMin)
402  {
403  switch( m_aContexts[--nPos]->GetToken() )
404  {
405  case HtmlTokenId::CENTER_ON:
406  case HtmlTokenId::DIVISION_ON:
407  xCntxt = std::move(m_aContexts[nPos]);
408  m_aContexts.erase( m_aContexts.begin() + nPos );
409  break;
410  default: break;
411  }
412  }
413 
414  if (xCntxt)
415  {
416  // close attribute
417  EndContext(xCntxt.get());
418  SetAttr(); // set paragraph attributes really fast because of JavaScript
419  if (xCntxt->IsHeaderOrFooter())
420  m_bReadingHeaderOrFooter = false;
421  }
422 }
423 
425  const SwPosition *pOldPos )
426 {
427  SwPageDesc *pPageDesc = m_pCSS1Parser->GetMasterPageDesc();
428  SwFrameFormat& rPageFormat = pPageDesc->GetMaster();
429 
430  SwFrameFormat *pHdFtFormat =
431  bHeader ? const_cast<SwFrameFormat*>(rPageFormat.GetHeader().GetHeaderFormat())
432  : const_cast<SwFrameFormat*>(rPageFormat.GetFooter().GetFooterFormat());
433  OSL_ENSURE( pHdFtFormat, "No header or footer" );
434 
435  const SwFormatContent& rFlyContent = pHdFtFormat->GetContent();
436  const SwNodeIndex& rContentStIdx = *rFlyContent.GetContentIdx();
437 
438  SwNodeOffset nPrvNxtIdx;
439  if( bHeader )
440  {
441  nPrvNxtIdx = rContentStIdx.GetNode().EndOfSectionIndex()-1;
442  }
443  else
444  {
445  nPrvNxtIdx = pOldPos->nNode.GetIndex() - 1;
446  }
447 
448  sal_uInt16 nSpace = 0;
449  SwTextNode *pTextNode = m_xDoc->GetNodes()[nPrvNxtIdx]->GetTextNode();
450  if( pTextNode )
451  {
452  const SvxULSpaceItem& rULSpace =
453  pTextNode->SwContentNode::GetAttr( RES_UL_SPACE );
454 
455  // The bottom paragraph padding becomes the padding
456  // to header or footer
457  nSpace = rULSpace.GetLower();
458 
459  // and afterwards set to a valid value
460  const SvxULSpaceItem& rCollULSpace =
461  pTextNode->GetAnyFormatColl().GetULSpace();
462  if( rCollULSpace.GetUpper() == rULSpace.GetUpper() )
463  pTextNode->ResetAttr( RES_UL_SPACE );
464  else
465  pTextNode->SetAttr(
466  SvxULSpaceItem( rULSpace.GetUpper(),
467  rCollULSpace.GetLower(), RES_UL_SPACE ) );
468  }
469 
470  if( bHeader )
471  {
472  nPrvNxtIdx = pOldPos->nNode.GetIndex();
473  }
474  else
475  {
476  nPrvNxtIdx = rContentStIdx.GetIndex() + 1;
477  }
478 
479  pTextNode = m_xDoc->GetNodes()[nPrvNxtIdx]
480  ->GetTextNode();
481  if( pTextNode )
482  {
483  const SvxULSpaceItem& rULSpace =
484  pTextNode->SwContentNode::GetAttr( RES_UL_SPACE );
485 
486  // The top paragraph padding becomes the padding
487  // to headline or footer if it is greater than the
488  // bottom padding of the paragraph beforehand
489  if( rULSpace.GetUpper() > nSpace )
490  nSpace = rULSpace.GetUpper();
491 
492  // and afterwards set to a valid value
493  const SvxULSpaceItem& rCollULSpace =
494  pTextNode->GetAnyFormatColl().GetULSpace();
495  if( rCollULSpace.GetLower() == rULSpace.GetLower() )
496  pTextNode->ResetAttr( RES_UL_SPACE );
497  else
498  pTextNode->SetAttr(
499  SvxULSpaceItem( rCollULSpace.GetUpper(),
500  rULSpace.GetLower(), RES_UL_SPACE ) );
501  }
502 
503  SvxULSpaceItem aULSpace( RES_UL_SPACE );
504  if( bHeader )
505  aULSpace.SetLower( nSpace );
506  else
507  aULSpace.SetUpper( nSpace );
508 
509  pHdFtFormat->SetFormatAttr( aULSpace );
510 }
511 
512 bool SwHTMLParser::EndSection( bool bLFStripped )
513 {
514  SwEndNode *pEndNd = m_xDoc->GetNodes()[m_pPam->GetPoint()->nNode.GetIndex()+1]
515  ->GetEndNode();
516  if( pEndNd && pEndNd->StartOfSectionNode()->IsSectionNode() )
517  {
518  // close the section
519  if( !bLFStripped )
522  return true;
523  }
524 
525  OSL_ENSURE( false, "Wrong PaM position at end of section" );
526 
527  return false;
528 }
529 
530 bool SwHTMLParser::EndSections( bool bLFStripped )
531 {
532  bool bSectionClosed = false;
533  auto nPos = m_aContexts.size();
534  while( nPos>m_nContextStMin )
535  {
536  HTMLAttrContext *pCntxt = m_aContexts[--nPos].get();
537  if( pCntxt->GetSpansSection() && EndSection( bLFStripped ) )
538  {
539  bSectionClosed = true;
540  pCntxt->SetSpansSection( false );
541  bLFStripped = false;
542  }
543  }
544 
545  return bSectionClosed;
546 }
547 
548 void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss )
549 {
550  OUString aId;
551  OUString aStyle, aClass, aLang, aDir;
552  tools::Long nWidth = 100;
553  sal_uInt16 nCols = columnsFromCss, nGutter = 10;
554  bool bPercentWidth = true;
555 
556  const HTMLOptions& rHTMLOptions = GetOptions();
557  for (size_t i = rHTMLOptions.size(); i; )
558  {
559  const HTMLOption& rOption = rHTMLOptions[--i];
560  switch( rOption.GetToken() )
561  {
562  case HtmlOptionId::ID:
563  aId = rOption.GetString();
564  break;
565  case HtmlOptionId::STYLE:
566  aStyle = rOption.GetString();
567  break;
568  case HtmlOptionId::CLASS:
569  aClass = rOption.GetString();
570  break;
571  case HtmlOptionId::LANG:
572  aLang = rOption.GetString();
573  break;
574  case HtmlOptionId::DIR:
575  aDir = rOption.GetString();
576  break;
577  case HtmlOptionId::COLS:
578  nCols = o3tl::narrowing<sal_uInt16>(rOption.GetNumber());
579  break;
580  case HtmlOptionId::WIDTH:
581  nWidth = rOption.GetNumber();
582  bPercentWidth = (rOption.GetString().indexOf('%') != -1);
583  if( bPercentWidth && nWidth>100 )
584  nWidth = 100;
585  break;
586  case HtmlOptionId::GUTTER:
587  nGutter = o3tl::narrowing<sal_uInt16>(rOption.GetNumber());
588  break;
589  default: break;
590  }
591  }
592 
593  std::unique_ptr<HTMLAttrContext> xCntxt(new HTMLAttrContext(HtmlTokenId::MULTICOL_ON));
594 
595  //.is the multicol element contained in a container? That may be the
596  // case for 5.0 documents.
597  bool bInCntnr = false;
598  auto i = m_aContexts.size();
599  while( !bInCntnr && i > m_nContextStMin )
600  bInCntnr = nullptr != m_aContexts[--i]->GetFrameItemSet();
601 
602  // Parse style sheets, but don't position anything by now.
603  bool bStyleParsed = false;
604  SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
605  SvxCSS1PropertyInfo aPropInfo;
606  if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
607  bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
608  aItemSet, aPropInfo, &aLang, &aDir );
609 
610  // Calculate width.
611  sal_uInt8 nPercentWidth = bPercentWidth ? static_cast<sal_uInt8>(nWidth) : 0;
612  SwTwips nTwipWidth = 0;
613  if( !bPercentWidth && nWidth && Application::GetDefaultDevice() )
614  {
615  nTwipWidth = Application::GetDefaultDevice()
616  ->PixelToLogic( Size(nWidth, 0),
617  MapMode(MapUnit::MapTwip) ).Width();
618  }
619 
620  if( !nPercentWidth && nTwipWidth < MINFLY )
621  nTwipWidth = MINFLY;
622 
623  // Do positioning.
624  bool bPositioned = false;
625  if( bInCntnr || SwCSS1Parser::MayBePositioned( aPropInfo, true ) )
626  {
627  SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() );
628  if( !IsNewDoc() )
629  Reader::ResetFrameFormatAttrs(aFrameItemSet );
630 
632  aFrameItemSet );
633 
634  // The width is either the WIDTH attribute's value or contained
635  // in some style option.
636  SetVarSize( aPropInfo, aFrameItemSet, nTwipWidth, nPercentWidth );
637 
638  SetSpace( Size(0,0), aItemSet, aPropInfo, aFrameItemSet );
639 
640  // Set some other frame attributes. If the background is set, its
641  // it will be cleared here. That for, it won't be set at the section,
642  // too.
643  SetFrameFormatAttrs( aItemSet,
645  aFrameItemSet );
646 
647  // Insert fly frame. If the are columns, the fly frame's name is not
648  // the sections name but a generated one.
649  OUString aFlyName;
650  if( nCols < 2 )
651  {
652  aFlyName = aId;
653  aPropInfo.m_aId.clear();
654  }
655 
656  InsertFlyFrame(aFrameItemSet, xCntxt.get(), aFlyName);
657 
658  xCntxt->SetPopStack( true );
659  bPositioned = true;
660  }
661 
662  bool bAppended = false;
663  if( !bPositioned )
664  {
665  if( m_pPam->GetPoint()->nContent.GetIndex() )
666  {
668  bAppended = true;
669  }
670  else
671  {
672  AddParSpace();
673  }
674  }
675 
676  // If there are less than 2 columns, no section is inserted.
677  if( nCols >= 2 )
678  {
679  if( !bAppended )
680  {
681  // If the pam is at the start of a section, an additional text
682  // node must be inserted. Otherwise, the new section will be
683  // inserted in front of the old one.
684  SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->nNode, -1 );
685  if (aPrvNdIdx.GetNode().IsSectionNode())
686  {
687  AppendTextNode();
688  bAppended = true;
689  }
690  }
691  std::unique_ptr<std::deque<std::unique_ptr<HTMLAttr>>> pPostIts(bAppended ? nullptr : new std::deque<std::unique_ptr<HTMLAttr>>);
692  SetAttr( true, true, pPostIts.get() );
693 
694  // Make section name unique.
695  OUString aName( m_xDoc->GetUniqueSectionName( !aId.isEmpty() ? &aId : nullptr ) );
696  SwSectionData aSection( SectionType::Content, aName );
697 
698  SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() );
699  if( !IsNewDoc() )
700  Reader::ResetFrameFormatAttrs(aFrameItemSet );
701 
702  if( nGutter && Application::GetDefaultDevice() )
703  {
704  nGutter = o3tl::narrowing<sal_uInt16>(Application::GetDefaultDevice()
705  ->PixelToLogic( Size(nGutter, 0),
706  MapMode(MapUnit::MapTwip) ).Width());
707  }
708 
709  SwFormatCol aFormatCol;
710 
711  aFormatCol.Init( nCols, nGutter, USHRT_MAX );
712  aFrameItemSet.Put( aFormatCol );
713 
714  if( const SvxBrushItem* pItem = aItemSet.GetItemIfSet( RES_BACKGROUND, false) )
715  {
716  aFrameItemSet.Put( *pItem );
717  aItemSet.ClearItem( RES_BACKGROUND );
718  }
719  if( const SvxFrameDirectionItem* pItem = aItemSet.GetItemIfSet( RES_FRAMEDIR, false ) )
720  {
721  aFrameItemSet.Put( *pItem );
722  aItemSet.ClearItem( RES_FRAMEDIR );
723  }
724  m_xDoc->InsertSwSection( *m_pPam, aSection, nullptr, &aFrameItemSet, false );
725 
726  // Jump to section, if this is requested.
727  if( JumpToMarks::Region == m_eJumpTo && aName == m_sJmpMark )
728  {
729  m_bChkJumpMark = true;
731  }
732 
733  SwTextNode* pOldTextNd =
734  bAppended ? nullptr : m_pPam->GetPoint()->nNode.GetNode().GetTextNode();
735 
737 
738  // Move PageDesc and SwFormatBreak attributes of the current node
739  // to the section's first node.
740  if( pOldTextNd )
741  MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->nNode.GetIndex(),
742  true );
743 
744  if( pPostIts )
745  {
746  // Move pending PostIts into the section.
747  InsertAttrs( std::move(*pPostIts) );
748  pPostIts.reset();
749  }
750 
751  xCntxt->SetSpansSection( true );
752 
753  // Insert a bookmark if its name differs from the section's name only.
754  if( !aPropInfo.m_aId.isEmpty() && aPropInfo.m_aId==aName )
755  aPropInfo.m_aId.clear();
756  }
757 
758  // Additional attributes must be set as hard ones.
759  if( bStyleParsed )
760  InsertAttrs( aItemSet, aPropInfo, xCntxt.get(), true );
761 
762  PushContext(xCntxt);
763 }
764 
766  HTMLAttrContext *pCntxt,
767  const OUString& rName )
768 {
769  RndStdIds eAnchorId =
770  rItemSet.Get( RES_ANCHOR ).GetAnchorId();
771 
772  // create frame
773  SwFlyFrameFormat* pFlyFormat = m_xDoc->MakeFlySection( eAnchorId, m_pPam->GetPoint(),
774  &rItemSet );
775  if( !rName.isEmpty() )
776  pFlyFormat->SetName( rName );
777 
778  RegisterFlyFrame( pFlyFormat );
779 
780  const SwFormatContent& rFlyContent = pFlyFormat->GetContent();
781  const SwNodeIndex& rFlyCntIdx = *rFlyContent.GetContentIdx();
782  SwContentNode *pCNd = m_xDoc->GetNodes()[rFlyCntIdx.GetIndex()+1]
783  ->GetContentNode();
784 
785  SwPosition aNewPos( SwNodeIndex( rFlyCntIdx, 1 ), SwIndex( pCNd, 0 ) );
787  SaveDocContext( pCntxt, nFlags, &aNewPos );
788 }
789 
791  SwNodeOffset nDestIdx,
792  bool bFormatBreak )
793 {
794  SwContentNode* pDestContentNd =
795  m_xDoc->GetNodes()[nDestIdx]->GetContentNode();
796 
797  OSL_ENSURE( pDestContentNd, "Why is the target not a Content-Node?" );
798 
799  if( pSrcNd->IsContentNode() )
800  {
801  SwContentNode* pSrcContentNd = pSrcNd->GetContentNode();
802 
803  const SwFormatPageDesc* pFormatPageDesc =
804  pSrcContentNd->GetSwAttrSet().GetItemIfSet( RES_PAGEDESC, false );
805  if( pFormatPageDesc && pFormatPageDesc->GetPageDesc() )
806  {
807  pDestContentNd->SetAttr( *pFormatPageDesc );
808  pSrcContentNd->ResetAttr( RES_PAGEDESC );
809  }
810  if( const SvxFormatBreakItem* pItem = pSrcContentNd->GetSwAttrSet()
811  .GetItemIfSet( RES_BREAK, false ) )
812  {
813  switch( pItem->GetBreak() )
814  {
815  case SvxBreak::PageBefore:
816  case SvxBreak::PageAfter:
817  case SvxBreak::PageBoth:
818  if( bFormatBreak )
819  pDestContentNd->SetAttr( *pItem );
820  pSrcContentNd->ResetAttr( RES_BREAK );
821  break;
822  default:
823  break;
824  }
825  }
826  }
827  else if( pSrcNd->IsTableNode() )
828  {
829  SwFrameFormat *pFrameFormat = pSrcNd->GetTableNode()->GetTable().GetFrameFormat();
830 
831  if( const SwFormatPageDesc* pItem = pFrameFormat->GetAttrSet().
832  GetItemIfSet( RES_PAGEDESC, false ) )
833  {
834  if (pDestContentNd)
835  pDestContentNd->SetAttr(*pItem);
836  pFrameFormat->ResetFormatAttr( RES_PAGEDESC );
837  }
838  }
839 }
840 
841 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Starts a section of nodes in the document model.
Definition: node.hxx:313
bool EndSection(bool bLFStripped=false)
Definition: htmlsect.cxx:512
constexpr TypedWhichId< SvxFrameDirectionItem > RES_FRAMEDIR(120)
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
static void SetSpace(const Size &rPixSpace, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, SfxItemSet &rFlyItemSet)
Definition: htmlplug.cxx:243
URL aURL
void SetAnchorAndAdjustment(sal_Int16 eVertOri, sal_Int16 eHoriOri, const SvxCSS1PropertyInfo &rPropInfo, SfxItemSet &rFrameSet)
Definition: htmlgrin.cxx:151
EnumT GetEnum(const HTMLOptionEnum< EnumT > *pOptEnums, EnumT nDflt=static_cast< EnumT >(0)) const
HtmlOptionId GetToken() const
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:687
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
Marks a position in the document model.
Definition: pam.hxx:36
void SetAttr(bool bChkEnd=true, bool bBeforeTable=false, std::deque< std::unique_ptr< HTMLAttr >> *pPostIts=nullptr)
Definition: swhtml.hxx:508
bool IsSectionNode() const
Definition: node.hxx:654
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
sal_uInt16 GetLower() const
void SetHidden(bool const bFlag)
Definition: section.hxx:97
SwPageDesc * GetPageDesc()
Definition: fmtpdsc.hxx:61
SAL_DLLPRIVATE void SetProtectFlag(bool const bFlag)
Definition: section.hxx:104
void FixHeaderFooterDistance(bool bHeader, const SwPosition *pOldPos)
Definition: htmlsect.cxx:424
void SetLinkFileName(OUString const &rNew)
Definition: section.hxx:116
const SwFormatHeader & GetHeader(bool=true) const
Definition: fmthdft.hxx:97
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:4885
SwNodeIndex nNode
Definition: pam.hxx:38
bool CreateContainer(std::u16string_view rClass, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, HTMLAttrContext *pContext)
Definition: htmlctxt.cxx:504
#define MINFLY
Definition: swtypes.hxx:61
long Long
const sal_Unicode cTokenSeparator
const OUString & GetString() const
constexpr sal_uInt16 RES_FRMATR_END(133)
JumpToMarks m_eJumpTo
Definition: swhtml.hxx:424
HTMLAttrContexts m_aContexts
Definition: swhtml.hxx:379
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(94)
SwNode & GetNode() const
Definition: ndindex.hxx:119
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:31
OUString m_sBaseURL
Definition: swhtml.hxx:357
bool m_bReadingHeaderOrFooter
Definition: swhtml.hxx:470
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:204
static OutputDevice * GetDefaultDevice()
void NewDivision(HtmlTokenId nToken)
Definition: htmlsect.cxx:55
sal_uInt16 sal_Unicode
static void ResetFrameFormatAttrs(SfxItemSet &rFrameSet)
Definition: shellio.cxx:613
SwTableNode * GetTableNode()
Definition: node.hxx:609
SwIndex nContent
Definition: pam.hxx:39
void InsertAttrs(std::deque< std::unique_ptr< HTMLAttr >> rAttrs)
Definition: swhtml.cxx:3486
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:1838
Footer, for pageformats Client of FrameFormat describing the footer.
Definition: fmthdft.hxx:64
virtual void SetName(const OUString &rNewName, bool bBroadcast=false) override
Definition: atrfrm.cxx:2560
HtmlContextFlags
Definition: swhtml.hxx:311
const SwTable & GetTable() const
Definition: node.hxx:506
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:152
SwPaM * m_pPam
Definition: swhtml.hxx:393
void EndDivision()
Definition: htmlsect.cxx:395
const sal_Unicode cDelim
#define OOO_STRING_SVTOOLS_HTML_sdfootnote
void SetLower(const sal_uInt16 nL, const sal_uInt16 nProp=100)
void InsertAttr(const SfxPoolItem &rItem, bool bInsAtStart)
Definition: swhtml.cxx:3477
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:717
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: node.cxx:1659
OUString m_sJmpMark
Definition: swhtml.hxx:368
static void SetFrameFormatAttrs(SfxItemSet &rItemSet, HtmlFrameFormatFlags nFlags, SfxItemSet &rFrameItemSet)
Definition: htmlcss1.cxx:2061
bool IsContentNode() const
Definition: node.hxx:638
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
SwNodeIndex * GetFootEndNoteSection(const OUString &rName)
Definition: htmlftn.cxx:220
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:502
Style of a layout element.
Definition: frmfmt.hxx:59
SvxAdjust
int i
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:133
const SwFrameFormat * GetFooterFormat() const
Definition: fmthdft.hxx:85
const SwPosition * GetPoint() const
Definition: pam.hxx:208
Text body.
Definition: poolfmt.hxx:251
std::unique_ptr< SwCSS1Parser > m_pCSS1Parser
Definition: swhtml.hxx:388
SwContentNode * GetContentNode()
Definition: node.hxx:625
void AddParSpace()
Definition: swhtml.cxx:2491
void EndContext(HTMLAttrContext *pContext)
Definition: htmlctxt.cxx:371
Marks a character position inside a document model node.
Definition: index.hxx:33
const SwFormatFooter & GetFooter(bool=true) const
Definition: fmthdft.hxx:99
void StripTrailingPara()
Definition: htmlgrin.cxx:1408
bool DoPositioning(SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, HTMLAttrContext *pContext)
Definition: htmlctxt.cxx:467
void SetSpansSection(bool bSet)
Definition: swhtml.hxx:269
Marks a node in the document model.
Definition: ndindex.hxx:30
void RegisterFlyFrame(SwFrameFormat *pFlyFrame)
Definition: htmlgrin.cxx:278
void InsertFlyFrame(const SfxItemSet &rItemSet, HTMLAttrContext *pCntxt, const OUString &rId)
Definition: htmlsect.cxx:765
tools::Long SwTwips
Definition: swtypes.hxx:51
sal_uInt32 GetNumber() const
size_t m_nContextStMin
Definition: swhtml.hxx:418
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
void NewMultiCol(sal_uInt16 columnsFromCss=0)
Definition: htmlsect.cxx:548
HtmlTokenId
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:448
SwFrameFormat & GetMaster()
Definition: pagedesc.hxx:238
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:76
void MovePageDescAttrs(SwNode *pSrcNd, SwNodeOffset nDestIdx, bool bFormatBreak)
Definition: htmlsect.cxx:790
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:619
bool EndSections(bool bLFStripped)
Definition: htmlsect.cxx:530
virtual bool SetAttr(const SfxPoolItem &)
made virtual
Definition: node.cxx:1566
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(105)
HTMLOptionEnum< SvxAdjust > const aHTMLPAlignTable[]
Definition: swhtml.cxx:141
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
#define OOO_STRING_SVTOOLS_HTML_sdendnote
unsigned char sal_uInt8
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
::std::vector< HTMLOption > HTMLOptions
OUString aName
sal_Int32 GetIndex() const
Definition: index.hxx:91
static void SetVarSize(SvxCSS1PropertyInfo const &rPropInfo, SfxItemSet &rFlyItemSet, SwTwips nDfltWidth=MINLAY, sal_uInt8 nDefaultPercentWidth=0)
Definition: htmlcss1.cxx:2022
Header, for PageFormats Client of FrameFormat describing the header.
Definition: fmthdft.hxx:33
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:724
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
RndStdIds
bool IsTableNode() const
Definition: node.hxx:650
Ends a section of nodes in the document model.
Definition: node.hxx:343
std::shared_ptr< HTMLAttrTable > m_xAttrTab
Definition: swhtml.hxx:378
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:476
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
bool AppendTextNode(SwHTMLAppendMode eMode=AM_NORMAL, bool bUpdateNum=true)
Definition: swhtml.cxx:2188
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0) override
Definition: ndtxt.cxx:5119
void Init(sal_uInt16 nNumCols, sal_uInt16 nGutterWidth, sal_uInt16 nAct)
This function allows to (repeatedly) initialize the columns.
Definition: atrfrm.cxx:970
void PushContext(std::unique_ptr< HTMLAttrContext > &rCntxt)
Definition: swhtml.hxx:572
bool m_bChkJumpMark
Definition: swhtml.hxx:458
void SetUpper(const sal_uInt16 nU, const sal_uInt16 nProp=100)
rtl::Reference< SwDoc > m_xDoc
Definition: swhtml.hxx:392
void SaveDocContext(HTMLAttrContext *pCntxt, HtmlContextFlags nFlags, const SwPosition *pNewPos)
Definition: htmlctxt.cxx:272
constexpr sal_uInt16 RES_FRMATR_BEGIN(RES_PARATR_LIST_END)
constexpr TypedWhichId< SvxULSpaceItem > RES_UL_SPACE(92)
constexpr TypedWhichId< SvxAdjustItem > RES_PARATR_ADJUST(64)
bool GetSpansSection() const
Definition: swhtml.hxx:270
const SwFrameFormat * GetHeaderFormat() const
Definition: fmthdft.hxx:54
sal_uInt16 nPos
static bool MayBePositioned(const SvxCSS1PropertyInfo &rPropInfo, bool bAutoWidth=false)
Definition: htmlcss1.cxx:1409
constexpr TypedWhichId< SwFormatAnchor > RES_ANCHOR(104)
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:1014
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:864
sal_uInt16 GetUpper() const
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)
Base class of the Writer document model elements.
Definition: node.hxx:81
OUString aId