remove assert looking for new compatibilityMode DOCX
[LibreOffice.git] / sw / source / filter / html / htmlctxt.cxx
blobe8ffc2c9884857a34d02deaba232f67dc906d948
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 <com/sun/star/text/HoriOrientation.hpp>
21 #include <com/sun/star/text/VertOrientation.hpp>
23 #include <hintids.hxx>
24 #include <svl/itemiter.hxx>
25 #include <editeng/lrspitem.hxx>
26 #include <editeng/ulspitem.hxx>
27 #include <editeng/brushitem.hxx>
28 #include <editeng/fhgtitem.hxx>
29 #include <svtools/htmltokn.h>
30 #include <editeng/boxitem.hxx>
31 #include <osl/diagnose.h>
32 #include <o3tl/string_view.hxx>
34 #include <doc.hxx>
35 #include <pam.hxx>
36 #include <shellio.hxx>
37 #include <paratr.hxx>
38 #include "htmlnum.hxx"
39 #include "swcss1.hxx"
40 #include "swhtml.hxx"
42 #include <memory>
43 #include <utility>
45 using namespace ::com::sun::star;
47 class HTMLAttrContext_SaveDoc
49 SwHTMLNumRuleInfo m_aNumRuleInfo; // Numbering for this environment
50 std::unique_ptr<SwPosition>
51 m_pPos; // Jump back to here when leaving context
52 std::shared_ptr<HTMLAttrTable>
53 m_xAttrTab; // Valid attributes for the environment,
54 // if attributes shouldn't be preserved
56 size_t m_nContextStMin; // Stack lower bound for the environment
57 // if stack needs to be protected
58 size_t m_nContextStAttrMin; // Stack lower bound for the environment
59 // if the attributes shouldn't be preserved
60 bool m_bStripTrailingPara : 1;
61 bool m_bKeepNumRules : 1;
62 bool m_bFixHeaderDist : 1;
63 bool m_bFixFooterDist : 1;
65 public:
67 HTMLAttrContext_SaveDoc() :
68 m_nContextStMin( SIZE_MAX ), m_nContextStAttrMin( SIZE_MAX ),
69 m_bStripTrailingPara( false ), m_bKeepNumRules( false ),
70 m_bFixHeaderDist( false ), m_bFixFooterDist( false )
73 // The position is ours, so we need to create and delete it
74 void SetPos( const SwPosition& rPos ) { m_pPos.reset( new SwPosition(rPos) ); }
75 const SwPosition *GetPos() const { return m_pPos.get(); }
77 // The index isn't ours. So no creation or deletion
78 void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { m_aNumRuleInfo.Set(rInf); }
79 const SwHTMLNumRuleInfo& GetNumInfo() const { return m_aNumRuleInfo; }
81 std::shared_ptr<HTMLAttrTable> const & GetAttrTab(bool bCreate = false);
83 void SetContextStMin( size_t nMin ) { m_nContextStMin = nMin; }
84 size_t GetContextStMin() const { return m_nContextStMin; }
86 void SetContextStAttrMin( size_t nMin ) { m_nContextStAttrMin = nMin; }
87 size_t GetContextStAttrMin() const { return m_nContextStAttrMin; }
89 void SetStripTrailingPara( bool bSet ) { m_bStripTrailingPara = bSet; }
90 bool GetStripTrailingPara() const { return m_bStripTrailingPara; }
92 void SetKeepNumRules( bool bSet ) { m_bKeepNumRules = bSet; }
93 bool GetKeepNumRules() const { return m_bKeepNumRules; }
95 void SetFixHeaderDist( bool bSet ) { m_bFixHeaderDist = bSet; }
96 bool GetFixHeaderDist() const { return m_bFixHeaderDist; }
98 void SetFixFooterDist( bool bSet ) { m_bFixFooterDist = bSet; }
99 bool GetFixFooterDist() const { return m_bFixFooterDist; }
102 std::shared_ptr<HTMLAttrTable> const & HTMLAttrContext_SaveDoc::GetAttrTab( bool bCreate )
104 if (!m_xAttrTab && bCreate)
106 m_xAttrTab = std::make_shared<HTMLAttrTable>();
107 memset(m_xAttrTab.get(), 0, sizeof(HTMLAttrTable));
109 return m_xAttrTab;
112 HTMLAttrContext_SaveDoc *HTMLAttrContext::GetSaveDocContext( bool bCreate )
114 if( !m_pSaveDocContext && bCreate )
115 m_pSaveDocContext.reset(new HTMLAttrContext_SaveDoc);
117 return m_pSaveDocContext.get();
120 HTMLAttrContext::HTMLAttrContext( HtmlTokenId nTokn, sal_uInt16 nPoolId, OUString aClass,
121 bool bDfltColl ) :
122 m_aClass(std::move( aClass )),
123 m_nToken( nTokn ),
124 m_nTextFormatColl( nPoolId ),
125 m_nLeftMargin( 0 ),
126 m_nRightMargin( 0 ),
127 m_nFirstLineIndent( 0 ),
128 m_nUpperSpace( 0 ),
129 m_nLowerSpace( 0 ),
130 m_eAppend( AM_NONE ),
131 m_bLRSpaceChanged( false ),
132 m_bULSpaceChanged( false ),
133 m_bDefaultTextFormatColl( bDfltColl ),
134 m_bSpansSection( false ),
135 m_bPopStack( false ),
136 m_bFinishPREListingXMP( false ),
137 m_bRestartPRE( false ),
138 m_bRestartXMP( false ),
139 m_bRestartListing( false ),
140 m_bHeaderOrFooter( false )
143 HTMLAttrContext::HTMLAttrContext( HtmlTokenId nTokn ) :
144 m_nToken( nTokn ),
145 m_nTextFormatColl( 0 ),
146 m_nLeftMargin( 0 ),
147 m_nRightMargin( 0 ),
148 m_nFirstLineIndent( 0 ),
149 m_nUpperSpace( 0 ),
150 m_nLowerSpace( 0 ),
151 m_eAppend( AM_NONE ),
152 m_bLRSpaceChanged( false ),
153 m_bULSpaceChanged( false ),
154 m_bDefaultTextFormatColl( false ),
155 m_bSpansSection( false ),
156 m_bPopStack( false ),
157 m_bFinishPREListingXMP( false ),
158 m_bRestartPRE( false ),
159 m_bRestartXMP( false ),
160 m_bRestartListing( false ),
161 m_bHeaderOrFooter( false )
164 HTMLAttrContext::~HTMLAttrContext()
166 m_pSaveDocContext.reset();
169 void HTMLAttrContext::ClearSaveDocContext()
171 m_pSaveDocContext.reset();
174 void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos )
176 // preliminary paragraph attributes are not allowed here, they could
177 // be set here and then the pointers become invalid!
178 OSL_ENSURE(m_aParaAttrs.empty(),
179 "Danger: there are non-final paragraph attributes");
180 m_aParaAttrs.clear();
182 const SwPosition* pOldEndPara = m_pPam->GetPoint();
183 #ifndef NDEBUG
184 auto const nOld(pOldEndPara->GetNodeIndex());
185 #endif
186 sal_Int32 nOldEndCnt = m_pPam->GetPoint()->GetContentIndex();
188 const SwPosition& rNewSttPara = rNewPos;
189 sal_Int32 nNewSttCnt = rNewPos.GetContentIndex();
191 bool bMoveBack = false;
193 // close all open attributes and re-open them after the table
194 HTMLAttr** pHTMLAttributes = reinterpret_cast<HTMLAttr**>(m_xAttrTab.get());
195 for (auto nCnt = sizeof(HTMLAttrTable) / sizeof(HTMLAttr*); nCnt--; ++pHTMLAttributes)
197 HTMLAttr *pAttr = *pHTMLAttributes;
198 while( pAttr )
200 HTMLAttr *pNext = pAttr->GetNext();
201 HTMLAttr *pPrev = pAttr->GetPrev();
203 sal_uInt16 nWhich = pAttr->m_pItem->Which();
204 if( !nOldEndCnt && RES_PARATR_BEGIN <= nWhich &&
205 pAttr->GetStartParagraphIdx() < pOldEndPara->GetNodeIndex() )
207 // The attribute needs to be closed one content position beforehand
208 if( !bMoveBack )
210 bMoveBack = m_pPam->Move( fnMoveBackward );
211 nOldEndCnt = m_pPam->GetPoint()->GetContentIndex();
214 else if( bMoveBack )
216 m_pPam->Move( fnMoveForward );
217 nOldEndCnt = m_pPam->GetPoint()->GetContentIndex();
218 bMoveBack = false;
221 if( (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
222 pAttr->GetStartParagraphIdx() < pOldEndPara->GetNodeIndex() ||
223 (pAttr->GetStartParagraph() == pOldEndPara->GetNode() &&
224 pAttr->GetStartContent() != nOldEndCnt) )
226 // The attribute needs to be set. Because we still need the original, since
227 // pointers to the attribute still exists in the contexts, we need to clone it.
228 // The next-list gets lost but the previous-list is preserved
229 HTMLAttr *pSetAttr = pAttr->Clone( pOldEndPara->GetNode(), nOldEndCnt );
231 if( pNext )
232 pNext->InsertPrev( pSetAttr );
233 else
235 if (pSetAttr->m_bInsAtStart)
236 m_aSetAttrTab.push_front( pSetAttr );
237 else
238 m_aSetAttrTab.push_back( pSetAttr );
241 else if( pPrev )
243 // The previous attributes still need to be set, even if the current attribute
244 // doesn't need to be set before the table
245 if( pNext )
246 pNext->InsertPrev( pPrev );
247 else
249 if (pPrev->m_bInsAtStart)
250 m_aSetAttrTab.push_front( pPrev );
251 else
252 m_aSetAttrTab.push_back( pPrev );
256 // Set the start of the attribute
257 pAttr->m_nStartPara = rNewSttPara.GetNode();
258 pAttr->m_nEndPara = rNewSttPara.GetNode();
259 pAttr->m_nStartContent = nNewSttCnt;
260 pAttr->m_nEndContent = nNewSttCnt;
261 pAttr->m_pPrev = nullptr;
263 pAttr = pNext;
267 if( bMoveBack )
268 m_pPam->Move( fnMoveForward );
270 assert(m_pPam->GetPoint()->GetNodeIndex() == nOld);
273 void SwHTMLParser::SaveDocContext( HTMLAttrContext *pCntxt,
274 HtmlContextFlags nFlags,
275 const SwPosition *pNewPos )
277 HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext( true );
278 pSave->SetStripTrailingPara( bool(HtmlContextFlags::StripPara & nFlags) );
279 pSave->SetKeepNumRules( bool(HtmlContextFlags::KeepNumrule & nFlags) );
280 pSave->SetFixHeaderDist( bool(HtmlContextFlags::HeaderDist & nFlags) );
281 pSave->SetFixFooterDist( bool(HtmlContextFlags::FooterDist & nFlags) );
283 if( pNewPos )
285 // If the PaM needs to be set to a different position, we need to preserve numbering
286 if( !pSave->GetKeepNumRules() )
288 // Numbering shall not be preserved. So we need to preserve the current state
289 // and turn off numbering afterwards
290 pSave->SetNumInfo( GetNumInfo() );
291 GetNumInfo().Clear();
294 if( HtmlContextFlags::KeepAttrs & nFlags )
296 // Close attribute on current position and start on new one
297 SplitAttrTab( *pNewPos );
299 else
301 std::shared_ptr<HTMLAttrTable> xSaveAttrTab = pSave->GetAttrTab(true);
302 SaveAttrTab(xSaveAttrTab);
305 pSave->SetPos( *m_pPam->GetPoint() );
306 *m_pPam->GetPoint() = *pNewPos;
309 // Settings nContextStMin automatically means, that no
310 // currently open lists (DL/OL/UL) can be closed
311 if( HtmlContextFlags::ProtectStack & nFlags )
313 pSave->SetContextStMin( m_nContextStMin );
314 m_nContextStMin = m_aContexts.size();
316 if( HtmlContextFlags::KeepAttrs & nFlags )
318 pSave->SetContextStAttrMin( m_nContextStAttrMin );
319 m_nContextStAttrMin = m_aContexts.size();
324 void SwHTMLParser::RestoreDocContext( HTMLAttrContext *pCntxt )
326 HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext();
327 if( !pSave )
328 return;
330 if( pSave->GetStripTrailingPara() )
331 StripTrailingPara();
333 if( pSave->GetPos() )
335 if( pSave->GetFixHeaderDist() || pSave->GetFixFooterDist() )
336 FixHeaderFooterDistance( pSave->GetFixHeaderDist(),
337 pSave->GetPos() );
339 std::shared_ptr<HTMLAttrTable> xSaveAttrTab = pSave->GetAttrTab();
340 if (!xSaveAttrTab)
342 // Close attribute on current position and start on the old one
343 SplitAttrTab( *pSave->GetPos() );
345 else
347 RestoreAttrTab(xSaveAttrTab);
350 *m_pPam->GetPoint() = *pSave->GetPos();
352 // We can already set the attributes so far
353 SetAttr();
356 if( SIZE_MAX != pSave->GetContextStMin() )
358 m_nContextStMin = pSave->GetContextStMin();
359 if( SIZE_MAX != pSave->GetContextStAttrMin() )
360 m_nContextStAttrMin = pSave->GetContextStAttrMin();
363 if( !pSave->GetKeepNumRules() )
365 // Set the preserved numbering back
366 GetNumInfo().Set( pSave->GetNumInfo() );
369 pCntxt->ClearSaveDocContext();
372 void SwHTMLParser::EndContext( HTMLAttrContext *pContext )
374 if( pContext->GetPopStack() )
376 // Close all still open contexts. Our own context needs to be deleted already!
377 while( m_aContexts.size() > m_nContextStMin )
379 std::unique_ptr<HTMLAttrContext> xCntxt(PopContext());
380 OSL_ENSURE(xCntxt.get() != pContext,
381 "Context still on the stack" );
382 if (xCntxt.get() == pContext)
383 break;
385 EndContext(xCntxt.get());
389 // Close all still open attributes
390 if( pContext->HasAttrs() )
391 EndContextAttrs( pContext );
393 // If a section has been opened, end it. Since sections can be part of absolute-positioned
394 // objects, this needs to be done before restoring document context
395 if( pContext->GetSpansSection() )
396 EndSection();
398 // Leave borders and other special sections
399 if( pContext->HasSaveDocContext() )
400 RestoreDocContext( pContext );
402 // Add a paragraph break if needed
403 if( AM_NONE != pContext->GetAppendMode() &&
404 m_pPam->GetPoint()->GetContentIndex() )
405 AppendTextNode( pContext->GetAppendMode() );
407 // Restart PRE, LISTING and XMP environments
408 if( pContext->IsFinishPREListingXMP() )
409 FinishPREListingXMP();
411 if( pContext->IsRestartPRE() )
412 StartPRE();
414 if( pContext->IsRestartXMP() )
415 StartXMP();
417 if( pContext->IsRestartListing() )
418 StartListing();
421 void SwHTMLParser::ClearContext( HTMLAttrContext *pContext )
423 HTMLAttrs &rAttrs = pContext->GetAttrs();
424 for( auto pAttr : rAttrs )
426 // Simple deletion doesn't to the job, since the attribute
427 // needs to be deregistered with its list.
428 // In theory, you could delete the list and its attributes separately
429 // but if you get that wrong, quite a lot is messed up
430 DeleteAttr( pAttr );
432 rAttrs.clear();
434 OSL_ENSURE( !pContext->GetSpansSection(),
435 "Area can no longer be exited" );
437 OSL_ENSURE( !pContext->HasSaveDocContext(),
438 "Frame can no longer be exited" );
440 // like RestoreDocContext reset enough of this to not catastrophically
441 // fail if we still have a SaveDocContext here
442 if (HTMLAttrContext_SaveDoc *pSave = pContext->GetSaveDocContext())
444 if (SIZE_MAX != pSave->GetContextStMin())
446 m_nContextStMin = pSave->GetContextStMin();
447 if (SIZE_MAX != pSave->GetContextStAttrMin())
448 m_nContextStAttrMin = pSave->GetContextStAttrMin();
451 pContext->ClearSaveDocContext();
454 // Restart PRE/LISTING/XMP environments
455 if( pContext->IsFinishPREListingXMP() )
456 FinishPREListingXMP();
458 if( pContext->IsRestartPRE() )
459 StartPRE();
461 if( pContext->IsRestartXMP() )
462 StartXMP();
464 if( pContext->IsRestartListing() )
465 StartListing();
468 bool SwHTMLParser::DoPositioning( SfxItemSet &rItemSet,
469 SvxCSS1PropertyInfo &rPropInfo,
470 HTMLAttrContext *pContext )
472 bool bRet = false;
474 // A border is opened on the following conditions
475 // - the tag is absolute-positioned AND left/top are both known AND don't contain a % property
476 // OR
477 // - the tag should be floating AND
478 // - there's a given width
479 if( SwCSS1Parser::MayBePositioned( rPropInfo ) )
481 SfxItemSet aFrameItemSet(SfxItemSet::makeFixedSfxItemSet<RES_FRMATR_BEGIN, RES_FRMATR_END-1>(m_xDoc->GetAttrPool()));
482 if( !IsNewDoc() )
483 Reader::ResetFrameFormatAttrs(aFrameItemSet );
485 SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, rPropInfo,
486 aFrameItemSet );
488 SetVarSize( rPropInfo, aFrameItemSet );
490 SetSpace( Size(0,0), rItemSet, rPropInfo, aFrameItemSet );
492 SetFrameFormatAttrs( rItemSet,
493 HtmlFrameFormatFlags::Box|HtmlFrameFormatFlags::Padding|HtmlFrameFormatFlags::Background|HtmlFrameFormatFlags::Direction,
494 aFrameItemSet );
496 InsertFlyFrame(aFrameItemSet, pContext, rPropInfo.m_aId);
497 pContext->SetPopStack( true );
498 rPropInfo.m_aId.clear();
499 bRet = true;
502 return bRet;
505 bool SwHTMLParser::CreateContainer( std::u16string_view rClass,
506 SfxItemSet &rItemSet,
507 SvxCSS1PropertyInfo &rPropInfo,
508 HTMLAttrContext *pContext )
510 bool bRet = false;
511 if( o3tl::equalsIgnoreAsciiCase( rClass, u"sd-abs-pos" ) &&
512 SwCSS1Parser::MayBePositioned( rPropInfo ) )
514 // Container class
515 SfxItemSet *pFrameItemSet = pContext->GetFrameItemSet( m_xDoc.get() );
516 if( !IsNewDoc() )
517 Reader::ResetFrameFormatAttrs( *pFrameItemSet );
519 SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE,
520 rPropInfo, *pFrameItemSet );
521 Size aDummy(0,0);
522 SetFixSize( aDummy, aDummy, false, false, rPropInfo, *pFrameItemSet );
523 SetSpace( aDummy, rItemSet, rPropInfo, *pFrameItemSet );
524 SetFrameFormatAttrs( rItemSet, HtmlFrameFormatFlags::Box|HtmlFrameFormatFlags::Background|HtmlFrameFormatFlags::Direction,
525 *pFrameItemSet );
527 bRet = true;
530 return bRet;
533 void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet,
534 SvxCSS1PropertyInfo const &rPropInfo,
535 HTMLAttrContext *pContext,
536 bool bCharLvl )
538 // Put together a DropCap attribute, if a "float:left" is before the first character
539 if( bCharLvl && !m_pPam->GetPoint()->GetContentIndex() &&
540 SvxAdjust::Left == rPropInfo.m_eFloat )
542 SwFormatDrop aDrop;
543 aDrop.SetChars(1);
545 m_pCSS1Parser->FillDropCap( aDrop, rItemSet );
547 // We only set the DropCap attribute if the initial spans multiple lines
548 if( aDrop.GetLines() > 1 )
550 NewAttr(m_xAttrTab, &m_xAttrTab->pDropCap, aDrop);
552 HTMLAttrs &rAttrs = pContext->GetAttrs();
553 rAttrs.push_back( m_xAttrTab->pDropCap );
555 return;
559 if( !bCharLvl )
560 m_pCSS1Parser->SetFormatBreak( rItemSet, rPropInfo );
562 OSL_ENSURE(m_aContexts.size() <= m_nContextStAttrMin ||
563 m_aContexts.back().get() != pContext,
564 "SwHTMLParser::InsertAttrs: Context already on the Stack");
566 SfxItemIter aIter( rItemSet );
568 const SvxFirstLineIndentItem * pFirstLineItem(nullptr);
569 const SvxTextLeftMarginItem * pTextLeftMargin(nullptr);
570 const SvxRightMarginItem * pRightMargin(nullptr);
572 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
574 switch( pItem->Which() )
576 case RES_MARGIN_FIRSTLINE:
578 pFirstLineItem = &(pItem->StaticWhichCast(RES_MARGIN_FIRSTLINE));
580 break;
581 case RES_MARGIN_TEXTLEFT:
583 pTextLeftMargin = &(pItem->StaticWhichCast(RES_MARGIN_TEXTLEFT));
585 break;
586 case RES_MARGIN_RIGHT:
588 pRightMargin = &(pItem->StaticWhichCast(RES_MARGIN_RIGHT));
590 break;
594 #if 1
596 // Paragraph indents need to be added and are generated for each paragraphs
597 // (here for the first paragraph only, all the following in SetTextCollAttrs)
599 // Get old paragraph indents without the top context (that's the one we're editing)
600 sal_uInt16 nOldLeft = 0, nOldRight = 0;
601 short nOldIndent = 0;
602 bool bIgnoreTop = m_aContexts.size() > m_nContextStMin &&
603 m_aContexts.back().get() == pContext;
604 GetMarginsFromContext( nOldLeft, nOldRight, nOldIndent,
605 bIgnoreTop );
607 // ... and the currently valid ones
608 sal_uInt16 nLeft = nOldLeft, nRight = nOldRight;
609 short nIndent = nOldIndent;
610 pContext->GetMargins( nLeft, nRight, nIndent );
612 // ... and add the new indents to the old ones
613 // Here, we don't get the ones from the item but the separately remembered ones,
614 // since they could be negative. Accessing those via the item still works, since
615 // the item (with value 0) will be added
616 if( rPropInfo.m_bLeftMargin )
618 OSL_ENSURE(rPropInfo.m_nLeftMargin < 0 || !pTextLeftMargin
619 || rPropInfo.m_nLeftMargin
620 == pTextLeftMargin->ResolveTextLeft({}),
621 "left margin does not match with item");
622 if( rPropInfo.m_nLeftMargin < 0 &&
623 -rPropInfo.m_nLeftMargin > nOldLeft )
624 nLeft = 0;
625 else
626 nLeft = nOldLeft + static_cast< sal_uInt16 >(rPropInfo.m_nLeftMargin);
628 if( rPropInfo.m_bRightMargin )
630 OSL_ENSURE(rPropInfo.m_nRightMargin < 0 || !pRightMargin
631 || rPropInfo.m_nRightMargin == pRightMargin->ResolveRight({}),
632 "right margin does not match with item");
633 if( rPropInfo.m_nRightMargin < 0 &&
634 -rPropInfo.m_nRightMargin > nOldRight )
635 nRight = 0;
636 else
637 nRight = nOldRight + static_cast< sal_uInt16 >(rPropInfo.m_nRightMargin);
639 if (rPropInfo.m_bTextIndent && pFirstLineItem)
640 nIndent = pFirstLineItem->ResolveTextFirstLineOffset({});
642 // Remember the value for the following paragraphs
643 pContext->SetMargins( nLeft, nRight, nIndent );
645 // Set the attribute on the current paragraph
646 SvxFirstLineIndentItem firstLine(SvxIndentValue::twips(nIndent),
647 RES_MARGIN_FIRSTLINE);
648 NewAttr(m_xAttrTab, &m_xAttrTab->pFirstLineIndent, firstLine);
649 EndAttr(m_xAttrTab->pFirstLineIndent, false);
650 SvxTextLeftMarginItem const leftMargin(SvxIndentValue::twips(nLeft),
651 RES_MARGIN_TEXTLEFT);
652 NewAttr(m_xAttrTab, &m_xAttrTab->pTextLeftMargin, leftMargin);
653 EndAttr(m_xAttrTab->pTextLeftMargin, false);
654 SvxRightMarginItem const rightMargin(SvxIndentValue::twips(nRight),
655 RES_MARGIN_RIGHT);
656 NewAttr(m_xAttrTab, &m_xAttrTab->pRightMargin, rightMargin);
657 EndAttr(m_xAttrTab->pRightMargin, false);
659 #endif
661 SfxItemIter aIter2(rItemSet);
662 for (const SfxPoolItem* pItem = aIter2.GetCurItem(); pItem; pItem = aIter2.NextItem())
664 HTMLAttr **ppAttr = nullptr;
666 switch( pItem->Which() )
669 case RES_UL_SPACE:
670 if( !rPropInfo.m_bTopMargin || !rPropInfo.m_bBottomMargin )
672 sal_uInt16 nUpper = 0, nLower = 0;
673 GetULSpaceFromContext( nUpper, nLower );
674 SvxULSpaceItem aULSpace( pItem->StaticWhichCast(RES_UL_SPACE) );
675 if( !rPropInfo.m_bTopMargin )
676 aULSpace.SetUpper( nUpper );
677 if( !rPropInfo.m_bBottomMargin )
678 aULSpace.SetLower( nLower );
680 NewAttr(m_xAttrTab, &m_xAttrTab->pULSpace, aULSpace);
682 // save context information
683 HTMLAttrs &rAttrs = pContext->GetAttrs();
684 rAttrs.push_back( m_xAttrTab->pULSpace );
686 pContext->SetULSpace( aULSpace.GetUpper(), aULSpace.GetLower() );
688 else
690 ppAttr = &m_xAttrTab->pULSpace;
692 break;
693 case RES_CHRATR_FONTSIZE:
694 // don't set attributes with a % property
695 if( pItem->StaticWhichCast(RES_CHRATR_FONTSIZE).GetProp() == 100 )
696 ppAttr = &m_xAttrTab->pFontHeight;
697 break;
698 case RES_CHRATR_CJK_FONTSIZE:
699 // don't set attributes with a % property
700 if( pItem->StaticWhichCast(RES_CHRATR_CJK_FONTSIZE).GetProp() == 100 )
701 ppAttr = &m_xAttrTab->pFontHeightCJK;
702 break;
703 case RES_CHRATR_CTL_FONTSIZE:
704 // don't set attributes with a % property
705 if( pItem->StaticWhichCast(RES_CHRATR_CTL_FONTSIZE).GetProp() == 100 )
706 ppAttr = &m_xAttrTab->pFontHeightCTL;
707 break;
709 case RES_BACKGROUND:
710 if( bCharLvl )
712 // Convert the Frame attribute to a Char attribute (if needed)
713 SvxBrushItem aBrushItem( pItem->StaticWhichCast(RES_BACKGROUND) );
714 aBrushItem.SetWhich( RES_CHRATR_BACKGROUND );
716 // Set the attribute
717 NewAttr(m_xAttrTab, &m_xAttrTab->pCharBrush, aBrushItem);
719 // and save context information
720 HTMLAttrs &rAttrs = pContext->GetAttrs();
721 rAttrs.push_back( m_xAttrTab->pCharBrush );
723 else if( pContext->GetToken() != HtmlTokenId::TABLEHEADER_ON &&
724 pContext->GetToken() != HtmlTokenId::TABLEDATA_ON )
726 ppAttr = &m_xAttrTab->pBrush;
728 break;
730 case RES_BOX:
731 if( bCharLvl )
733 SvxBoxItem aBoxItem( pItem->StaticWhichCast(RES_BOX) );
734 aBoxItem.SetWhich( RES_CHRATR_BOX );
736 NewAttr(m_xAttrTab, &m_xAttrTab->pCharBox, aBoxItem);
738 HTMLAttrs &rAttrs = pContext->GetAttrs();
739 rAttrs.push_back( m_xAttrTab->pCharBox );
741 else
743 ppAttr = &m_xAttrTab->pBox;
745 break;
747 default:
748 ppAttr = GetAttrTabEntry( pItem->Which() );
749 break;
752 if( ppAttr )
754 // Set the attribute
755 NewAttr(m_xAttrTab, ppAttr, *pItem);
757 // and save context information
758 HTMLAttrs &rAttrs = pContext->GetAttrs();
759 rAttrs.push_back( *ppAttr );
763 if( !rPropInfo.m_aId.isEmpty() )
764 InsertBookmark( rPropInfo.m_aId );
767 void SwHTMLParser::InsertAttr( HTMLAttr **ppAttr, const SfxPoolItem & rItem,
768 HTMLAttrContext *pCntxt )
770 if( !ppAttr )
772 ppAttr = GetAttrTabEntry( rItem.Which() );
773 if( !ppAttr )
774 return;
777 // Set the attribute
778 NewAttr(m_xAttrTab, ppAttr, rItem);
780 // save context information
781 HTMLAttrs &rAttrs = pCntxt->GetAttrs();
782 rAttrs.push_back( *ppAttr );
785 void SwHTMLParser::SplitPREListingXMP( HTMLAttrContext *pCntxt )
787 // PRE/Listing/XMP need to be finished when finishing context
788 pCntxt->SetFinishPREListingXMP( true );
790 // And set all now valid flags
791 if( IsReadPRE() )
792 pCntxt->SetRestartPRE( true );
793 if( IsReadXMP() )
794 pCntxt->SetRestartXMP( true );
795 if( IsReadListing() )
796 pCntxt->SetRestartListing( true );
798 FinishPREListingXMP();
801 SfxItemSet *HTMLAttrContext::GetFrameItemSet( SwDoc *pCreateDoc )
803 if( !m_pFrameItemSet && pCreateDoc )
804 m_pFrameItemSet = std::make_unique<SfxItemSet>(SfxItemSet::makeFixedSfxItemSet<
805 RES_FRMATR_BEGIN, RES_FRMATR_END-1>(pCreateDoc->GetAttrPool()));
806 return m_pFrameItemSet.get();
809 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */