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/string.hxx>
23 #include <comphelper/documentinfo.hxx>
24 #include <vcl/svapp.hxx>
25 #include <i18nlangtag/languagetag.hxx>
26 #include <svl/stritem.hxx>
27 #include <svl/urihelper.hxx>
28 #include <svl/languageoptions.hxx>
29 #include <editeng/fhgtitem.hxx>
30 #include <editeng/brushitem.hxx>
31 #include <editeng/colritem.hxx>
32 #include <editeng/boxitem.hxx>
33 #include <editeng/ulspitem.hxx>
34 #include <editeng/langitem.hxx>
35 #include <sfx2/docfile.hxx>
36 #include <sfx2/event.hxx>
37 #include <vcl/imap.hxx>
38 #include <svtools/htmltokn.h>
39 #include <svtools/htmlkywd.hxx>
40 #include <unotools/eventcfg.hxx>
41 #include <sal/log.hxx>
42 #include <osl/diagnose.h>
43 #include <o3tl/string_view.hxx>
45 #include <fmtornt.hxx>
47 #include <fmtsrnd.hxx>
48 #include <fmtinfmt.hxx>
49 #include <fmtcntnt.hxx>
50 #include <fmtanchr.hxx>
51 #include <fmtfsize.hxx>
52 #include <charatr.hxx>
54 #include <charfmt.hxx>
59 #include <shellio.hxx>
60 #include <poolfmt.hxx>
63 #include "htmlnum.hxx"
66 #include <numrule.hxx>
67 #include <IDocumentMarkAccess.hxx>
68 #include <frameformats.hxx>
70 #include <vcl/graphicfilter.hxx>
71 #include <tools/UnitConversion.hxx>
72 #include <tools/urlobj.hxx>
73 #include <unotools/securityoptions.hxx>
75 using namespace ::com::sun::star
;
77 HTMLOptionEnum
<sal_Int16
> const aHTMLImgHAlignTable
[] =
79 { OOO_STRING_SVTOOLS_HTML_AL_left
, text::HoriOrientation::LEFT
},
80 { OOO_STRING_SVTOOLS_HTML_AL_right
, text::HoriOrientation::RIGHT
},
84 HTMLOptionEnum
<sal_Int16
> const aHTMLImgVAlignTable
[] =
86 { OOO_STRING_SVTOOLS_HTML_VA_top
, text::VertOrientation::LINE_TOP
},
87 { OOO_STRING_SVTOOLS_HTML_VA_texttop
, text::VertOrientation::CHAR_TOP
},
88 { OOO_STRING_SVTOOLS_HTML_VA_middle
, text::VertOrientation::CENTER
},
89 { OOO_STRING_SVTOOLS_HTML_AL_center
, text::VertOrientation::CENTER
},
90 { OOO_STRING_SVTOOLS_HTML_VA_absmiddle
, text::VertOrientation::LINE_CENTER
},
91 { OOO_STRING_SVTOOLS_HTML_VA_bottom
, text::VertOrientation::TOP
},
92 { OOO_STRING_SVTOOLS_HTML_VA_baseline
, text::VertOrientation::TOP
},
93 { OOO_STRING_SVTOOLS_HTML_VA_absbottom
, text::VertOrientation::LINE_BOTTOM
},
97 ImageMap
*SwHTMLParser::FindImageMap( std::u16string_view rName
) const
99 OSL_ENSURE( rName
[0] != '#', "FindImageMap: name begins with '#'!" );
103 for (const auto &rpIMap
: *m_pImageMaps
)
105 if (o3tl::equalsIgnoreAsciiCase(rName
, rpIMap
->GetName()))
114 void SwHTMLParser::ConnectImageMaps()
116 SwNodes
& rNds
= m_xDoc
->GetNodes();
117 // on the first node of section #1
118 SwNodeOffset nIdx
= rNds
.GetEndOfAutotext().StartOfSectionIndex() + 1;
119 SwNodeOffset nEndIdx
= rNds
.GetEndOfAutotext().GetIndex();
122 while( m_nMissingImgMaps
> 0 && nIdx
< nEndIdx
)
124 SwNode
*pNd
= rNds
[nIdx
+ 1];
125 pGrfNd
= pNd
->GetGrfNode();
126 if( nullptr != pGrfNd
)
128 SwFrameFormat
*pFormat
= pGrfNd
->GetFlyFormat();
129 SwFormatURL
aURL( pFormat
->GetURL() );
130 const ImageMap
*pIMap
= aURL
.GetMap();
131 if( pIMap
&& pIMap
->GetIMapObjectCount()==0 )
133 // The (empty) image map of the node will be either
134 // replaced with found image map or deleted.
136 FindImageMap( pIMap
->GetName() );
137 aURL
.SetMap( pNewIMap
);
138 pFormat
->SetFormatAttr( aURL
);
139 if( !pGrfNd
->IsScaleImageMap() )
141 // meanwhile the graphic size is known or the
142 // graphic don't need scaling
143 pGrfNd
->ScaleImageMap();
145 m_nMissingImgMaps
--; // search a map less
148 nIdx
= rNds
[nIdx
]->EndOfSectionIndex() + 1;
152 void SwHTMLParser::SetAnchorAndAdjustment( sal_Int16 eVertOri
,
154 const SvxCSS1PropertyInfo
&rCSS1PropInfo
,
155 SfxItemSet
& rFrameItemSet
)
157 const SfxItemSet
*pCntnrItemSet
= nullptr;
158 auto i
= m_aContexts
.size();
159 while( !pCntnrItemSet
&& i
> m_nContextStMin
)
160 pCntnrItemSet
= m_aContexts
[--i
]->GetFrameItemSet();
164 // If we are in a container then the anchoring of the container is used.
165 rFrameItemSet
.Put( *pCntnrItemSet
);
167 else if( SwCSS1Parser::MayBePositioned( rCSS1PropInfo
, true ) )
169 // If the alignment can be set via CSS1 options we use them.
170 SetAnchorAndAdjustment( rCSS1PropInfo
, rFrameItemSet
);
174 // Otherwise the alignment is set correspondingly the normal HTML options.
175 SetAnchorAndAdjustment( eVertOri
, eHoriOri
, rFrameItemSet
);
179 void SwHTMLParser::SetAnchorAndAdjustment( sal_Int16 eVertOri
,
181 SfxItemSet
& rFrameSet
,
184 bool bMoveBackward
= false;
185 SwFormatAnchor
aAnchor( RndStdIds::FLY_AS_CHAR
);
186 sal_Int16 eVertRel
= text::RelOrientation::FRAME
;
188 if( text::HoriOrientation::NONE
!= eHoriOri
)
190 // determine paragraph indent
191 sal_uInt16 nLeftSpace
= 0, nRightSpace
= 0;
193 GetMarginsFromContextWithNumberBullet( nLeftSpace
, nRightSpace
, nIndent
);
195 // determine horizontal alignment and wrapping
197 css::text::WrapTextMode eSurround
;
200 case text::HoriOrientation::LEFT
:
201 eHoriRel
= nLeftSpace
? text::RelOrientation::PRINT_AREA
: text::RelOrientation::FRAME
;
202 eSurround
= css::text::WrapTextMode_RIGHT
;
204 case text::HoriOrientation::RIGHT
:
205 eHoriRel
= nRightSpace
? text::RelOrientation::PRINT_AREA
: text::RelOrientation::FRAME
;
206 eSurround
= css::text::WrapTextMode_LEFT
;
208 case text::HoriOrientation::CENTER
: // for tables
209 eHoriRel
= text::RelOrientation::FRAME
;
210 eSurround
= css::text::WrapTextMode_NONE
;
213 eHoriRel
= text::RelOrientation::FRAME
;
214 eSurround
= css::text::WrapTextMode_PARALLEL
;
218 // Create a new paragraph, if the current one has frames
219 // anchored at paragraph/at char without wrapping.
220 if( !bDontAppend
&& HasCurrentParaFlys( true ) )
222 // When the paragraph only contains graphics then there
223 // is no need for bottom margin. Since here also with use of
224 // styles no margin should be created, set attributes to
226 sal_uInt16 nUpper
=0, nLower
=0;
227 GetULSpaceFromContext( nUpper
, nLower
);
228 InsertAttr( SvxULSpaceItem( nUpper
, 0, RES_UL_SPACE
), true );
230 AppendTextNode( AM_NOSPACE
);
234 NewAttr(m_xAttrTab
, &m_xAttrTab
->pULSpace
, SvxULSpaceItem(0, nLower
, RES_UL_SPACE
));
235 m_aParaAttrs
.push_back( m_xAttrTab
->pULSpace
);
236 EndAttr( m_xAttrTab
->pULSpace
, false );
240 // determine vertical alignment and anchoring
241 const sal_Int32 nContent
= m_pPam
->GetPoint()->GetContentIndex();
244 aAnchor
.SetType( RndStdIds::FLY_AT_CHAR
);
245 bMoveBackward
= true;
246 eVertOri
= text::VertOrientation::CHAR_BOTTOM
;
247 eVertRel
= text::RelOrientation::CHAR
;
251 aAnchor
.SetType( RndStdIds::FLY_AT_PARA
);
252 eVertOri
= text::VertOrientation::TOP
;
253 eVertRel
= text::RelOrientation::PRINT_AREA
;
256 rFrameSet
.Put( SwFormatHoriOrient( 0, eHoriOri
, eHoriRel
) );
258 rFrameSet
.Put( SwFormatSurround( eSurround
) );
260 rFrameSet
.Put( SwFormatVertOrient( 0, eVertOri
, eVertRel
) );
263 m_pPam
->Move( fnMoveBackward
);
265 if (aAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
&& !m_pPam
->GetPointNode().GetTextNode())
267 eState
= SvParserState::Error
;
271 aAnchor
.SetAnchor( m_pPam
->GetPoint() );
274 m_pPam
->Move( fnMoveForward
);
276 rFrameSet
.Put( aAnchor
);
279 void SwHTMLParser::RegisterFlyFrame( SwFrameFormat
*pFlyFormat
)
281 // automatically anchored frames must be moved forward by one position
282 if( RES_DRAWFRMFMT
!= pFlyFormat
->Which() &&
283 (RndStdIds::FLY_AT_PARA
== pFlyFormat
->GetAnchor().GetAnchorId()) &&
284 css::text::WrapTextMode_THROUGH
== pFlyFormat
->GetSurround().GetSurround() )
286 m_aMoveFlyFrames
.emplace_back(std::make_unique
<SwHTMLFrameFormatListener
>(pFlyFormat
));
287 m_aMoveFlyCnts
.push_back( m_pPam
->GetPoint()->GetContentIndex() );
293 void SwHTMLParser::GetDefaultScriptType( ScriptType
& rType
,
294 OUString
& rTypeStr
) const
296 SwDocShell
*pDocSh
= m_xDoc
->GetDocShell();
297 SvKeyValueIterator
* pHeaderAttrs
= pDocSh
? pDocSh
->GetHeaderAttributes()
299 rType
= GetScriptType( pHeaderAttrs
);
300 rTypeStr
= GetScriptTypeString( pHeaderAttrs
);
305 bool allowAccessLink(const SwDoc
& rDoc
)
308 SfxObjectShell
* sh
= rDoc
.GetPersist();
309 if (sh
!= nullptr && sh
->HasName())
311 sReferer
= sh
->GetMedium()->GetName();
313 return !SvtSecurityOptions::isUntrustedReferer(sReferer
);
319 void SwHTMLParser::InsertImage()
322 OUString sAltNm
, aId
, aClass
, aStyle
, aMap
, sHTMLGrfName
;
324 OUString aGraphicData
;
325 sal_Int16 eVertOri
= text::VertOrientation::TOP
;
326 sal_Int16 eHoriOri
= text::HoriOrientation::NONE
;
327 bool bWidthProvided
=false, bHeightProvided
=false;
328 tools::Long nWidth
=0, nHeight
=0;
329 tools::Long nVSpace
=0, nHSpace
=0;
331 sal_uInt16 nBorder
= (m_xAttrTab
->pINetFormat
? 1 : 0);
333 bool bPercentWidth
= false;
334 bool bPercentHeight
= false;
335 OUString sWidthAsString
, sHeightAsString
;
336 SvxMacroItem
aMacroItem(RES_FRMMACRO
);
338 ScriptType eDfltScriptType
;
339 OUString sDfltScriptType
;
340 GetDefaultScriptType( eDfltScriptType
, sDfltScriptType
);
342 const HTMLOptions
& rHTMLOptions
= GetOptions();
343 for (size_t i
= rHTMLOptions
.size(); i
; )
345 SvMacroItemId nEvent
= SvMacroItemId::NONE
;
346 ScriptType eScriptType2
= eDfltScriptType
;
347 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
348 switch( rOption
.GetToken() )
350 case HtmlOptionId::ID
:
351 aId
= rOption
.GetString();
353 case HtmlOptionId::STYLE
:
354 aStyle
= rOption
.GetString();
356 case HtmlOptionId::CLASS
:
357 aClass
= rOption
.GetString();
359 case HtmlOptionId::SRC
:
360 sGrfNm
= rOption
.GetString();
361 if( !InternalImgToPrivateURL(sGrfNm
) )
362 sGrfNm
= INetURLObject::GetAbsURL( m_sBaseURL
, sGrfNm
);
364 case HtmlOptionId::DATA
:
365 aGraphicData
= rOption
.GetString();
366 if (!InternalImgToPrivateURL(aGraphicData
))
367 aGraphicData
= INetURLObject::GetAbsURL(
368 m_sBaseURL
, SwHTMLParser::StripQueryFromPath(m_sBaseURL
, aGraphicData
));
370 case HtmlOptionId::ALIGN
:
372 rOption
.GetEnum( aHTMLImgVAlignTable
,
373 text::VertOrientation::TOP
);
375 rOption
.GetEnum( aHTMLImgHAlignTable
);
377 case HtmlOptionId::WIDTH
:
378 // for now only store as pixel value!
379 nWidth
= rOption
.GetNumber();
380 sWidthAsString
= rOption
.GetString();
381 bPercentWidth
= (sWidthAsString
.indexOf('%') != -1);
382 if( bPercentWidth
&& nWidth
>100 )
384 // width|height = "auto" means viewing app decides the size
385 // i.e. proceed as if no particular size was provided
386 bWidthProvided
= (sWidthAsString
!= "auto");
388 case HtmlOptionId::HEIGHT
:
389 // for now only store as pixel value!
390 nHeight
= rOption
.GetNumber();
391 sHeightAsString
= rOption
.GetString();
392 bPercentHeight
= (sHeightAsString
.indexOf('%') != -1);
393 if( bPercentHeight
&& nHeight
>100 )
395 // the same as above w/ HtmlOptionId::WIDTH
396 bHeightProvided
= (sHeightAsString
!= "auto");
398 case HtmlOptionId::VSPACE
:
399 nVSpace
= rOption
.GetNumber();
401 case HtmlOptionId::HSPACE
:
402 nHSpace
= rOption
.GetNumber();
404 case HtmlOptionId::ALT
:
405 sAltNm
= rOption
.GetString();
407 case HtmlOptionId::BORDER
:
408 nBorder
= o3tl::narrowing
<sal_uInt16
>(rOption
.GetNumber());
410 case HtmlOptionId::ISMAP
:
413 case HtmlOptionId::USEMAP
:
414 aMap
= rOption
.GetString();
416 case HtmlOptionId::NAME
:
417 sHTMLGrfName
= rOption
.GetString();
420 case HtmlOptionId::SDONLOAD
:
421 eScriptType2
= STARBASIC
;
423 case HtmlOptionId::ONLOAD
:
424 nEvent
= SvMacroItemId::OnImageLoadDone
;
427 case HtmlOptionId::SDONABORT
:
428 eScriptType2
= STARBASIC
;
430 case HtmlOptionId::ONABORT
:
431 nEvent
= SvMacroItemId::OnImageLoadCancel
;
434 case HtmlOptionId::SDONERROR
:
435 eScriptType2
= STARBASIC
;
437 case HtmlOptionId::ONERROR
:
438 nEvent
= SvMacroItemId::OnImageLoadError
;
442 OUString
sTmp( rOption
.GetString() );
443 if( !sTmp
.isEmpty() )
445 sTmp
= convertLineEnd(sTmp
, GetSystemLineEnd());
446 OUString sScriptType
;
447 if( EXTENDED_STYPE
== eScriptType2
)
448 sScriptType
= sDfltScriptType
;
449 aMacroItem
.SetMacro( nEvent
,
450 SvxMacro( sTmp
, sScriptType
, eScriptType2
));
458 if (sGrfNm
.isEmpty() && !aGraphicData
.isEmpty())
459 sGrfNm
= aGraphicData
;
461 if( sGrfNm
.isEmpty() )
464 // When we are in an ordered list and the paragraph is still empty and not
465 // numbered, it may be a graphic for a bullet list.
466 if( !m_pPam
->GetPoint()->GetContentIndex() &&
467 GetNumInfo().GetDepth() > 0 && GetNumInfo().GetDepth() <= MAXLEVEL
&&
468 !m_aBulletGrfs
[GetNumInfo().GetDepth()-1].isEmpty() &&
469 m_aBulletGrfs
[GetNumInfo().GetDepth()-1]==sGrfNm
)
471 SwTextNode
* pTextNode
= m_pPam
->GetPointNode().GetTextNode();
473 if( pTextNode
&& ! pTextNode
->IsCountedInList())
475 OSL_ENSURE( pTextNode
->GetActualListLevel() == GetNumInfo().GetLevel(),
476 "Numbering level is wrong" );
478 pTextNode
->SetCountedInList( true );
480 // It's necessary to invalidate the rule, because between the reading
481 // of LI and the graphic an EndAction could be called.
482 if( GetNumInfo().GetNumRule() )
483 GetNumInfo().GetNumRule()->SetInvalidRule( true );
485 // Set the style again, so that indent of the first line is correct.
493 INetURLObject
aGraphicURL( sGrfNm
);
494 if( aGraphicURL
.GetProtocol() == INetProtocol::Data
)
496 std::unique_ptr
<SvMemoryStream
> const pStream(aGraphicURL
.getData());
499 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
500 aGraphic
= rFilter
.ImportUnloadedGraphic(*pStream
);
503 if (!sGrfNm
.isEmpty())
505 if (ERRCODE_NONE
== rFilter
.ImportGraphic(aGraphic
, u
"", *pStream
))
510 else if (m_sBaseURL
.isEmpty() || !aGraphicData
.isEmpty())
512 // sBaseURL is empty if the source is clipboard
513 // aGraphicData is non-empty for <object data="..."> -> not a linked graphic.
514 if (ERRCODE_NONE
== GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic
, aGraphicURL
))
518 if (!sGrfNm
.isEmpty())
520 aGraphic
.SetDefaultType();
523 if (!nHeight
|| !nWidth
)
525 Size aPixelSize
= aGraphic
.GetSizePixel(Application::GetDefaultDevice());
527 nWidth
= aPixelSize
.Width();
528 if (!bHeightProvided
)
529 nHeight
= aPixelSize
.Height();
530 // tdf#142781 - calculate the width/height keeping the aspect ratio
531 if (bWidthProvided
&& !bHeightProvided
&& aPixelSize
.Width())
535 nHeight
= SwFormatFrameSize::SYNCED
;
536 bPercentHeight
= true;
540 nHeight
= nWidth
* aPixelSize
.Height() / aPixelSize
.Width();
543 else if (!bWidthProvided
&& bHeightProvided
&& aPixelSize
.Height())
547 nWidth
= SwFormatFrameSize::SYNCED
;
548 bPercentWidth
= true;
552 nWidth
= nHeight
* aPixelSize
.Width() / aPixelSize
.Height();
557 SfxItemSet
aItemSet( m_xDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
558 SvxCSS1PropertyInfo aPropInfo
;
559 if( HasStyleOptions( aStyle
, aId
, aClass
) )
560 ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
);
562 SfxItemSetFixed
<RES_FRMATR_BEGIN
, RES_FRMATR_END
-1> aFrameSet( m_xDoc
->GetAttrPool() );
564 Reader::ResetFrameFormatAttrs( aFrameSet
);
567 tools::Long nHBorderWidth
= 0, nVBorderWidth
= 0;
570 nHBorderWidth
= static_cast<tools::Long
>(nBorder
);
571 nVBorderWidth
= static_cast<tools::Long
>(nBorder
);
572 SvxCSS1Parser::PixelToTwip( nVBorderWidth
, nHBorderWidth
);
574 ::editeng::SvxBorderLine
aHBorderLine( nullptr, nHBorderWidth
);
575 ::editeng::SvxBorderLine
aVBorderLine( nullptr, nVBorderWidth
);
577 if( m_xAttrTab
->pINetFormat
)
579 const OUString
& rURL
=
580 static_cast<const SwFormatINetFormat
&>(m_xAttrTab
->pINetFormat
->GetItem()).GetValue();
582 m_pCSS1Parser
->SetATagStyles();
583 sal_uInt16 nPoolId
= static_cast< sal_uInt16
>(m_xDoc
->IsVisitedURL( rURL
)
584 ? RES_POOLCHR_INET_VISIT
585 : RES_POOLCHR_INET_NORMAL
);
586 const SwCharFormat
*pCharFormat
= m_pCSS1Parser
->GetCharFormatFromPool( nPoolId
);
587 aHBorderLine
.SetColor( pCharFormat
->GetColor().GetValue() );
588 aVBorderLine
.SetColor( aHBorderLine
.GetColor() );
592 const SvxColorItem
& rColorItem
= m_xAttrTab
->pFontColor
?
593 static_cast<const SvxColorItem
&>(m_xAttrTab
->pFontColor
->GetItem()) :
594 m_xDoc
->GetDefault(RES_CHRATR_COLOR
);
595 aHBorderLine
.SetColor( rColorItem
.GetValue() );
596 aVBorderLine
.SetColor( aHBorderLine
.GetColor() );
599 SvxBoxItem
aBoxItem( RES_BOX
);
600 aBoxItem
.SetLine( &aHBorderLine
, SvxBoxItemLine::TOP
);
601 aBoxItem
.SetLine( &aHBorderLine
, SvxBoxItemLine::BOTTOM
);
602 aBoxItem
.SetLine( &aVBorderLine
, SvxBoxItemLine::LEFT
);
603 aBoxItem
.SetLine( &aVBorderLine
, SvxBoxItemLine::RIGHT
);
604 aFrameSet
.Put( aBoxItem
);
607 SetAnchorAndAdjustment( eVertOri
, eHoriOri
, aPropInfo
, aFrameSet
);
609 SetSpace( Size( nHSpace
, nVSpace
), aItemSet
, aPropInfo
, aFrameSet
);
611 // set other CSS1 attributes
612 SetFrameFormatAttrs( aItemSet
, HtmlFrameFormatFlags::Box
, aFrameSet
);
614 Size
aTwipSz( bPercentWidth
? 0 : nWidth
, bPercentHeight
? 0 : nHeight
);
615 if( aTwipSz
.Width() || aTwipSz
.Height() )
617 if (bWidthProvided
|| bHeightProvided
|| // attributes imply pixel!
618 aGraphic
.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
620 aTwipSz
= o3tl::convert(aTwipSz
, o3tl::Length::px
, o3tl::Length::twip
);
623 { // some bitmaps may have a size in metric units (e.g. PNG); use that
624 assert(aGraphic
.GetPrefMapMode().GetMapUnit() < MapUnit::MapPixel
);
625 aTwipSz
= o3tl::convert(aGraphic
.GetPrefSize(),
626 MapToO3tlLength(aGraphic
.GetPrefMapMode().GetMapUnit()),
631 // convert CSS1 size to "normal" size
632 switch( aPropInfo
.m_eWidthType
)
634 case SVX_CSS1_LTYPE_TWIP
:
635 aTwipSz
.setWidth( aPropInfo
.m_nWidth
);
637 bPercentWidth
= false;
639 case SVX_CSS1_LTYPE_PERCENTAGE
:
640 aTwipSz
.setWidth( 0 );
641 nWidth
= aPropInfo
.m_nWidth
;
642 bPercentWidth
= true;
647 switch( aPropInfo
.m_eHeightType
)
649 case SVX_CSS1_LTYPE_TWIP
:
650 aTwipSz
.setHeight( aPropInfo
.m_nHeight
);
652 bPercentHeight
= false;
654 case SVX_CSS1_LTYPE_PERCENTAGE
:
655 aTwipSz
.setHeight( 0 );
656 nHeight
= aPropInfo
.m_nHeight
;
657 bPercentHeight
= true;
664 bool bSetTwipSize
= true; // Set Twip-Size on Node?
665 bool bChangeFrameSize
= false; // Change frame format later?
666 bool bRequestGrfNow
= false;
667 bool bSetScaleImageMap
= false;
668 sal_uInt8 nPercentWidth
= 0, nPercentHeight
= 0;
670 // bPercentWidth / bPercentHeight means we have a percent size. If that's not the case and we have no
671 // size from nWidth / nHeight either, then inspect the image header.
672 bool bRelWidthScale
= bPercentWidth
&& nWidth
== SwFormatFrameSize::SYNCED
;
673 bool bNeedWidth
= (!bPercentWidth
&& !nWidth
) || bRelWidthScale
;
674 bool bRelHeightScale
= bPercentHeight
&& nHeight
== SwFormatFrameSize::SYNCED
;
675 bool bNeedHeight
= (!bPercentHeight
&& !nHeight
) || bRelHeightScale
;
676 if ((bNeedWidth
|| bNeedHeight
) && !bFuzzing
&& allowAccessLink(*m_xDoc
))
678 GraphicDescriptor
aDescriptor(aGraphicURL
);
679 if (aDescriptor
.Detect(/*bExtendedInfo=*/true))
681 // Try to use size info from the image header before defaulting to
682 // HTML_DFLT_IMG_WIDTH/HEIGHT.
684 = o3tl::convert(aDescriptor
.GetSizePixel(), o3tl::Length::px
, o3tl::Length::twip
);
685 if (!bPercentWidth
&& !nWidth
)
687 nWidth
= aTwipSz
.getWidth();
689 if (!bPercentHeight
&& !nHeight
)
691 nHeight
= aTwipSz
.getHeight();
696 if( !(nWidth
&& !bRelWidthScale
) || !(nHeight
&& !bRelHeightScale
) )
698 // When the graphic is in a table, it will be requested immediately,
699 // so that it is available before the table is layouted.
700 if (m_xTable
&& !nWidth
)
702 bRequestGrfNow
= true;
703 IncGrfsThatResizeTable();
706 // The frame size is set later
707 bChangeFrameSize
= true;
709 if( !nWidth
&& !nHeight
)
711 aTwipSz
.setWidth( HTML_DFLT_IMG_WIDTH
);
712 aTwipSz
.setHeight( HTML_DFLT_IMG_HEIGHT
);
716 // a percentage value
719 nPercentWidth
= static_cast<sal_uInt8
>(nWidth
);
720 nPercentHeight
= 255;
724 aTwipSz
.setHeight( HTML_DFLT_IMG_HEIGHT
);
731 nPercentHeight
= static_cast<sal_uInt8
>(nHeight
);
736 aTwipSz
.setWidth( HTML_DFLT_IMG_WIDTH
);
742 // Width and height were given and don't need to be set
743 bSetTwipSize
= false;
746 nPercentWidth
= static_cast<sal_uInt8
>(nWidth
);
749 nPercentHeight
= static_cast<sal_uInt8
>(nHeight
);
753 aMap
= comphelper::string::stripEnd(aMap
, ' ');
754 if( !aMap
.isEmpty() )
756 // Since we only know local image maps we just use everything
758 sal_Int32 nPos
= aMap
.indexOf( '#' );
763 aName
= aMap
.copy(nPos
+1);
765 ImageMap
*pImgMap
= FindImageMap( aName
);
768 SwFormatURL aURL
; aURL
.SetMap( pImgMap
);// is copied
770 bSetScaleImageMap
= !nPercentWidth
|| !nPercentHeight
;
771 aFrameSet
.Put( aURL
);
775 ImageMap
aEmptyImgMap( aName
);
776 SwFormatURL aURL
; aURL
.SetMap( &aEmptyImgMap
);// is copied
777 aFrameSet
.Put( aURL
);
778 m_nMissingImgMaps
++; // image maps are missing
780 // the graphic has to scaled during SetTwipSize, if we didn't
781 // set a size on the node or the size doesn't match the graphic size.
782 bSetScaleImageMap
= true;
786 // observe minimum values !!
787 bool bRelSizeScale
= bRelWidthScale
|| bRelHeightScale
;
790 OSL_ENSURE( !aTwipSz
.Width() || bRelSizeScale
,
791 "Why is a width set if we already have percentage value?" );
792 aTwipSz
.setWidth( aGrfSz
.Width() ? aGrfSz
.Width()
793 : HTML_DFLT_IMG_WIDTH
);
797 aTwipSz
.AdjustWidth(2*nVBorderWidth
);
798 if( aTwipSz
.Width() < MINFLY
)
799 aTwipSz
.setWidth( MINFLY
);
803 OSL_ENSURE( !aTwipSz
.Height() || bRelSizeScale
,
804 "Why is a height set if we already have percentage value?" );
805 aTwipSz
.setHeight( aGrfSz
.Height() ? aGrfSz
.Height()
806 : HTML_DFLT_IMG_HEIGHT
);
810 aTwipSz
.AdjustHeight(2*nHBorderWidth
);
811 if( aTwipSz
.Height() < MINFLY
)
812 aTwipSz
.setHeight( MINFLY
);
815 SwFormatFrameSize
aFrameSize( SwFrameSize::Fixed
, aTwipSz
.Width(), aTwipSz
.Height() );
816 aFrameSize
.SetWidthPercent( nPercentWidth
);
817 aFrameSize
.SetHeightPercent( nPercentHeight
);
818 aFrameSet
.Put( aFrameSize
);
820 const SwNodeType eNodeType
= m_pPam
->GetPointNode().GetNodeType();
821 if (eNodeType
!= SwNodeType::Text
&& eNodeType
!= SwNodeType::Table
)
824 // passing empty sGrfNm here, means we don't want the graphic to be linked
825 SwFrameFormat
*const pFlyFormat
=
826 m_xDoc
->getIDocumentContentOperations().InsertGraphic(
827 *m_pPam
, sGrfNm
, OUString(), &aGraphic
,
828 &aFrameSet
, nullptr, nullptr);
829 SwGrfNode
*pGrfNd
= m_xDoc
->GetNodes()[ pFlyFormat
->GetContent().GetContentIdx()
830 ->GetIndex()+1 ]->GetGrfNode();
832 if( !sHTMLGrfName
.isEmpty() )
834 pFlyFormat
->SetFormatName( sHTMLGrfName
);
836 // maybe jump to graphic
837 if( JumpToMarks::Graphic
== m_eJumpTo
&& sHTMLGrfName
== m_sJmpMark
)
839 m_bChkJumpMark
= true;
840 m_eJumpTo
= JumpToMarks::NONE
;
846 if( !sAltNm
.isEmpty() )
847 pGrfNd
->SetTitle( sAltNm
);
850 pGrfNd
->SetTwipSize( aGrfSz
);
852 pGrfNd
->SetChgTwipSize( bChangeFrameSize
);
854 if( bSetScaleImageMap
)
855 pGrfNd
->SetScaleImageMap( true );
858 if( m_xAttrTab
->pINetFormat
)
860 const SwFormatINetFormat
&rINetFormat
=
861 static_cast<const SwFormatINetFormat
&>(m_xAttrTab
->pINetFormat
->GetItem());
863 SwFormatURL
aURL( pFlyFormat
->GetURL() );
865 aURL
.SetURL( rINetFormat
.GetValue(), bIsMap
);
866 aURL
.SetTargetFrameName( rINetFormat
.GetTargetFrame() );
867 aURL
.SetName( rINetFormat
.GetName() );
868 pFlyFormat
->SetFormatAttr( aURL
);
871 static const SvMacroItemId aEvents
[] = {
872 SvMacroItemId::OnMouseOver
,
873 SvMacroItemId::OnClick
,
874 SvMacroItemId::OnMouseOut
};
876 for( SvMacroItemId id
: aEvents
)
878 const SvxMacro
*pMacro
= rINetFormat
.GetMacro( id
);
879 if( nullptr != pMacro
)
880 aMacroItem
.SetMacro( id
, *pMacro
);
884 if ((RndStdIds::FLY_AS_CHAR
== pFlyFormat
->GetAnchor().GetAnchorId()) &&
885 m_xAttrTab
->pINetFormat
->GetStartParagraph() ==
886 m_pPam
->GetPoint()->GetNode() &&
887 m_xAttrTab
->pINetFormat
->GetStartContent() ==
888 m_pPam
->GetPoint()->GetContentIndex() - 1 )
890 // the attribute was insert right before as-character anchored
891 // graphic, therefore we move it
892 m_xAttrTab
->pINetFormat
->SetStart( *m_pPam
->GetPoint() );
894 // When the attribute is also an anchor, we'll insert
895 // a bookmark before the graphic, because SwFormatURL
897 if( !rINetFormat
.GetName().isEmpty() )
899 m_pPam
->Move( fnMoveBackward
);
900 InsertBookmark( rINetFormat
.GetName() );
901 m_pPam
->Move( fnMoveForward
);
906 else if (!m_aEmbedURL
.isEmpty())
908 // This is an inner <object> image and the outer <object> has a URL for us. Set that on the
910 SwFormatURL
aURL(pFlyFormat
->GetURL());
911 aURL
.SetURL(m_aEmbedURL
, bIsMap
);
913 pFlyFormat
->SetFormatAttr(aURL
);
916 if( !aMacroItem
.GetMacroTable().empty() )
918 NotifyMacroEventRead();
919 pFlyFormat
->SetFormatAttr( aMacroItem
);
922 // tdf#87083 If the graphic has not been loaded yet, then load it now.
923 // Otherwise it may be loaded during the first paint of the object and it
924 // will be too late to adapt the size of the graphic at that point.
925 if (bRequestGrfNow
&& pGrfNd
)
927 Size aUpdatedSize
= pGrfNd
->GetTwipSize(); //trigger a swap-in
928 SAL_WARN_IF(!aUpdatedSize
.Width() || !aUpdatedSize
.Height(), "sw.html", "html image with no width or height");
931 // maybe create frames and register auto bound frames
932 RegisterFlyFrame( pFlyFormat
);
935 InsertBookmark( aId
);
940 void SwHTMLParser::InsertBodyOptions()
942 m_xDoc
->SetTextFormatColl( *m_pPam
,
943 m_pCSS1Parser
->GetTextCollFromPool( RES_POOLCOLL_TEXT
) );
945 OUString aBackGround
, aId
, aStyle
, aLang
, aDir
;
946 Color aBGColor
, aTextColor
, aLinkColor
, aVLinkColor
;
947 bool bBGColor
=false, bTextColor
=false;
948 bool bLinkColor
=false, bVLinkColor
=false;
950 ScriptType eDfltScriptType
;
951 OUString sDfltScriptType
;
952 GetDefaultScriptType( eDfltScriptType
, sDfltScriptType
);
954 const HTMLOptions
& rHTMLOptions
= GetOptions();
955 for (size_t i
= rHTMLOptions
.size(); i
; )
957 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
958 ScriptType eScriptType2
= eDfltScriptType
;
960 bool bSetEvent
= false;
962 switch( rOption
.GetToken() )
964 case HtmlOptionId::ID
:
965 aId
= rOption
.GetString();
967 case HtmlOptionId::BACKGROUND
:
968 aBackGround
= rOption
.GetString();
970 case HtmlOptionId::BGCOLOR
:
971 rOption
.GetColor( aBGColor
);
974 case HtmlOptionId::TEXT
:
975 rOption
.GetColor( aTextColor
);
978 case HtmlOptionId::LINK
:
979 rOption
.GetColor( aLinkColor
);
982 case HtmlOptionId::VLINK
:
983 rOption
.GetColor( aVLinkColor
);
987 case HtmlOptionId::SDONLOAD
:
988 eScriptType2
= STARBASIC
;
990 case HtmlOptionId::ONLOAD
:
991 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::OPENDOC
);
995 case HtmlOptionId::SDONUNLOAD
:
996 eScriptType2
= STARBASIC
;
998 case HtmlOptionId::ONUNLOAD
:
999 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::PREPARECLOSEDOC
);
1003 case HtmlOptionId::SDONFOCUS
:
1004 eScriptType2
= STARBASIC
;
1006 case HtmlOptionId::ONFOCUS
:
1007 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::ACTIVATEDOC
);
1011 case HtmlOptionId::SDONBLUR
:
1012 eScriptType2
= STARBASIC
;
1014 case HtmlOptionId::ONBLUR
:
1015 aEvent
= GlobalEventConfig::GetEventName( GlobalEventId::DEACTIVATEDOC
);
1019 case HtmlOptionId::ONERROR
:
1022 case HtmlOptionId::STYLE
:
1023 aStyle
= rOption
.GetString();
1026 case HtmlOptionId::LANG
:
1027 aLang
= rOption
.GetString();
1029 case HtmlOptionId::DIR:
1030 aDir
= rOption
.GetString();
1037 const OUString
& rEvent
= rOption
.GetString();
1038 if( !rEvent
.isEmpty() )
1039 InsertBasicDocEvent( aEvent
, rEvent
, eScriptType2
,
1044 if( bTextColor
&& !m_pCSS1Parser
->IsBodyTextSet() )
1046 // The font colour is set in the default style
1047 m_pCSS1Parser
->GetTextCollFromPool( RES_POOLCOLL_STANDARD
)
1048 ->SetFormatAttr( SvxColorItem(aTextColor
, RES_CHRATR_COLOR
) );
1049 m_pCSS1Parser
->SetBodyTextSet();
1052 // Prepare the items for the page style (background, frame)
1053 // If BrushItem already set values must remain!
1054 std::unique_ptr
<SvxBrushItem
> aBrushItem( m_pCSS1Parser
->makePageDescBackground() );
1055 bool bSetBrush
= false;
1057 if( bBGColor
&& !m_pCSS1Parser
->IsBodyBGColorSet() )
1059 // background colour from "BGCOLOR"
1061 if( !aBrushItem
->GetGraphicLink().isEmpty() )
1062 aLink
= aBrushItem
->GetGraphicLink();
1063 SvxGraphicPosition ePos
= aBrushItem
->GetGraphicPos();
1065 aBrushItem
->SetColor( aBGColor
);
1067 if( !aLink
.isEmpty() )
1069 aBrushItem
->SetGraphicLink( aLink
);
1070 aBrushItem
->SetGraphicPos( ePos
);
1073 m_pCSS1Parser
->SetBodyBGColorSet();
1076 if( !aBackGround
.isEmpty() && !m_pCSS1Parser
->IsBodyBackgroundSet() )
1078 // background graphic from "BACKGROUND"
1079 aBrushItem
->SetGraphicLink( INetURLObject::GetAbsURL( m_sBaseURL
, aBackGround
) );
1080 aBrushItem
->SetGraphicPos( GPOS_TILED
);
1082 m_pCSS1Parser
->SetBodyBackgroundSet();
1085 if( !aStyle
.isEmpty() || !aDir
.isEmpty() )
1087 SfxItemSet
aItemSet( m_xDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
1088 SvxCSS1PropertyInfo aPropInfo
;
1090 ParseStyleOptions( aStyle
, aDummy
, aDummy
, aItemSet
, aPropInfo
, nullptr, &aDir
);
1092 // Some attributes have to set on the page style, in fact the ones
1093 // which aren't inherited
1094 m_pCSS1Parser
->SetPageDescAttrs( bSetBrush
? aBrushItem
.get() : nullptr,
1097 static const TypedWhichId
<SvxFontHeightItem
> aWhichIds
[3] = { RES_CHRATR_FONTSIZE
,
1098 RES_CHRATR_CJK_FONTSIZE
,
1099 RES_CHRATR_CTL_FONTSIZE
};
1100 for(auto const & i
: aWhichIds
)
1102 const SvxFontHeightItem
*pItem
= aItemSet
.GetItemIfSet( i
, false );
1103 if( pItem
&& pItem
->GetProp() != 100)
1105 sal_uInt32 nHeight
=
1106 ( m_aFontHeights
[2] * pItem
->GetProp() ) / 100;
1107 SvxFontHeightItem
aNewItem( nHeight
, 100, i
);
1108 aItemSet
.Put( aNewItem
);
1112 // all remaining options can be set on the default style
1113 m_pCSS1Parser
->GetTextCollFromPool( RES_POOLCOLL_STANDARD
)
1114 ->SetFormatAttr( aItemSet
);
1116 else if( bSetBrush
)
1118 m_pCSS1Parser
->SetPageDescAttrs( aBrushItem
.get() );
1121 if( bLinkColor
&& !m_pCSS1Parser
->IsBodyLinkSet() )
1123 SwCharFormat
*pCharFormat
=
1124 m_pCSS1Parser
->GetCharFormatFromPool(RES_POOLCHR_INET_NORMAL
);
1125 pCharFormat
->SetFormatAttr( SvxColorItem(aLinkColor
, RES_CHRATR_COLOR
) );
1126 m_pCSS1Parser
->SetBodyLinkSet();
1128 if( bVLinkColor
&& !m_pCSS1Parser
->IsBodyVLinkSet() )
1130 SwCharFormat
*pCharFormat
=
1131 m_pCSS1Parser
->GetCharFormatFromPool(RES_POOLCHR_INET_VISIT
);
1132 pCharFormat
->SetFormatAttr( SvxColorItem(aVLinkColor
, RES_CHRATR_COLOR
) );
1133 m_pCSS1Parser
->SetBodyVLinkSet();
1135 if( !aLang
.isEmpty() )
1137 LanguageType eLang
= LanguageTag::convertToLanguageTypeWithFallback( aLang
);
1138 if( LANGUAGE_DONTKNOW
!= eLang
)
1140 sal_uInt16 nWhich
= 0;
1141 switch( SvtLanguageOptions::GetScriptTypeOfLanguage( eLang
) )
1143 case SvtScriptType::LATIN
:
1144 nWhich
= RES_CHRATR_LANGUAGE
;
1146 case SvtScriptType::ASIAN
:
1147 nWhich
= RES_CHRATR_CJK_LANGUAGE
;
1149 case SvtScriptType::COMPLEX
:
1150 nWhich
= RES_CHRATR_CTL_LANGUAGE
;
1156 SvxLanguageItem
aLanguage( eLang
, nWhich
);
1157 aLanguage
.SetWhich( nWhich
);
1158 m_xDoc
->SetDefault( aLanguage
);
1163 if( !aId
.isEmpty() )
1164 InsertBookmark( aId
);
1169 void SwHTMLParser::NewAnchor()
1171 // end previous link if there was one
1172 std::unique_ptr
<HTMLAttrContext
> xOldCntxt(PopContext(HtmlTokenId::ANCHOR_ON
));
1175 // and maybe end attributes
1176 EndContext(xOldCntxt
.get());
1179 SvxMacroTableDtor aMacroTable
;
1180 OUString sHRef
, aName
, sTarget
;
1181 OUString aId
, aStyle
, aClass
, aLang
, aDir
;
1182 bool bHasHRef
= false, bFixed
= false;
1184 ScriptType eDfltScriptType
;
1185 OUString sDfltScriptType
;
1186 GetDefaultScriptType( eDfltScriptType
, sDfltScriptType
);
1188 const HTMLOptions
& rHTMLOptions
= GetOptions();
1189 for (size_t i
= rHTMLOptions
.size(); i
; )
1191 SvMacroItemId nEvent
= SvMacroItemId::NONE
;
1192 ScriptType eScriptType2
= eDfltScriptType
;
1193 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
1194 switch( rOption
.GetToken() )
1196 case HtmlOptionId::NAME
:
1197 aName
= rOption
.GetString();
1200 case HtmlOptionId::HREF
:
1201 sHRef
= rOption
.GetString();
1204 case HtmlOptionId::TARGET
:
1205 sTarget
= rOption
.GetString();
1208 case HtmlOptionId::STYLE
:
1209 aStyle
= rOption
.GetString();
1211 case HtmlOptionId::ID
:
1212 aId
= rOption
.GetString();
1214 case HtmlOptionId::CLASS
:
1215 aClass
= rOption
.GetString();
1217 case HtmlOptionId::SDFIXED
:
1220 case HtmlOptionId::LANG
:
1221 aLang
= rOption
.GetString();
1223 case HtmlOptionId::DIR:
1224 aDir
= rOption
.GetString();
1227 case HtmlOptionId::SDONCLICK
:
1228 eScriptType2
= STARBASIC
;
1230 case HtmlOptionId::ONCLICK
:
1231 nEvent
= SvMacroItemId::OnClick
;
1232 goto ANCHOR_SETEVENT
;
1234 case HtmlOptionId::SDONMOUSEOVER
:
1235 eScriptType2
= STARBASIC
;
1237 case HtmlOptionId::ONMOUSEOVER
:
1238 nEvent
= SvMacroItemId::OnMouseOver
;
1239 goto ANCHOR_SETEVENT
;
1241 case HtmlOptionId::SDONMOUSEOUT
:
1242 eScriptType2
= STARBASIC
;
1244 case HtmlOptionId::ONMOUSEOUT
:
1245 nEvent
= SvMacroItemId::OnMouseOut
;
1246 goto ANCHOR_SETEVENT
;
1249 OUString
sTmp( rOption
.GetString() );
1250 if( !sTmp
.isEmpty() )
1252 sTmp
= convertLineEnd(sTmp
, GetSystemLineEnd());
1253 OUString sScriptType
;
1254 if( EXTENDED_STYPE
== eScriptType2
)
1255 sScriptType
= sDfltScriptType
;
1256 aMacroTable
.Insert( nEvent
, SvxMacro( sTmp
, sScriptType
, eScriptType2
));
1264 // Jump targets, which match our implicit targets,
1265 // here we throw out rigorously.
1266 if( !aName
.isEmpty() )
1268 OUString
sDecoded( INetURLObject::decode( aName
,
1269 INetURLObject::DecodeMechanism::Unambiguous
));
1270 sal_Int32 nPos
= sDecoded
.lastIndexOf( cMarkSeparator
);
1273 OUString sCmp
= sDecoded
.copy(nPos
+1).replaceAll(" ","");
1274 if( !sCmp
.isEmpty() )
1276 sCmp
= sCmp
.toAsciiLowerCase();
1277 if( sCmp
== "region" ||
1279 sCmp
== "graphic" ||
1282 sCmp
== "outline" ||
1291 // create a new context
1292 std::unique_ptr
<HTMLAttrContext
> xCntxt(new HTMLAttrContext(HtmlTokenId::ANCHOR_ON
));
1294 bool bEnAnchor
= false, bFootnoteAnchor
= false, bFootnoteEnSymbol
= false;
1295 OUString aFootnoteName
;
1296 OUString
aStrippedClass( aClass
);
1297 SwCSS1Parser::GetScriptFromClass( aStrippedClass
, false );
1298 if( aStrippedClass
.getLength() >=9 && bHasHRef
&& sHRef
.getLength() > 1 &&
1299 ('s' == aStrippedClass
[0] || 'S' == aStrippedClass
[0]) &&
1300 ('d' == aStrippedClass
[1] || 'D' == aStrippedClass
[1]) )
1302 if( aStrippedClass
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote_anc
) )
1304 else if( aStrippedClass
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote_anc
) )
1305 bFootnoteAnchor
= true;
1306 else if( aStrippedClass
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdendnote_sym
) ||
1307 aStrippedClass
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_sdfootnote_sym
) )
1308 bFootnoteEnSymbol
= true;
1309 if( bEnAnchor
|| bFootnoteAnchor
|| bFootnoteEnSymbol
)
1311 aFootnoteName
= sHRef
.copy( 1 );
1313 aStrippedClass
.clear();
1320 if( HasStyleOptions( aStyle
, aId
, aStrippedClass
, &aLang
, &aDir
) )
1322 SfxItemSet
aItemSet( m_xDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
1323 SvxCSS1PropertyInfo aPropInfo
;
1325 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
1327 DoPositioning(aItemSet
, aPropInfo
, xCntxt
.get());
1328 InsertAttrs(aItemSet
, aPropInfo
, xCntxt
.get(), true);
1334 if( !sHRef
.isEmpty() )
1336 sHRef
= URIHelper::SmartRel2Abs( INetURLObject(m_sBaseURL
), sHRef
, Link
<OUString
*, bool>(), false );
1340 // use directory if empty URL
1341 INetURLObject
aURLObj( m_aPathToFile
);
1342 sHRef
= aURLObj
.GetPartBeforeLastName();
1345 m_pCSS1Parser
->SetATagStyles();
1346 SwFormatINetFormat
aINetFormat( sHRef
, sTarget
);
1347 aINetFormat
.SetName( aName
);
1349 if( !aMacroTable
.empty() )
1351 NotifyMacroEventRead();
1352 aINetFormat
.SetMacroTable( &aMacroTable
);
1355 // set the default attribute
1356 InsertAttr(&m_xAttrTab
->pINetFormat
, aINetFormat
, xCntxt
.get());
1358 else if( !aName
.isEmpty() )
1360 InsertBookmark( aName
);
1363 if( bEnAnchor
|| bFootnoteAnchor
)
1365 InsertFootEndNote( aFootnoteName
, bEnAnchor
, bFixed
);
1366 m_bInFootEndNoteAnchor
= m_bCallNextToken
= true;
1368 else if( bFootnoteEnSymbol
)
1370 m_bInFootEndNoteSymbol
= m_bCallNextToken
= true;
1374 PushContext(xCntxt
);
1377 void SwHTMLParser::EndAnchor()
1379 if( m_bInFootEndNoteAnchor
)
1381 FinishFootEndNote();
1382 m_bInFootEndNoteAnchor
= false;
1384 else if( m_bInFootEndNoteSymbol
)
1386 m_bInFootEndNoteSymbol
= false;
1389 EndTag( HtmlTokenId::ANCHOR_OFF
);
1394 void SwHTMLParser::InsertBookmark( const OUString
& rName
)
1396 HTMLAttr
* pTmp
= new HTMLAttr( *m_pPam
->GetPoint(),
1397 SfxStringItem(RES_FLTR_BOOKMARK
, rName
), nullptr, std::shared_ptr
<HTMLAttrTable
>());
1398 m_aSetAttrTab
.push_back( pTmp
);
1401 bool SwHTMLParser::HasCurrentParaBookmarks( bool bIgnoreStack
) const
1403 bool bHasMarks
= false;
1404 SwNodeOffset nNodeIdx
= m_pPam
->GetPoint()->GetNodeIndex();
1406 // first step: are there still bookmark in the attribute-stack?
1407 // bookmarks are added to the end of the stack - thus we only have
1408 // to check the last bookmark
1411 for( auto i
= m_aSetAttrTab
.size(); i
; )
1413 HTMLAttr
* pAttr
= m_aSetAttrTab
[ --i
];
1414 if( RES_FLTR_BOOKMARK
== pAttr
->m_pItem
->Which() )
1416 if( pAttr
->GetStartParagraphIdx() == nNodeIdx
)
1425 // second step: when we didn't find a bookmark, check if there is one set already
1426 IDocumentMarkAccess
* const pMarkAccess
= m_xDoc
->getIDocumentMarkAccess();
1427 for(IDocumentMarkAccess::const_iterator_t ppMark
= pMarkAccess
->getAllMarksBegin();
1428 ppMark
!= pMarkAccess
->getAllMarksEnd();
1431 const ::sw::mark::IMark
* pBookmark
= *ppMark
;
1433 const SwNodeOffset nBookNdIdx
= pBookmark
->GetMarkPos().GetNodeIndex();
1434 if( nBookNdIdx
==nNodeIdx
)
1439 else if( nBookNdIdx
> nNodeIdx
)
1449 void SwHTMLParser::StripTrailingPara()
1451 bool bSetSmallFont
= false;
1453 SwContentNode
* pCNd
= m_pPam
->GetPointContentNode();
1454 SwNodeOffset nNodeIdx
= m_pPam
->GetPoint()->GetNodeIndex();
1455 if( !m_pPam
->GetPoint()->GetContentIndex() )
1457 if( pCNd
&& pCNd
->StartOfSectionIndex() + 2 <
1458 pCNd
->EndOfSectionIndex() && CanRemoveNode(nNodeIdx
))
1461 for(sw::SpzFrameFormat
* pSpz
: *m_xDoc
->GetSpzFrameFormats())
1463 SwFormatAnchor
const*const pAnchor
= &pSpz
->GetAnchor();
1464 SwNode
const*const pAnchorNode
= pAnchor
->GetAnchorNode();
1466 ((RndStdIds::FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
1467 (RndStdIds::FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
1468 pAnchorNode
->GetIndex() == nNodeIdx
)
1470 return; // we can't delete the node
1473 SetAttr( false ); // the still open attributes must be
1474 // closed before the node is deleted,
1475 // otherwise the last index is dangling
1477 if( pCNd
->Len() && pCNd
->IsTextNode() )
1479 // fields were inserted into the node, now they have
1481 SwTextNode
*pPrvNd
= m_xDoc
->GetNodes()[nNodeIdx
-1]->GetTextNode();
1484 SwContentIndex
aSrc( pCNd
, 0 );
1485 pCNd
->GetTextNode()->CutText( pPrvNd
, aSrc
, pCNd
->Len() );
1489 // now we have to move maybe existing bookmarks
1490 IDocumentMarkAccess
* const pMarkAccess
= m_xDoc
->getIDocumentMarkAccess();
1491 for(IDocumentMarkAccess::const_iterator_t ppMark
= pMarkAccess
->getAllMarksBegin();
1492 ppMark
!= pMarkAccess
->getAllMarksEnd();
1495 ::sw::mark::IMark
* pMark
= *ppMark
;
1497 SwNodeOffset nBookNdIdx
= pMark
->GetMarkPos().GetNodeIndex();
1498 if(nBookNdIdx
==nNodeIdx
)
1500 SwNodeIndex
nNewNdIdx(m_pPam
->GetPoint()->GetNode());
1501 SwContentNode
* pNd
= SwNodes::GoPrevious(&nNewNdIdx
);
1504 OSL_ENSURE(false, "Oops, where is my predecessor node?");
1507 // #i81002# - refactoring
1508 // Do not directly manipulate member of <SwBookmark>
1510 const SwPaM
aPaM(*pNd
, pNd
->Len());
1511 pMarkAccess
->repositionMark(*ppMark
, aPaM
);
1514 else if( nBookNdIdx
> nNodeIdx
)
1518 SwNode
& rDelNode
= m_pPam
->GetPoint()->GetNode();
1519 m_pPam
->Move( fnMoveBackward
, GoInNode
);
1521 m_pPam
->DeleteMark();
1522 m_xDoc
->GetNodes().Delete( rDelNode
);
1524 else if (pCNd
&& pCNd
->IsTextNode() && m_xTable
)
1526 // In empty cells we set a small font, so that the cell doesn't
1527 // get higher than the graphic resp. as low as possible.
1528 bSetSmallFont
= true;
1531 else if( pCNd
&& pCNd
->IsTextNode() && m_xTable
&&
1532 pCNd
->StartOfSectionIndex()+2 ==
1533 pCNd
->EndOfSectionIndex() )
1535 // When the cell contains only as-character anchored graphics/frames,
1536 // then we also set a small font.
1537 bSetSmallFont
= true;
1538 SwTextNode
* pTextNd
= pCNd
->GetTextNode();
1540 sal_Int32 nPos
= m_pPam
->GetPoint()->GetContentIndex();
1541 while( bSetSmallFont
&& nPos
>0 )
1545 (CH_TXTATR_BREAKWORD
== pTextNd
->GetText()[nPos
]) &&
1546 (nullptr != pTextNd
->GetTextAttrForCharAt( nPos
, RES_TXTATR_FLYCNT
));
1552 // Added default to CJK and CTL
1553 SvxFontHeightItem
aFontHeight( 40, 100, RES_CHRATR_FONTSIZE
);
1554 pCNd
->SetAttr( aFontHeight
);
1555 SvxFontHeightItem
aFontHeightCJK( 40, 100, RES_CHRATR_CJK_FONTSIZE
);
1556 pCNd
->SetAttr( aFontHeightCJK
);
1557 SvxFontHeightItem
aFontHeightCTL( 40, 100, RES_CHRATR_CTL_FONTSIZE
);
1558 pCNd
->SetAttr( aFontHeightCTL
);
1562 void SwHTMLParser::NotifyMacroEventRead()
1564 if (m_bNotifyMacroEventRead
)
1566 SwDocShell
*pDocSh
= m_xDoc
->GetDocShell();
1569 uno::Reference
<frame::XModel
> const xModel(pDocSh
->GetBaseModel());
1570 comphelper::DocumentInfo::notifyMacroEventRead(xModel
);
1571 m_bNotifyMacroEventRead
= true;
1574 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */