1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
49 #include <fmtsrnd.hxx>
50 #include <fmtinfmt.hxx>
51 #include <fmtcntnt.hxx>
52 #include <fmtanchr.hxx>
53 #include <fmtfsize.hxx>
54 #include <charatr.hxx>
56 #include <charfmt.hxx>
61 #include <shellio.hxx>
62 #include <poolfmt.hxx>
65 #include "htmlnum.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
},
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
},
101 ImageMap
*SwHTMLParser::FindImageMap( std::u16string_view rName
) const
103 OSL_ENSURE( rName
[0] != '#', "FindImageMap: name begins with '#'!" );
107 for (const auto &rpIMap
: *m_pImageMaps
)
109 if (o3tl::equalsIgnoreAsciiCase(rName
, rpIMap
->GetName()))
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();
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.
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
,
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();
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
);
178 // Otherwise the alignment is set correspondingly the normal HTML options.
179 SetAnchorAndAdjustment( eVertOri
, eHoriOri
, rFrameItemSet
);
183 void SwHTMLParser::SetAnchorAndAdjustment( sal_Int16 eVertOri
,
185 SfxItemSet
& rFrameSet
,
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;
197 GetMarginsFromContextWithNumberBullet( nLeftSpace
, nRightSpace
, nIndent
);
199 // determine horizontal alignment and wrapping
201 css::text::WrapTextMode eSurround
;
204 case text::HoriOrientation::LEFT
:
205 eHoriRel
= nLeftSpace
? text::RelOrientation::PRINT_AREA
: text::RelOrientation::FRAME
;
206 eSurround
= css::text::WrapTextMode_RIGHT
;
208 case text::HoriOrientation::RIGHT
:
209 eHoriRel
= nRightSpace
? text::RelOrientation::PRINT_AREA
: text::RelOrientation::FRAME
;
210 eSurround
= css::text::WrapTextMode_LEFT
;
212 case text::HoriOrientation::CENTER
: // for tables
213 eHoriRel
= text::RelOrientation::FRAME
;
214 eSurround
= css::text::WrapTextMode_NONE
;
217 eHoriRel
= text::RelOrientation::FRAME
;
218 eSurround
= css::text::WrapTextMode_PARALLEL
;
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
230 sal_uInt16 nUpper
=0, nLower
=0;
231 GetULSpaceFromContext( nUpper
, nLower
);
232 InsertAttr( SvxULSpaceItem( nUpper
, 0, RES_UL_SPACE
), true );
234 AppendTextNode( AM_NOSPACE
);
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();
248 aAnchor
.SetType( RndStdIds::FLY_AT_CHAR
);
249 bMoveBackward
= true;
250 eVertOri
= text::VertOrientation::CHAR_BOTTOM
;
251 eVertRel
= text::RelOrientation::CHAR
;
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
) );
267 m_pPam
->Move( fnMoveBackward
);
269 if (aAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
&& !m_pPam
->GetPointNode().GetTextNode())
271 eState
= SvParserState::Error
;
275 aAnchor
.SetAnchor( m_pPam
->GetPoint() );
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() );
297 void SwHTMLParser::GetDefaultScriptType( ScriptType
& rType
,
298 OUString
& rTypeStr
) const
300 SwDocShell
*pDocSh
= m_xDoc
->GetDocShell();
301 SvKeyValueIterator
* pHeaderAttrs
= pDocSh
? pDocSh
->GetHeaderAttributes()
303 rType
= GetScriptType( pHeaderAttrs
);
304 rTypeStr
= GetScriptTypeString( pHeaderAttrs
);
309 bool allowAccessLink(const SwDoc
& rDoc
)
312 SfxObjectShell
* sh
= rDoc
.GetPersist();
313 if (sh
!= nullptr && sh
->HasName())
315 sReferer
= sh
->GetMedium()->GetName();
317 return !SvtSecurityOptions::isUntrustedReferer(sReferer
);
323 void SwHTMLParser::InsertImage()
326 OUString sAltNm
, aId
, aClass
, aStyle
, aMap
, sHTMLGrfName
;
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);
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();
357 case HtmlOptionId::STYLE
:
358 aStyle
= rOption
.GetString();
360 case HtmlOptionId::CLASS
:
361 aClass
= rOption
.GetString();
363 case HtmlOptionId::SRC
:
364 sGrfNm
= rOption
.GetString();
365 if( !InternalImgToPrivateURL(sGrfNm
) )
366 sGrfNm
= INetURLObject::GetAbsURL( m_sBaseURL
, sGrfNm
);
368 case HtmlOptionId::DATA
:
369 aGraphicData
= rOption
.GetString();
370 if (!InternalImgToPrivateURL(aGraphicData
))
371 aGraphicData
= INetURLObject::GetAbsURL(
372 m_sBaseURL
, SwHTMLParser::StripQueryFromPath(m_sBaseURL
, aGraphicData
));
374 case HtmlOptionId::ALIGN
:
376 rOption
.GetEnum( aHTMLImgVAlignTable
,
377 text::VertOrientation::TOP
);
379 rOption
.GetEnum( aHTMLImgHAlignTable
);
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 )
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");
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 )
399 // the same as above w/ HtmlOptionId::WIDTH
400 bHeightProvided
= (sHeightAsString
!= "auto");
402 case HtmlOptionId::VSPACE
:
403 nVSpace
= rOption
.GetNumber();
405 case HtmlOptionId::HSPACE
:
406 nHSpace
= rOption
.GetNumber();
408 case HtmlOptionId::ALT
:
409 sAltNm
= rOption
.GetString();
411 case HtmlOptionId::BORDER
:
412 nBorder
= o3tl::narrowing
<sal_uInt16
>(rOption
.GetNumber());
414 case HtmlOptionId::ISMAP
:
417 case HtmlOptionId::USEMAP
:
418 aMap
= rOption
.GetString();
420 case HtmlOptionId::NAME
:
421 sHTMLGrfName
= rOption
.GetString();
424 case HtmlOptionId::SDONLOAD
:
425 eScriptType2
= STARBASIC
;
427 case HtmlOptionId::ONLOAD
:
428 nEvent
= SvMacroItemId::OnImageLoadDone
;
431 case HtmlOptionId::SDONABORT
:
432 eScriptType2
= STARBASIC
;
434 case HtmlOptionId::ONABORT
:
435 nEvent
= SvMacroItemId::OnImageLoadCancel
;
438 case HtmlOptionId::SDONERROR
:
439 eScriptType2
= STARBASIC
;
441 case HtmlOptionId::ONERROR
:
442 nEvent
= SvMacroItemId::OnImageLoadError
;
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
));
462 if (sGrfNm
.isEmpty() && !aGraphicData
.isEmpty())
463 sGrfNm
= aGraphicData
;
465 if( sGrfNm
.isEmpty() )
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.
497 INetURLObject
aGraphicURL( sGrfNm
);
498 if( aGraphicURL
.GetProtocol() == INetProtocol::Data
)
500 std::unique_ptr
<SvMemoryStream
> const pStream(aGraphicURL
.getData());
503 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
504 aGraphic
= rFilter
.ImportUnloadedGraphic(*pStream
);
507 if (!sGrfNm
.isEmpty())
509 if (ERRCODE_NONE
== rFilter
.ImportGraphic(aGraphic
, u
"", *pStream
))
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
))
525 if (!sGrfNm
.isEmpty())
527 aGraphic
.SetDefaultType();
530 if (!nHeight
|| !nWidth
)
532 Size aPixelSize
= aGraphic
.GetSizePixel(Application::GetDefaultDevice());
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())
542 nHeight
= SwFormatFrameSize::SYNCED
;
543 bPercentHeight
= true;
547 nHeight
= nWidth
* aPixelSize
.Height() / aPixelSize
.Width();
550 else if (!bWidthProvided
&& bHeightProvided
&& aPixelSize
.Height())
554 nWidth
= SwFormatFrameSize::SYNCED
;
555 bPercentWidth
= true;
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() );
571 Reader::ResetFrameFormatAttrs( aFrameSet
);
574 tools::Long nHBorderWidth
= 0, nVBorderWidth
= 0;
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() );
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
);
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()),
638 // convert CSS1 size to "normal" size
639 switch( aPropInfo
.m_eWidthType
)
641 case SVX_CSS1_LTYPE_TWIP
:
642 aTwipSz
.setWidth( aPropInfo
.m_nWidth
);
644 bPercentWidth
= false;
646 case SVX_CSS1_LTYPE_PERCENTAGE
:
647 aTwipSz
.setWidth( 0 );
648 nWidth
= aPropInfo
.m_nWidth
;
649 bPercentWidth
= true;
654 switch( aPropInfo
.m_eHeightType
)
656 case SVX_CSS1_LTYPE_TWIP
:
657 aTwipSz
.setHeight( aPropInfo
.m_nHeight
);
659 bPercentHeight
= false;
661 case SVX_CSS1_LTYPE_PERCENTAGE
:
662 aTwipSz
.setHeight( 0 );
663 nHeight
= aPropInfo
.m_nHeight
;
664 bPercentHeight
= true;
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.
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;
717 if( !nWidth
&& !nHeight
)
719 aTwipSz
.setWidth( HTML_DFLT_IMG_WIDTH
);
720 aTwipSz
.setHeight( HTML_DFLT_IMG_HEIGHT
);
724 // a percentage value
727 nPercentWidth
= static_cast<sal_uInt8
>(nWidth
);
728 nPercentHeight
= 255;
732 aTwipSz
.setHeight( HTML_DFLT_IMG_HEIGHT
);
739 nPercentHeight
= static_cast<sal_uInt8
>(nHeight
);
744 aTwipSz
.setWidth( HTML_DFLT_IMG_WIDTH
);
750 // Width and height were given and don't need to be set
751 bSetTwipSize
= false;
754 nPercentWidth
= static_cast<sal_uInt8
>(nWidth
);
757 nPercentHeight
= static_cast<sal_uInt8
>(nHeight
);
761 aMap
= comphelper::string::stripEnd(aMap
, ' ');
762 if( !aMap
.isEmpty() )
764 // Since we only know local image maps we just use everything
766 sal_Int32 nPos
= aMap
.indexOf( '#' );
771 aName
= aMap
.copy(nPos
+1);
773 ImageMap
*pImgMap
= FindImageMap( aName
);
776 SwFormatURL aURL
; aURL
.SetMap( pImgMap
);// is copied
778 bSetScaleImageMap
= !nPercentWidth
|| !nPercentHeight
;
779 aFrameSet
.Put( aURL
);
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
;
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
);
805 aTwipSz
.AdjustWidth(2*nVBorderWidth
);
806 if( aTwipSz
.Width() < MINFLY
)
807 aTwipSz
.setWidth( MINFLY
);
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
);
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
)
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
;
854 if( !sAltNm
.isEmpty() )
855 pGrfNd
->SetTitle( sAltNm
);
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
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
918 SwFormatURL
aURL(pFlyFormat
->GetURL());
919 aURL
.SetURL(m_aEmbedURL
, bIsMap
);
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
);
943 InsertBookmark( aId
);
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
;
968 bool bSetEvent
= false;
970 switch( rOption
.GetToken() )
972 case HtmlOptionId::ID
:
973 aId
= rOption
.GetString();
975 case HtmlOptionId::BACKGROUND
:
976 aBackGround
= rOption
.GetString();
978 case HtmlOptionId::BGCOLOR
:
979 rOption
.GetColor( aBGColor
);
982 case HtmlOptionId::TEXT
:
983 rOption
.GetColor( aTextColor
);
986 case HtmlOptionId::LINK
:
987 rOption
.GetColor( aLinkColor
);
990 case HtmlOptionId::VLINK
:
991 rOption
.GetColor( aVLinkColor
);
995 case HtmlOptionId::SDONLOAD
:
996 eScriptType2
= STARBASIC
;
998 case HtmlOptionId::ONLOAD
:
999 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::OPENDOC
);
1003 case HtmlOptionId::SDONUNLOAD
:
1004 eScriptType2
= STARBASIC
;
1006 case HtmlOptionId::ONUNLOAD
:
1007 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::PREPARECLOSEDOC
);
1011 case HtmlOptionId::SDONFOCUS
:
1012 eScriptType2
= STARBASIC
;
1014 case HtmlOptionId::ONFOCUS
:
1015 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::ACTIVATEDOC
);
1019 case HtmlOptionId::SDONBLUR
:
1020 eScriptType2
= STARBASIC
;
1022 case HtmlOptionId::ONBLUR
:
1023 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::DEACTIVATEDOC
);
1027 case HtmlOptionId::ONERROR
:
1030 case HtmlOptionId::STYLE
:
1031 aStyle
= rOption
.GetString();
1034 case HtmlOptionId::LANG
:
1035 aLang
= rOption
.GetString();
1037 case HtmlOptionId::DIR:
1038 aDir
= rOption
.GetString();
1045 const OUString
& rEvent
= rOption
.GetString();
1046 if( !rEvent
.isEmpty() )
1047 InsertBasicDocEvent( aEvent
, rEvent
, eScriptType2
,
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"
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
);
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
);
1090 m_pCSS1Parser
->SetBodyBackgroundSet();
1093 if( !aStyle
.isEmpty() || !aDir
.isEmpty() )
1095 SfxItemSet
aItemSet( m_xDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
1096 SvxCSS1PropertyInfo aPropInfo
;
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,
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
;
1154 case SvtScriptType::ASIAN
:
1155 nWhich
= RES_CHRATR_CJK_LANGUAGE
;
1157 case SvtScriptType::COMPLEX
:
1158 nWhich
= RES_CHRATR_CTL_LANGUAGE
;
1164 SvxLanguageItem
aLanguage( eLang
, nWhich
);
1165 aLanguage
.SetWhich( nWhich
);
1166 m_xDoc
->SetDefault( aLanguage
);
1171 if( !aId
.isEmpty() )
1172 InsertBookmark( aId
);
1177 void SwHTMLParser::NewAnchor()
1179 // end previous link if there was one
1180 std::unique_ptr
<HTMLAttrContext
> xOldCntxt(PopContext(HtmlTokenId::ANCHOR_ON
));
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();
1208 case HtmlOptionId::HREF
:
1209 sHRef
= rOption
.GetString();
1212 case HtmlOptionId::TARGET
:
1213 sTarget
= rOption
.GetString();
1216 case HtmlOptionId::STYLE
:
1217 aStyle
= rOption
.GetString();
1219 case HtmlOptionId::ID
:
1220 aId
= rOption
.GetString();
1222 case HtmlOptionId::CLASS
:
1223 aClass
= rOption
.GetString();
1225 case HtmlOptionId::SDFIXED
:
1228 case HtmlOptionId::LANG
:
1229 aLang
= rOption
.GetString();
1231 case HtmlOptionId::DIR:
1232 aDir
= rOption
.GetString();
1235 case HtmlOptionId::SDONCLICK
:
1236 eScriptType2
= STARBASIC
;
1238 case HtmlOptionId::ONCLICK
:
1239 nEvent
= SvMacroItemId::OnClick
;
1240 goto ANCHOR_SETEVENT
;
1242 case HtmlOptionId::SDONMOUSEOVER
:
1243 eScriptType2
= STARBASIC
;
1245 case HtmlOptionId::ONMOUSEOVER
:
1246 nEvent
= SvMacroItemId::OnMouseOver
;
1247 goto ANCHOR_SETEVENT
;
1249 case HtmlOptionId::SDONMOUSEOUT
:
1250 eScriptType2
= STARBASIC
;
1252 case HtmlOptionId::ONMOUSEOUT
:
1253 nEvent
= SvMacroItemId::OnMouseOut
;
1254 goto 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
));
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
);
1281 OUString sCmp
= sDecoded
.copy(nPos
+1).replaceAll(" ","");
1282 if( !sCmp
.isEmpty() )
1284 sCmp
= sCmp
.toAsciiLowerCase();
1285 if( sCmp
== "region" ||
1287 sCmp
== "graphic" ||
1290 sCmp
== "outline" ||
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
) )
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 );
1321 aStrippedClass
.clear();
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);
1342 if( !sHRef
.isEmpty() )
1344 sHRef
= URIHelper::SmartRel2Abs( INetURLObject(m_sBaseURL
), sHRef
, Link
<OUString
*, bool>(), false );
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;
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
);
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
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
)
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();
1439 const ::sw::mark::MarkBase
* pBookmark
= *ppMark
;
1441 const SwNodeOffset nBookNdIdx
= pBookmark
->GetMarkPos().GetNodeIndex();
1442 if( nBookNdIdx
==nNodeIdx
)
1447 else if( nBookNdIdx
> nNodeIdx
)
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();
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
1489 SwTextNode
*pPrvNd
= m_xDoc
->GetNodes()[nNodeIdx
-1]->GetTextNode();
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();
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
);
1512 OSL_ENSURE(false, "Oops, where is my predecessor node?");
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
)
1526 SwNode
& rDelNode
= m_pPam
->GetPoint()->GetNode();
1527 m_pPam
->Move( fnMoveBackward
, GoInNode
);
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 )
1553 (CH_TXTATR_BREAKWORD
== pTextNd
->GetText()[nPos
]) &&
1554 (nullptr != pTextNd
->GetTextAttrForCharAt( nPos
, RES_TXTATR_FLYCNT
));
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
)
1574 SwDocShell
*pDocSh
= m_xDoc
->GetDocShell();
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: */