sw a11y: clang-format SidebarWinAccessible code
[LibreOffice.git] / sw / source / filter / html / htmlgrin.cxx
blobbe46359ae39f77b9f23e16705bff43c26bbc1a12
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 <memory>
21 #include <hintids.hxx>
22 #include <comphelper/lok.hxx>
23 #include <comphelper/string.hxx>
24 #include <comphelper/documentinfo.hxx>
25 #include <vcl/svapp.hxx>
26 #include <i18nlangtag/languagetag.hxx>
27 #include <svl/stritem.hxx>
28 #include <svl/urihelper.hxx>
29 #include <svl/languageoptions.hxx>
30 #include <editeng/fhgtitem.hxx>
31 #include <editeng/brushitem.hxx>
32 #include <editeng/colritem.hxx>
33 #include <editeng/boxitem.hxx>
34 #include <editeng/ulspitem.hxx>
35 #include <editeng/langitem.hxx>
36 #include <sfx2/docfile.hxx>
37 #include <sfx2/event.hxx>
38 #include <sfx2/lokhelper.hxx>
39 #include <vcl/imap.hxx>
40 #include <svtools/htmltokn.h>
41 #include <svtools/htmlkywd.hxx>
42 #include <unotools/eventcfg.hxx>
43 #include <sal/log.hxx>
44 #include <osl/diagnose.h>
45 #include <o3tl/string_view.hxx>
47 #include <fmtornt.hxx>
48 #include <fmturl.hxx>
49 #include <fmtsrnd.hxx>
50 #include <fmtinfmt.hxx>
51 #include <fmtcntnt.hxx>
52 #include <fmtanchr.hxx>
53 #include <fmtfsize.hxx>
54 #include <charatr.hxx>
55 #include <frmfmt.hxx>
56 #include <charfmt.hxx>
57 #include <docsh.hxx>
58 #include <pam.hxx>
59 #include <doc.hxx>
60 #include <ndtxt.hxx>
61 #include <shellio.hxx>
62 #include <poolfmt.hxx>
63 #include <IMark.hxx>
64 #include <ndgrf.hxx>
65 #include "htmlnum.hxx"
66 #include "swcss1.hxx"
67 #include "swhtml.hxx"
68 #include <numrule.hxx>
69 #include <IDocumentMarkAccess.hxx>
70 #include <frameformats.hxx>
72 #include <vcl/graphicfilter.hxx>
73 #include <tools/UnitConversion.hxx>
74 #include <tools/hostfilter.hxx>
75 #include <tools/urlobj.hxx>
76 #include <unotools/securityoptions.hxx>
77 #include <unotxdoc.hxx>
79 using namespace ::com::sun::star;
81 HTMLOptionEnum<sal_Int16> const aHTMLImgHAlignTable[] =
83 { OOO_STRING_SVTOOLS_HTML_AL_left, text::HoriOrientation::LEFT },
84 { OOO_STRING_SVTOOLS_HTML_AL_right, text::HoriOrientation::RIGHT },
85 { nullptr, 0 }
88 HTMLOptionEnum<sal_Int16> const aHTMLImgVAlignTable[] =
90 { OOO_STRING_SVTOOLS_HTML_VA_top, text::VertOrientation::LINE_TOP },
91 { OOO_STRING_SVTOOLS_HTML_VA_texttop, text::VertOrientation::CHAR_TOP },
92 { OOO_STRING_SVTOOLS_HTML_VA_middle, text::VertOrientation::CENTER },
93 { OOO_STRING_SVTOOLS_HTML_AL_center, text::VertOrientation::CENTER },
94 { OOO_STRING_SVTOOLS_HTML_VA_absmiddle, text::VertOrientation::LINE_CENTER },
95 { OOO_STRING_SVTOOLS_HTML_VA_bottom, text::VertOrientation::TOP },
96 { OOO_STRING_SVTOOLS_HTML_VA_baseline, text::VertOrientation::TOP },
97 { OOO_STRING_SVTOOLS_HTML_VA_absbottom, text::VertOrientation::LINE_BOTTOM },
98 { nullptr, 0 }
101 ImageMap *SwHTMLParser::FindImageMap( std::u16string_view rName ) const
103 OSL_ENSURE( rName[0] != '#', "FindImageMap: name begins with '#'!" );
105 if (m_pImageMaps)
107 for (const auto &rpIMap : *m_pImageMaps)
109 if (o3tl::equalsIgnoreAsciiCase(rName, rpIMap->GetName()))
111 return rpIMap.get();
115 return nullptr;
118 void SwHTMLParser::ConnectImageMaps()
120 SwNodes& rNds = m_xDoc->GetNodes();
121 // on the first node of section #1
122 SwNodeOffset nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 1;
123 SwNodeOffset nEndIdx = rNds.GetEndOfAutotext().GetIndex();
125 SwGrfNode* pGrfNd;
126 while( m_nMissingImgMaps > 0 && nIdx < nEndIdx )
128 SwNode *pNd = rNds[nIdx + 1];
129 pGrfNd = pNd->GetGrfNode();
130 if( nullptr != pGrfNd )
132 SwFrameFormat *pFormat = pGrfNd->GetFlyFormat();
133 SwFormatURL aURL( pFormat->GetURL() );
134 const ImageMap *pIMap = aURL.GetMap();
135 if( pIMap && pIMap->GetIMapObjectCount()==0 )
137 // The (empty) image map of the node will be either
138 // replaced with found image map or deleted.
139 ImageMap *pNewIMap =
140 FindImageMap( pIMap->GetName() );
141 aURL.SetMap( pNewIMap );
142 pFormat->SetFormatAttr( aURL );
143 if( !pGrfNd->IsScaleImageMap() )
145 // meanwhile the graphic size is known or the
146 // graphic don't need scaling
147 pGrfNd->ScaleImageMap();
149 m_nMissingImgMaps--; // search a map less
152 nIdx = rNds[nIdx]->EndOfSectionIndex() + 1;
156 void SwHTMLParser::SetAnchorAndAdjustment( sal_Int16 eVertOri,
157 sal_Int16 eHoriOri,
158 const SvxCSS1PropertyInfo &rCSS1PropInfo,
159 SfxItemSet& rFrameItemSet )
161 const SfxItemSet *pCntnrItemSet = nullptr;
162 auto i = m_aContexts.size();
163 while( !pCntnrItemSet && i > m_nContextStMin )
164 pCntnrItemSet = m_aContexts[--i]->GetFrameItemSet();
166 if( pCntnrItemSet )
168 // If we are in a container then the anchoring of the container is used.
169 rFrameItemSet.Put( *pCntnrItemSet );
171 else if( SwCSS1Parser::MayBePositioned( rCSS1PropInfo, true ) )
173 // If the alignment can be set via CSS1 options we use them.
174 SetAnchorAndAdjustment( rCSS1PropInfo, rFrameItemSet );
176 else
178 // Otherwise the alignment is set correspondingly the normal HTML options.
179 SetAnchorAndAdjustment( eVertOri, eHoriOri, rFrameItemSet );
183 void SwHTMLParser::SetAnchorAndAdjustment( sal_Int16 eVertOri,
184 sal_Int16 eHoriOri,
185 SfxItemSet& rFrameSet,
186 bool bDontAppend )
188 bool bMoveBackward = false;
189 SwFormatAnchor aAnchor( RndStdIds::FLY_AS_CHAR );
190 sal_Int16 eVertRel = text::RelOrientation::FRAME;
192 if( text::HoriOrientation::NONE != eHoriOri )
194 // determine paragraph indent
195 sal_uInt16 nLeftSpace = 0, nRightSpace = 0;
196 short nIndent = 0;
197 GetMarginsFromContextWithNumberBullet( nLeftSpace, nRightSpace, nIndent );
199 // determine horizontal alignment and wrapping
200 sal_Int16 eHoriRel;
201 css::text::WrapTextMode eSurround;
202 switch( eHoriOri )
204 case text::HoriOrientation::LEFT:
205 eHoriRel = nLeftSpace ? text::RelOrientation::PRINT_AREA : text::RelOrientation::FRAME;
206 eSurround = css::text::WrapTextMode_RIGHT;
207 break;
208 case text::HoriOrientation::RIGHT:
209 eHoriRel = nRightSpace ? text::RelOrientation::PRINT_AREA : text::RelOrientation::FRAME;
210 eSurround = css::text::WrapTextMode_LEFT;
211 break;
212 case text::HoriOrientation::CENTER: // for tables
213 eHoriRel = text::RelOrientation::FRAME;
214 eSurround = css::text::WrapTextMode_NONE;
215 break;
216 default:
217 eHoriRel = text::RelOrientation::FRAME;
218 eSurround = css::text::WrapTextMode_PARALLEL;
219 break;
222 // Create a new paragraph, if the current one has frames
223 // anchored at paragraph/at char without wrapping.
224 if( !bDontAppend && HasCurrentParaFlys( true ) )
226 // When the paragraph only contains graphics then there
227 // is no need for bottom margin. Since here also with use of
228 // styles no margin should be created, set attributes to
229 // override!
230 sal_uInt16 nUpper=0, nLower=0;
231 GetULSpaceFromContext( nUpper, nLower );
232 InsertAttr( SvxULSpaceItem( nUpper, 0, RES_UL_SPACE ), true );
234 AppendTextNode( AM_NOSPACE );
236 if( nUpper )
238 NewAttr(m_xAttrTab, &m_xAttrTab->pULSpace, SvxULSpaceItem(0, nLower, RES_UL_SPACE));
239 m_aParaAttrs.push_back( m_xAttrTab->pULSpace );
240 EndAttr( m_xAttrTab->pULSpace, false );
244 // determine vertical alignment and anchoring
245 const sal_Int32 nContent = m_pPam->GetPoint()->GetContentIndex();
246 if( nContent )
248 aAnchor.SetType( RndStdIds::FLY_AT_CHAR );
249 bMoveBackward = true;
250 eVertOri = text::VertOrientation::CHAR_BOTTOM;
251 eVertRel = text::RelOrientation::CHAR;
253 else
255 aAnchor.SetType( RndStdIds::FLY_AT_PARA );
256 eVertOri = text::VertOrientation::TOP;
257 eVertRel = text::RelOrientation::PRINT_AREA;
260 rFrameSet.Put( SwFormatHoriOrient( 0, eHoriOri, eHoriRel) );
262 rFrameSet.Put( SwFormatSurround( eSurround ) );
264 rFrameSet.Put( SwFormatVertOrient( 0, eVertOri, eVertRel) );
266 if( bMoveBackward )
267 m_pPam->Move( fnMoveBackward );
269 if (aAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR && !m_pPam->GetPointNode().GetTextNode())
271 eState = SvParserState::Error;
272 return;
275 aAnchor.SetAnchor( m_pPam->GetPoint() );
277 if( bMoveBackward )
278 m_pPam->Move( fnMoveForward );
280 rFrameSet.Put( aAnchor );
283 void SwHTMLParser::RegisterFlyFrame( SwFrameFormat *pFlyFormat )
285 // automatically anchored frames must be moved forward by one position
286 if( RES_DRAWFRMFMT != pFlyFormat->Which() &&
287 (RndStdIds::FLY_AT_PARA == pFlyFormat->GetAnchor().GetAnchorId()) &&
288 css::text::WrapTextMode_THROUGH == pFlyFormat->GetSurround().GetSurround() )
290 m_aMoveFlyFrames.emplace_back(std::make_unique<SwHTMLFrameFormatListener>(pFlyFormat));
291 m_aMoveFlyCnts.push_back( m_pPam->GetPoint()->GetContentIndex() );
295 /* */
297 void SwHTMLParser::GetDefaultScriptType( ScriptType& rType,
298 OUString& rTypeStr ) const
300 SwDocShell *pDocSh = m_xDoc->GetDocShell();
301 SvKeyValueIterator* pHeaderAttrs = pDocSh ? pDocSh->GetHeaderAttributes()
302 : nullptr;
303 rType = GetScriptType( pHeaderAttrs );
304 rTypeStr = GetScriptTypeString( pHeaderAttrs );
307 namespace
309 bool allowAccessLink(const SwDoc& rDoc)
311 OUString sReferer;
312 SfxObjectShell * sh = rDoc.GetPersist();
313 if (sh != nullptr && sh->HasName())
315 sReferer = sh->GetMedium()->GetName();
317 return !SvtSecurityOptions::isUntrustedReferer(sReferer);
321 /* */
323 void SwHTMLParser::InsertImage()
325 // and now analyze
326 OUString sAltNm, aId, aClass, aStyle, aMap, sHTMLGrfName;
327 OUString sGrfNm;
328 OUString aGraphicData;
329 sal_Int16 eVertOri = text::VertOrientation::TOP;
330 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
331 bool bWidthProvided=false, bHeightProvided=false;
332 tools::Long nWidth=0, nHeight=0;
333 tools::Long nVSpace=0, nHSpace=0;
335 sal_uInt16 nBorder = (m_xAttrTab->pINetFormat ? 1 : 0);
336 bool bIsMap = false;
337 bool bPercentWidth = false;
338 bool bPercentHeight = false;
339 OUString sWidthAsString, sHeightAsString;
340 SvxMacroItem aMacroItem(RES_FRMMACRO);
342 ScriptType eDfltScriptType;
343 OUString sDfltScriptType;
344 GetDefaultScriptType( eDfltScriptType, sDfltScriptType );
346 const HTMLOptions& rHTMLOptions = GetOptions();
347 for (size_t i = rHTMLOptions.size(); i; )
349 SvMacroItemId nEvent = SvMacroItemId::NONE;
350 ScriptType eScriptType2 = eDfltScriptType;
351 const HTMLOption& rOption = rHTMLOptions[--i];
352 switch( rOption.GetToken() )
354 case HtmlOptionId::ID:
355 aId = rOption.GetString();
356 break;
357 case HtmlOptionId::STYLE:
358 aStyle = rOption.GetString();
359 break;
360 case HtmlOptionId::CLASS:
361 aClass = rOption.GetString();
362 break;
363 case HtmlOptionId::SRC:
364 sGrfNm = rOption.GetString();
365 if( !InternalImgToPrivateURL(sGrfNm) )
366 sGrfNm = INetURLObject::GetAbsURL( m_sBaseURL, sGrfNm );
367 break;
368 case HtmlOptionId::DATA:
369 aGraphicData = rOption.GetString();
370 if (!InternalImgToPrivateURL(aGraphicData))
371 aGraphicData = INetURLObject::GetAbsURL(
372 m_sBaseURL, SwHTMLParser::StripQueryFromPath(m_sBaseURL, aGraphicData));
373 break;
374 case HtmlOptionId::ALIGN:
375 eVertOri =
376 rOption.GetEnum( aHTMLImgVAlignTable,
377 text::VertOrientation::TOP );
378 eHoriOri =
379 rOption.GetEnum( aHTMLImgHAlignTable );
380 break;
381 case HtmlOptionId::WIDTH:
382 // for now only store as pixel value!
383 nWidth = rOption.GetNumber();
384 sWidthAsString = rOption.GetString();
385 bPercentWidth = (sWidthAsString.indexOf('%') != -1);
386 if( bPercentWidth && nWidth>100 )
387 nWidth = 100;
388 // width|height = "auto" means viewing app decides the size
389 // i.e. proceed as if no particular size was provided
390 bWidthProvided = (sWidthAsString != "auto");
391 break;
392 case HtmlOptionId::HEIGHT:
393 // for now only store as pixel value!
394 nHeight = rOption.GetNumber();
395 sHeightAsString = rOption.GetString();
396 bPercentHeight = (sHeightAsString.indexOf('%') != -1);
397 if( bPercentHeight && nHeight>100 )
398 nHeight = 100;
399 // the same as above w/ HtmlOptionId::WIDTH
400 bHeightProvided = (sHeightAsString != "auto");
401 break;
402 case HtmlOptionId::VSPACE:
403 nVSpace = rOption.GetNumber();
404 break;
405 case HtmlOptionId::HSPACE:
406 nHSpace = rOption.GetNumber();
407 break;
408 case HtmlOptionId::ALT:
409 sAltNm = rOption.GetString();
410 break;
411 case HtmlOptionId::BORDER:
412 nBorder = o3tl::narrowing<sal_uInt16>(rOption.GetNumber());
413 break;
414 case HtmlOptionId::ISMAP:
415 bIsMap = true;
416 break;
417 case HtmlOptionId::USEMAP:
418 aMap = rOption.GetString();
419 break;
420 case HtmlOptionId::NAME:
421 sHTMLGrfName = rOption.GetString();
422 break;
424 case HtmlOptionId::SDONLOAD:
425 eScriptType2 = STARBASIC;
426 [[fallthrough]];
427 case HtmlOptionId::ONLOAD:
428 nEvent = SvMacroItemId::OnImageLoadDone;
429 goto IMAGE_SETEVENT;
431 case HtmlOptionId::SDONABORT:
432 eScriptType2 = STARBASIC;
433 [[fallthrough]];
434 case HtmlOptionId::ONABORT:
435 nEvent = SvMacroItemId::OnImageLoadCancel;
436 goto IMAGE_SETEVENT;
438 case HtmlOptionId::SDONERROR:
439 eScriptType2 = STARBASIC;
440 [[fallthrough]];
441 case HtmlOptionId::ONERROR:
442 nEvent = SvMacroItemId::OnImageLoadError;
443 goto IMAGE_SETEVENT;
444 IMAGE_SETEVENT:
446 OUString sTmp( rOption.GetString() );
447 if( !sTmp.isEmpty() )
449 sTmp = convertLineEnd(sTmp, GetSystemLineEnd());
450 OUString sScriptType;
451 if( EXTENDED_STYPE == eScriptType2 )
452 sScriptType = sDfltScriptType;
453 aMacroItem.SetMacro( nEvent,
454 SvxMacro( sTmp, sScriptType, eScriptType2 ));
457 break;
458 default: break;
462 if (sGrfNm.isEmpty() && !aGraphicData.isEmpty())
463 sGrfNm = aGraphicData;
465 if( sGrfNm.isEmpty() )
466 return;
468 // When we are in an ordered list and the paragraph is still empty and not
469 // numbered, it may be a graphic for a bullet list.
470 if( !m_pPam->GetPoint()->GetContentIndex() &&
471 GetNumInfo().GetDepth() > 0 && GetNumInfo().GetDepth() <= MAXLEVEL &&
472 !m_aBulletGrfs[GetNumInfo().GetDepth()-1].isEmpty() &&
473 m_aBulletGrfs[GetNumInfo().GetDepth()-1]==sGrfNm )
475 SwTextNode* pTextNode = m_pPam->GetPointNode().GetTextNode();
477 if( pTextNode && ! pTextNode->IsCountedInList())
479 OSL_ENSURE( pTextNode->GetActualListLevel() == GetNumInfo().GetLevel(),
480 "Numbering level is wrong" );
482 pTextNode->SetCountedInList( true );
484 // It's necessary to invalidate the rule, because between the reading
485 // of LI and the graphic an EndAction could be called.
486 if( GetNumInfo().GetNumRule() )
487 GetNumInfo().GetNumRule()->Invalidate();
489 // Set the style again, so that indent of the first line is correct.
490 SetTextCollAttrs();
492 return;
496 Graphic aGraphic;
497 INetURLObject aGraphicURL( sGrfNm );
498 if( aGraphicURL.GetProtocol() == INetProtocol::Data )
500 std::unique_ptr<SvMemoryStream> const pStream(aGraphicURL.getData());
501 if (pStream)
503 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
504 aGraphic = rFilter.ImportUnloadedGraphic(*pStream);
505 sGrfNm.clear();
507 if (!sGrfNm.isEmpty())
509 if (ERRCODE_NONE == rFilter.ImportGraphic(aGraphic, u"", *pStream))
510 sGrfNm.clear();
514 else if (m_sBaseURL.isEmpty() || !aGraphicData.isEmpty())
516 if (comphelper::LibreOfficeKit::isActive() && HostFilter::isForbidden(aGraphicURL.GetHost()))
517 SfxLokHelper::sendNetworkAccessError("paste");
519 // sBaseURL is empty if the source is clipboard
520 // aGraphicData is non-empty for <object data="..."> -> not a linked graphic.
521 if (ERRCODE_NONE == GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aGraphicURL))
522 sGrfNm.clear();
525 if (!sGrfNm.isEmpty())
527 aGraphic.SetDefaultType();
530 if (!nHeight || !nWidth)
532 Size aPixelSize = aGraphic.GetSizePixel(Application::GetDefaultDevice());
533 if (!bWidthProvided)
534 nWidth = aPixelSize.Width();
535 if (!bHeightProvided)
536 nHeight = aPixelSize.Height();
537 // tdf#142781 - calculate the width/height keeping the aspect ratio
538 if (bWidthProvided && !bHeightProvided && aPixelSize.Width())
540 if (bPercentWidth)
542 nHeight = SwFormatFrameSize::SYNCED;
543 bPercentHeight = true;
545 else
547 nHeight = nWidth * aPixelSize.Height() / aPixelSize.Width();
550 else if (!bWidthProvided && bHeightProvided && aPixelSize.Height())
552 if (bPercentHeight)
554 nWidth = SwFormatFrameSize::SYNCED;
555 bPercentWidth = true;
557 else
559 nWidth = nHeight * aPixelSize.Width() / aPixelSize.Height();
564 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
565 SvxCSS1PropertyInfo aPropInfo;
566 if( HasStyleOptions( aStyle, aId, aClass ) )
567 (void)ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
569 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() );
570 if( !IsNewDoc() )
571 Reader::ResetFrameFormatAttrs( aFrameSet );
573 // set the border
574 tools::Long nHBorderWidth = 0, nVBorderWidth = 0;
575 if( nBorder )
577 nHBorderWidth = static_cast<tools::Long>(nBorder);
578 nVBorderWidth = static_cast<tools::Long>(nBorder);
579 SvxCSS1Parser::PixelToTwip( nVBorderWidth, nHBorderWidth );
581 ::editeng::SvxBorderLine aHBorderLine( nullptr, nHBorderWidth );
582 ::editeng::SvxBorderLine aVBorderLine( nullptr, nVBorderWidth );
584 if( m_xAttrTab->pINetFormat )
586 const OUString& rURL =
587 static_cast<const SwFormatINetFormat&>(m_xAttrTab->pINetFormat->GetItem()).GetValue();
589 m_pCSS1Parser->SetATagStyles();
590 sal_uInt16 nPoolId = static_cast< sal_uInt16 >(m_xDoc->IsVisitedURL( rURL )
591 ? RES_POOLCHR_INET_VISIT
592 : RES_POOLCHR_INET_NORMAL);
593 const SwCharFormat *pCharFormat = m_pCSS1Parser->GetCharFormatFromPool( nPoolId );
594 aHBorderLine.SetColor( pCharFormat->GetColor().GetValue() );
595 aVBorderLine.SetColor( aHBorderLine.GetColor() );
597 else
599 const SvxColorItem& rColorItem = m_xAttrTab->pFontColor ?
600 static_cast<const SvxColorItem &>(m_xAttrTab->pFontColor->GetItem()) :
601 m_xDoc->GetDefault(RES_CHRATR_COLOR);
602 aHBorderLine.SetColor( rColorItem.GetValue() );
603 aVBorderLine.SetColor( aHBorderLine.GetColor() );
606 SvxBoxItem aBoxItem( RES_BOX );
607 aBoxItem.SetLine( &aHBorderLine, SvxBoxItemLine::TOP );
608 aBoxItem.SetLine( &aHBorderLine, SvxBoxItemLine::BOTTOM );
609 aBoxItem.SetLine( &aVBorderLine, SvxBoxItemLine::LEFT );
610 aBoxItem.SetLine( &aVBorderLine, SvxBoxItemLine::RIGHT );
611 aFrameSet.Put( aBoxItem );
614 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet );
616 SetSpace( Size( nHSpace, nVSpace), aItemSet, aPropInfo, aFrameSet );
618 // set other CSS1 attributes
619 SetFrameFormatAttrs( aItemSet, HtmlFrameFormatFlags::Box, aFrameSet );
621 Size aTwipSz( bPercentWidth ? 0 : nWidth, bPercentHeight ? 0 : nHeight );
622 if( aTwipSz.Width() || aTwipSz.Height() )
624 if (bWidthProvided || bHeightProvided || // attributes imply pixel!
625 aGraphic.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
627 aTwipSz = o3tl::convert(aTwipSz, o3tl::Length::px, o3tl::Length::twip);
629 else
630 { // some bitmaps may have a size in metric units (e.g. PNG); use that
631 assert(aGraphic.GetPrefMapMode().GetMapUnit() < MapUnit::MapPixel);
632 aTwipSz = o3tl::convert(aGraphic.GetPrefSize(),
633 MapToO3tlLength(aGraphic.GetPrefMapMode().GetMapUnit()),
634 o3tl::Length::twip);
638 // convert CSS1 size to "normal" size
639 switch( aPropInfo.m_eWidthType )
641 case SVX_CSS1_LTYPE_TWIP:
642 aTwipSz.setWidth( aPropInfo.m_nWidth );
643 nWidth = 1; // != 0
644 bPercentWidth = false;
645 break;
646 case SVX_CSS1_LTYPE_PERCENTAGE:
647 aTwipSz.setWidth( 0 );
648 nWidth = aPropInfo.m_nWidth;
649 bPercentWidth = true;
650 break;
651 default:
654 switch( aPropInfo.m_eHeightType )
656 case SVX_CSS1_LTYPE_TWIP:
657 aTwipSz.setHeight( aPropInfo.m_nHeight );
658 nHeight = 1; // != 0
659 bPercentHeight = false;
660 break;
661 case SVX_CSS1_LTYPE_PERCENTAGE:
662 aTwipSz.setHeight( 0 );
663 nHeight = aPropInfo.m_nHeight;
664 bPercentHeight = true;
665 break;
666 default:
670 Size aGrfSz( 0, 0 );
671 bool bSetTwipSize = true; // Set Twip-Size on Node?
672 bool bChangeFrameSize = false; // Change frame format later?
673 bool bRequestGrfNow = false;
674 bool bSetScaleImageMap = false;
675 sal_uInt8 nPercentWidth = 0, nPercentHeight = 0;
677 // bPercentWidth / bPercentHeight means we have a percent size. If that's not the case and we have no
678 // size from nWidth / nHeight either, then inspect the image header.
679 bool bRelWidthScale = bPercentWidth && nWidth == SwFormatFrameSize::SYNCED;
680 bool bNeedWidth = (!bPercentWidth && !nWidth) || bRelWidthScale;
681 bool bRelHeightScale = bPercentHeight && nHeight == SwFormatFrameSize::SYNCED;
682 bool bNeedHeight = (!bPercentHeight && !nHeight) || bRelHeightScale;
683 if ((bNeedWidth || bNeedHeight) && !bFuzzing && allowAccessLink(*m_xDoc) &&
684 !aGraphicURL.IsExoticProtocol())
686 GraphicDescriptor aDescriptor(aGraphicURL);
687 if (aDescriptor.Detect(/*bExtendedInfo=*/true))
689 // Try to use size info from the image header before defaulting to
690 // HTML_DFLT_IMG_WIDTH/HEIGHT.
691 aTwipSz
692 = o3tl::convert(aDescriptor.GetSizePixel(), o3tl::Length::px, o3tl::Length::twip);
693 if (!bPercentWidth && !nWidth)
695 nWidth = aTwipSz.getWidth();
697 if (!bPercentHeight && !nHeight)
699 nHeight = aTwipSz.getHeight();
704 if( !(nWidth && !bRelWidthScale) || !(nHeight && !bRelHeightScale) )
706 // When the graphic is in a table, it will be requested immediately,
707 // so that it is available before the table is layouted.
708 if (m_xTable && !nWidth)
710 bRequestGrfNow = true;
711 IncGrfsThatResizeTable();
714 // The frame size is set later
715 bChangeFrameSize = true;
716 aGrfSz = aTwipSz;
717 if( !nWidth && !nHeight )
719 aTwipSz.setWidth( HTML_DFLT_IMG_WIDTH );
720 aTwipSz.setHeight( HTML_DFLT_IMG_HEIGHT );
722 else if( nWidth )
724 // a percentage value
725 if( bPercentWidth )
727 nPercentWidth = static_cast<sal_uInt8>(nWidth);
728 nPercentHeight = 255;
730 else
732 aTwipSz.setHeight( HTML_DFLT_IMG_HEIGHT );
735 else if( nHeight )
737 if( bPercentHeight )
739 nPercentHeight = static_cast<sal_uInt8>(nHeight);
740 nPercentWidth = 255;
742 else
744 aTwipSz.setWidth( HTML_DFLT_IMG_WIDTH );
748 else
750 // Width and height were given and don't need to be set
751 bSetTwipSize = false;
753 if( bPercentWidth )
754 nPercentWidth = static_cast<sal_uInt8>(nWidth);
756 if( bPercentHeight )
757 nPercentHeight = static_cast<sal_uInt8>(nHeight);
760 // set image map
761 aMap = comphelper::string::stripEnd(aMap, ' ');
762 if( !aMap.isEmpty() )
764 // Since we only know local image maps we just use everything
765 // after # as name
766 sal_Int32 nPos = aMap.indexOf( '#' );
767 OUString aName;
768 if ( -1 == nPos )
769 aName = aMap ;
770 else
771 aName = aMap.copy(nPos+1);
773 ImageMap *pImgMap = FindImageMap( aName );
774 if( pImgMap )
776 SwFormatURL aURL; aURL.SetMap( pImgMap );// is copied
778 bSetScaleImageMap = !nPercentWidth || !nPercentHeight;
779 aFrameSet.Put( aURL );
781 else
783 ImageMap aEmptyImgMap( aName );
784 SwFormatURL aURL; aURL.SetMap( &aEmptyImgMap );// is copied
785 aFrameSet.Put( aURL );
786 m_nMissingImgMaps++; // image maps are missing
788 // the graphic has to scaled during SetTwipSize, if we didn't
789 // set a size on the node or the size doesn't match the graphic size.
790 bSetScaleImageMap = true;
794 // observe minimum values !!
795 bool bRelSizeScale = bRelWidthScale || bRelHeightScale;
796 if( nPercentWidth )
798 OSL_ENSURE( !aTwipSz.Width() || bRelSizeScale,
799 "Why is a width set if we already have percentage value?" );
800 aTwipSz.setWidth( aGrfSz.Width() ? aGrfSz.Width()
801 : HTML_DFLT_IMG_WIDTH );
803 else
805 aTwipSz.AdjustWidth(2*nVBorderWidth );
806 if( aTwipSz.Width() < MINFLY )
807 aTwipSz.setWidth( MINFLY );
809 if( nPercentHeight )
811 OSL_ENSURE( !aTwipSz.Height() || bRelSizeScale,
812 "Why is a height set if we already have percentage value?" );
813 aTwipSz.setHeight( aGrfSz.Height() ? aGrfSz.Height()
814 : HTML_DFLT_IMG_HEIGHT );
816 else
818 aTwipSz.AdjustHeight(2*nHBorderWidth );
819 if( aTwipSz.Height() < MINFLY )
820 aTwipSz.setHeight( MINFLY );
823 SwFormatFrameSize aFrameSize( SwFrameSize::Fixed, aTwipSz.Width(), aTwipSz.Height() );
824 aFrameSize.SetWidthPercent( nPercentWidth );
825 aFrameSize.SetHeightPercent( nPercentHeight );
826 aFrameSet.Put( aFrameSize );
828 const SwNodeType eNodeType = m_pPam->GetPointNode().GetNodeType();
829 if (eNodeType != SwNodeType::Text && eNodeType != SwNodeType::Table)
830 return;
832 // passing empty sGrfNm here, means we don't want the graphic to be linked
833 SwFrameFormat *const pFlyFormat =
834 m_xDoc->getIDocumentContentOperations().InsertGraphic(
835 *m_pPam, sGrfNm, OUString(), &aGraphic,
836 &aFrameSet, nullptr, nullptr);
837 SwGrfNode *pGrfNd = m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
838 ->GetIndex()+1 ]->GetGrfNode();
840 if( !sHTMLGrfName.isEmpty() )
842 pFlyFormat->SetFormatName( sHTMLGrfName );
844 // maybe jump to graphic
845 if( JumpToMarks::Graphic == m_eJumpTo && sHTMLGrfName == m_sJmpMark )
847 m_bChkJumpMark = true;
848 m_eJumpTo = JumpToMarks::NONE;
852 if (pGrfNd)
854 if( !sAltNm.isEmpty() )
855 pGrfNd->SetTitle( sAltNm );
857 if( bSetTwipSize )
858 pGrfNd->SetTwipSize( aGrfSz );
860 pGrfNd->SetChgTwipSize( bChangeFrameSize );
862 if( bSetScaleImageMap )
863 pGrfNd->SetScaleImageMap( true );
866 if( m_xAttrTab->pINetFormat )
868 const SwFormatINetFormat &rINetFormat =
869 static_cast<const SwFormatINetFormat&>(m_xAttrTab->pINetFormat->GetItem());
871 SwFormatURL aURL( pFlyFormat->GetURL() );
873 aURL.SetURL( rINetFormat.GetValue(), bIsMap );
874 aURL.SetTargetFrameName( rINetFormat.GetTargetFrame() );
875 aURL.SetName( rINetFormat.GetName() );
876 pFlyFormat->SetFormatAttr( aURL );
879 static const SvMacroItemId aEvents[] = {
880 SvMacroItemId::OnMouseOver,
881 SvMacroItemId::OnClick,
882 SvMacroItemId::OnMouseOut };
884 for( SvMacroItemId id : aEvents )
886 const SvxMacro *pMacro = rINetFormat.GetMacro( id );
887 if( nullptr != pMacro )
888 aMacroItem.SetMacro( id, *pMacro );
892 if ((RndStdIds::FLY_AS_CHAR == pFlyFormat->GetAnchor().GetAnchorId()) &&
893 m_xAttrTab->pINetFormat->GetStartParagraph() ==
894 m_pPam->GetPoint()->GetNode() &&
895 m_xAttrTab->pINetFormat->GetStartContent() ==
896 m_pPam->GetPoint()->GetContentIndex() - 1 )
898 // the attribute was insert right before as-character anchored
899 // graphic, therefore we move it
900 m_xAttrTab->pINetFormat->SetStart( *m_pPam->GetPoint() );
902 // When the attribute is also an anchor, we'll insert
903 // a bookmark before the graphic, because SwFormatURL
904 // isn't an anchor.
905 if( !rINetFormat.GetName().isEmpty() )
907 m_pPam->Move( fnMoveBackward );
908 InsertBookmark( rINetFormat.GetName() );
909 m_pPam->Move( fnMoveForward );
914 else if (!m_aEmbedURL.isEmpty())
916 // This is an inner <object> image and the outer <object> has a URL for us. Set that on the
917 // image.
918 SwFormatURL aURL(pFlyFormat->GetURL());
919 aURL.SetURL(m_aEmbedURL, bIsMap);
920 m_aEmbedURL.clear();
921 pFlyFormat->SetFormatAttr(aURL);
924 if( !aMacroItem.GetMacroTable().empty() )
926 NotifyMacroEventRead();
927 pFlyFormat->SetFormatAttr( aMacroItem );
930 // tdf#87083 If the graphic has not been loaded yet, then load it now.
931 // Otherwise it may be loaded during the first paint of the object and it
932 // will be too late to adapt the size of the graphic at that point.
933 if (bRequestGrfNow && pGrfNd)
935 Size aUpdatedSize = pGrfNd->GetTwipSize(); //trigger a swap-in
936 SAL_WARN_IF(!aUpdatedSize.Width() || !aUpdatedSize.Height(), "sw.html", "html image with no width or height");
939 // maybe create frames and register auto bound frames
940 RegisterFlyFrame( pFlyFormat );
942 if( !aId.isEmpty() )
943 InsertBookmark( aId );
946 /* */
948 void SwHTMLParser::InsertBodyOptions()
950 m_xDoc->SetTextFormatColl( *m_pPam,
951 m_pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_TEXT ) );
953 OUString aBackGround, aId, aStyle, aLang, aDir;
954 Color aBGColor, aTextColor, aLinkColor, aVLinkColor;
955 bool bBGColor=false, bTextColor=false;
956 bool bLinkColor=false, bVLinkColor=false;
958 ScriptType eDfltScriptType;
959 OUString sDfltScriptType;
960 GetDefaultScriptType( eDfltScriptType, sDfltScriptType );
962 const HTMLOptions& rHTMLOptions = GetOptions();
963 for (size_t i = rHTMLOptions.size(); i; )
965 const HTMLOption& rOption = rHTMLOptions[--i];
966 ScriptType eScriptType2 = eDfltScriptType;
967 OUString aEvent;
968 bool bSetEvent = false;
970 switch( rOption.GetToken() )
972 case HtmlOptionId::ID:
973 aId = rOption.GetString();
974 break;
975 case HtmlOptionId::BACKGROUND:
976 aBackGround = rOption.GetString();
977 break;
978 case HtmlOptionId::BGCOLOR:
979 rOption.GetColor( aBGColor );
980 bBGColor = true;
981 break;
982 case HtmlOptionId::TEXT:
983 rOption.GetColor( aTextColor );
984 bTextColor = true;
985 break;
986 case HtmlOptionId::LINK:
987 rOption.GetColor( aLinkColor );
988 bLinkColor = true;
989 break;
990 case HtmlOptionId::VLINK:
991 rOption.GetColor( aVLinkColor );
992 bVLinkColor = true;
993 break;
995 case HtmlOptionId::SDONLOAD:
996 eScriptType2 = STARBASIC;
997 [[fallthrough]];
998 case HtmlOptionId::ONLOAD:
999 aEvent = GlobalEventConfig::GetEventName( GlobalEventId::OPENDOC );
1000 bSetEvent = true;
1001 break;
1003 case HtmlOptionId::SDONUNLOAD:
1004 eScriptType2 = STARBASIC;
1005 [[fallthrough]];
1006 case HtmlOptionId::ONUNLOAD:
1007 aEvent = GlobalEventConfig::GetEventName( GlobalEventId::PREPARECLOSEDOC );
1008 bSetEvent = true;
1009 break;
1011 case HtmlOptionId::SDONFOCUS:
1012 eScriptType2 = STARBASIC;
1013 [[fallthrough]];
1014 case HtmlOptionId::ONFOCUS:
1015 aEvent = GlobalEventConfig::GetEventName( GlobalEventId::ACTIVATEDOC );
1016 bSetEvent = true;
1017 break;
1019 case HtmlOptionId::SDONBLUR:
1020 eScriptType2 = STARBASIC;
1021 [[fallthrough]];
1022 case HtmlOptionId::ONBLUR:
1023 aEvent = GlobalEventConfig::GetEventName( GlobalEventId::DEACTIVATEDOC );
1024 bSetEvent = true;
1025 break;
1027 case HtmlOptionId::ONERROR:
1028 break;
1030 case HtmlOptionId::STYLE:
1031 aStyle = rOption.GetString();
1032 bTextColor = true;
1033 break;
1034 case HtmlOptionId::LANG:
1035 aLang = rOption.GetString();
1036 break;
1037 case HtmlOptionId::DIR:
1038 aDir = rOption.GetString();
1039 break;
1040 default: break;
1043 if( bSetEvent )
1045 const OUString& rEvent = rOption.GetString();
1046 if( !rEvent.isEmpty() )
1047 InsertBasicDocEvent( aEvent, rEvent, eScriptType2,
1048 sDfltScriptType );
1052 if( bTextColor && !m_pCSS1Parser->IsBodyTextSet() )
1054 // The font colour is set in the default style
1055 m_pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_STANDARD )
1056 ->SetFormatAttr( SvxColorItem(aTextColor, RES_CHRATR_COLOR) );
1057 m_pCSS1Parser->SetBodyTextSet();
1060 // Prepare the items for the page style (background, frame)
1061 // If BrushItem already set values must remain!
1062 std::unique_ptr<SvxBrushItem> aBrushItem( m_pCSS1Parser->makePageDescBackground() );
1063 bool bSetBrush = false;
1065 if( bBGColor && !m_pCSS1Parser->IsBodyBGColorSet() )
1067 // background colour from "BGCOLOR"
1068 OUString aLink;
1069 if( !aBrushItem->GetGraphicLink().isEmpty() )
1070 aLink = aBrushItem->GetGraphicLink();
1071 SvxGraphicPosition ePos = aBrushItem->GetGraphicPos();
1073 aBrushItem->SetColor( aBGColor );
1075 if( !aLink.isEmpty() )
1077 aBrushItem->SetGraphicLink( aLink );
1078 aBrushItem->SetGraphicPos( ePos );
1080 bSetBrush = true;
1081 m_pCSS1Parser->SetBodyBGColorSet();
1084 if( !aBackGround.isEmpty() && !m_pCSS1Parser->IsBodyBackgroundSet() )
1086 // background graphic from "BACKGROUND"
1087 aBrushItem->SetGraphicLink( INetURLObject::GetAbsURL( m_sBaseURL, aBackGround ) );
1088 aBrushItem->SetGraphicPos( GPOS_TILED );
1089 bSetBrush = true;
1090 m_pCSS1Parser->SetBodyBackgroundSet();
1093 if( !aStyle.isEmpty() || !aDir.isEmpty() )
1095 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
1096 SvxCSS1PropertyInfo aPropInfo;
1097 OUString aDummy;
1098 (void)ParseStyleOptions( aStyle, aDummy, aDummy, aItemSet, aPropInfo, nullptr, &aDir );
1100 // Some attributes have to set on the page style, in fact the ones
1101 // which aren't inherited
1102 m_pCSS1Parser->SetPageDescAttrs( bSetBrush ? aBrushItem.get() : nullptr,
1103 &aItemSet );
1105 static const TypedWhichId<SvxFontHeightItem> aWhichIds[3] = { RES_CHRATR_FONTSIZE,
1106 RES_CHRATR_CJK_FONTSIZE,
1107 RES_CHRATR_CTL_FONTSIZE };
1108 for(auto const & i : aWhichIds)
1110 const SvxFontHeightItem *pItem = aItemSet.GetItemIfSet( i, false );
1111 if( pItem && pItem->GetProp() != 100)
1113 sal_uInt32 nHeight =
1114 ( m_aFontHeights[2] * pItem->GetProp() ) / 100;
1115 SvxFontHeightItem aNewItem( nHeight, 100, i );
1116 aItemSet.Put( aNewItem );
1120 // all remaining options can be set on the default style
1121 m_pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_STANDARD )
1122 ->SetFormatAttr( aItemSet );
1124 else if( bSetBrush )
1126 m_pCSS1Parser->SetPageDescAttrs( aBrushItem.get() );
1129 if( bLinkColor && !m_pCSS1Parser->IsBodyLinkSet() )
1131 SwCharFormat *pCharFormat =
1132 m_pCSS1Parser->GetCharFormatFromPool(RES_POOLCHR_INET_NORMAL);
1133 pCharFormat->SetFormatAttr( SvxColorItem(aLinkColor, RES_CHRATR_COLOR) );
1134 m_pCSS1Parser->SetBodyLinkSet();
1136 if( bVLinkColor && !m_pCSS1Parser->IsBodyVLinkSet() )
1138 SwCharFormat *pCharFormat =
1139 m_pCSS1Parser->GetCharFormatFromPool(RES_POOLCHR_INET_VISIT);
1140 pCharFormat->SetFormatAttr( SvxColorItem(aVLinkColor, RES_CHRATR_COLOR) );
1141 m_pCSS1Parser->SetBodyVLinkSet();
1143 if( !aLang.isEmpty() )
1145 LanguageType eLang = LanguageTag::convertToLanguageTypeWithFallback( aLang );
1146 if( LANGUAGE_DONTKNOW != eLang )
1148 TypedWhichId<SvxLanguageItem> nWhich(0);
1149 switch( SvtLanguageOptions::GetScriptTypeOfLanguage( eLang ) )
1151 case SvtScriptType::LATIN:
1152 nWhich = RES_CHRATR_LANGUAGE;
1153 break;
1154 case SvtScriptType::ASIAN:
1155 nWhich = RES_CHRATR_CJK_LANGUAGE;
1156 break;
1157 case SvtScriptType::COMPLEX:
1158 nWhich = RES_CHRATR_CTL_LANGUAGE;
1159 break;
1160 default: break;
1162 if( nWhich )
1164 SvxLanguageItem aLanguage( eLang, nWhich );
1165 aLanguage.SetWhich( nWhich );
1166 m_xDoc->SetDefault( aLanguage );
1171 if( !aId.isEmpty() )
1172 InsertBookmark( aId );
1175 /* */
1177 void SwHTMLParser::NewAnchor()
1179 // end previous link if there was one
1180 std::unique_ptr<HTMLAttrContext> xOldCntxt(PopContext(HtmlTokenId::ANCHOR_ON));
1181 if (xOldCntxt)
1183 // and maybe end attributes
1184 EndContext(xOldCntxt.get());
1187 SvxMacroTableDtor aMacroTable;
1188 OUString sHRef, aName, sTarget;
1189 OUString aId, aStyle, aClass, aLang, aDir;
1190 bool bHasHRef = false, bFixed = false;
1192 ScriptType eDfltScriptType;
1193 OUString sDfltScriptType;
1194 GetDefaultScriptType( eDfltScriptType, sDfltScriptType );
1196 const HTMLOptions& rHTMLOptions = GetOptions();
1197 for (size_t i = rHTMLOptions.size(); i; )
1199 SvMacroItemId nEvent = SvMacroItemId::NONE;
1200 ScriptType eScriptType2 = eDfltScriptType;
1201 const HTMLOption& rOption = rHTMLOptions[--i];
1202 switch( rOption.GetToken() )
1204 case HtmlOptionId::NAME:
1205 aName = rOption.GetString();
1206 break;
1208 case HtmlOptionId::HREF:
1209 sHRef = rOption.GetString();
1210 bHasHRef = true;
1211 break;
1212 case HtmlOptionId::TARGET:
1213 sTarget = rOption.GetString();
1214 break;
1216 case HtmlOptionId::STYLE:
1217 aStyle = rOption.GetString();
1218 break;
1219 case HtmlOptionId::ID:
1220 aId = rOption.GetString();
1221 break;
1222 case HtmlOptionId::CLASS:
1223 aClass = rOption.GetString();
1224 break;
1225 case HtmlOptionId::SDFIXED:
1226 bFixed = true;
1227 break;
1228 case HtmlOptionId::LANG:
1229 aLang = rOption.GetString();
1230 break;
1231 case HtmlOptionId::DIR:
1232 aDir = rOption.GetString();
1233 break;
1235 case HtmlOptionId::SDONCLICK:
1236 eScriptType2 = STARBASIC;
1237 [[fallthrough]];
1238 case HtmlOptionId::ONCLICK:
1239 nEvent = SvMacroItemId::OnClick;
1240 goto ANCHOR_SETEVENT;
1242 case HtmlOptionId::SDONMOUSEOVER:
1243 eScriptType2 = STARBASIC;
1244 [[fallthrough]];
1245 case HtmlOptionId::ONMOUSEOVER:
1246 nEvent = SvMacroItemId::OnMouseOver;
1247 goto ANCHOR_SETEVENT;
1249 case HtmlOptionId::SDONMOUSEOUT:
1250 eScriptType2 = STARBASIC;
1251 [[fallthrough]];
1252 case HtmlOptionId::ONMOUSEOUT:
1253 nEvent = SvMacroItemId::OnMouseOut;
1254 goto ANCHOR_SETEVENT;
1255 ANCHOR_SETEVENT:
1257 OUString sTmp( rOption.GetString() );
1258 if( !sTmp.isEmpty() )
1260 sTmp = convertLineEnd(sTmp, GetSystemLineEnd());
1261 OUString sScriptType;
1262 if( EXTENDED_STYPE == eScriptType2 )
1263 sScriptType = sDfltScriptType;
1264 aMacroTable.Insert( nEvent, SvxMacro( sTmp, sScriptType, eScriptType2 ));
1267 break;
1268 default: break;
1272 // Jump targets, which match our implicit targets,
1273 // here we throw out rigorously.
1274 if( !aName.isEmpty() )
1276 OUString sDecoded( INetURLObject::decode( aName,
1277 INetURLObject::DecodeMechanism::Unambiguous ));
1278 sal_Int32 nPos = sDecoded.lastIndexOf( cMarkSeparator );
1279 if( nPos != -1 )
1281 OUString sCmp= sDecoded.copy(nPos+1).replaceAll(" ","");
1282 if( !sCmp.isEmpty() )
1284 sCmp = sCmp.toAsciiLowerCase();
1285 if( sCmp == "region" ||
1286 sCmp == "frame" ||
1287 sCmp == "graphic" ||
1288 sCmp == "ole" ||
1289 sCmp == "table" ||
1290 sCmp == "outline" ||
1291 sCmp == "text" )
1293 aName.clear();
1299 // create a new context
1300 std::unique_ptr<HTMLAttrContext> xCntxt(new HTMLAttrContext(HtmlTokenId::ANCHOR_ON));
1302 bool bEnAnchor = false, bFootnoteAnchor = false, bFootnoteEnSymbol = false;
1303 OUString aFootnoteName;
1304 OUString aStrippedClass( aClass );
1305 SwCSS1Parser::GetScriptFromClass( aStrippedClass, false );
1306 if( aStrippedClass.getLength() >=9 && bHasHRef && sHRef.getLength() > 1 &&
1307 ('s' == aStrippedClass[0] || 'S' == aStrippedClass[0]) &&
1308 ('d' == aStrippedClass[1] || 'D' == aStrippedClass[1]) )
1310 if( aStrippedClass.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote_anc ) )
1311 bEnAnchor = true;
1312 else if( aStrippedClass.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote_anc ) )
1313 bFootnoteAnchor = true;
1314 else if( aStrippedClass.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote_sym ) ||
1315 aStrippedClass.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote_sym ) )
1316 bFootnoteEnSymbol = true;
1317 if( bEnAnchor || bFootnoteAnchor || bFootnoteEnSymbol )
1319 aFootnoteName = sHRef.copy( 1 );
1320 aClass.clear();
1321 aStrippedClass.clear();
1322 aName.clear();
1323 bHasHRef = false;
1327 // Styles parsen
1328 if( HasStyleOptions( aStyle, aId, aStrippedClass, &aLang, &aDir ) )
1330 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
1331 SvxCSS1PropertyInfo aPropInfo;
1333 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
1335 DoPositioning(aItemSet, aPropInfo, xCntxt.get());
1336 InsertAttrs(aItemSet, aPropInfo, xCntxt.get(), true);
1340 if( bHasHRef )
1342 if( !sHRef.isEmpty() )
1344 sHRef = URIHelper::SmartRel2Abs( INetURLObject(m_sBaseURL), sHRef, Link<OUString *, bool>(), false );
1346 else
1348 // use directory if empty URL
1349 INetURLObject aURLObj( m_aPathToFile );
1350 sHRef = aURLObj.GetPartBeforeLastName();
1353 m_pCSS1Parser->SetATagStyles();
1354 SwFormatINetFormat aINetFormat( sHRef, sTarget );
1355 aINetFormat.SetName( aName );
1357 if( !aMacroTable.empty() )
1359 NotifyMacroEventRead();
1360 aINetFormat.SetMacroTable( &aMacroTable );
1363 // set the default attribute
1364 InsertAttr(&m_xAttrTab->pINetFormat, aINetFormat, xCntxt.get());
1366 else if( !aName.isEmpty() )
1368 InsertBookmark( aName );
1371 if( bEnAnchor || bFootnoteAnchor )
1373 InsertFootEndNote( aFootnoteName, bEnAnchor, bFixed );
1374 m_bInFootEndNoteAnchor = m_bCallNextToken = true;
1376 else if( bFootnoteEnSymbol )
1378 m_bInFootEndNoteSymbol = m_bCallNextToken = true;
1381 // save context
1382 PushContext(xCntxt);
1385 void SwHTMLParser::EndAnchor()
1387 if( m_bInFootEndNoteAnchor )
1389 FinishFootEndNote();
1390 m_bInFootEndNoteAnchor = false;
1392 else if( m_bInFootEndNoteSymbol )
1394 m_bInFootEndNoteSymbol = false;
1397 EndTag( HtmlTokenId::ANCHOR_OFF );
1400 /* */
1402 void SwHTMLParser::InsertBookmark( const OUString& rName )
1404 HTMLAttr* pTmp = new HTMLAttr( *m_pPam->GetPoint(),
1405 SfxStringItem(RES_FLTR_BOOKMARK, rName), nullptr, std::shared_ptr<HTMLAttrTable>());
1406 m_aSetAttrTab.push_back( pTmp );
1409 bool SwHTMLParser::HasCurrentParaBookmarks( bool bIgnoreStack ) const
1411 bool bHasMarks = false;
1412 SwNodeOffset nNodeIdx = m_pPam->GetPoint()->GetNodeIndex();
1414 // first step: are there still bookmark in the attribute-stack?
1415 // bookmarks are added to the end of the stack - thus we only have
1416 // to check the last bookmark
1417 if( !bIgnoreStack )
1419 for( auto i = m_aSetAttrTab.size(); i; )
1421 HTMLAttr* pAttr = m_aSetAttrTab[ --i ];
1422 if( RES_FLTR_BOOKMARK == pAttr->m_pItem->Which() )
1424 if( pAttr->GetStartParagraphIdx() == nNodeIdx )
1425 bHasMarks = true;
1426 break;
1431 if( !bHasMarks )
1433 // second step: when we didn't find a bookmark, check if there is one set already
1434 IDocumentMarkAccess* const pMarkAccess = m_xDoc->getIDocumentMarkAccess();
1435 for(auto ppMark = pMarkAccess->getAllMarksBegin();
1436 ppMark != pMarkAccess->getAllMarksEnd();
1437 ++ppMark)
1439 const ::sw::mark::MarkBase* pBookmark = *ppMark;
1441 const SwNodeOffset nBookNdIdx = pBookmark->GetMarkPos().GetNodeIndex();
1442 if( nBookNdIdx==nNodeIdx )
1444 bHasMarks = true;
1445 break;
1447 else if( nBookNdIdx > nNodeIdx )
1448 break;
1452 return bHasMarks;
1455 /* */
1457 void SwHTMLParser::StripTrailingPara()
1459 bool bSetSmallFont = false;
1461 SwContentNode* pCNd = m_pPam->GetPointContentNode();
1462 SwNodeOffset nNodeIdx = m_pPam->GetPoint()->GetNodeIndex();
1463 if( !m_pPam->GetPoint()->GetContentIndex() )
1465 if( pCNd && pCNd->StartOfSectionIndex() + 2 <
1466 pCNd->EndOfSectionIndex() && CanRemoveNode(nNodeIdx))
1469 for(sw::SpzFrameFormat* pSpz: *m_xDoc->GetSpzFrameFormats())
1471 SwFormatAnchor const*const pAnchor = &pSpz->GetAnchor();
1472 SwNode const*const pAnchorNode = pAnchor->GetAnchorNode();
1473 if (pAnchorNode &&
1474 ((RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId()) ||
1475 (RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
1476 pAnchorNode->GetIndex() == nNodeIdx )
1478 return; // we can't delete the node
1481 SetAttr( false ); // the still open attributes must be
1482 // closed before the node is deleted,
1483 // otherwise the last index is dangling
1485 if( pCNd->Len() && pCNd->IsTextNode() )
1487 // fields were inserted into the node, now they have
1488 // to be moved
1489 SwTextNode *pPrvNd = m_xDoc->GetNodes()[nNodeIdx-1]->GetTextNode();
1490 if( pPrvNd )
1492 SwContentIndex aSrc( pCNd, 0 );
1493 pCNd->GetTextNode()->CutText( pPrvNd, aSrc, pCNd->Len() );
1497 // now we have to move maybe existing bookmarks
1498 IDocumentMarkAccess* const pMarkAccess = m_xDoc->getIDocumentMarkAccess();
1499 for(auto ppMark = pMarkAccess->getAllMarksBegin();
1500 ppMark != pMarkAccess->getAllMarksEnd();
1501 ++ppMark)
1503 ::sw::mark::MarkBase* pMark = *ppMark;
1505 SwNodeOffset nBookNdIdx = pMark->GetMarkPos().GetNodeIndex();
1506 if(nBookNdIdx==nNodeIdx)
1508 SwNodeIndex nNewNdIdx(m_pPam->GetPoint()->GetNode());
1509 SwContentNode* pNd = SwNodes::GoPrevious(&nNewNdIdx);
1510 if(!pNd)
1512 OSL_ENSURE(false, "Oops, where is my predecessor node?");
1513 return;
1515 // #i81002# - refactoring
1516 // Do not directly manipulate member of <SwBookmark>
1518 const SwPaM aPaM(*pNd, pNd->Len());
1519 pMarkAccess->repositionMark(*ppMark, aPaM);
1522 else if( nBookNdIdx > nNodeIdx )
1523 break;
1526 SwNode& rDelNode = m_pPam->GetPoint()->GetNode();
1527 m_pPam->Move( fnMoveBackward, GoInNode );
1528 m_pPam->SetMark();
1529 m_pPam->DeleteMark();
1530 m_xDoc->GetNodes().Delete( rDelNode );
1532 else if (pCNd && pCNd->IsTextNode() && m_xTable)
1534 // In empty cells we set a small font, so that the cell doesn't
1535 // get higher than the graphic resp. as low as possible.
1536 bSetSmallFont = true;
1539 else if( pCNd && pCNd->IsTextNode() && m_xTable &&
1540 pCNd->StartOfSectionIndex()+2 ==
1541 pCNd->EndOfSectionIndex() )
1543 // When the cell contains only as-character anchored graphics/frames,
1544 // then we also set a small font.
1545 bSetSmallFont = true;
1546 SwTextNode* pTextNd = pCNd->GetTextNode();
1548 sal_Int32 nPos = m_pPam->GetPoint()->GetContentIndex();
1549 while( bSetSmallFont && nPos>0 )
1551 --nPos;
1552 bSetSmallFont =
1553 (CH_TXTATR_BREAKWORD == pTextNd->GetText()[nPos]) &&
1554 (nullptr != pTextNd->GetTextAttrForCharAt( nPos, RES_TXTATR_FLYCNT ));
1558 if( bSetSmallFont )
1560 // Added default to CJK and CTL
1561 SvxFontHeightItem aFontHeight( 40, 100, RES_CHRATR_FONTSIZE );
1562 pCNd->SetAttr( aFontHeight );
1563 SvxFontHeightItem aFontHeightCJK( 40, 100, RES_CHRATR_CJK_FONTSIZE );
1564 pCNd->SetAttr( aFontHeightCJK );
1565 SvxFontHeightItem aFontHeightCTL( 40, 100, RES_CHRATR_CTL_FONTSIZE );
1566 pCNd->SetAttr( aFontHeightCTL );
1570 void SwHTMLParser::NotifyMacroEventRead()
1572 if (m_bNotifyMacroEventRead)
1573 return;
1574 SwDocShell *pDocSh = m_xDoc->GetDocShell();
1575 if (!pDocSh)
1576 return;
1577 rtl::Reference<SwXTextDocument> const xModel(pDocSh->GetBaseModel());
1578 comphelper::DocumentInfo::notifyMacroEventRead(static_cast<SfxBaseModel*>(xModel.get()));
1579 m_bNotifyMacroEventRead = true;
1582 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */