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 .
20 #include <hintids.hxx>
21 #include <svl/itemiter.hxx>
22 #include <svl/urihelper.hxx>
23 #include <i18nlangtag/languagetag.hxx>
24 #include <sfx2/docfile.hxx>
25 #include <editeng/editids.hrc>
26 #include <editeng/fhgtitem.hxx>
27 #include <editeng/brushitem.hxx>
28 #include <editeng/lrspitem.hxx>
29 #include <editeng/ulspitem.hxx>
30 #include <editeng/boxitem.hxx>
31 #include <editeng/flstitem.hxx>
32 #include <editeng/formatbreakitem.hxx>
33 #include <editeng/keepitem.hxx>
34 #include <editeng/fontitem.hxx>
35 #include <editeng/langitem.hxx>
36 #include <editeng/frmdiritem.hxx>
37 #include <o3tl/string_view.hxx>
38 #include <svtools/htmltokn.h>
39 #include <svtools/htmlkywd.hxx>
40 #include <fmtpdsc.hxx>
41 #include <fmtanchr.hxx>
42 #include <fmtornt.hxx>
43 #include <fmtsrnd.hxx>
44 #include <fmtfsize.hxx>
46 #include <charfmt.hxx>
48 #include <osl/diagnose.h>
51 #include <IDocumentStylePoolAccess.hxx>
53 #include <poolfmt.hxx>
56 #include <pagedesc.hxx>
57 #include "css1kywd.hxx"
59 #include "htmlnum.hxx"
61 #include <numrule.hxx>
62 #include "css1atr.hxx"
64 using namespace ::com::sun::star
;
66 // How many rows/characters are allowed for DropCaps?
67 // (Are there maybe somewhere else corresponding values?)
68 #define MAX_DROPCAP_LINES 9
69 #define MAX_DROPCAP_CHARS 9
71 static void lcl_swcss1_setEncoding( SwFormat
& rFormat
, rtl_TextEncoding eEnc
);
73 // Implementation of SwCSS1Parsers (actually swcss1.cxx)
74 const sal_uInt16 aItemIds
[] =
81 void SwCSS1Parser::ChgPageDesc( const SwPageDesc
*pPageDesc
,
82 const SwPageDesc
& rNewPageDesc
)
85 bool found
= m_pDoc
->ContainsPageDesc( pPageDesc
, &pos
);
86 OSL_ENSURE( found
, "style not found" );
88 m_pDoc
->ChgPageDesc( pos
, rNewPageDesc
);
91 SwCSS1Parser::SwCSS1Parser(SwDoc
*const pDoc
, SwHTMLParser
const& rParser
,
92 const sal_uInt32 aFHeights
[7], const OUString
& rBaseURL
, bool const bNewDoc
)
93 : SvxCSS1Parser(pDoc
->GetAttrPool(), rBaseURL
,
94 aItemIds
, SAL_N_ELEMENTS(aItemIds
))
96 , m_rHTMLParser(rParser
)
98 m_bIsNewDoc( bNewDoc
),
99 m_bBodyBGColorSet( false ),
100 m_bBodyBackgroundSet( false ),
101 m_bBodyTextSet( false ),
102 m_bBodyLinkSet( false ),
103 m_bBodyVLinkSet( false ),
104 m_bSetFirstPageDesc( false ),
105 m_bSetRightPageDesc( false ),
106 m_bTableHeaderTextCollSet( false ),
107 m_bTableTextCollSet( false ),
108 m_bLinkCharFormatsSet( false )
110 m_aFontHeights
[0] = aFHeights
[0];
111 m_aFontHeights
[1] = aFHeights
[1];
112 m_aFontHeights
[2] = aFHeights
[2];
113 m_aFontHeights
[3] = aFHeights
[3];
114 m_aFontHeights
[4] = aFHeights
[4];
115 m_aFontHeights
[5] = aFHeights
[5];
116 m_aFontHeights
[6] = aFHeights
[6];
119 SwCSS1Parser::~SwCSS1Parser()
124 bool SwCSS1Parser::SetFormatBreak( SfxItemSet
& rItemSet
,
125 const SvxCSS1PropertyInfo
& rPropInfo
)
127 SvxBreak eBreak
= SvxBreak::NONE
;
129 bool bSetKeep
= false, bSetBreak
= false, bSetPageDesc
= false;
130 const SwPageDesc
*pPageDesc
= nullptr;
131 switch( rPropInfo
.m_ePageBreakBefore
)
133 case SVX_CSS1_PBREAK_ALWAYS
:
134 eBreak
= SvxBreak::PageBefore
;
137 case SVX_CSS1_PBREAK_LEFT
:
138 pPageDesc
= GetLeftPageDesc( true );
141 case SVX_CSS1_PBREAK_RIGHT
:
142 pPageDesc
= GetRightPageDesc( true );
145 case SVX_CSS1_PBREAK_AUTO
:
146 bSetBreak
= bSetPageDesc
= true;
151 switch( rPropInfo
.m_ePageBreakAfter
)
153 case SVX_CSS1_PBREAK_ALWAYS
:
154 case SVX_CSS1_PBREAK_LEFT
:
155 case SVX_CSS1_PBREAK_RIGHT
:
156 // LEFT/RIGHT also could be set in the previous paragraph
157 eBreak
= SvxBreak::PageAfter
;
160 case SVX_CSS1_PBREAK_AUTO
:
161 bSetBreak
= bSetKeep
= bSetPageDesc
= true;
163 case SVX_CSS1_PBREAK_AVOID
:
164 bKeep
= bSetKeep
= true;
171 rItemSet
.Put( SvxFormatBreakItem( eBreak
, RES_BREAK
) );
173 rItemSet
.Put( SwFormatPageDesc( pPageDesc
) );
175 rItemSet
.Put( SvxFormatKeepItem( bKeep
, RES_KEEP
) );
180 static void SetCharFormatAttrs( SwCharFormat
*pCharFormat
, SfxItemSet
& rItemSet
)
182 static const TypedWhichId
<SvxFontHeightItem
> aWhichIds
[3] = { RES_CHRATR_FONTSIZE
,RES_CHRATR_CJK_FONTSIZE
,
183 RES_CHRATR_CTL_FONTSIZE
};
184 for(auto const & i
: aWhichIds
)
186 const SvxFontHeightItem
* pItem
= rItemSet
.GetItemIfSet( i
, false );
187 if( pItem
&& pItem
->GetProp() != 100)
189 // percentage values at the FontHeight item aren't supported
190 rItemSet
.ClearItem( i
);
194 pCharFormat
->SetFormatAttr( rItemSet
);
196 if( const SvxBrushItem
* pItem
= rItemSet
.GetItemIfSet( RES_BACKGROUND
, false ) )
198 // A Brush-Item with RES_BACKGROUND must be converted to one
199 // with RES_CHRATR_BACKGROUND
201 SvxBrushItem
aBrushItem( *pItem
);
202 aBrushItem
.SetWhich( RES_CHRATR_BACKGROUND
);
203 pCharFormat
->SetFormatAttr( aBrushItem
);
206 if( const SvxBoxItem
* pItem
= rItemSet
.GetItemIfSet( RES_BOX
, false ) )
208 SvxBoxItem
aBoxItem( *pItem
);
209 aBoxItem
.SetWhich( RES_CHRATR_BOX
);
210 pCharFormat
->SetFormatAttr( aBoxItem
);
214 void SwCSS1Parser::SetLinkCharFormats()
216 OSL_ENSURE( !m_bLinkCharFormatsSet
, "Call SetLinkCharFormats unnecessary" );
218 SvxCSS1MapEntry
*pStyleEntry
=
219 GetTag( u
"" OOO_STRING_SVTOOLS_HTML_anchor
""_ustr
);
220 SwCharFormat
*pUnvisited
= nullptr, *pVisited
= nullptr;
223 SfxItemSet
& rItemSet
= pStyleEntry
->GetItemSet();
224 bool bColorSet
= (SfxItemState::SET
==rItemSet
.GetItemState(RES_CHRATR_COLOR
,
226 pUnvisited
= GetCharFormatFromPool( RES_POOLCHR_INET_NORMAL
);
227 SetCharFormatAttrs( pUnvisited
, rItemSet
);
228 m_bBodyLinkSet
|= bColorSet
;
230 pVisited
= GetCharFormatFromPool( RES_POOLCHR_INET_VISIT
);
231 SetCharFormatAttrs( pVisited
, rItemSet
);
232 m_bBodyVLinkSet
|= bColorSet
;
235 OUString sTmp
= u
"" OOO_STRING_SVTOOLS_HTML_anchor
":link"_ustr
;
237 pStyleEntry
= GetTag( sTmp
);
240 SfxItemSet
& rItemSet
= pStyleEntry
->GetItemSet();
241 bool bColorSet
= (SfxItemState::SET
==rItemSet
.GetItemState(RES_CHRATR_COLOR
,
244 pUnvisited
= GetCharFormatFromPool( RES_POOLCHR_INET_NORMAL
);
245 SetCharFormatAttrs( pUnvisited
, rItemSet
);
246 m_bBodyLinkSet
|= bColorSet
;
249 sTmp
= OOO_STRING_SVTOOLS_HTML_anchor
":visited";
251 pStyleEntry
= GetTag( sTmp
);
254 SfxItemSet
& rItemSet
= pStyleEntry
->GetItemSet();
255 bool bColorSet
= (SfxItemState::SET
==rItemSet
.GetItemState(RES_CHRATR_COLOR
,
258 pVisited
= GetCharFormatFromPool( RES_POOLCHR_INET_VISIT
);
259 SetCharFormatAttrs( pVisited
, rItemSet
);
260 m_bBodyVLinkSet
|= bColorSet
;
263 m_bLinkCharFormatsSet
= true;
266 static void SetTextCollAttrs( SwTextFormatColl
*pColl
, SfxItemSet
& rItemSet
,
267 SvxCSS1PropertyInfo
const & rPropInfo
,
268 SwCSS1Parser
*pCSS1Parser
)
270 const SfxItemSet
& rCollItemSet
= pColl
->GetAttrSet();
272 // note: there was some SvxLRSpaceItem code here that was nonobvious
273 // but it looks like the only cases in which it would be required
274 // with split items are if some nProp != 100 or if SetAutoFirst() had
275 // been called (on the pColl items) but it looks like none of these are
276 // possible in HTML import.
278 // top and bottom border
279 const SvxULSpaceItem
* pCollULItem
;
280 const SvxULSpaceItem
* pULItem
;
281 if( (rPropInfo
.m_bTopMargin
|| rPropInfo
.m_bBottomMargin
) &&
282 (!rPropInfo
.m_bTopMargin
|| !rPropInfo
.m_bBottomMargin
) &&
283 (pCollULItem
= rCollItemSet
.GetItemIfSet(RES_UL_SPACE
)) &&
284 (pULItem
= rItemSet
.GetItemIfSet(RES_UL_SPACE
,false)) )
286 SvxULSpaceItem
aULItem( *pCollULItem
);
287 if( rPropInfo
.m_bTopMargin
)
288 aULItem
.SetUpper( pULItem
->GetUpper() );
289 if( rPropInfo
.m_bBottomMargin
)
290 aULItem
.SetLower( pULItem
->GetLower() );
292 rItemSet
.Put( aULItem
);
295 static const TypedWhichId
<SvxFontHeightItem
> aWhichIds
[3] = { RES_CHRATR_FONTSIZE
,RES_CHRATR_CJK_FONTSIZE
,
296 RES_CHRATR_CTL_FONTSIZE
};
297 for(auto const & i
: aWhichIds
)
299 const SvxFontHeightItem
* pItem
= rItemSet
.GetItemIfSet( i
, false );
300 if( pItem
&& pItem
->GetProp() != 100)
302 // percentage values at the FontHeight item aren't supported
303 rItemSet
.ClearItem( i
);
307 pCSS1Parser
->SetFormatBreak( rItemSet
, rPropInfo
);
309 pColl
->SetFormatAttr( rItemSet
);
312 void SwCSS1Parser::SetTableTextColl( bool bHeader
)
314 OSL_ENSURE( !(bHeader
? m_bTableHeaderTextCollSet
: m_bTableTextCollSet
),
315 "Call SetTableTextColl unnecessary" );
321 nPoolId
= RES_POOLCOLL_TABLE_HDLN
;
322 sTag
= OOO_STRING_SVTOOLS_HTML_tableheader
;
326 nPoolId
= RES_POOLCOLL_TABLE
;
327 sTag
= OOO_STRING_SVTOOLS_HTML_tabledata
;
330 SwTextFormatColl
*pColl
= nullptr;
332 // The following entries will never be used again and may be changed.
333 SvxCSS1MapEntry
*pStyleEntry
= GetTag( sTag
);
336 pColl
= GetTextFormatColl(nPoolId
, OUString());
337 SetTextCollAttrs( pColl
, pStyleEntry
->GetItemSet(),
338 pStyleEntry
->GetPropertyInfo(), this );
341 OUString sTmp
= sTag
+ " " OOO_STRING_SVTOOLS_HTML_parabreak
;
342 pStyleEntry
= GetTag( sTmp
);
346 pColl
= GetTextFormatColl(nPoolId
, OUString());
347 SetTextCollAttrs( pColl
, pStyleEntry
->GetItemSet(),
348 pStyleEntry
->GetPropertyInfo(), this );
352 m_bTableHeaderTextCollSet
= true;
354 m_bTableTextCollSet
= true;
357 void SwCSS1Parser::SetPageDescAttrs( const SvxBrushItem
*pBrush
,
358 SfxItemSet
*pItemSet2
)
360 std::shared_ptr
<SvxBrushItem
> aBrushItem(std::make_shared
<SvxBrushItem
>(RES_BACKGROUND
));
361 std::shared_ptr
<SvxBoxItem
> aBoxItem(std::make_shared
<SvxBoxItem
>(RES_BOX
));
362 std::shared_ptr
<SvxFrameDirectionItem
> aFrameDirItem(std::make_shared
<SvxFrameDirectionItem
>(SvxFrameDirection::Environment
, RES_FRAMEDIR
));
363 bool bSetBrush
= pBrush
!=nullptr, bSetBox
= false, bSetFrameDir
= false;
365 aBrushItem
.reset(pBrush
->Clone());
369 if( const SvxBrushItem
* pItem
= pItemSet2
->GetItemIfSet( RES_BACKGROUND
, false ) )
372 aBrushItem
.reset(pItem
->Clone());
373 pItemSet2
->ClearItem( RES_BACKGROUND
);
377 if( const SvxBoxItem
* pItem
= pItemSet2
->GetItemIfSet( RES_BOX
, false ) )
380 aBoxItem
.reset(pItem
->Clone());
381 pItemSet2
->ClearItem( RES_BOX
);
385 if( const SvxFrameDirectionItem
* pItem
= pItemSet2
->GetItemIfSet( RES_FRAMEDIR
, false ) )
388 aFrameDirItem
.reset(pItem
->Clone());
389 pItemSet2
->ClearItem( RES_FRAMEDIR
);
394 if( !(bSetBrush
|| bSetBox
|| bSetFrameDir
) )
397 static sal_uInt16 aPoolIds
[] = { RES_POOLPAGE_HTML
, RES_POOLPAGE_FIRST
,
398 RES_POOLPAGE_LEFT
, RES_POOLPAGE_RIGHT
};
399 for(sal_uInt16 i
: aPoolIds
)
401 const SwPageDesc
*pPageDesc
= GetPageDesc( i
, false );
404 SwPageDesc
aNewPageDesc( *pPageDesc
);
405 SwFrameFormat
&rMaster
= aNewPageDesc
.GetMaster();
407 rMaster
.SetFormatAttr( *aBrushItem
);
409 rMaster
.SetFormatAttr( *aBoxItem
);
411 rMaster
.SetFormatAttr( *aFrameDirItem
);
413 ChgPageDesc( pPageDesc
, aNewPageDesc
);
419 void SwCSS1Parser::SetPageDescAttrs( const SwPageDesc
*pPageDesc
,
420 SfxItemSet
& rItemSet
,
421 const SvxCSS1PropertyInfo
& rPropInfo
)
426 SwPageDesc
aNewPageDesc( *pPageDesc
);
427 SwFrameFormat
&rMaster
= aNewPageDesc
.GetMaster();
428 const SfxItemSet
& rPageItemSet
= rMaster
.GetAttrSet();
429 bool bChanged
= false;
431 // left, right border and first line indentation
432 ::std::optional
<SvxLRSpaceItem
> oLRSpace
;
433 assert(!rItemSet
.GetItemIfSet(RES_LR_SPACE
,false));
434 if (rPropInfo
.m_bLeftMargin
)
436 // note: parser never creates SvxLeftMarginItem! must be converted
437 if (SvxTextLeftMarginItem
const*const pLeft
= rItemSet
.GetItemIfSet(RES_MARGIN_TEXTLEFT
, false))
441 if (const SvxLRSpaceItem
* pPageItem
= rPageItemSet
.GetItemIfSet(RES_LR_SPACE
))
443 oLRSpace
.emplace(*pPageItem
);
447 oLRSpace
.emplace(RES_LR_SPACE
);
450 oLRSpace
->SetLeft(pLeft
->GetTextLeft());
453 if (rPropInfo
.m_bRightMargin
)
455 // note: parser never creates SvxLeftMarginItem! must be converted
456 if (SvxRightMarginItem
const*const pRight
= rItemSet
.GetItemIfSet(RES_MARGIN_RIGHT
, false))
460 if (const SvxLRSpaceItem
* pPageItem
= rPageItemSet
.GetItemIfSet(RES_LR_SPACE
))
462 oLRSpace
.emplace(*pPageItem
);
466 oLRSpace
.emplace(RES_LR_SPACE
);
469 oLRSpace
->SetRight(pRight
->GetRight());
474 rMaster
.SetFormatAttr(*oLRSpace
);
478 // top and bottom border
479 const SvxULSpaceItem
*pULItem
;
480 if( (rPropInfo
.m_bTopMargin
|| rPropInfo
.m_bBottomMargin
) &&
481 (pULItem
= rItemSet
.GetItemIfSet(RES_UL_SPACE
,false)) )
483 const SvxULSpaceItem
* pPageItem
;
484 if( (!rPropInfo
.m_bTopMargin
|| !rPropInfo
.m_bBottomMargin
) &&
485 (pPageItem
= rPageItemSet
.GetItemIfSet(RES_UL_SPACE
) ) )
487 SvxULSpaceItem
aULItem( *pPageItem
);
488 if( rPropInfo
.m_bTopMargin
)
489 aULItem
.SetUpper( pULItem
->GetUpper() );
490 if( rPropInfo
.m_bBottomMargin
)
491 aULItem
.SetLower( pULItem
->GetLower() );
493 rMaster
.SetFormatAttr( aULItem
);
497 rMaster
.SetFormatAttr( *pULItem
);
503 if( rPropInfo
.m_eSizeType
!= SVX_CSS1_STYPE_NONE
)
505 if( rPropInfo
.m_eSizeType
== SVX_CSS1_STYPE_TWIP
)
507 rMaster
.SetFormatAttr( SwFormatFrameSize( SwFrameSize::Fixed
, rPropInfo
.m_nWidth
,
508 rPropInfo
.m_nHeight
) );
513 // With "size: auto|portrait|landscape" the current size
514 // of the style remains. If "landscape" and "portrait" then
515 // the landscape flag will be set and maybe the width/height
517 SwFormatFrameSize
aFrameSz( rMaster
.GetFrameSize() );
518 bool bLandscape
= aNewPageDesc
.GetLandscape();
520 rPropInfo
.m_eSizeType
== SVX_CSS1_STYPE_PORTRAIT
) ||
522 rPropInfo
.m_eSizeType
== SVX_CSS1_STYPE_LANDSCAPE
) )
524 SwTwips nTmp
= aFrameSz
.GetHeight();
525 aFrameSz
.SetHeight( aFrameSz
.GetWidth() );
526 aFrameSz
.SetWidth( nTmp
);
527 rMaster
.SetFormatAttr( aFrameSz
);
528 aNewPageDesc
.SetLandscape( !bLandscape
);
535 if( const SvxBrushItem
* pItem
= rItemSet
.GetItemIfSet( RES_BACKGROUND
, false ) )
538 rMaster
.SetFormatAttr( *pItem
);
539 rItemSet
.ClearItem( RES_BACKGROUND
);
544 ChgPageDesc( pPageDesc
, aNewPageDesc
);
547 std::unique_ptr
<SvxBrushItem
> SwCSS1Parser::makePageDescBackground() const
549 return m_pDoc
->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML
, false )
550 ->GetMaster().makeBackgroundBrushItem();
553 Css1ScriptFlags
SwCSS1Parser::GetScriptFromClass( OUString
& rClass
,
556 Css1ScriptFlags nScriptFlags
= Css1ScriptFlags::AllMask
;
557 sal_Int32 nLen
= rClass
.getLength();
558 sal_Int32 nPos
= nLen
> 4 ? rClass
.lastIndexOf( '-' ) : -1;
575 if( rClass
.matchIgnoreAsciiCase( "cjk", nPos
) )
577 nScriptFlags
= Css1ScriptFlags::CJK
;
579 else if( rClass
.matchIgnoreAsciiCase( "ctl", nPos
) )
581 nScriptFlags
= Css1ScriptFlags::CTL
;
585 if( rClass
.matchIgnoreAsciiCase( "western", nPos
) )
587 nScriptFlags
= Css1ScriptFlags::Western
;
591 if( Css1ScriptFlags::AllMask
!= nScriptFlags
)
595 rClass
= rClass
.copy( 0, nPos
-1 );
606 static CSS1SelectorType
GetTokenAndClass( const CSS1Selector
*pSelector
,
607 OUString
& rToken
, OUString
& rClass
,
608 Css1ScriptFlags
& rScriptFlags
)
610 rToken
= pSelector
->GetString();
612 rScriptFlags
= Css1ScriptFlags::AllMask
;
614 CSS1SelectorType eType
= pSelector
->GetType();
615 if( CSS1_SELTYPE_ELEM_CLASS
==eType
)
617 sal_Int32 nPos
= rToken
.indexOf( '.' );
618 OSL_ENSURE( nPos
>= 0, "No dot in Class-Selector???" );
621 rClass
= rToken
.copy( nPos
+1 );
622 rToken
= rToken
.copy( 0, nPos
);
624 rScriptFlags
= SwCSS1Parser::GetScriptFromClass( rClass
, false );
625 if( rClass
.isEmpty() )
626 eType
= CSS1_SELTYPE_ELEMENT
;
630 rToken
= rToken
.toAsciiLowerCase();
634 static void RemoveScriptItems( SfxItemSet
& rItemSet
, Css1ScriptFlags nScript
,
635 const SfxItemSet
*pParentItemSet
= nullptr )
637 static const sal_uInt16 aWhichIds
[3][5] =
639 { RES_CHRATR_FONT
, RES_CHRATR_FONTSIZE
, RES_CHRATR_LANGUAGE
,
640 RES_CHRATR_POSTURE
, RES_CHRATR_WEIGHT
},
641 { RES_CHRATR_CJK_FONT
, RES_CHRATR_CJK_FONTSIZE
, RES_CHRATR_CJK_LANGUAGE
,
642 RES_CHRATR_CJK_POSTURE
, RES_CHRATR_CJK_WEIGHT
},
643 { RES_CHRATR_CTL_FONT
, RES_CHRATR_CTL_FONTSIZE
, RES_CHRATR_CTL_LANGUAGE
,
644 RES_CHRATR_CTL_POSTURE
, RES_CHRATR_CTL_WEIGHT
}
647 bool aClearItems
[3] = { false, false, false };
650 case Css1ScriptFlags::Western
:
651 aClearItems
[1] = aClearItems
[2] = true;
653 case Css1ScriptFlags::CJK
:
654 aClearItems
[0] = aClearItems
[2] = true;
656 case Css1ScriptFlags::CTL
:
657 aClearItems
[0] = aClearItems
[1] = true;
659 case Css1ScriptFlags::AllMask
:
662 OSL_ENSURE( aClearItems
[0], "unknown script type" );
666 for( size_t j
=0; j
< SAL_N_ELEMENTS(aWhichIds
); ++j
)
668 for( size_t i
=0; i
< SAL_N_ELEMENTS(aWhichIds
[0]); ++i
)
670 sal_uInt16 nWhich
= aWhichIds
[j
][i
];
671 const SfxPoolItem
*pItem
;
672 if( aClearItems
[j
] ||
674 SfxItemState::SET
== rItemSet
.GetItemState( nWhich
, false, &pItem
) &&
675 (0==i
? swhtml_css1atr_equalFontItems( *pItem
, pParentItemSet
->Get(nWhich
) )
676 : *pItem
== pParentItemSet
->Get(nWhich
) ) ) )
678 rItemSet
.ClearItem( nWhich
);
684 void SwCSS1Parser::StyleParsed( const CSS1Selector
*pSelector
,
685 SfxItemSet
& rItemSet
,
686 SvxCSS1PropertyInfo
& rPropInfo
)
691 CSS1SelectorType eSelType
= pSelector
->GetType();
692 const CSS1Selector
*pNext
= pSelector
->GetNext();
694 if( CSS1_SELTYPE_ID
==eSelType
&& !pNext
)
696 InsertId( pSelector
->GetString(), rItemSet
, rPropInfo
);
698 else if( CSS1_SELTYPE_CLASS
==eSelType
&& !pNext
)
700 OUString
aClass( pSelector
->GetString() );
701 Css1ScriptFlags nScript
= GetScriptFromClass( aClass
);
702 if( Css1ScriptFlags::AllMask
!= nScript
)
704 SfxItemSet
aScriptItemSet( rItemSet
);
705 RemoveScriptItems( aScriptItemSet
, nScript
);
706 InsertClass( aClass
, aScriptItemSet
, rPropInfo
);
710 InsertClass( aClass
, rItemSet
, rPropInfo
);
713 else if( CSS1_SELTYPE_PAGE
==eSelType
)
716 (CSS1_SELTYPE_PSEUDO
== pNext
->GetType() &&
717 (pNext
->GetString().equalsIgnoreAsciiCase( "left" ) ||
718 pNext
->GetString().equalsIgnoreAsciiCase( "right" ) ||
719 pNext
->GetString().equalsIgnoreAsciiCase( "first" ) ) ) )
723 aName
= pNext
->GetString();
726 rItemSet
, rPropInfo
);
730 if( CSS1_SELTYPE_ELEMENT
!= eSelType
&&
731 CSS1_SELTYPE_ELEM_CLASS
!= eSelType
)
734 // get token and class of selector
737 Css1ScriptFlags nScript
;
738 eSelType
= GetTokenAndClass( pSelector
, aToken2
, aClass
, nScript
);
739 HtmlTokenId nToken2
= GetHTMLToken( aToken2
);
741 // and also some information of the next element
742 CSS1SelectorType eNextType
= pNext
? pNext
->GetType()
743 : CSS1_SELTYPE_ELEMENT
;
745 // first some special cases
746 if( CSS1_SELTYPE_ELEMENT
==eSelType
)
750 case HtmlTokenId::ANCHOR_ON
:
753 InsertTag( aToken2
, rItemSet
, rPropInfo
);
756 else if (CSS1_SELTYPE_PSEUDO
== eNextType
)
758 // maybe A:visited or A:link
760 OUString
aPseudo( pNext
->GetString() );
761 aPseudo
= aPseudo
.toAsciiLowerCase();
762 bool bInsert
= false;
766 if( aPseudo
== "link" )
772 if( aPseudo
== "visited" )
780 OUString sTmp
= aToken2
+ ":" + aPseudo
;
781 if( Css1ScriptFlags::AllMask
!= nScript
)
783 SfxItemSet
aScriptItemSet( rItemSet
);
784 RemoveScriptItems( aScriptItemSet
, nScript
);
785 InsertTag( sTmp
, aScriptItemSet
, rPropInfo
);
789 InsertTag( sTmp
, rItemSet
, rPropInfo
);
795 case HtmlTokenId::BODY_ON
:
800 // We must test the background before setting, because
801 // in SetPageDescAttrs it will be deleted.
802 if( const SvxBrushItem
*pBrushItem
= rItemSet
.GetItemIfSet(RES_BACKGROUND
,false) )
804 /// Body has a background color, if it is not "no fill"/"auto fill"
805 if( pBrushItem
->GetColor() != COL_TRANSPARENT
)
806 m_bBodyBGColorSet
= true;
807 if( GPOS_NONE
!= pBrushItem
->GetGraphicPos() )
808 m_bBodyBackgroundSet
= true;
811 // Border and Padding
812 rPropInfo
.SetBoxItem( rItemSet
, MIN_BORDER_DIST
);
814 // Some attributes must be set at the style, the ones which
816 SetPageDescAttrs( nullptr, &rItemSet
);
818 // all remaining options can be set at the default style,
819 // then they're the default
820 if( SfxItemState::SET
==rItemSet
.GetItemState(RES_CHRATR_COLOR
,false) )
821 m_bBodyTextSet
= true;
823 GetTextCollFromPool( RES_POOLCOLL_STANDARD
),
824 rItemSet
, rPropInfo
, this );
832 else if( CSS1_SELTYPE_ELEM_CLASS
==eSelType
&& HtmlTokenId::ANCHOR_ON
==nToken2
&&
833 !pNext
&& aClass
.getLength() >= 9 &&
834 ('s' == aClass
[0] || 'S' == aClass
[0]) )
836 sal_uInt16 nPoolFormatId
= 0;
837 if( aClass
.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdendnote_sym
) )
838 nPoolFormatId
= RES_POOLCHR_ENDNOTE
;
839 else if( aClass
.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdfootnote_sym
) )
840 nPoolFormatId
= RES_POOLCHR_FOOTNOTE
;
843 if( Css1ScriptFlags::AllMask
== nScript
)
845 SetCharFormatAttrs( GetCharFormatFromPool(nPoolFormatId
), rItemSet
);
849 SfxItemSet
aScriptItemSet( rItemSet
);
850 RemoveScriptItems( aScriptItemSet
, nScript
);
851 SetCharFormatAttrs( GetCharFormatFromPool(nPoolFormatId
),
858 // Now the selectors are processed which belong to a paragraph style
859 sal_uInt16 nPoolCollId
= 0;
862 case HtmlTokenId::HEAD1_ON
:
863 nPoolCollId
= RES_POOLCOLL_HEADLINE1
;
865 case HtmlTokenId::HEAD2_ON
:
866 nPoolCollId
= RES_POOLCOLL_HEADLINE2
;
868 case HtmlTokenId::HEAD3_ON
:
869 nPoolCollId
= RES_POOLCOLL_HEADLINE3
;
871 case HtmlTokenId::HEAD4_ON
:
872 nPoolCollId
= RES_POOLCOLL_HEADLINE4
;
874 case HtmlTokenId::HEAD5_ON
:
875 nPoolCollId
= RES_POOLCOLL_HEADLINE5
;
877 case HtmlTokenId::HEAD6_ON
:
878 nPoolCollId
= RES_POOLCOLL_HEADLINE6
;
880 case HtmlTokenId::PARABREAK_ON
:
881 if( aClass
.getLength() >= 9 &&
882 ('s' == aClass
[0] || 'S' == aClass
[0]) )
884 if( aClass
.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdendnote
) )
885 nPoolCollId
= RES_POOLCOLL_ENDNOTE
;
886 else if( aClass
.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdfootnote
) )
887 nPoolCollId
= RES_POOLCOLL_FOOTNOTE
;
892 nPoolCollId
= RES_POOLCOLL_TEXT
;
896 nPoolCollId
= RES_POOLCOLL_TEXT
;
899 case HtmlTokenId::ADDRESS_ON
:
900 nPoolCollId
= RES_POOLCOLL_SEND_ADDRESS
;
902 case HtmlTokenId::BLOCKQUOTE_ON
:
903 nPoolCollId
= RES_POOLCOLL_HTML_BLOCKQUOTE
;
905 case HtmlTokenId::DT_ON
:
906 nPoolCollId
= RES_POOLCOLL_HTML_DT
;
908 case HtmlTokenId::DD_ON
:
909 nPoolCollId
= RES_POOLCOLL_HTML_DD
;
911 case HtmlTokenId::PREFORMTXT_ON
:
912 nPoolCollId
= RES_POOLCOLL_HTML_PRE
;
914 case HtmlTokenId::TABLEHEADER_ON
:
915 case HtmlTokenId::TABLEDATA_ON
:
916 if( CSS1_SELTYPE_ELEMENT
==eSelType
&& !pNext
)
918 InsertTag( aToken2
, rItemSet
, rPropInfo
);
921 else if( CSS1_SELTYPE_ELEMENT
==eSelType
&& pNext
&&
922 (CSS1_SELTYPE_ELEMENT
==eNextType
||
923 CSS1_SELTYPE_ELEM_CLASS
==eNextType
) )
925 // not TH and TD, but TH P and TD P
926 OUString aSubToken
, aSubClass
;
927 GetTokenAndClass( pNext
, aSubToken
, aSubClass
, nScript
);
928 if( HtmlTokenId::PARABREAK_ON
== GetHTMLToken( aSubToken
) )
931 pNext
= pNext
->GetNext();
932 eNextType
= pNext
? pNext
->GetType() : CSS1_SELTYPE_ELEMENT
;
934 if( !aClass
.isEmpty() || pNext
)
936 nPoolCollId
= static_cast< sal_uInt16
>(
937 HtmlTokenId::TABLEHEADER_ON
== nToken2
? RES_POOLCOLL_TABLE_HDLN
938 : RES_POOLCOLL_TABLE
);
942 OUString sTmp
= aToken2
+ " " OOO_STRING_SVTOOLS_HTML_parabreak
;
944 if( Css1ScriptFlags::AllMask
== nScript
)
946 InsertTag( sTmp
, rItemSet
, rPropInfo
);
950 SfxItemSet
aScriptItemSet( rItemSet
);
951 RemoveScriptItems( aScriptItemSet
, nScript
);
952 InsertTag( sTmp
, aScriptItemSet
, rPropInfo
);
968 (CSS1_SELTYPE_PSEUDO
==eNextType
&&
969 pNext
->GetString().equalsIgnoreAsciiCase( "first-letter" ) &&
970 SvxAdjust::Left
== rPropInfo
.m_eFloat
) )
972 // either not a composed selector or a X:first-line { float: left; ... }
974 // search resp. create the style
975 SwTextFormatColl
* pColl
= GetTextFormatColl(nPoolCollId
, OUString());
976 SwTextFormatColl
* pParentColl
= nullptr;
977 if( !aClass
.isEmpty() )
979 OUString
aName( pColl
->GetName() );
980 AddClassName( aName
, aClass
);
983 pColl
= m_pDoc
->FindTextFormatCollByName( aName
);
985 pColl
= m_pDoc
->MakeTextFormatColl( aName
, pParentColl
);
989 // set only the attributes at the style
990 const SvxBoxItem
*pBoxItem
=
991 pColl
->GetAttrSet().GetItemIfSet(RES_BOX
);
992 rPropInfo
.SetBoxItem( rItemSet
, MIN_BORDER_DIST
, pBoxItem
);
993 if( Css1ScriptFlags::AllMask
== nScript
&& !pParentColl
)
995 SetTextCollAttrs( pColl
, rItemSet
, rPropInfo
, this );
999 SfxItemSet
aScriptItemSet( rItemSet
);
1000 RemoveScriptItems( aScriptItemSet
, nScript
,
1001 pParentColl
? &pParentColl
->GetAttrSet() : nullptr );
1002 SetTextCollAttrs( pColl
, aScriptItemSet
, rPropInfo
, this );
1007 // create a DropCap attribute
1008 SwFormatDrop
aDrop( pColl
->GetDrop() );
1009 aDrop
.SetChars( 1 );
1011 // set the attributes of the DropCap attribute
1012 if( Css1ScriptFlags::AllMask
== nScript
)
1014 OUString
sName(pColl
->GetName());
1015 FillDropCap( aDrop
, rItemSet
, &sName
);
1019 SfxItemSet
aScriptItemSet( rItemSet
);
1020 if( Css1ScriptFlags::Western
!= nScript
)
1022 aScriptItemSet
.ClearItem( RES_CHRATR_FONT
);
1023 aScriptItemSet
.ClearItem( RES_CHRATR_LANGUAGE
);
1024 aScriptItemSet
.ClearItem( RES_CHRATR_POSTURE
);
1025 aScriptItemSet
.ClearItem( RES_CHRATR_WEIGHT
);
1027 if( Css1ScriptFlags::CJK
!= nScript
)
1029 aScriptItemSet
.ClearItem( RES_CHRATR_CJK_FONT
);
1030 aScriptItemSet
.ClearItem( RES_CHRATR_CJK_LANGUAGE
);
1031 aScriptItemSet
.ClearItem( RES_CHRATR_CJK_POSTURE
);
1032 aScriptItemSet
.ClearItem( RES_CHRATR_CJK_WEIGHT
);
1034 if( Css1ScriptFlags::CTL
!= nScript
)
1036 aScriptItemSet
.ClearItem( RES_CHRATR_CTL_FONT
);
1037 aScriptItemSet
.ClearItem( RES_CHRATR_CTL_LANGUAGE
);
1038 aScriptItemSet
.ClearItem( RES_CHRATR_CTL_POSTURE
);
1039 aScriptItemSet
.ClearItem( RES_CHRATR_CTL_WEIGHT
);
1041 OUString
sName(pColl
->GetName());
1042 FillDropCap( aDrop
, aScriptItemSet
, &sName
);
1045 // Only set the attribute if "float: left" is specified and
1046 // the Initial is over several lines. Otherwise the maybe
1047 // created character style will be later searched and set
1049 if( aDrop
.GetLines() > 1 &&
1050 (SvxAdjust::Left
== rPropInfo
.m_eFloat
||
1051 Css1ScriptFlags::AllMask
== nScript
) )
1053 pColl
->SetFormatAttr( aDrop
);
1061 // Now the selectors are processed which are belonging to the character
1062 // template. There are no composed ones here.
1066 SwCharFormat
* pCFormat
= GetChrFormat(nToken2
, OUString());
1070 SwCharFormat
*pParentCFormat
= nullptr;
1071 if( !aClass
.isEmpty() )
1073 OUString
aName( pCFormat
->GetName() );
1074 AddClassName( aName
, aClass
);
1075 pParentCFormat
= pCFormat
;
1077 pCFormat
= m_pDoc
->FindCharFormatByName( aName
);
1080 pCFormat
= m_pDoc
->MakeCharFormat( aName
, pParentCFormat
);
1081 pCFormat
->SetAuto(false);
1085 if( Css1ScriptFlags::AllMask
== nScript
&& !pParentCFormat
)
1087 SetCharFormatAttrs( pCFormat
, rItemSet
);
1091 SfxItemSet
aScriptItemSet( rItemSet
);
1092 RemoveScriptItems( aScriptItemSet
, nScript
,
1093 pParentCFormat
? &pParentCFormat
->GetAttrSet() : nullptr );
1094 SetCharFormatAttrs( pCFormat
, aScriptItemSet
);
1098 sal_uInt32
SwCSS1Parser::GetFontHeight( sal_uInt16 nSize
) const
1100 return m_aFontHeights
[ std::min
<sal_uInt16
>(nSize
,6) ];
1103 const FontList
*SwCSS1Parser::GetFontList() const
1105 const FontList
*pFList
= nullptr;
1106 SwDocShell
*pDocSh
= m_pDoc
->GetDocShell();
1109 const SvxFontListItem
*pFListItem
=
1110 static_cast<const SvxFontListItem
*>(pDocSh
->GetItem(SID_ATTR_CHAR_FONTLIST
));
1112 pFList
= pFListItem
->GetFontList();
1118 SwCharFormat
* SwCSS1Parser::GetChrFormat( HtmlTokenId nToken2
, const OUString
& rClass
) const
1120 // search the corresponding style
1121 sal_uInt16 nPoolId
= 0;
1122 const char* sName
= nullptr;
1125 case HtmlTokenId::EMPHASIS_ON
: nPoolId
= RES_POOLCHR_HTML_EMPHASIS
; break;
1126 case HtmlTokenId::CITATION_ON
: nPoolId
= RES_POOLCHR_HTML_CITATION
; break;
1127 case HtmlTokenId::STRONG_ON
: nPoolId
= RES_POOLCHR_HTML_STRONG
; break;
1128 case HtmlTokenId::CODE_ON
: nPoolId
= RES_POOLCHR_HTML_CODE
; break;
1129 case HtmlTokenId::SAMPLE_ON
: nPoolId
= RES_POOLCHR_HTML_SAMPLE
; break;
1130 case HtmlTokenId::KEYBOARD_ON
: nPoolId
= RES_POOLCHR_HTML_KEYBOARD
; break;
1131 case HtmlTokenId::VARIABLE_ON
: nPoolId
= RES_POOLCHR_HTML_VARIABLE
; break;
1132 case HtmlTokenId::DEFINSTANCE_ON
: nPoolId
= RES_POOLCHR_HTML_DEFINSTANCE
; break;
1133 case HtmlTokenId::TELETYPE_ON
: nPoolId
= RES_POOLCHR_HTML_TELETYPE
; break;
1135 case HtmlTokenId::SHORTQUOTE_ON
: sName
= OOO_STRING_SVTOOLS_HTML_shortquote
; break;
1136 case HtmlTokenId::LANGUAGE_ON
: sName
= OOO_STRING_SVTOOLS_HTML_language
; break;
1137 case HtmlTokenId::AUTHOR_ON
: sName
= OOO_STRING_SVTOOLS_HTML_author
; break;
1138 case HtmlTokenId::PERSON_ON
: sName
= OOO_STRING_SVTOOLS_HTML_person
; break;
1139 case HtmlTokenId::ACRONYM_ON
: sName
= OOO_STRING_SVTOOLS_HTML_acronym
; break;
1140 case HtmlTokenId::ABBREVIATION_ON
: sName
= OOO_STRING_SVTOOLS_HTML_abbreviation
; break;
1141 case HtmlTokenId::INSERTEDTEXT_ON
: sName
= OOO_STRING_SVTOOLS_HTML_insertedtext
; break;
1142 case HtmlTokenId::DELETEDTEXT_ON
: sName
= OOO_STRING_SVTOOLS_HTML_deletedtext
; break;
1146 // search or create the style (only possible with name)
1147 if( !nPoolId
&& !sName
)
1150 // search or create style (without class)
1151 SwCharFormat
*pCFormat
= nullptr;
1154 pCFormat
= GetCharFormatFromPool( nPoolId
);
1158 OUString
sCName( OUString::createFromAscii(sName
) );
1159 pCFormat
= m_pDoc
->FindCharFormatByName( sCName
);
1162 pCFormat
= m_pDoc
->MakeCharFormat( sCName
, m_pDoc
->GetDfltCharFormat() );
1163 pCFormat
->SetAuto(false);
1167 assert(pCFormat
&& "No character style???");
1169 // If a class exists, then search for the class style but don't
1171 OUString
aClass( rClass
);
1172 GetScriptFromClass( aClass
, false );
1173 if( !aClass
.isEmpty() )
1175 OUString
aTmp( pCFormat
->GetName() );
1176 AddClassName( aTmp
, aClass
);
1177 SwCharFormat
*pClassCFormat
= m_pDoc
->FindCharFormatByName( aTmp
);
1180 pCFormat
= pClassCFormat
;
1184 const SvxCSS1MapEntry
*pClass
= GetClass( aClass
);
1187 pCFormat
= m_pDoc
->MakeCharFormat( aTmp
, pCFormat
);
1188 pCFormat
->SetAuto(false);
1189 SfxItemSet
aItemSet( pClass
->GetItemSet() );
1190 SetCharFormatAttrs( pCFormat
, aItemSet
);
1198 SwTextFormatColl
*SwCSS1Parser::GetTextCollFromPool( sal_uInt16 nPoolId
) const
1200 const SwTextFormatColls::size_type nOldArrLen
= m_pDoc
->GetTextFormatColls()->size();
1202 SwTextFormatColl
*pColl
= m_pDoc
->getIDocumentStylePoolAccess().GetTextCollFromPool( nPoolId
, false );
1206 const SwTextFormatColls::size_type nArrLen
= m_pDoc
->GetTextFormatColls()->size();
1207 for( SwTextFormatColls::size_type i
=nOldArrLen
; i
<nArrLen
; ++i
)
1208 lcl_swcss1_setEncoding( *(*m_pDoc
->GetTextFormatColls())[i
],
1209 GetDfltEncoding() );
1215 SwCharFormat
*SwCSS1Parser::GetCharFormatFromPool( sal_uInt16 nPoolId
) const
1217 const SwCharFormats::size_type nOldArrLen
= m_pDoc
->GetCharFormats()->size();
1219 SwCharFormat
*pCharFormat
= m_pDoc
->getIDocumentStylePoolAccess().GetCharFormatFromPool( nPoolId
);
1223 const SwCharFormats::size_type nArrLen
= m_pDoc
->GetCharFormats()->size();
1225 for( SwCharFormats::size_type i
=nOldArrLen
; i
<nArrLen
; i
++ )
1226 lcl_swcss1_setEncoding( *(*m_pDoc
->GetCharFormats())[i
],
1227 GetDfltEncoding() );
1233 SwTextFormatColl
*SwCSS1Parser::GetTextFormatColl( sal_uInt16 nTextColl
,
1234 const OUString
& rClass
)
1236 SwTextFormatColl
* pColl
= nullptr;
1238 OUString
aClass( rClass
);
1239 GetScriptFromClass( aClass
, false );
1240 if( RES_POOLCOLL_TEXT
== nTextColl
&& aClass
.getLength() >= 9 &&
1241 ('s' == aClass
[0] || 'S' == aClass
[0] ) )
1243 if( aClass
.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdendnote
) )
1245 nTextColl
= RES_POOLCOLL_ENDNOTE
;
1248 else if( aClass
.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdfootnote
) )
1250 nTextColl
= RES_POOLCOLL_FOOTNOTE
;
1255 if( USER_FMT
& nTextColl
) // one created by Reader
1257 OSL_ENSURE( false, "Where does the user style comes from?" );
1258 pColl
= GetTextCollFromPool( RES_POOLCOLL_STANDARD
);
1262 pColl
= GetTextCollFromPool( nTextColl
);
1265 if( !aClass
.isEmpty() )
1267 assert(pColl
&& "No paragraph style???");
1268 OUString
aTmp( pColl
->GetName() );
1269 AddClassName( aTmp
, aClass
);
1270 SwTextFormatColl
* pClassColl
= m_pDoc
->FindTextFormatCollByName( aTmp
);
1273 (nTextColl
==RES_POOLCOLL_TABLE
||
1274 nTextColl
==RES_POOLCOLL_TABLE_HDLN
) )
1276 // In this case there was a <TD><P CLASS=foo>, but no TD.foo
1277 // style was found. The we must use P.foo, if available.
1278 SwTextFormatColl
* pCollText
=
1279 GetTextCollFromPool( RES_POOLCOLL_TEXT
);
1280 aTmp
= pCollText
->GetName();
1281 AddClassName( aTmp
, aClass
);
1282 pClassColl
= m_pDoc
->FindTextFormatCollByName( aTmp
);
1291 const SvxCSS1MapEntry
*pClass
= GetClass( aClass
);
1294 pColl
= m_pDoc
->MakeTextFormatColl( aTmp
, pColl
);
1295 SfxItemSet
aItemSet( pClass
->GetItemSet() );
1296 SvxCSS1PropertyInfo
aPropInfo( pClass
->GetPropertyInfo() );
1297 aPropInfo
.SetBoxItem( aItemSet
, MIN_BORDER_DIST
);
1298 bool bPositioned
= MayBePositioned( pClass
->GetPropertyInfo() );
1300 aItemSet
.ClearItem( RES_BACKGROUND
);
1301 SetTextCollAttrs( pColl
, aItemSet
, aPropInfo
,
1309 lcl_swcss1_setEncoding( *pColl
, GetDfltEncoding() );
1314 SwPageDesc
*SwCSS1Parser::GetMasterPageDesc()
1316 return m_pDoc
->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML
, false );
1319 static SwPageDesc
*FindPageDesc(SwDoc
*pDoc
, sal_uInt16 nPoolId
)
1321 size_t nPageDescs
= pDoc
->GetPageDescCnt();
1323 for (nPage
=0; nPage
< nPageDescs
&&
1324 pDoc
->GetPageDesc(nPage
).GetPoolFormatId() != nPoolId
; ++nPage
)
1327 return nPage
< nPageDescs
? &pDoc
->GetPageDesc(nPage
) : nullptr;
1330 const SwPageDesc
*SwCSS1Parser::GetPageDesc( sal_uInt16 nPoolId
, bool bCreate
)
1332 if( RES_POOLPAGE_HTML
== nPoolId
)
1333 return m_pDoc
->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML
, false );
1335 const SwPageDesc
*pPageDesc
= FindPageDesc(m_pDoc
, nPoolId
);
1336 if( !pPageDesc
&& bCreate
)
1338 if (m_rHTMLParser
.IsReadingHeaderOrFooter())
1339 { // (there should be only one definition of header/footer in HTML)
1340 SAL_WARN("sw.html", "no creating PageDesc while reading header/footer");
1344 // The first page is created from the right page, if there is one.
1345 SwPageDesc
*pMasterPageDesc
= nullptr;
1346 if( RES_POOLPAGE_FIRST
== nPoolId
)
1347 pMasterPageDesc
= FindPageDesc(m_pDoc
, RES_POOLPAGE_RIGHT
);
1348 if( !pMasterPageDesc
)
1349 pMasterPageDesc
= m_pDoc
->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML
, false );
1351 // The new page style is created by copying from master
1352 SwPageDesc
*pNewPageDesc
= m_pDoc
->
1353 getIDocumentStylePoolAccess().GetPageDescFromPool( nPoolId
, false );
1355 // therefore we also need the number of the new style
1356 OSL_ENSURE(pNewPageDesc
== FindPageDesc(m_pDoc
, nPoolId
), "page style not found");
1358 m_pDoc
->CopyPageDesc( *pMasterPageDesc
, *pNewPageDesc
, false );
1360 // Modify the styles for their new purpose.
1361 const SwPageDesc
*pFollow
= nullptr;
1362 bool bSetFollowFollow
= false;
1365 case RES_POOLPAGE_FIRST
:
1366 // If there is already a left page, then is it the follow-up
1367 // style, else it is the HTML style.
1368 pFollow
= GetLeftPageDesc();
1370 pFollow
= pMasterPageDesc
;
1373 case RES_POOLPAGE_RIGHT
:
1374 // If the left style is already created, nothing will happen here.
1375 // Otherwise the left style is created and ensures the link with
1377 GetLeftPageDesc( true );
1380 case RES_POOLPAGE_LEFT
:
1381 // The right style is created if none exists. No links are created.
1382 // If there is already a first page style, then the left style becomes
1383 // follow-up style of the first page.
1384 pFollow
= GetRightPageDesc( true );
1385 bSetFollowFollow
= true;
1387 const SwPageDesc
*pFirstPageDesc
= GetFirstPageDesc();
1388 if( pFirstPageDesc
)
1390 SwPageDesc
aNewFirstPageDesc( *pFirstPageDesc
);
1391 aNewFirstPageDesc
.SetFollow( pNewPageDesc
);
1392 ChgPageDesc( pFirstPageDesc
, aNewFirstPageDesc
);
1400 SwPageDesc
aNewPageDesc( *pNewPageDesc
);
1401 aNewPageDesc
.SetFollow( pFollow
);
1402 ChgPageDesc( pNewPageDesc
, aNewPageDesc
);
1404 if( bSetFollowFollow
)
1406 SwPageDesc
aNewFollowPageDesc( *pFollow
);
1407 aNewFollowPageDesc
.SetFollow( pNewPageDesc
);
1408 ChgPageDesc( pFollow
, aNewFollowPageDesc
);
1411 pPageDesc
= pNewPageDesc
;
1417 bool SwCSS1Parser::MayBePositioned( const SvxCSS1PropertyInfo
& rPropInfo
,
1420 if (!rPropInfo
.m_bVisible
)
1422 // Don't create a textframe for this div if it's hidden.
1427 // left/top none auto twip perc
1434 // - the tag will be positioned absolutely and left/top are both
1435 // present and don't contain a percentage value, or
1436 // - the tag should flow, and
1437 // - a width was specified (needed in both cases)
1438 return ( ( SVX_CSS1_POS_ABSOLUTE
== rPropInfo
.m_ePosition
&&
1439 SVX_CSS1_LTYPE_PERCENTAGE
!= rPropInfo
.m_eLeftType
&&
1440 SVX_CSS1_LTYPE_PERCENTAGE
!= rPropInfo
.m_eTopType
&&
1441 (SVX_CSS1_LTYPE_TWIP
== rPropInfo
.m_eLeftType
||
1442 SVX_CSS1_LTYPE_TWIP
!= rPropInfo
.m_eTopType
) ) ||
1443 ( SvxAdjust::End
!= rPropInfo
.m_eFloat
) ) &&
1445 SVX_CSS1_LTYPE_TWIP
== rPropInfo
.m_eWidthType
||
1446 SVX_CSS1_LTYPE_PERCENTAGE
== rPropInfo
.m_eWidthType
);
1449 void SwCSS1Parser::AddClassName( OUString
& rFormatName
, std::u16string_view rClass
)
1451 OSL_ENSURE( !rClass
.empty(), "Style class without length?" );
1453 rFormatName
+= OUString::Concat(".") + rClass
;
1456 void SwCSS1Parser::FillDropCap( SwFormatDrop
& rDrop
,
1457 SfxItemSet
& rItemSet
,
1458 const OUString
*pName
)
1460 // the number of lines matches somehow a percentage value
1461 // for the height (what happens with absolute heights???)
1462 sal_uInt8 nLines
= rDrop
.GetLines();
1463 if( const SvxFontHeightItem
* pFontHeightItem
= rItemSet
.GetItemIfSet( RES_CHRATR_FONTSIZE
, false ) )
1465 sal_uInt16 nProp
= pFontHeightItem
->GetProp();
1466 nLines
= static_cast<sal_uInt8
>((nProp
+ 50) / 100);
1469 else if( nLines
> MAX_DROPCAP_LINES
)
1470 nLines
= MAX_DROPCAP_LINES
;
1472 // Only when nLines>1, then the attribute also is set. Then
1473 // we don't need the font height in the character style.
1476 rItemSet
.ClearItem( RES_CHRATR_FONTSIZE
);
1477 rItemSet
.ClearItem( RES_CHRATR_CJK_FONTSIZE
);
1478 rItemSet
.ClearItem( RES_CHRATR_CTL_FONTSIZE
);
1482 // In case of hard attribution (pName==0) we can stop, if the Initial is
1487 rDrop
.SetLines(nLines
);
1489 // a right border becomes the spacing to text!
1490 if (const SvxRightMarginItem
*const pRightMargin
= rItemSet
.GetItemIfSet(RES_MARGIN_RIGHT
, false))
1492 rDrop
.SetDistance(static_cast<sal_uInt16
>(pRightMargin
->ResolveRight({})));
1493 rItemSet
.ClearItem(RES_MARGIN_RIGHT
);
1495 rItemSet
.ClearItem(RES_MARGIN_FIRSTLINE
);
1496 rItemSet
.ClearItem(RES_MARGIN_TEXTLEFT
);
1498 // for every other attribute create a character style
1499 if( !rItemSet
.Count() )
1502 SwCharFormat
*pCFormat
= nullptr;
1506 aName
= *pName
+ ".FL"; // first letter
1507 pCFormat
= m_pDoc
->FindCharFormatByName( aName
);
1513 aName
= "first-letter " + OUString::number( static_cast<sal_Int32
>(++m_nDropCapCnt
) );
1515 while( m_pDoc
->FindCharFormatByName(aName
) );
1520 pCFormat
= m_pDoc
->MakeCharFormat( aName
, m_pDoc
->GetDfltCharFormat() );
1521 pCFormat
->SetAuto(false);
1523 SetCharFormatAttrs( pCFormat
, rItemSet
);
1525 // The character style needs only be set in the attribute, when
1526 // the attribute also is set.
1528 rDrop
.SetCharFormat( pCFormat
);
1531 // specific CSS1 of SwHTMLParsers
1533 HTMLAttr
**SwHTMLParser::GetAttrTabEntry( sal_uInt16 nWhich
)
1535 // find the table entry of the item ...
1536 HTMLAttr
**ppAttr
= nullptr;
1539 case RES_CHRATR_BLINK
:
1540 ppAttr
= &m_xAttrTab
->pBlink
;
1542 case RES_CHRATR_CASEMAP
:
1543 ppAttr
= &m_xAttrTab
->pCaseMap
;
1545 case RES_CHRATR_COLOR
:
1546 ppAttr
= &m_xAttrTab
->pFontColor
;
1548 case RES_CHRATR_CROSSEDOUT
:
1549 ppAttr
= &m_xAttrTab
->pStrike
;
1551 case RES_CHRATR_ESCAPEMENT
:
1552 ppAttr
= &m_xAttrTab
->pEscapement
;
1554 case RES_CHRATR_FONT
:
1555 ppAttr
= &m_xAttrTab
->pFont
;
1557 case RES_CHRATR_CJK_FONT
:
1558 ppAttr
= &m_xAttrTab
->pFontCJK
;
1560 case RES_CHRATR_CTL_FONT
:
1561 ppAttr
= &m_xAttrTab
->pFontCTL
;
1563 case RES_CHRATR_FONTSIZE
:
1564 ppAttr
= &m_xAttrTab
->pFontHeight
;
1566 case RES_CHRATR_CJK_FONTSIZE
:
1567 ppAttr
= &m_xAttrTab
->pFontHeightCJK
;
1569 case RES_CHRATR_CTL_FONTSIZE
:
1570 ppAttr
= &m_xAttrTab
->pFontHeightCTL
;
1572 case RES_CHRATR_KERNING
:
1573 ppAttr
= &m_xAttrTab
->pKerning
;
1575 case RES_CHRATR_POSTURE
:
1576 ppAttr
= &m_xAttrTab
->pItalic
;
1578 case RES_CHRATR_CJK_POSTURE
:
1579 ppAttr
= &m_xAttrTab
->pItalicCJK
;
1581 case RES_CHRATR_CTL_POSTURE
:
1582 ppAttr
= &m_xAttrTab
->pItalicCTL
;
1584 case RES_CHRATR_UNDERLINE
:
1585 ppAttr
= &m_xAttrTab
->pUnderline
;
1587 case RES_CHRATR_WEIGHT
:
1588 ppAttr
= &m_xAttrTab
->pBold
;
1590 case RES_CHRATR_CJK_WEIGHT
:
1591 ppAttr
= &m_xAttrTab
->pBoldCJK
;
1593 case RES_CHRATR_CTL_WEIGHT
:
1594 ppAttr
= &m_xAttrTab
->pBoldCTL
;
1596 case RES_CHRATR_BACKGROUND
:
1597 ppAttr
= &m_xAttrTab
->pCharBrush
;
1599 case RES_CHRATR_BOX
:
1600 ppAttr
= &m_xAttrTab
->pCharBox
;
1603 case RES_PARATR_LINESPACING
:
1604 ppAttr
= &m_xAttrTab
->pLineSpacing
;
1606 case RES_PARATR_ADJUST
:
1607 ppAttr
= &m_xAttrTab
->pAdjust
;
1610 case RES_MARGIN_FIRSTLINE
:
1611 ppAttr
= &m_xAttrTab
->pFirstLineIndent
;
1613 case RES_MARGIN_TEXTLEFT
:
1614 ppAttr
= &m_xAttrTab
->pTextLeftMargin
;
1616 case RES_MARGIN_RIGHT
:
1617 ppAttr
= &m_xAttrTab
->pRightMargin
;
1620 ppAttr
= &m_xAttrTab
->pULSpace
;
1623 ppAttr
= &m_xAttrTab
->pBox
;
1625 case RES_BACKGROUND
:
1626 ppAttr
= &m_xAttrTab
->pBrush
;
1629 ppAttr
= &m_xAttrTab
->pBreak
;
1632 ppAttr
= &m_xAttrTab
->pPageDesc
;
1634 case RES_PARATR_SPLIT
:
1635 ppAttr
= &m_xAttrTab
->pSplit
;
1637 case RES_PARATR_WIDOWS
:
1638 ppAttr
= &m_xAttrTab
->pWidows
;
1640 case RES_PARATR_ORPHANS
:
1641 ppAttr
= &m_xAttrTab
->pOrphans
;
1644 ppAttr
= &m_xAttrTab
->pKeep
;
1647 case RES_CHRATR_LANGUAGE
:
1648 ppAttr
= &m_xAttrTab
->pLanguage
;
1650 case RES_CHRATR_CJK_LANGUAGE
:
1651 ppAttr
= &m_xAttrTab
->pLanguageCJK
;
1653 case RES_CHRATR_CTL_LANGUAGE
:
1654 ppAttr
= &m_xAttrTab
->pLanguageCTL
;
1658 ppAttr
= &m_xAttrTab
->pDirection
;
1665 void SwHTMLParser::NewStyle()
1669 const HTMLOptions
& rOptions2
= GetOptions();
1670 for (size_t i
= rOptions2
.size(); i
; )
1672 const HTMLOption
& rOption
= rOptions2
[--i
];
1673 if( HtmlOptionId::TYPE
== rOption
.GetToken() )
1674 sType
= rOption
.GetString();
1677 m_bIgnoreRawData
= sType
.getLength() && o3tl::getToken(sType
, 0,';') != sCSS_mimetype
;
1680 void SwHTMLParser::EndStyle()
1682 m_bIgnoreRawData
= false;
1684 if( !m_aStyleSource
.isEmpty() )
1686 m_pCSS1Parser
->ParseStyleSheet( m_aStyleSource
);
1687 m_aStyleSource
.clear();
1691 bool SwHTMLParser::FileDownload( const OUString
& rURL
,
1694 // depose view (because of reschedule)
1695 SwViewShell
*pOldVSh
= CallEndAction();
1697 SfxMedium
aDLMedium( rURL
, StreamMode::READ
| StreamMode::SHARE_DENYWRITE
);
1699 SvStream
* pStream
= aDLMedium
.GetInStream();
1702 SvMemoryStream aStream
;
1703 aStream
.WriteStream( *pStream
);
1705 rStr
= OUString(static_cast<const char *>(aStream
.GetData()), aStream
.TellEnd(),
1710 SwDocShell
* pShell
= m_xDoc
->GetDocShell();
1711 if( ( pShell
&& pShell
->IsAbortingImport() )
1712 || 1 == m_xDoc
->getReferenceCount() )
1714 // was the import aborted from SFX?
1715 eState
= SvParserState::Error
;
1720 SwViewShell
*const pVSh
= CallStartAction( pOldVSh
);
1721 OSL_ENSURE( pOldVSh
== pVSh
, "FileDownload: SwViewShell changed on us" );
1723 return pStream
!=nullptr;
1726 void SwHTMLParser::InsertLink()
1728 bool bFinishDownload
= false;
1729 if( !m_vPendingStack
.empty() )
1731 OSL_ENSURE( ShouldFinishFileDownload(),
1732 "Pending-Stack without File-Download?" );
1734 m_vPendingStack
.pop_back();
1735 assert( m_vPendingStack
.empty() && "Where does the Pending-Stack come from?" );
1737 bFinishDownload
= true;
1741 OUString sRel
, sHRef
, sType
;
1743 const HTMLOptions
& rOptions2
= GetOptions();
1744 for (size_t i
= rOptions2
.size(); i
; )
1746 const HTMLOption
& rOption
= rOptions2
[--i
];
1747 switch( rOption
.GetToken() )
1749 case HtmlOptionId::REL
:
1750 sRel
= rOption
.GetString();
1752 case HtmlOptionId::HREF
:
1753 sHRef
= URIHelper::SmartRel2Abs( INetURLObject( m_sBaseURL
), rOption
.GetString(), Link
<OUString
*, bool>(), false );
1755 case HtmlOptionId::TYPE
:
1756 sType
= rOption
.GetString();
1762 if( !sHRef
.isEmpty() && sRel
.equalsIgnoreAsciiCase( "STYLESHEET" ) &&
1763 ( sType
.isEmpty() || o3tl::getToken(sType
, 0,';') == sCSS_mimetype
) )
1767 // start download of style source
1768 StartFileDownload(sHRef
);
1769 if( IsParserWorking() )
1771 // The style was loaded synchronously and we can call it directly.
1772 bFinishDownload
= true;
1776 // The style was load asynchronously and is only available
1777 // on the next continue call. Therefore we must create a
1778 // Pending stack, so that we will return to here.
1779 m_vPendingStack
.emplace_back( HtmlTokenId::LINK
);
1784 // load file synchronous
1786 if( FileDownload( sHRef
, sSource
) )
1787 m_pCSS1Parser
->ParseStyleSheet( sSource
);
1792 if( bFinishDownload
)
1795 if( FinishFileDownload( sSource
) && !sSource
.isEmpty() )
1796 m_pCSS1Parser
->ParseStyleSheet( sSource
);
1800 bool SwCSS1Parser::ParseStyleSheet( const OUString
& rIn
)
1802 if( !SvxCSS1Parser::ParseStyleSheet( rIn
) )
1805 SwPageDesc
*pMasterPageDesc
=
1806 m_pDoc
->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML
, false );
1808 SvxCSS1MapEntry
* pPageEntry
= GetPage(OUString(), false);
1811 // @page (affects all already existing pages)
1813 SetPageDescAttrs( pMasterPageDesc
, pPageEntry
->GetItemSet(),
1814 pPageEntry
->GetPropertyInfo() );
1816 // For all other already existing page styles the attributes
1819 SetPageDescAttrs( GetFirstPageDesc(), pPageEntry
->GetItemSet(),
1820 pPageEntry
->GetPropertyInfo() );
1821 SetPageDescAttrs( GetLeftPageDesc(), pPageEntry
->GetItemSet(),
1822 pPageEntry
->GetPropertyInfo() );
1823 SetPageDescAttrs( GetRightPageDesc(), pPageEntry
->GetItemSet(),
1824 pPageEntry
->GetPropertyInfo() );
1828 pPageEntry
= GetPage( u
"first"_ustr
, true );
1831 SetPageDescAttrs( GetFirstPageDesc(true), pPageEntry
->GetItemSet(),
1832 pPageEntry
->GetPropertyInfo() );
1833 m_bSetFirstPageDesc
= true;
1836 pPageEntry
= GetPage( u
"right"_ustr
, true );
1839 SetPageDescAttrs( GetRightPageDesc(true), pPageEntry
->GetItemSet(),
1840 pPageEntry
->GetPropertyInfo() );
1841 m_bSetRightPageDesc
= true;
1844 pPageEntry
= GetPage( u
"left"_ustr
, true );
1846 SetPageDescAttrs( GetLeftPageDesc(true), pPageEntry
->GetItemSet(),
1847 pPageEntry
->GetPropertyInfo() );
1852 bool SwHTMLParser::ParseStyleOptions( const OUString
&rStyle
,
1853 const OUString
&rId
,
1854 const OUString
&rClass
,
1855 SfxItemSet
&rItemSet
,
1856 SvxCSS1PropertyInfo
&rPropInfo
,
1857 const OUString
*pLang
,
1858 const OUString
*pDir
)
1862 if( !rClass
.isEmpty() )
1864 OUString
aClass( rClass
);
1865 SwCSS1Parser::GetScriptFromClass( aClass
);
1866 const SvxCSS1MapEntry
*pClass
= m_pCSS1Parser
->GetClass( aClass
);
1869 SvxCSS1Parser::MergeStyles( pClass
->GetItemSet(),
1870 pClass
->GetPropertyInfo(),
1871 rItemSet
, rPropInfo
, false );
1876 if( !rId
.isEmpty() )
1878 const SvxCSS1MapEntry
*pId
= m_pCSS1Parser
->GetId( rId
);
1880 SvxCSS1Parser::MergeStyles( pId
->GetItemSet(),
1881 pId
->GetPropertyInfo(),
1882 rItemSet
, rPropInfo
, !rClass
.isEmpty() );
1883 rPropInfo
.m_aId
= rId
;
1887 if( !rStyle
.isEmpty() )
1889 m_pCSS1Parser
->ParseStyleOption( rStyle
, rItemSet
, rPropInfo
);
1894 rPropInfo
.SetBoxItem( rItemSet
, MIN_BORDER_DIST
);
1896 if( pLang
&& !pLang
->isEmpty() )
1898 LanguageType eLang
= LanguageTag::convertToLanguageTypeWithFallback( *pLang
);
1899 if( LANGUAGE_DONTKNOW
!= eLang
)
1901 SvxLanguageItem
aLang( eLang
, RES_CHRATR_LANGUAGE
);
1902 rItemSet
.Put( aLang
);
1903 aLang
.SetWhich( RES_CHRATR_CJK_LANGUAGE
);
1904 rItemSet
.Put( aLang
);
1905 aLang
.SetWhich( RES_CHRATR_CTL_LANGUAGE
);
1906 rItemSet
.Put( aLang
);
1911 if( pDir
&& !pDir
->isEmpty() )
1913 OUString
aValue( *pDir
);
1914 SvxFrameDirection eDir
= SvxFrameDirection::Environment
;
1915 if (aValue
.equalsIgnoreAsciiCase("LTR"))
1916 eDir
= SvxFrameDirection::Horizontal_LR_TB
;
1917 else if (aValue
.equalsIgnoreAsciiCase("RTL"))
1918 eDir
= SvxFrameDirection::Horizontal_RL_TB
;
1920 if( SvxFrameDirection::Environment
!= eDir
)
1922 SvxFrameDirectionItem
aDir( eDir
, RES_FRAMEDIR
);
1923 rItemSet
.Put( aDir
);
1932 void SwHTMLParser::SetAnchorAndAdjustment( const SvxCSS1PropertyInfo
&rPropInfo
,
1933 SfxItemSet
&rFrameItemSet
)
1935 SwFormatAnchor aAnchor
;
1937 sal_Int16 eHoriOri
= text::HoriOrientation::NONE
;
1938 sal_Int16 eVertOri
= text::VertOrientation::NONE
;
1939 sal_Int16 eHoriRel
= text::RelOrientation::FRAME
;
1940 sal_Int16 eVertRel
= text::RelOrientation::FRAME
;
1941 SwTwips nHoriPos
= 0, nVertPos
= 0;
1942 css::text::WrapTextMode eSurround
= css::text::WrapTextMode_THROUGH
;
1943 if( SVX_CSS1_POS_ABSOLUTE
== rPropInfo
.m_ePosition
)
1945 if( SVX_CSS1_LTYPE_TWIP
== rPropInfo
.m_eLeftType
&&
1946 SVX_CSS1_LTYPE_TWIP
== rPropInfo
.m_eTopType
)
1948 // Absolute positioned objects are page-bound, when they
1949 // aren't in a frame and otherwise frame-bound.
1950 const SwStartNode
*pFlySttNd
=
1951 m_pPam
->GetPoint()->GetNode().FindFlyStartNode();
1954 aAnchor
.SetType( RndStdIds::FLY_AT_FLY
);
1955 SwPosition
aPos( *pFlySttNd
);
1956 aAnchor
.SetAnchor( &aPos
);
1960 aAnchor
.SetType( RndStdIds::FLY_AT_PAGE
);
1961 aAnchor
.SetPageNum( 1 );
1963 nHoriPos
= rPropInfo
.m_nLeft
;
1964 nVertPos
= rPropInfo
.m_nTop
;
1968 aAnchor
.SetType( RndStdIds::FLY_AT_PARA
);
1969 aAnchor
.SetAnchor( m_pPam
->GetPoint() );
1970 eVertOri
= text::VertOrientation::TOP
;
1971 eVertRel
= text::RelOrientation::CHAR
;
1972 if( SVX_CSS1_LTYPE_TWIP
== rPropInfo
.m_eLeftType
)
1974 eHoriOri
= text::HoriOrientation::NONE
;
1975 eHoriRel
= text::RelOrientation::PAGE_FRAME
;
1976 nHoriPos
= rPropInfo
.m_nLeft
;
1980 eHoriOri
= text::HoriOrientation::LEFT
;
1981 eHoriRel
= text::RelOrientation::FRAME
; // to be changed later
1987 // Flowing object are inserted as paragraph-bound, when the paragraph is
1988 // still empty and otherwise auto-bound.
1989 // Auto-bound frames for the time being inserted at the previous position
1991 const sal_Int32 nContent
= m_pPam
->GetPoint()->GetContentIndex();
1994 aAnchor
.SetType( RndStdIds::FLY_AT_CHAR
);
1995 m_pPam
->Move( fnMoveBackward
);
1996 eVertOri
= text::VertOrientation::CHAR_BOTTOM
;
1997 eVertRel
= text::RelOrientation::CHAR
;
2001 aAnchor
.SetType( RndStdIds::FLY_AT_PARA
);
2002 eVertOri
= text::VertOrientation::TOP
;
2003 eVertRel
= text::RelOrientation::PRINT_AREA
;
2006 aAnchor
.SetAnchor( m_pPam
->GetPoint() );
2009 m_pPam
->Move( fnMoveForward
);
2011 sal_uInt16 nLeftSpace
= 0, nRightSpace
= 0;
2013 GetMarginsFromContextWithNumberBullet( nLeftSpace
, nRightSpace
, nIndent
);
2015 if( SvxAdjust::Right
==rPropInfo
.m_eFloat
)
2017 eHoriOri
= text::HoriOrientation::RIGHT
;
2018 eHoriRel
= nRightSpace
? text::RelOrientation::PRINT_AREA
: text::RelOrientation::FRAME
;
2019 eSurround
= css::text::WrapTextMode_LEFT
;
2023 eHoriOri
= text::HoriOrientation::LEFT
;
2024 eHoriRel
= nLeftSpace
? text::RelOrientation::PRINT_AREA
: text::RelOrientation::FRAME
;
2025 eSurround
= css::text::WrapTextMode_RIGHT
;
2028 rFrameItemSet
.Put( aAnchor
);
2030 // positioned absolutely with wrap
2031 rFrameItemSet
.Put( SwFormatHoriOrient( nHoriPos
, eHoriOri
, eHoriRel
) );
2032 rFrameItemSet
.Put( SwFormatVertOrient( nVertPos
, eVertOri
, eVertRel
) );
2033 rFrameItemSet
.Put( SwFormatSurround( eSurround
) );
2036 void SwHTMLParser::SetVarSize( SvxCSS1PropertyInfo
const &rPropInfo
,
2037 SfxItemSet
&rFrameItemSet
,
2038 SwTwips nDfltWidth
, sal_uInt8 nDfltPrcWidth
)
2040 SwTwips nWidth
= nDfltWidth
, nHeight
= MINFLY
;
2041 sal_uInt8 nPercentWidth
= nDfltPrcWidth
, nPercentHeight
= 0;
2042 switch( rPropInfo
.m_eWidthType
)
2044 case SVX_CSS1_LTYPE_PERCENTAGE
:
2045 nPercentWidth
= rPropInfo
.m_nWidth
> 0 ? static_cast<sal_uInt8
>(rPropInfo
.m_nWidth
) : 1;
2048 case SVX_CSS1_LTYPE_TWIP
:
2049 nWidth
= std::max
<tools::Long
>(rPropInfo
.m_nWidth
, MINFLY
);
2055 switch( rPropInfo
.m_eHeightType
)
2057 case SVX_CSS1_LTYPE_PERCENTAGE
:
2058 nPercentHeight
= rPropInfo
.m_nHeight
> 0 ? static_cast<sal_uInt8
>(rPropInfo
.m_nHeight
) : 1;
2060 case SVX_CSS1_LTYPE_TWIP
:
2061 // Netscape and MS-IE interpreting the height incorrectly as minimum height,
2062 // therefore we are doing the same.
2063 nHeight
= std::max
<tools::Long
>(rPropInfo
.m_nHeight
, MINFLY
);
2069 SwFormatFrameSize
aFrameSize( SwFrameSize::Minimum
, nWidth
, nHeight
);
2070 aFrameSize
.SetWidthPercent( nPercentWidth
);
2071 aFrameSize
.SetHeightPercent( nPercentHeight
);
2072 rFrameItemSet
.Put( aFrameSize
);
2075 void SwHTMLParser::SetFrameFormatAttrs( SfxItemSet
&rItemSet
,
2076 HtmlFrameFormatFlags nFlags
,
2077 SfxItemSet
&rFrameItemSet
)
2079 const SvxBoxItem
*pBoxItem
;
2080 if( (nFlags
& HtmlFrameFormatFlags::Box
) &&
2081 (pBoxItem
= rItemSet
.GetItemIfSet( RES_BOX
)) )
2083 if( nFlags
& HtmlFrameFormatFlags::Padding
)
2085 SvxBoxItem
aBoxItem( *pBoxItem
);
2086 // reset all 4 sides to 0
2087 aBoxItem
.SetAllDistances(0);
2088 rFrameItemSet
.Put( aBoxItem
);
2092 rFrameItemSet
.Put( *pBoxItem
);
2094 rItemSet
.ClearItem( RES_BOX
);
2097 const SvxBrushItem
* pBrushItem
;
2098 if( (nFlags
& HtmlFrameFormatFlags::Background
) &&
2099 (pBrushItem
= rItemSet
.GetItemIfSet( RES_BACKGROUND
)) )
2101 rFrameItemSet
.Put( *pBrushItem
);
2102 rItemSet
.ClearItem( RES_BACKGROUND
);
2105 const SvxFrameDirectionItem
* pFrameDirectionItem
;
2106 if( (nFlags
& HtmlFrameFormatFlags::Direction
) &&
2107 (pFrameDirectionItem
= rItemSet
.GetItemIfSet( RES_FRAMEDIR
)) )
2109 rFrameItemSet
.Put( *pFrameDirectionItem
);
2110 rItemSet
.ClearItem( RES_FRAMEDIR
);
2114 std::unique_ptr
<HTMLAttrContext
> SwHTMLParser::PopContext( HtmlTokenId nToken
)
2116 std::unique_ptr
<HTMLAttrContext
> xCntxt
;
2118 HTMLAttrContexts::size_type nPos
= m_aContexts
.size();
2119 if( nPos
<= m_nContextStMin
)
2122 bool bFound
= HtmlTokenId::NONE
== nToken
;
2123 if( nToken
!= HtmlTokenId::NONE
)
2125 // search for stack entry of token ...
2126 while( nPos
> m_nContextStMin
)
2128 HtmlTokenId nCntxtToken
= m_aContexts
[--nPos
]->GetToken();
2129 if( nCntxtToken
== nToken
)
2134 else if( nCntxtToken
== HtmlTokenId::NONE
) // zero as token doesn't occur
2147 xCntxt
= std::move(m_aContexts
[nPos
]);
2148 m_aContexts
.erase( m_aContexts
.begin() + nPos
);
2154 void SwHTMLParser::GetMarginsFromContext( sal_uInt16
& nLeft
,
2157 bool bIgnoreTopContext
) const
2159 HTMLAttrContexts::size_type nPos
= m_aContexts
.size();
2160 if( bIgnoreTopContext
)
2168 while( nPos
> m_nContextStAttrMin
)
2170 const HTMLAttrContext
*pCntxt
= m_aContexts
[--nPos
].get();
2171 if( pCntxt
->IsLRSpaceChanged() )
2173 pCntxt
->GetMargins( nLeft
, nRight
, nIndent
);
2179 void SwHTMLParser::GetMarginsFromContextWithNumberBullet( sal_uInt16
& nLeft
,
2181 short& nIndent
) const
2183 GetMarginsFromContext( nLeft
, nRight
, nIndent
);
2184 const SwHTMLNumRuleInfo
& rInfo
= const_cast<SwHTMLParser
*>(this)->GetNumInfo();
2185 if( rInfo
.GetDepth() )
2187 sal_uInt8 nLevel
= static_cast<sal_uInt8
>( (rInfo
.GetDepth() <= MAXLEVEL
? rInfo
.GetDepth()
2189 const SwNumFormat
& rNumFormat
= rInfo
.GetNumRule()->Get(nLevel
);
2190 nLeft
= nLeft
+ rNumFormat
.GetAbsLSpace(); //TODO: overflow
2191 nIndent
= rNumFormat
.GetFirstLineOffset(); //TODO: overflow
2195 void SwHTMLParser::GetULSpaceFromContext( sal_uInt16
& nUpper
,
2196 sal_uInt16
& nLower
) const
2198 sal_uInt16 nDefaultColl
= 0;
2199 OUString aDefaultClass
;
2201 HTMLAttrContexts::size_type nPos
= m_aContexts
.size();
2202 while( nPos
> m_nContextStAttrMin
)
2204 const HTMLAttrContext
*pCntxt
= m_aContexts
[--nPos
].get();
2205 if( pCntxt
->IsULSpaceChanged() )
2207 pCntxt
->GetULSpace( nUpper
, nLower
);
2210 else if (!nDefaultColl
)
2212 nDefaultColl
= pCntxt
->GetDefaultTextFormatColl();
2214 aDefaultClass
= pCntxt
->GetClass();
2219 nDefaultColl
= RES_POOLCOLL_TEXT
;
2221 const SwTextFormatColl
*pColl
=
2222 m_pCSS1Parser
->GetTextFormatColl(nDefaultColl
, aDefaultClass
);
2223 const SvxULSpaceItem
& rULSpace
= pColl
->GetULSpace();
2224 nUpper
= rULSpace
.GetUpper();
2225 nLower
= rULSpace
.GetLower();
2228 void SwHTMLParser::EndContextAttrs( HTMLAttrContext
*pContext
)
2230 HTMLAttrs
&rAttrs
= pContext
->GetAttrs();
2231 for( auto pAttr
: rAttrs
)
2233 if( RES_PARATR_DROP
==pAttr
->GetItem().Which() )
2235 // Set the number of characters for DropCaps. If it's zero at the
2236 // end, the attribute is set to invalid and then isn't set from SetAttr.
2237 sal_Int32 nChars
= m_pPam
->GetPoint()->GetContentIndex();
2239 pAttr
->Invalidate();
2240 else if( nChars
> MAX_DROPCAP_CHARS
)
2241 nChars
= MAX_DROPCAP_CHARS
;
2242 static_cast<SwFormatDrop
&>(pAttr
->GetItem()).SetChars(static_cast<sal_uInt8
>(nChars
));
2249 void SwHTMLParser::InsertParaAttrs( const SfxItemSet
& rItemSet
)
2251 SfxItemIter
aIter( rItemSet
);
2253 for (const SfxPoolItem
* pItem
= aIter
.GetCurItem(); pItem
; pItem
= aIter
.NextItem())
2255 // search for the table entry of the item...
2256 sal_uInt16 nWhich
= pItem
->Which();
2257 HTMLAttr
**ppAttr
= GetAttrTabEntry( nWhich
);
2261 NewAttr(m_xAttrTab
, ppAttr
, *pItem
);
2262 if( RES_PARATR_BEGIN
> nWhich
)
2263 (*ppAttr
)->SetLikePara();
2264 m_aParaAttrs
.push_back( *ppAttr
);
2265 bool bSuccess
= EndAttr( *ppAttr
, false );
2267 m_aParaAttrs
.pop_back();
2272 static void lcl_swcss1_setEncoding( SwFormat
& rFormat
, rtl_TextEncoding eEnc
)
2274 if( RTL_TEXTENCODING_DONTKNOW
== eEnc
)
2277 const SfxItemSet
& rItemSet
= rFormat
.GetAttrSet();
2278 static const TypedWhichId
<SvxFontItem
> aWhichIds
[3] = { RES_CHRATR_FONT
, RES_CHRATR_CJK_FONT
,
2279 RES_CHRATR_CTL_FONT
};
2280 for (auto const & i
: aWhichIds
)
2282 const SvxFontItem
*pFontItem
= rItemSet
.GetItemIfSet(i
, false);
2285 if (RTL_TEXTENCODING_SYMBOL
== pFontItem
->GetCharSet())
2287 if (eEnc
== pFontItem
->GetCharSet())
2289 SvxFontItem
aFont(pFontItem
->GetFamily(), pFontItem
->GetFamilyName(),
2290 pFontItem
->GetStyleName(), pFontItem
->GetPitch(),
2292 rFormat
.SetFormatAttr(aFont
);
2296 void SwCSS1Parser::SetDfltEncoding( rtl_TextEncoding eEnc
)
2298 if( eEnc
== GetDfltEncoding() )
2303 // Set new encoding as pool default
2304 static const sal_uInt16 aWhichIds
[3] = { RES_CHRATR_FONT
, RES_CHRATR_CJK_FONT
,
2305 RES_CHRATR_CTL_FONT
};
2306 for(sal_uInt16 i
: aWhichIds
)
2308 const SvxFontItem
& rDfltFont
=
2309 static_cast<const SvxFontItem
&>(m_pDoc
->GetDefault( i
));
2310 SvxFontItem
aFont( rDfltFont
.GetFamily(),
2311 rDfltFont
.GetFamilyName(),
2312 rDfltFont
.GetStyleName(),
2313 rDfltFont
.GetPitch(),
2315 m_pDoc
->SetDefault( aFont
);
2318 // Change all paragraph styles that do specify a font.
2319 for( auto pTextFormatColl
: *m_pDoc
->GetTextFormatColls() )
2320 lcl_swcss1_setEncoding( *pTextFormatColl
, eEnc
);
2322 // Change all character styles that do specify a font.
2323 for( auto pCharFormat
: *m_pDoc
->GetCharFormats() )
2324 lcl_swcss1_setEncoding( *pCharFormat
, eEnc
);
2327 SvxCSS1Parser::SetDfltEncoding( eEnc
);
2330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */