build fix
[LibreOffice.git] / sw / source / filter / html / htmlcss1.cxx
blobbd0bfab5dc17b82263b66db66a41de5c2940f592
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "hintids.hxx"
21 #include <svl/itemiter.hxx>
22 #include <svl/whiter.hxx>
23 #include <svl/urihelper.hxx>
24 #include <i18nlangtag/languagetag.hxx>
25 #include <sfx2/docfile.hxx>
26 #include <vcl/svapp.hxx>
27 #include <editeng/fhgtitem.hxx>
28 #include <editeng/brushitem.hxx>
29 #include <editeng/lrspitem.hxx>
30 #include <editeng/ulspitem.hxx>
31 #include <editeng/boxitem.hxx>
32 #include <editeng/flstitem.hxx>
33 #include <editeng/formatbreakitem.hxx>
34 #include <editeng/keepitem.hxx>
35 #include <editeng/fontitem.hxx>
36 #include <editeng/langitem.hxx>
37 #include <editeng/frmdiritem.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>
45 #include "frmatr.hxx"
46 #include <charfmt.hxx>
47 #include <docary.hxx>
48 #include <svx/svxids.hrc>
50 #include "doc.hxx"
51 #include <IDocumentStylePoolAccess.hxx>
52 #include "pam.hxx"
53 #include "ndtxt.hxx"
54 #include "poolfmt.hxx"
55 #include "docsh.hxx"
56 #include "paratr.hxx"
57 #include "pagedesc.hxx"
58 #include "css1kywd.hxx"
59 #include "swcss1.hxx"
60 #include "htmlnum.hxx"
61 #include "swhtml.hxx"
62 #include <numrule.hxx>
63 #include <css1atr.hxx>
65 using namespace ::com::sun::star;
67 // Wie viele Zeilen/Zeichen sind fuer DropCaps erlaubt?
68 // (Gibt es vielleicht woanders entsprechende Werte?)
69 #define MAX_DROPCAP_LINES 9
70 #define MAX_DROPCAP_CHARS 9
72 static void lcl_swcss1_setEncoding( SwFormat& rFormat, rtl_TextEncoding eEnc );
74 // Implementierung des SwCSS1Parsers (eigentlich swcss1.cxx)
75 static struct SwCSS1ItemIds
77 sal_uInt16 nFormatBreak;
78 sal_uInt16 nFormatPageDesc;
79 sal_uInt16 nFormatKeep;
81 SwCSS1ItemIds() :
82 nFormatBreak( RES_BREAK ),
83 nFormatPageDesc( RES_PAGEDESC ),
84 nFormatKeep( RES_KEEP )
87 } aItemIds;
89 void SwCSS1Parser::ChgPageDesc( const SwPageDesc *pPageDesc,
90 const SwPageDesc& rNewPageDesc )
92 size_t pos;
93 bool found = pDoc->ContainsPageDesc( pPageDesc, &pos );
94 OSL_ENSURE( found, "Seitenvorlage nicht gefunden" );
95 if (found)
96 pDoc->ChgPageDesc( pos, rNewPageDesc );
99 SwCSS1Parser::SwCSS1Parser( SwDoc *pD, sal_uInt32 aFHeights[7], const OUString& rBaseURL, bool bNewDoc ) :
100 SvxCSS1Parser( pD->GetAttrPool(), rBaseURL,
101 reinterpret_cast<sal_uInt16*>(&aItemIds), sizeof(aItemIds) / sizeof(sal_uInt16) ),
102 pDoc( pD ),
103 nDropCapCnt( 0 ),
104 bIsNewDoc( bNewDoc ),
105 bBodyBGColorSet( false ),
106 bBodyBackgroundSet( false ),
107 bBodyTextSet( false ),
108 bBodyLinkSet( false ),
109 bBodyVLinkSet( false ),
110 bSetFirstPageDesc( false ),
111 bSetRightPageDesc( false ),
112 bTableHeaderTextCollSet( false ),
113 bTableTextCollSet( false ),
114 bLinkCharFormatsSet( false )
116 aFontHeights[0] = aFHeights[0];
117 aFontHeights[1] = aFHeights[1];
118 aFontHeights[2] = aFHeights[2];
119 aFontHeights[3] = aFHeights[3];
120 aFontHeights[4] = aFHeights[4];
121 aFontHeights[5] = aFHeights[5];
122 aFontHeights[6] = aFHeights[6];
125 SwCSS1Parser::~SwCSS1Parser()
129 // Feature: PrintExt
130 bool SwCSS1Parser::SetFormatBreak( SfxItemSet& rItemSet,
131 const SvxCSS1PropertyInfo& rPropInfo )
133 SvxBreak eBreak = SvxBreak::NONE;
134 bool bKeep = false;
135 bool bSetKeep = false, bSetBreak = false, bSetPageDesc = false;
136 const SwPageDesc *pPageDesc = nullptr;
137 switch( rPropInfo.m_ePageBreakBefore )
139 case SVX_CSS1_PBREAK_ALWAYS:
140 eBreak = SvxBreak::PageBefore;
141 bSetBreak = true;
142 break;
143 case SVX_CSS1_PBREAK_LEFT:
144 pPageDesc = GetLeftPageDesc( true );
145 bSetPageDesc = true;
146 break;
147 case SVX_CSS1_PBREAK_RIGHT:
148 pPageDesc = GetRightPageDesc( true );
149 bSetPageDesc = true;
150 break;
151 case SVX_CSS1_PBREAK_AUTO:
152 bSetBreak = bSetPageDesc = true;
153 break;
154 default:
157 switch( rPropInfo.m_ePageBreakAfter )
159 case SVX_CSS1_PBREAK_ALWAYS:
160 case SVX_CSS1_PBREAK_LEFT:
161 case SVX_CSS1_PBREAK_RIGHT:
162 // LEFT/RIGHT koennte man auch am Absatz davor setzen
163 eBreak = SvxBreak::PageAfter;
164 bSetBreak = true;
165 break;
166 case SVX_CSS1_PBREAK_AUTO:
167 bSetBreak = bSetKeep = bSetPageDesc = true;
168 break;
169 case SVX_CSS1_PBREAK_AVOID:
170 bKeep = bSetKeep = true;
171 break;
172 default:
176 if( bSetBreak )
177 rItemSet.Put( SvxFormatBreakItem( eBreak, RES_BREAK ) );
178 if( bSetPageDesc )
179 rItemSet.Put( SwFormatPageDesc( pPageDesc ) );
180 if( bSetKeep )
181 rItemSet.Put( SvxFormatKeepItem( bKeep, RES_KEEP ) );
183 return bSetBreak;
186 static void SetCharFormatAttrs( SwCharFormat *pCharFormat, SfxItemSet& rItemSet )
188 const SfxPoolItem *pItem;
189 static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE,
190 RES_CHRATR_CTL_FONTSIZE };
191 for(sal_uInt16 i : aWhichIds)
193 if( SfxItemState::SET == rItemSet.GetItemState( i, false,
194 &pItem ) &&
195 static_cast<const SvxFontHeightItem *>(pItem)->GetProp() != 100)
197 // %-Angaben beim FontHeight-Item werden nicht unterstuetzt
198 rItemSet.ClearItem( i );
202 pCharFormat->SetFormatAttr( rItemSet );
204 if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
206 // Ein Brush-Item mit RES_BACKGROUND muss noch in eines mit
207 // RES_CHRATR_BACKGROUND gewandelt werden
209 SvxBrushItem aBrushItem( *static_cast<const SvxBrushItem *>(pItem) );
210 aBrushItem.SetWhich( RES_CHRATR_BACKGROUND );
211 pCharFormat->SetFormatAttr( aBrushItem );
214 if( SfxItemState::SET == rItemSet.GetItemState( RES_BOX, false, &pItem ) )
216 SvxBoxItem aBoxItem( *static_cast<const SvxBoxItem *>(pItem) );
217 aBoxItem.SetWhich( RES_CHRATR_BOX );
218 pCharFormat->SetFormatAttr( aBoxItem );
222 void SwCSS1Parser::SetLinkCharFormats()
224 OSL_ENSURE( !bLinkCharFormatsSet, "Aufruf von SetLinkCharFormats unnoetig" );
226 SvxCSS1MapEntry *pStyleEntry =
227 GetTag( OOO_STRING_SVTOOLS_HTML_anchor );
228 SwCharFormat *pUnvisited = nullptr, *pVisited = nullptr;
229 if( pStyleEntry )
231 SfxItemSet& rItemSet = pStyleEntry->GetItemSet();
232 bool bColorSet = (SfxItemState::SET==rItemSet.GetItemState(RES_CHRATR_COLOR,
233 false));
234 pUnvisited = GetCharFormatFromPool( RES_POOLCHR_INET_NORMAL );
235 SetCharFormatAttrs( pUnvisited, rItemSet );
236 bBodyLinkSet |= bColorSet;
238 pVisited = GetCharFormatFromPool( RES_POOLCHR_INET_VISIT );
239 SetCharFormatAttrs( pVisited, rItemSet );
240 bBodyVLinkSet |= bColorSet;
243 OUString sTmp = OOO_STRING_SVTOOLS_HTML_anchor ":link";
245 pStyleEntry = GetTag( sTmp );
246 if( pStyleEntry )
248 SfxItemSet& rItemSet = pStyleEntry->GetItemSet();
249 bool bColorSet = (SfxItemState::SET==rItemSet.GetItemState(RES_CHRATR_COLOR,
250 false));
251 if( !pUnvisited )
252 pUnvisited = GetCharFormatFromPool( RES_POOLCHR_INET_NORMAL );
253 SetCharFormatAttrs( pUnvisited, rItemSet );
254 bBodyLinkSet |= bColorSet;
257 sTmp = OOO_STRING_SVTOOLS_HTML_anchor ":visited";
259 pStyleEntry = GetTag( sTmp );
260 if( pStyleEntry )
262 SfxItemSet& rItemSet = pStyleEntry->GetItemSet();
263 bool bColorSet = (SfxItemState::SET==rItemSet.GetItemState(RES_CHRATR_COLOR,
264 false));
265 if( !pVisited )
266 pVisited = GetCharFormatFromPool( RES_POOLCHR_INET_VISIT );
267 SetCharFormatAttrs( pVisited, rItemSet );
268 bBodyVLinkSet |= bColorSet;
271 bLinkCharFormatsSet = true;
274 static void SetTextCollAttrs( SwTextFormatColl *pColl, SfxItemSet& rItemSet,
275 SvxCSS1PropertyInfo& rPropInfo,
276 SwCSS1Parser *pCSS1Parser )
278 const SfxItemSet& rCollItemSet = pColl->GetAttrSet();
279 const SfxPoolItem *pCollItem, *pItem;
281 // linker, rechter Rand und Erstzeilen-Einzug
282 if( (rPropInfo.m_bLeftMargin || rPropInfo.m_bRightMargin ||
283 rPropInfo.m_bTextIndent) &&
284 (!rPropInfo.m_bLeftMargin || !rPropInfo.m_bRightMargin ||
285 !rPropInfo.m_bTextIndent) &&
286 SfxItemState::SET == rCollItemSet.GetItemState(RES_LR_SPACE,true,&pCollItem) &&
287 SfxItemState::SET == rItemSet.GetItemState(RES_LR_SPACE,false,&pItem) )
289 const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem);
291 SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem *>(pCollItem) );
292 if( rPropInfo.m_bLeftMargin )
293 aLRItem.SetTextLeft( pLRItem->GetTextLeft() );
294 if( rPropInfo.m_bRightMargin )
295 aLRItem.SetRight( pLRItem->GetRight() );
296 if( rPropInfo.m_bTextIndent )
297 aLRItem.SetTextFirstLineOfst( pLRItem->GetTextFirstLineOfst() );
299 rItemSet.Put( aLRItem );
302 // oberer und unterer Rand
303 if( (rPropInfo.m_bTopMargin || rPropInfo.m_bBottomMargin) &&
304 (!rPropInfo.m_bTopMargin || !rPropInfo.m_bBottomMargin) &&
305 SfxItemState::SET == rCollItemSet.GetItemState(RES_UL_SPACE,true,
306 &pCollItem) &&
307 SfxItemState::SET == rItemSet.GetItemState(RES_UL_SPACE,false,&pItem) )
309 const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem);
311 SvxULSpaceItem aULItem( *static_cast<const SvxULSpaceItem *>(pCollItem) );
312 if( rPropInfo.m_bTopMargin )
313 aULItem.SetUpper( pULItem->GetUpper() );
314 if( rPropInfo.m_bBottomMargin )
315 aULItem.SetLower( pULItem->GetLower() );
317 rItemSet.Put( aULItem );
320 static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE,
321 RES_CHRATR_CTL_FONTSIZE };
322 for(sal_uInt16 i : aWhichIds)
324 if( SfxItemState::SET == rItemSet.GetItemState( i, false,
325 &pItem ) &&
326 static_cast<const SvxFontHeightItem *>(pItem)->GetProp() != 100)
328 // %-Angaben beim FontHeight-Item werden nicht unterstuetzt
329 rItemSet.ClearItem( i );
333 pCSS1Parser->SetFormatBreak( rItemSet, rPropInfo );
335 pColl->SetFormatAttr( rItemSet );
338 void SwCSS1Parser::SetTableTextColl( bool bHeader )
340 OSL_ENSURE( !(bHeader ? bTableHeaderTextCollSet : bTableTextCollSet),
341 "Aufruf von SetTableTextColl unnoetig" );
343 sal_uInt16 nPoolId;
344 OUString sTag;
345 if( bHeader )
347 nPoolId = RES_POOLCOLL_TABLE_HDLN;
348 sTag = OOO_STRING_SVTOOLS_HTML_tableheader;
350 else
352 nPoolId = RES_POOLCOLL_TABLE;
353 sTag = OOO_STRING_SVTOOLS_HTML_tabledata;
356 SwTextFormatColl *pColl = nullptr;
358 // The following entries will never be used again and may be changed.
359 SvxCSS1MapEntry *pStyleEntry = GetTag( sTag );
360 if( pStyleEntry )
362 pColl = GetTextFormatColl( nPoolId, aEmptyOUStr );
363 SetTextCollAttrs( pColl, pStyleEntry->GetItemSet(),
364 pStyleEntry->GetPropertyInfo(), this );
367 OUString sTmp = sTag + " " OOO_STRING_SVTOOLS_HTML_parabreak;
368 pStyleEntry = GetTag( sTmp );
369 if( pStyleEntry )
371 if( !pColl )
372 pColl = GetTextFormatColl( nPoolId, aEmptyOUStr );
373 SetTextCollAttrs( pColl, pStyleEntry->GetItemSet(),
374 pStyleEntry->GetPropertyInfo(), this );
377 if( bHeader )
378 bTableHeaderTextCollSet = true;
379 else
380 bTableTextCollSet = true;
383 void SwCSS1Parser::SetPageDescAttrs( const SvxBrushItem *pBrush,
384 SfxItemSet *pItemSet2 )
386 SvxBrushItem aBrushItem( RES_BACKGROUND );
387 SvxBoxItem aBoxItem( RES_BOX );
388 SvxFrameDirectionItem aFrameDirItem(FRMDIR_ENVIRONMENT, RES_FRAMEDIR);
389 bool bSetBrush = pBrush!=nullptr, bSetBox = false, bSetFrameDir = false;
390 if( pBrush )
391 aBrushItem = *pBrush;
393 if( pItemSet2 )
395 const SfxPoolItem *pItem = nullptr;
396 if( SfxItemState::SET == pItemSet2->GetItemState( RES_BACKGROUND, false,
397 &pItem ) )
399 // ein Hintergrund wird gesetzt
400 aBrushItem = *static_cast<const SvxBrushItem *>(pItem);
401 pItemSet2->ClearItem( RES_BACKGROUND );
402 bSetBrush = true;
405 if( SfxItemState::SET == pItemSet2->GetItemState( RES_BOX, false, &pItem ) )
407 // eine Umrandung wird gesetzt
408 aBoxItem = *static_cast<const SvxBoxItem *>(pItem);
409 pItemSet2->ClearItem( RES_BOX );
410 bSetBox = true;
413 if( SfxItemState::SET == pItemSet2->GetItemState( RES_FRAMEDIR, false, &pItem ) )
415 // eine Umrandung wird gesetzt
416 aFrameDirItem = *static_cast< const SvxFrameDirectionItem *>( pItem );
417 pItemSet2->ClearItem( RES_FRAMEDIR );
418 bSetFrameDir = true;
422 if( bSetBrush || bSetBox || bSetFrameDir )
424 static sal_uInt16 aPoolIds[] = { RES_POOLPAGE_HTML, RES_POOLPAGE_FIRST,
425 RES_POOLPAGE_LEFT, RES_POOLPAGE_RIGHT };
426 for(sal_uInt16 i : aPoolIds)
428 const SwPageDesc *pPageDesc = GetPageDesc( i, false );
429 if( pPageDesc )
431 SwPageDesc aNewPageDesc( *pPageDesc );
432 SwFrameFormat &rMaster = aNewPageDesc.GetMaster();
433 if( bSetBrush )
434 rMaster.SetFormatAttr( aBrushItem );
435 if( bSetBox )
436 rMaster.SetFormatAttr( aBoxItem );
437 if( bSetFrameDir )
438 rMaster.SetFormatAttr( aFrameDirItem );
440 ChgPageDesc( pPageDesc, aNewPageDesc );
446 // Feature: PrintExt
447 void SwCSS1Parser::SetPageDescAttrs( const SwPageDesc *pPageDesc,
448 SfxItemSet& rItemSet,
449 const SvxCSS1PropertyInfo& rPropInfo )
451 if( !pPageDesc )
452 return;
454 SwPageDesc aNewPageDesc( *pPageDesc );
455 SwFrameFormat &rMaster = aNewPageDesc.GetMaster();
456 const SfxItemSet& rPageItemSet = rMaster.GetAttrSet();
457 const SfxPoolItem *pPageItem, *pItem;
458 bool bChanged = false;
460 // linker, rechter Rand und Erstzeilen-Einzug
461 if( (rPropInfo.m_bLeftMargin || rPropInfo.m_bRightMargin) &&
462 SfxItemState::SET == rItemSet.GetItemState(RES_LR_SPACE,false,&pItem) )
464 if( (!rPropInfo.m_bLeftMargin || !rPropInfo.m_bRightMargin) &&
465 SfxItemState::SET == rPageItemSet.GetItemState(RES_LR_SPACE,
466 true,&pPageItem) )
468 const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem);
470 SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem *>(pPageItem) );
471 if( rPropInfo.m_bLeftMargin )
472 aLRItem.SetLeft( pLRItem->GetLeft() );
473 if( rPropInfo.m_bRightMargin )
474 aLRItem.SetRight( pLRItem->GetRight() );
476 rMaster.SetFormatAttr( aLRItem );
478 else
480 rMaster.SetFormatAttr( *pItem );
482 bChanged = true;
485 // oberer und unterer Rand
486 if( (rPropInfo.m_bTopMargin || rPropInfo.m_bBottomMargin) &&
487 SfxItemState::SET == rItemSet.GetItemState(RES_UL_SPACE,false,&pItem) )
489 if( (!rPropInfo.m_bTopMargin || !rPropInfo.m_bBottomMargin) &&
490 SfxItemState::SET == rPageItemSet.GetItemState(RES_UL_SPACE,
491 true,&pPageItem) )
493 const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem);
495 SvxULSpaceItem aULItem( *static_cast<const SvxULSpaceItem *>(pPageItem) );
496 if( rPropInfo.m_bTopMargin )
497 aULItem.SetUpper( pULItem->GetUpper() );
498 if( rPropInfo.m_bBottomMargin )
499 aULItem.SetLower( pULItem->GetLower() );
501 rMaster.SetFormatAttr( aULItem );
503 else
505 rMaster.SetFormatAttr( *pItem );
507 bChanged = true;
510 // die Groesse
511 if( rPropInfo.m_eSizeType != SVX_CSS1_STYPE_NONE )
513 if( rPropInfo.m_eSizeType == SVX_CSS1_STYPE_TWIP )
515 rMaster.SetFormatAttr( SwFormatFrameSize( ATT_FIX_SIZE, rPropInfo.m_nWidth,
516 rPropInfo.m_nHeight ) );
517 bChanged = true;
519 else
521 // Bei "size: auto|portrait|landscape" bleibt die bisherige
522 // Groesse der Vorlage erhalten. Bei "landscape" und "portrait"
523 // wird das Landscape-Flag gesetzt und evtl. die Breite/Hoehe
524 // vertauscht.
525 SwFormatFrameSize aFrameSz( rMaster.GetFrameSize() );
526 bool bLandscape = aNewPageDesc.GetLandscape();
527 if( ( bLandscape &&
528 rPropInfo.m_eSizeType == SVX_CSS1_STYPE_PORTRAIT ) ||
529 ( !bLandscape &&
530 rPropInfo.m_eSizeType == SVX_CSS1_STYPE_LANDSCAPE ) )
532 SwTwips nTmp = aFrameSz.GetHeight();
533 aFrameSz.SetHeight( aFrameSz.GetWidth() );
534 aFrameSz.SetWidth( nTmp );
535 rMaster.SetFormatAttr( aFrameSz );
536 aNewPageDesc.SetLandscape( !bLandscape );
537 bChanged = true;
542 // Geht das wirklich?
543 if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
545 // eine Umrandung wird gesetzt
546 rMaster.SetFormatAttr( *pItem );
547 rItemSet.ClearItem( RES_BACKGROUND );
548 bChanged = true;
551 if( bChanged )
552 ChgPageDesc( pPageDesc, aNewPageDesc );
555 SvxBrushItem SwCSS1Parser::makePageDescBackground() const
557 return pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML, false )
558 ->GetMaster().makeBackgroundBrushItem();
561 sal_uInt16 SwCSS1Parser::GetScriptFromClass( OUString& rClass,
562 bool bSubClassOnly )
564 sal_uInt16 nScriptFlags = CSS1_SCRIPT_ALL;
565 sal_Int32 nLen = rClass.getLength();
566 sal_Int32 nPos = nLen > 4 ? rClass.lastIndexOf( '-' ) : -1;
568 if( nPos == -1 )
570 if( bSubClassOnly )
571 return nScriptFlags;
572 nPos = 0;
574 else
576 nPos++;
577 nLen = nLen - nPos;
580 switch( nLen )
582 case 3:
583 if( rClass.matchIgnoreAsciiCase( "cjk", nPos ) )
585 nScriptFlags = CSS1_SCRIPT_CJK;
587 else if( rClass.matchIgnoreAsciiCase( "ctl", nPos ) )
589 nScriptFlags = CSS1_SCRIPT_CTL;
591 break;
592 case 7:
593 if( rClass.matchIgnoreAsciiCase( "western", nPos ) )
595 nScriptFlags = CSS1_SCRIPT_WESTERN;
597 break;
599 if( CSS1_SCRIPT_ALL != nScriptFlags )
601 if( nPos )
603 rClass = rClass.copy( 0, nPos-1 );
605 else
607 rClass.clear();
611 return nScriptFlags;
614 static CSS1SelectorType GetTokenAndClass( const CSS1Selector *pSelector,
615 OUString& rToken, OUString& rClass,
616 sal_uInt16& rScriptFlags )
618 rToken = pSelector->GetString();
619 rClass.clear();
620 rScriptFlags = CSS1_SCRIPT_ALL;
622 CSS1SelectorType eType = pSelector->GetType();
623 if( CSS1_SELTYPE_ELEM_CLASS==eType )
625 sal_Int32 nPos = rToken.indexOf( '.' );
626 OSL_ENSURE( nPos >= 0, "kein Punkt in Class-Selektor???" );
627 if( nPos >= 0 )
629 rClass = rToken.copy( nPos+1 );
630 rToken = rToken.copy( 0, nPos );
632 rScriptFlags = SwCSS1Parser::GetScriptFromClass( rClass, false );
633 if( rClass.isEmpty() )
634 eType = CSS1_SELTYPE_ELEMENT;
638 rToken = rToken.toAsciiLowerCase();
639 return eType;
642 static void RemoveScriptItems( SfxItemSet& rItemSet, sal_uInt16 nScript,
643 const SfxItemSet *pParentItemSet = nullptr )
645 static const sal_uInt16 aWhichIds[3][5] =
647 { RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, RES_CHRATR_LANGUAGE,
648 RES_CHRATR_POSTURE, RES_CHRATR_WEIGHT },
649 { RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CJK_LANGUAGE,
650 RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT },
651 { RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE, RES_CHRATR_CTL_LANGUAGE,
652 RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT }
655 bool aClearItems[3] = { false, false, false };
656 switch( nScript )
658 case CSS1_SCRIPT_WESTERN:
659 aClearItems[1] = aClearItems[2] = true;
660 break;
661 case CSS1_SCRIPT_CJK:
662 aClearItems[0] = aClearItems[2] = true;
663 break;
664 case CSS1_SCRIPT_CTL:
665 aClearItems[0] = aClearItems[1] = true;
666 break;
667 case CSS1_SCRIPT_ALL:
668 break;
669 default:
670 OSL_ENSURE( aClearItems[0], "unknown script type" );
671 break;
674 for( size_t j=0; j < SAL_N_ELEMENTS(aWhichIds); ++j )
676 for( size_t i=0; i < SAL_N_ELEMENTS(aWhichIds[0]); ++i )
678 sal_uInt16 nWhich = aWhichIds[j][i];
679 const SfxPoolItem *pItem;
680 if( aClearItems[j] ||
681 (pParentItemSet &&
682 SfxItemState::SET == rItemSet.GetItemState( nWhich, false, &pItem ) &&
683 (0==i ? swhtml_css1atr_equalFontItems( *pItem, pParentItemSet->Get(nWhich ) )
684 : *pItem == pParentItemSet->Get(nWhich ) ) ) )
686 rItemSet.ClearItem( nWhich );
692 void SwCSS1Parser::StyleParsed( const CSS1Selector *pSelector,
693 SfxItemSet& rItemSet,
694 SvxCSS1PropertyInfo& rPropInfo )
696 if( !bIsNewDoc )
697 return;
699 CSS1SelectorType eSelType = pSelector->GetType();
700 const CSS1Selector *pNext = pSelector->GetNext();
702 if( CSS1_SELTYPE_ID==eSelType && !pNext )
704 InsertId( pSelector->GetString(), rItemSet, rPropInfo );
706 else if( CSS1_SELTYPE_CLASS==eSelType && !pNext )
708 OUString aClass( pSelector->GetString() );
709 sal_uInt16 nScript = GetScriptFromClass( aClass );
710 if( CSS1_SCRIPT_ALL != nScript )
712 SfxItemSet aScriptItemSet( rItemSet );
713 RemoveScriptItems( aScriptItemSet, nScript );
714 InsertClass( aClass, aScriptItemSet, rPropInfo );
716 else
718 InsertClass( aClass, rItemSet, rPropInfo );
721 else if( CSS1_SELTYPE_PAGE==eSelType )
723 if( !pNext ||
724 (CSS1_SELTYPE_PSEUDO == pNext->GetType() &&
725 (pNext->GetString().equalsIgnoreAsciiCase( "left" ) ||
726 pNext->GetString().equalsIgnoreAsciiCase( "right" ) ||
727 pNext->GetString().equalsIgnoreAsciiCase( "first" ) ) ) )
729 OUString aName;
730 if( pNext )
731 aName = pNext->GetString();
732 InsertPage( aName,
733 pNext != nullptr,
734 rItemSet, rPropInfo );
738 if( CSS1_SELTYPE_ELEMENT != eSelType &&
739 CSS1_SELTYPE_ELEM_CLASS != eSelType)
740 return;
742 // Token und Class zu dem Selektor holen
743 OUString aToken2;
744 OUString aClass;
745 sal_uInt16 nScript;
746 eSelType = GetTokenAndClass( pSelector, aToken2, aClass, nScript );
747 int nToken2 = GetHTMLToken( aToken2 );
749 // und noch ein ganz par Infos zum naechsten Element
750 CSS1SelectorType eNextType = pNext ? pNext->GetType()
751 : CSS1_SELTYPE_ELEMENT;
753 // Erstmal ein par Spezialfaelle
754 if( CSS1_SELTYPE_ELEMENT==eSelType )
756 switch( nToken2 )
758 case HTML_ANCHOR_ON:
759 if( !pNext )
761 InsertTag( aToken2, rItemSet, rPropInfo );
762 return;
764 else if( pNext && CSS1_SELTYPE_PSEUDO == eNextType )
766 // vielleicht A:visited oder A:link
768 OUString aPseudo( pNext->GetString() );
769 aPseudo = aPseudo.toAsciiLowerCase();
770 bool bInsert = false;
771 switch( aPseudo[0] )
773 case 'l':
774 if( aPseudo == "link" )
776 bInsert = true;
778 break;
779 case 'v':
780 if( aPseudo == "visited" )
782 bInsert = true;
784 break;
786 if( bInsert )
788 OUString sTmp = aToken2 + ":" + aPseudo;
789 if( CSS1_SCRIPT_ALL != nScript )
791 SfxItemSet aScriptItemSet( rItemSet );
792 RemoveScriptItems( aScriptItemSet, nScript );
793 InsertTag( sTmp, aScriptItemSet, rPropInfo );
795 else
797 InsertTag( sTmp, rItemSet, rPropInfo );
799 return;
802 break;
803 case HTML_BODY_ON:
804 if( !pNext )
806 // BODY
808 // Den Hintergrund muessen wir vor dem Setzen abfragen,
809 // denn in SetPageDescAttrs wird er geloescht.
810 const SfxPoolItem *pItem;
811 if( SfxItemState::SET==rItemSet.GetItemState(RES_BACKGROUND,false,&pItem) )
813 const SvxBrushItem *pBrushItem =
814 static_cast<const SvxBrushItem *>(pItem);
816 /// Body has a background color, if it is not "no fill"/"auto fill"
817 if( pBrushItem->GetColor() != COL_TRANSPARENT )
818 bBodyBGColorSet = true;
819 if( GPOS_NONE != pBrushItem->GetGraphicPos() )
820 bBodyBackgroundSet = true;
823 // Border and Padding
824 rPropInfo.SetBoxItem( rItemSet, MIN_BORDER_DIST );
826 // Ein par Attribute muessen an der Seitenvorlage gesetzt werden,
827 // und zwar die, die nicht vererbt werden
828 SetPageDescAttrs( nullptr, &rItemSet );
830 // alle noch uebrigen Optionen koennen an der Standard-Vorlage
831 // gesetzt werden und gelten dann automatisch als defaults
832 if( SfxItemState::SET==rItemSet.GetItemState(RES_CHRATR_COLOR,false) )
833 bBodyTextSet = true;
834 SetTextCollAttrs(
835 GetTextCollFromPool( RES_POOLCOLL_STANDARD ),
836 rItemSet, rPropInfo, this );
838 return;
840 break;
843 else if( CSS1_SELTYPE_ELEM_CLASS==eSelType && HTML_ANCHOR_ON==nToken2 &&
844 !pNext && aClass.getLength() >= 9 &&
845 ('s' == aClass[0] || 'S' == aClass[0]) )
847 sal_uInt16 nPoolFormatId = 0;
848 if( aClass.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdendnote_sym) )
849 nPoolFormatId = RES_POOLCHR_ENDNOTE;
850 else if( aClass.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdfootnote_sym) )
851 nPoolFormatId = RES_POOLCHR_FOOTNOTE;
852 if( nPoolFormatId )
854 if( CSS1_SCRIPT_ALL == nScript )
856 SetCharFormatAttrs( GetCharFormatFromPool(nPoolFormatId), rItemSet );
858 else
860 SfxItemSet aScriptItemSet( rItemSet );
861 RemoveScriptItems( aScriptItemSet, nScript );
862 SetCharFormatAttrs( GetCharFormatFromPool(nPoolFormatId),
863 aScriptItemSet);
865 return;
869 // Jetzt werden die Selektoren verarbeitet, die zu einer Absatz-Vorlage
870 // gehoehren
871 sal_uInt16 nPoolCollId = 0;
872 switch( nToken2 )
874 case HTML_HEAD1_ON:
875 nPoolCollId = RES_POOLCOLL_HEADLINE1;
876 break;
877 case HTML_HEAD2_ON:
878 nPoolCollId = RES_POOLCOLL_HEADLINE2;
879 break;
880 case HTML_HEAD3_ON:
881 nPoolCollId = RES_POOLCOLL_HEADLINE3;
882 break;
883 case HTML_HEAD4_ON:
884 nPoolCollId = RES_POOLCOLL_HEADLINE4;
885 break;
886 case HTML_HEAD5_ON:
887 nPoolCollId = RES_POOLCOLL_HEADLINE5;
888 break;
889 case HTML_HEAD6_ON:
890 nPoolCollId = RES_POOLCOLL_HEADLINE6;
891 break;
892 case HTML_PARABREAK_ON:
893 if( aClass.getLength() >= 9 &&
894 ('s' == aClass[0] || 'S' == aClass[0]) )
896 if( aClass.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdendnote) )
897 nPoolCollId = RES_POOLCOLL_ENDNOTE;
898 else if( aClass.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdfootnote) )
899 nPoolCollId = RES_POOLCOLL_FOOTNOTE;
901 if( nPoolCollId )
902 aClass = aEmptyOUStr;
903 else
904 nPoolCollId = RES_POOLCOLL_TEXT;
906 else
908 nPoolCollId = RES_POOLCOLL_TEXT;
910 break;
911 case HTML_ADDRESS_ON:
912 nPoolCollId = RES_POOLCOLL_SENDADRESS;
913 break;
914 case HTML_BLOCKQUOTE_ON:
915 nPoolCollId = RES_POOLCOLL_HTML_BLOCKQUOTE;
916 break;
917 case HTML_DT_ON:
918 nPoolCollId = RES_POOLCOLL_HTML_DT;
919 break;
920 case HTML_DD_ON:
921 nPoolCollId = RES_POOLCOLL_HTML_DD;
922 break;
923 case HTML_PREFORMTXT_ON:
924 nPoolCollId = RES_POOLCOLL_HTML_PRE;
925 break;
926 case HTML_TABLEHEADER_ON:
927 case HTML_TABLEDATA_ON:
928 if( CSS1_SELTYPE_ELEMENT==eSelType && !pNext )
930 InsertTag( aToken2, rItemSet, rPropInfo );
931 return;
933 else if( CSS1_SELTYPE_ELEMENT==eSelType && pNext &&
934 (CSS1_SELTYPE_ELEMENT==eNextType ||
935 CSS1_SELTYPE_ELEM_CLASS==eNextType) )
937 // nicht TH und TD, aber TH P und TD P
938 OUString aSubToken, aSubClass;
939 GetTokenAndClass( pNext, aSubToken, aSubClass, nScript );
940 if( HTML_PARABREAK_ON == GetHTMLToken( aSubToken ) )
942 aClass = aSubClass;
943 pNext = pNext->GetNext();
944 eNextType = pNext ? pNext->GetType() : CSS1_SELTYPE_ELEMENT;
946 if( !aClass.isEmpty() || pNext )
948 nPoolCollId = static_cast< sal_uInt16 >(
949 HTML_TABLEHEADER_ON == nToken2 ? RES_POOLCOLL_TABLE_HDLN
950 : RES_POOLCOLL_TABLE );
952 else
954 OUString sTmp = aToken2 + " " OOO_STRING_SVTOOLS_HTML_parabreak;
956 if( CSS1_SCRIPT_ALL == nScript )
958 InsertTag( sTmp, rItemSet, rPropInfo );
960 else
962 SfxItemSet aScriptItemSet( rItemSet );
963 RemoveScriptItems( aScriptItemSet, nScript );
964 InsertTag( sTmp, aScriptItemSet, rPropInfo );
967 return;
971 break;
973 default:
977 if( nPoolCollId )
979 if( !pNext ||
980 (CSS1_SELTYPE_PSEUDO==eNextType &&
981 pNext->GetString().equalsIgnoreAsciiCase( "first-letter" ) &&
982 SVX_ADJUST_LEFT == rPropInfo.m_eFloat) )
984 // Entweder kein zusammengesetzter Selektor oder
985 // ein X:first-line { float: left; ... }
987 // Die Vorlage Suchen bzw. Anlegen
988 SwTextFormatColl *pColl = GetTextFormatColl( nPoolCollId, aEmptyOUStr );
989 SwTextFormatColl* pParentColl = nullptr;
990 if( !aClass.isEmpty() )
992 OUString aName( pColl->GetName() );
993 AddClassName( aName, aClass );
995 pParentColl = pColl;
996 pColl = pDoc->FindTextFormatCollByName( aName );
997 if( !pColl )
998 pColl = pDoc->MakeTextFormatColl( aName, pParentColl );
1000 if( !pNext )
1002 // nur die Attribute an der Vorlage setzen
1003 const SfxPoolItem *pItem;
1004 const SvxBoxItem *pBoxItem = nullptr;
1005 if( SfxItemState::SET ==
1006 pColl->GetAttrSet().GetItemState(RES_BOX,true,&pItem) )
1007 pBoxItem = static_cast<const SvxBoxItem *>(pItem);
1008 rPropInfo.SetBoxItem( rItemSet, MIN_BORDER_DIST, pBoxItem );
1009 if( CSS1_SCRIPT_ALL == nScript && !pParentColl )
1011 SetTextCollAttrs( pColl, rItemSet, rPropInfo, this );
1013 else
1015 SfxItemSet aScriptItemSet( rItemSet );
1016 RemoveScriptItems( aScriptItemSet, nScript,
1017 pParentColl ? &pParentColl->GetAttrSet() : nullptr );
1018 SetTextCollAttrs( pColl, aScriptItemSet, rPropInfo, this );
1021 else
1023 // ein Drop-Cap-Attribut basteln
1024 SwFormatDrop aDrop( pColl->GetDrop() );
1025 aDrop.GetChars() = 1;
1027 // die Attribute in das DropCap-Attribut einfuegen
1028 if( CSS1_SCRIPT_ALL == nScript )
1030 OUString sName(pColl->GetName());
1031 FillDropCap( aDrop, rItemSet, &sName );
1033 else
1035 SfxItemSet aScriptItemSet( rItemSet );
1036 if( CSS1_SCRIPT_WESTERN != nScript )
1038 aScriptItemSet.ClearItem( RES_CHRATR_FONT );
1039 aScriptItemSet.ClearItem( RES_CHRATR_LANGUAGE );
1040 aScriptItemSet.ClearItem( RES_CHRATR_POSTURE );
1041 aScriptItemSet.ClearItem( RES_CHRATR_WEIGHT );
1043 if( CSS1_SCRIPT_CJK != nScript )
1045 aScriptItemSet.ClearItem( RES_CHRATR_CJK_FONT );
1046 aScriptItemSet.ClearItem( RES_CHRATR_CJK_LANGUAGE );
1047 aScriptItemSet.ClearItem( RES_CHRATR_CJK_POSTURE );
1048 aScriptItemSet.ClearItem( RES_CHRATR_CJK_WEIGHT );
1050 if( CSS1_SCRIPT_CTL != nScript )
1052 aScriptItemSet.ClearItem( RES_CHRATR_CTL_FONT );
1053 aScriptItemSet.ClearItem( RES_CHRATR_CTL_LANGUAGE );
1054 aScriptItemSet.ClearItem( RES_CHRATR_CTL_POSTURE );
1055 aScriptItemSet.ClearItem( RES_CHRATR_CTL_WEIGHT );
1057 OUString sName(pColl->GetName());
1058 FillDropCap( aDrop, aScriptItemSet, &sName );
1061 // Das Attribut nur setzen, wenn float: left angegeben wurde
1062 // und das Initial ueber mehrere Zeilen geht. Sonst wird die
1063 // ggf. angelegte Zeichen-Vorlage spaeter ueber den Namen
1064 // gesucht und gesetzt.
1065 if( aDrop.GetLines() > 1 &&
1066 (SVX_ADJUST_LEFT == rPropInfo.m_eFloat ||
1067 CSS1_SCRIPT_ALL == nScript) )
1069 pColl->SetFormatAttr( aDrop );
1074 return;
1077 // Jetzt werden die Selektoten verarbeitet, die zu einer Zechenvorlage
1078 // gehoehren. Zusammengesetzte gibt es hier allerdings nich nicht.
1079 if( pNext )
1080 return;
1082 SwCharFormat *pCFormat = GetChrFormat( static_cast< sal_uInt16 >(nToken2), aEmptyOUStr );
1083 if( pCFormat )
1085 SwCharFormat *pParentCFormat = nullptr;
1086 if( !aClass.isEmpty() )
1088 OUString aName( pCFormat->GetName() );
1089 AddClassName( aName, aClass );
1090 pParentCFormat = pCFormat;
1092 pCFormat = pDoc->FindCharFormatByName( aName );
1093 if( !pCFormat )
1095 pCFormat = pDoc->MakeCharFormat( aName, pParentCFormat );
1096 pCFormat->SetAuto(false);
1100 if( CSS1_SCRIPT_ALL == nScript && !pParentCFormat )
1102 SetCharFormatAttrs( pCFormat, rItemSet );
1104 else
1106 SfxItemSet aScriptItemSet( rItemSet );
1107 RemoveScriptItems( aScriptItemSet, nScript,
1108 pParentCFormat ? &pParentCFormat->GetAttrSet() : nullptr );
1109 SetCharFormatAttrs( pCFormat, aScriptItemSet );
1114 sal_uInt32 SwCSS1Parser::GetFontHeight( sal_uInt16 nSize ) const
1116 return aFontHeights[ nSize>6 ? 6 : nSize ];
1119 const FontList *SwCSS1Parser::GetFontList() const
1121 const FontList *pFList = nullptr;
1122 SwDocShell *pDocSh = pDoc->GetDocShell();
1123 if( pDocSh )
1125 const SvxFontListItem *pFListItem =
1126 static_cast<const SvxFontListItem *>(pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST));
1127 if( pFListItem )
1128 pFList = pFListItem->GetFontList();
1131 return pFList;
1134 SwCharFormat* SwCSS1Parser::GetChrFormat( sal_uInt16 nToken2, const OUString& rClass ) const
1136 // die entsprechende Vorlage suchen
1137 sal_uInt16 nPoolId = 0;
1138 const sal_Char* sName = nullptr;
1139 switch( nToken2 )
1141 case HTML_EMPHASIS_ON: nPoolId = RES_POOLCHR_HTML_EMPHASIS; break;
1142 case HTML_CITIATION_ON: nPoolId = RES_POOLCHR_HTML_CITIATION; break;
1143 case HTML_STRONG_ON: nPoolId = RES_POOLCHR_HTML_STRONG; break;
1144 case HTML_CODE_ON: nPoolId = RES_POOLCHR_HTML_CODE; break;
1145 case HTML_SAMPLE_ON: nPoolId = RES_POOLCHR_HTML_SAMPLE; break;
1146 case HTML_KEYBOARD_ON: nPoolId = RES_POOLCHR_HTML_KEYBOARD; break;
1147 case HTML_VARIABLE_ON: nPoolId = RES_POOLCHR_HTML_VARIABLE; break;
1148 case HTML_DEFINSTANCE_ON: nPoolId = RES_POOLCHR_HTML_DEFINSTANCE; break;
1149 case HTML_TELETYPE_ON: nPoolId = RES_POOLCHR_HTML_TELETYPE; break;
1151 case HTML_SHORTQUOTE_ON: sName = OOO_STRING_SVTOOLS_HTML_shortquote; break;
1152 case HTML_LANGUAGE_ON: sName = OOO_STRING_SVTOOLS_HTML_language; break;
1153 case HTML_AUTHOR_ON: sName = OOO_STRING_SVTOOLS_HTML_author; break;
1154 case HTML_PERSON_ON: sName = OOO_STRING_SVTOOLS_HTML_person; break;
1155 case HTML_ACRONYM_ON: sName = OOO_STRING_SVTOOLS_HTML_acronym; break;
1156 case HTML_ABBREVIATION_ON: sName = OOO_STRING_SVTOOLS_HTML_abbreviation; break;
1157 case HTML_INSERTEDTEXT_ON: sName = OOO_STRING_SVTOOLS_HTML_insertedtext; break;
1158 case HTML_DELETEDTEXT_ON: sName = OOO_STRING_SVTOOLS_HTML_deletedtext; break;
1161 // die Vorlage suchen oder anlegen (geht nur mit Namen)
1162 if( !nPoolId && !sName )
1163 return nullptr;
1165 // Die Vorlage (ohne Class) suchen oder anlegen
1166 SwCharFormat *pCFormat = nullptr;
1167 if( nPoolId )
1169 pCFormat = GetCharFormatFromPool( nPoolId );
1171 else
1173 OUString sCName( OUString::createFromAscii(sName) );
1174 pCFormat = pDoc->FindCharFormatByName( sCName );
1175 if( !pCFormat )
1177 pCFormat = pDoc->MakeCharFormat( sCName, pDoc->GetDfltCharFormat() );
1178 pCFormat->SetAuto(false);
1182 OSL_ENSURE( pCFormat, "Keine Zeichen-Vorlage???" );
1184 // Wenn es eine Klasse gibt, die Klassen-Vorlage suchen aber nicht
1185 // neu anlegen.
1186 OUString aClass( rClass );
1187 GetScriptFromClass( aClass, false );
1188 if( !aClass.isEmpty() )
1190 OUString aTmp( pCFormat->GetName() );
1191 AddClassName( aTmp, aClass );
1192 SwCharFormat *pClassCFormat = pDoc->FindCharFormatByName( aTmp );
1193 if( pClassCFormat )
1195 pCFormat = pClassCFormat;
1197 else
1199 const SvxCSS1MapEntry *pClass = GetClass( aClass );
1200 if( pClass )
1202 pCFormat = pDoc->MakeCharFormat( aTmp, pCFormat );
1203 pCFormat->SetAuto(false);
1204 SfxItemSet aItemSet( pClass->GetItemSet() );
1205 SetCharFormatAttrs( pCFormat, aItemSet );
1210 return pCFormat;
1213 SwTextFormatColl *SwCSS1Parser::GetTextCollFromPool( sal_uInt16 nPoolId ) const
1215 const SwTextFormatColls::size_type nOldArrLen = pDoc->GetTextFormatColls()->size();
1217 SwTextFormatColl *pColl = pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( nPoolId, false );
1219 if( bIsNewDoc )
1221 const SwTextFormatColls::size_type nArrLen = pDoc->GetTextFormatColls()->size();
1222 for( SwTextFormatColls::size_type i=nOldArrLen; i<nArrLen; ++i )
1223 lcl_swcss1_setEncoding( *(*pDoc->GetTextFormatColls())[i],
1224 GetDfltEncoding() );
1227 return pColl;
1230 SwCharFormat *SwCSS1Parser::GetCharFormatFromPool( sal_uInt16 nPoolId ) const
1232 const SwCharFormats::size_type nOldArrLen = pDoc->GetCharFormats()->size();
1234 SwCharFormat *pCharFormat = pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( nPoolId );
1236 if( bIsNewDoc )
1238 const SwCharFormats::size_type nArrLen = pDoc->GetCharFormats()->size();
1240 for( SwCharFormats::size_type i=nOldArrLen; i<nArrLen; i++ )
1241 lcl_swcss1_setEncoding( *(*pDoc->GetCharFormats())[i],
1242 GetDfltEncoding() );
1245 return pCharFormat;
1248 SwTextFormatColl *SwCSS1Parser::GetTextFormatColl( sal_uInt16 nTextColl,
1249 const OUString& rClass )
1251 SwTextFormatColl* pColl = nullptr;
1253 OUString aClass( rClass );
1254 GetScriptFromClass( aClass, false );
1255 if( RES_POOLCOLL_TEXT == nTextColl && aClass.getLength() >= 9 &&
1256 ('s' == aClass[0] || 'S' == aClass[0] ) )
1258 if( aClass.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdendnote) )
1260 nTextColl = RES_POOLCOLL_ENDNOTE;
1261 aClass = aEmptyOUStr;
1263 else if( aClass.equalsIgnoreAsciiCase(OOO_STRING_SVTOOLS_HTML_sdfootnote) )
1265 nTextColl = RES_POOLCOLL_FOOTNOTE;
1266 aClass = aEmptyOUStr;
1270 if( USER_FMT & nTextColl ) // eine vom Reader angelegte
1272 OSL_ENSURE( false, "Wo kommt die Benutzer-Vorlage her?" );
1273 pColl = GetTextCollFromPool( RES_POOLCOLL_STANDARD );
1275 else
1277 pColl = GetTextCollFromPool( nTextColl );
1280 OSL_ENSURE( pColl, "Keine Absatz-Vorlage???" );
1281 if( !aClass.isEmpty() )
1283 OUString aTmp( pColl->GetName() );
1284 AddClassName( aTmp, aClass );
1285 SwTextFormatColl* pClassColl = pDoc->FindTextFormatCollByName( aTmp );
1287 if( !pClassColl &&
1288 (nTextColl==RES_POOLCOLL_TABLE ||
1289 nTextColl==RES_POOLCOLL_TABLE_HDLN) )
1291 // Wenn dieser Fall eintritt, dann wurde ein <TD><P CLASS=foo>
1292 // gelesen, aber die TD.foo Vorlage nicht gefunden. Dann muessen
1293 // wir P.foo nehmen, wenn es sie gibt.
1294 SwTextFormatColl* pCollText =
1295 GetTextCollFromPool( RES_POOLCOLL_TEXT );
1296 aTmp = pCollText->GetName();
1297 AddClassName( aTmp, aClass );
1298 pClassColl = pDoc->FindTextFormatCollByName( aTmp );
1301 if( pClassColl )
1303 pColl = pClassColl;
1305 else
1307 const SvxCSS1MapEntry *pClass = GetClass( aClass );
1308 if( pClass )
1310 pColl = pDoc->MakeTextFormatColl( aTmp, pColl );
1311 SfxItemSet aItemSet( pClass->GetItemSet() );
1312 SvxCSS1PropertyInfo aPropInfo( pClass->GetPropertyInfo() );
1313 aPropInfo.SetBoxItem( aItemSet, MIN_BORDER_DIST );
1314 bool bPositioned = MayBePositioned( pClass->GetPropertyInfo() );
1315 if( bPositioned )
1316 aItemSet.ClearItem( RES_BACKGROUND );
1317 SetTextCollAttrs( pColl, aItemSet, aPropInfo,
1318 this );
1324 if( pColl )
1325 lcl_swcss1_setEncoding( *pColl, GetDfltEncoding() );
1327 return pColl;
1330 SwPageDesc *SwCSS1Parser::GetMasterPageDesc()
1332 return pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1335 static SwPageDesc *FindPageDesc(SwDoc *pDoc, sal_uInt16 nPoolId)
1337 size_t nPageDescs = pDoc->GetPageDescCnt();
1338 size_t nPage;
1339 for (nPage=0; nPage < nPageDescs &&
1340 pDoc->GetPageDesc(nPage).GetPoolFormatId() != nPoolId; ++nPage)
1343 return nPage < nPageDescs ? &pDoc->GetPageDesc(nPage) : nullptr;
1346 const SwPageDesc *SwCSS1Parser::GetPageDesc( sal_uInt16 nPoolId, bool bCreate )
1348 if( RES_POOLPAGE_HTML == nPoolId )
1349 return pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1351 const SwPageDesc *pPageDesc = FindPageDesc(pDoc, nPoolId);
1352 if( !pPageDesc && bCreate )
1354 // Die erste Seite wird aus der rechten Seite erzeugt, wenn es die
1355 // gibt.
1356 SwPageDesc *pMasterPageDesc = nullptr;
1357 if( RES_POOLPAGE_FIRST == nPoolId )
1358 pMasterPageDesc = FindPageDesc(pDoc, RES_POOLPAGE_RIGHT);
1359 if( !pMasterPageDesc )
1360 pMasterPageDesc = pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1362 // Die neue Seitenvorlage entsteht aus dem Master durch kopieren.
1363 SwPageDesc *pNewPageDesc = pDoc->
1364 getIDocumentStylePoolAccess().GetPageDescFromPool( nPoolId, false );
1366 // dazu brauchen wir auch die Nummer der neuen Vorlage
1367 OSL_ENSURE(pNewPageDesc == FindPageDesc(pDoc, nPoolId), "Seitenvorlage nicht gefunden");
1369 pDoc->CopyPageDesc( *pMasterPageDesc, *pNewPageDesc, false );
1371 // Die Vorlagen an ihren neuen Zweck anpassen.
1372 const SwPageDesc *pFollow = nullptr;
1373 bool bSetFollowFollow = false;
1374 switch( nPoolId )
1376 case RES_POOLPAGE_FIRST:
1377 // Wenn es schon eine linke Seite gibt, dann ist das die
1378 // Folge-Vorlage, sonst ist es die HTML-Vorlage.
1379 pFollow = GetLeftPageDesc();
1380 if( !pFollow )
1381 pFollow = pMasterPageDesc;
1382 break;
1384 case RES_POOLPAGE_RIGHT:
1385 // Wenn die linke Vorlage schon angelegt ist, passiert hier gar
1386 // nichts. Sonst wird die linke Vorlage angelegt und sorgt auch
1387 // fuer die richtige Verkettung mit der rechten Voralge.
1388 GetLeftPageDesc( true );
1389 break;
1391 case RES_POOLPAGE_LEFT:
1392 // Die rechte Vorlage wird angelegt, wenn sie noch nicht existiert.
1393 // Es findet aber keine Verkettung statt.
1394 // Wenn schon eine erste Seitenvorlage existiert, wird die linke
1395 // Vorlage die Folge-Vorlage der ersten Seite.
1396 pFollow = GetRightPageDesc( true );
1397 bSetFollowFollow = true;
1399 const SwPageDesc *pFirstPageDesc = GetFirstPageDesc();
1400 if( pFirstPageDesc )
1402 SwPageDesc aNewFirstPageDesc( *pFirstPageDesc );
1403 aNewFirstPageDesc.SetFollow( pNewPageDesc );
1404 ChgPageDesc( pFirstPageDesc, aNewFirstPageDesc );
1407 break;
1410 if( pFollow )
1412 SwPageDesc aNewPageDesc( *pNewPageDesc );
1413 aNewPageDesc.SetFollow( pFollow );
1414 ChgPageDesc( pNewPageDesc, aNewPageDesc );
1416 if( bSetFollowFollow )
1418 SwPageDesc aNewFollowPageDesc( *pFollow );
1419 aNewFollowPageDesc.SetFollow( pNewPageDesc );
1420 ChgPageDesc( pFollow, aNewFollowPageDesc );
1423 pPageDesc = pNewPageDesc;
1426 return pPageDesc;
1429 bool SwCSS1Parser::MayBePositioned( const SvxCSS1PropertyInfo& rPropInfo,
1430 bool bAutoWidth )
1432 // abs-pos
1433 // left/top none auto twip perc
1435 // none Z Z - -
1436 // auto Z Z - -
1437 // twip Z Z S/R -
1438 // perc - - - -
1440 // - das Tag wird absolut positioniert und left/top sind beide
1441 // gegeben und enthalten auch keine %-Angabe, oder
1442 // - das Tag soll fliessen, und
1443 // - es wurde eine Breite angegeben (in beiden Faellen noetig)
1444 return ( ( SVX_CSS1_POS_ABSOLUTE == rPropInfo.m_ePosition &&
1445 SVX_CSS1_LTYPE_PERCENTAGE != rPropInfo.m_eLeftType &&
1446 SVX_CSS1_LTYPE_PERCENTAGE != rPropInfo.m_eTopType &&
1447 (SVX_CSS1_LTYPE_TWIP == rPropInfo.m_eLeftType ||
1448 SVX_CSS1_LTYPE_TWIP != rPropInfo.m_eTopType) ) ||
1449 ( SVX_ADJUST_END != rPropInfo.m_eFloat ) ) &&
1450 ( bAutoWidth ||
1451 SVX_CSS1_LTYPE_TWIP == rPropInfo.m_eWidthType ||
1452 SVX_CSS1_LTYPE_PERCENTAGE == rPropInfo.m_eWidthType );
1455 void SwCSS1Parser::AddClassName( OUString& rFormatName, const OUString& rClass )
1457 OSL_ENSURE( !rClass.isEmpty(), "Style-Klasse ohne Laenge?" );
1459 rFormatName += "." + rClass;
1462 void SwCSS1Parser::FillDropCap( SwFormatDrop& rDrop,
1463 SfxItemSet& rItemSet,
1464 const OUString *pName )
1466 // die Anzahl der Zeilen entspricht in etwa einer %-Angabe
1467 // fuer die Hoehe (was passiert mit absoluten Hoehen???)
1468 sal_uInt8 nLines = rDrop.GetLines();
1469 const SfxPoolItem *pItem;
1470 if( SfxItemState::SET == rItemSet.GetItemState( RES_CHRATR_FONTSIZE, false, &pItem ) )
1472 sal_uInt16 nProp = static_cast<const SvxFontHeightItem *>(pItem)->GetProp();
1473 nLines = (sal_uInt8)((nProp + 50) / 100);
1474 if( nLines < 1 )
1475 nLines = 1;
1476 else if( nLines > MAX_DROPCAP_LINES )
1477 nLines = MAX_DROPCAP_LINES;
1479 // Nur wenn nLines>1 ist, wird das Attribut auch gesetzt. Dann
1480 // brauchen wir die Font-Hoehe aber auch nicht in der Zeichen-Vorlage.
1481 if( nLines > 1 )
1483 rItemSet.ClearItem( RES_CHRATR_FONTSIZE );
1484 rItemSet.ClearItem( RES_CHRATR_CJK_FONTSIZE );
1485 rItemSet.ClearItem( RES_CHRATR_CTL_FONTSIZE );
1489 // Bei harter Attributierung (pName==0) koennen wir aufhoehren, wenn
1490 // das Initial nur ueber eine Zeile geht.
1491 if( nLines<=1 )
1492 return;
1494 rDrop.GetLines() = nLines;
1496 // ein rechter Rand wird der Abstand zum Text!
1497 if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE, false, &pItem ) )
1499 rDrop.GetDistance() = static_cast< sal_uInt16 >(
1500 static_cast<const SvxLRSpaceItem *>(pItem)->GetRight() );
1501 rItemSet.ClearItem( RES_LR_SPACE );
1504 // Fuer alle anderen Attribute eine Zeichen-Vorlage anlegen
1505 if( rItemSet.Count() )
1507 SwCharFormat *pCFormat = nullptr;
1508 OUString aName;
1509 if( pName )
1511 aName = *pName;
1512 aName += ".FL"; // first letter
1513 pCFormat = pDoc->FindCharFormatByName( aName );
1515 else
1519 aName = "first-letter " + OUString::number( (sal_Int32)(++nDropCapCnt) );
1521 while( pDoc->FindCharFormatByName(aName) );
1524 if( !pCFormat )
1526 pCFormat = pDoc->MakeCharFormat( aName, pDoc->GetDfltCharFormat() );
1527 pCFormat->SetAuto(false);
1529 SetCharFormatAttrs( pCFormat, rItemSet );
1531 // Die Zeichenvorlage braucht nur im Attribut gesetzt werden, wenn
1532 // auch das Attribut gesetzt wird.
1533 if( nLines > 1 )
1534 rDrop.SetCharFormat( pCFormat );
1538 // CSS1-sezifisches des SwHTMLParsers
1540 HTMLAttr **SwHTMLParser::GetAttrTabEntry( sal_uInt16 nWhich )
1542 // den zu dem Item gehoehrenden Tabellen-Eintrag ermitteln ...
1543 HTMLAttr **ppAttr = nullptr;
1544 switch( nWhich )
1546 case RES_CHRATR_BLINK:
1547 ppAttr = &m_aAttrTab.pBlink;
1548 break;
1549 case RES_CHRATR_CASEMAP:
1550 ppAttr = &m_aAttrTab.pCaseMap;
1551 break;
1552 case RES_CHRATR_COLOR:
1553 ppAttr = &m_aAttrTab.pFontColor;
1554 break;
1555 case RES_CHRATR_CROSSEDOUT:
1556 ppAttr = &m_aAttrTab.pStrike;
1557 break;
1558 case RES_CHRATR_ESCAPEMENT:
1559 ppAttr = &m_aAttrTab.pEscapement;
1560 break;
1561 case RES_CHRATR_FONT:
1562 ppAttr = &m_aAttrTab.pFont;
1563 break;
1564 case RES_CHRATR_CJK_FONT:
1565 ppAttr = &m_aAttrTab.pFontCJK;
1566 break;
1567 case RES_CHRATR_CTL_FONT:
1568 ppAttr = &m_aAttrTab.pFontCTL;
1569 break;
1570 case RES_CHRATR_FONTSIZE:
1571 ppAttr = &m_aAttrTab.pFontHeight;
1572 break;
1573 case RES_CHRATR_CJK_FONTSIZE:
1574 ppAttr = &m_aAttrTab.pFontHeightCJK;
1575 break;
1576 case RES_CHRATR_CTL_FONTSIZE:
1577 ppAttr = &m_aAttrTab.pFontHeightCTL;
1578 break;
1579 case RES_CHRATR_KERNING:
1580 ppAttr = &m_aAttrTab.pKerning;
1581 break;
1582 case RES_CHRATR_POSTURE:
1583 ppAttr = &m_aAttrTab.pItalic;
1584 break;
1585 case RES_CHRATR_CJK_POSTURE:
1586 ppAttr = &m_aAttrTab.pItalicCJK;
1587 break;
1588 case RES_CHRATR_CTL_POSTURE:
1589 ppAttr = &m_aAttrTab.pItalicCTL;
1590 break;
1591 case RES_CHRATR_UNDERLINE:
1592 ppAttr = &m_aAttrTab.pUnderline;
1593 break;
1594 case RES_CHRATR_WEIGHT:
1595 ppAttr = &m_aAttrTab.pBold;
1596 break;
1597 case RES_CHRATR_CJK_WEIGHT:
1598 ppAttr = &m_aAttrTab.pBoldCJK;
1599 break;
1600 case RES_CHRATR_CTL_WEIGHT:
1601 ppAttr = &m_aAttrTab.pBoldCTL;
1602 break;
1603 case RES_CHRATR_BACKGROUND:
1604 ppAttr = &m_aAttrTab.pCharBrush;
1605 break;
1606 case RES_CHRATR_BOX:
1607 ppAttr = &m_aAttrTab.pCharBox;
1608 break;
1610 case RES_PARATR_LINESPACING:
1611 ppAttr = &m_aAttrTab.pLineSpacing;
1612 break;
1613 case RES_PARATR_ADJUST:
1614 ppAttr = &m_aAttrTab.pAdjust;
1615 break;
1617 case RES_LR_SPACE:
1618 ppAttr = &m_aAttrTab.pLRSpace;
1619 break;
1620 case RES_UL_SPACE:
1621 ppAttr = &m_aAttrTab.pULSpace;
1622 break;
1623 case RES_BOX:
1624 ppAttr = &m_aAttrTab.pBox;
1625 break;
1626 case RES_BACKGROUND:
1627 ppAttr = &m_aAttrTab.pBrush;
1628 break;
1629 case RES_BREAK:
1630 ppAttr = &m_aAttrTab.pBreak;
1631 break;
1632 case RES_PAGEDESC:
1633 ppAttr = &m_aAttrTab.pPageDesc;
1634 break;
1635 case RES_PARATR_SPLIT:
1636 ppAttr = &m_aAttrTab.pSplit;
1637 break;
1638 case RES_PARATR_WIDOWS:
1639 ppAttr = &m_aAttrTab.pWidows;
1640 break;
1641 case RES_PARATR_ORPHANS:
1642 ppAttr = &m_aAttrTab.pOrphans;
1643 break;
1644 case RES_KEEP:
1645 ppAttr = &m_aAttrTab.pKeep;
1646 break;
1648 case RES_CHRATR_LANGUAGE:
1649 ppAttr = &m_aAttrTab.pLanguage;
1650 break;
1651 case RES_CHRATR_CJK_LANGUAGE:
1652 ppAttr = &m_aAttrTab.pLanguageCJK;
1653 break;
1654 case RES_CHRATR_CTL_LANGUAGE:
1655 ppAttr = &m_aAttrTab.pLanguageCTL;
1656 break;
1658 case RES_FRAMEDIR:
1659 ppAttr = &m_aAttrTab.pDirection;
1660 break;
1663 return ppAttr;
1666 void SwHTMLParser::NewStyle()
1668 OUString sType;
1670 const HTMLOptions& rOptions2 = GetOptions();
1671 for (size_t i = rOptions2.size(); i; )
1673 const HTMLOption& rOption = rOptions2[--i];
1674 if( HTML_O_TYPE == rOption.GetToken() )
1675 sType = rOption.GetString();
1678 m_bIgnoreRawData = sType.getLength() &&
1679 !sType.getToken(0,';').equalsAscii(sCSS_mimetype);
1682 void SwHTMLParser::EndStyle()
1684 m_bIgnoreRawData = false;
1686 if( !m_aStyleSource.isEmpty() )
1688 m_pCSS1Parser->ParseStyleSheet( m_aStyleSource );
1689 m_aStyleSource.clear();
1693 bool SwHTMLParser::FileDownload( const OUString& rURL,
1694 OUString& rStr )
1696 // View wegschmeissen (wegen Reschedule)
1697 SwViewShell *pOldVSh = CallEndAction();
1699 // Ein Medium anlegen
1700 SfxMedium aDLMedium( rURL, StreamMode::READ | StreamMode::SHARE_DENYWRITE );
1702 SvStream* pStream = aDLMedium.GetInStream();
1703 if( pStream )
1705 SvMemoryStream aStream;
1706 aStream.WriteStream( *pStream );
1708 aStream.Seek( STREAM_SEEK_TO_END );
1709 rStr = OUString(static_cast<const sal_Char *>(aStream.GetData()), aStream.Tell(),
1710 GetSrcEncoding());
1713 // wurde abgebrochen?
1714 if( ( m_pDoc->GetDocShell() && m_pDoc->GetDocShell()->IsAbortingImport() )
1715 || 1 == m_pDoc->getReferenceCount() )
1717 // wurde der Import vom SFX abgebrochen?
1718 eState = SVPAR_ERROR;
1719 pStream = nullptr;
1722 // recreate View
1723 SwViewShell *const pVSh = CallStartAction( pOldVSh );
1724 OSL_ENSURE( pOldVSh == pVSh, "FileDownload: SwViewShell changed on us" );
1725 (void) pVSh;
1727 return pStream!=nullptr;
1730 void SwHTMLParser::InsertLink()
1732 bool bFinishDownload = false;
1733 if( m_pPendStack )
1735 OSL_ENSURE( ShouldFinishFileDownload(),
1736 "Pending-Stack ohne File-Download?" );
1738 SwPendingStack* pTmp = m_pPendStack->pNext;
1739 delete m_pPendStack;
1740 m_pPendStack = pTmp;
1741 OSL_ENSURE( !m_pPendStack, "Wo kommt der Pending-Stack her?" );
1743 bFinishDownload = true;
1745 else
1747 OUString sRel, sHRef, sType;
1749 const HTMLOptions& rOptions2 = GetOptions();
1750 for (size_t i = rOptions2.size(); i; )
1752 const HTMLOption& rOption = rOptions2[--i];
1753 switch( rOption.GetToken() )
1755 case HTML_O_REL:
1756 sRel = rOption.GetString();
1757 break;
1758 case HTML_O_HREF:
1759 sHRef = URIHelper::SmartRel2Abs( INetURLObject( m_sBaseURL ), rOption.GetString(), Link<OUString *, bool>(), false );
1760 break;
1761 case HTML_O_TYPE:
1762 sType = rOption.GetString();
1763 break;
1767 if( !sHRef.isEmpty() && sRel.equalsIgnoreAsciiCase( "STYLESHEET" ) &&
1768 ( sType.isEmpty() ||
1769 sType.getToken(0,';').equalsAscii(sCSS_mimetype) ) )
1771 if( GetMedium() )
1773 // Download des Style-Source starten
1774 StartFileDownload(sHRef);
1775 if( IsParserWorking() )
1777 // Der Style wurde synchron geladen und wir koennen
1778 // es direkt aufrufen.
1779 bFinishDownload = true;
1781 else
1783 // Der Style wird asynchron geladen und ist erst beim
1784 // naechsten Continue-Aufruf da. Wir muessen deshalb einen
1785 // Pending-Stack anlegen, damit wir hierher zurueckkehren
1786 m_pPendStack = new SwPendingStack( HTML_LINK, m_pPendStack );
1789 else
1791 // File synchron holen
1792 OUString sSource;
1793 if( FileDownload( sHRef, sSource ) )
1794 m_pCSS1Parser->ParseStyleSheet( sSource );
1799 if( bFinishDownload )
1801 OUString sSource;
1802 if( FinishFileDownload( sSource ) && !sSource.isEmpty() )
1803 m_pCSS1Parser->ParseStyleSheet( sSource );
1807 bool SwCSS1Parser::ParseStyleSheet( const OUString& rIn )
1809 if( !SvxCSS1Parser::ParseStyleSheet( rIn ) )
1810 return false;
1812 SwPageDesc *pMasterPageDesc =
1813 pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1815 SvxCSS1MapEntry *pPageEntry = GetPage( aEmptyOUStr, false );
1816 if( pPageEntry )
1818 // @page (wirkt auf alle Seiten, die es schon gibt
1820 SetPageDescAttrs( pMasterPageDesc, pPageEntry->GetItemSet(),
1821 pPageEntry->GetPropertyInfo() );
1823 // Fuer alle anderen Seiten-Vorlagen, die es schon gibt,
1824 // muessen die Attribute auch noch gesetzt werden
1826 SetPageDescAttrs( GetFirstPageDesc(), pPageEntry->GetItemSet(),
1827 pPageEntry->GetPropertyInfo() );
1828 SetPageDescAttrs( GetLeftPageDesc(), pPageEntry->GetItemSet(),
1829 pPageEntry->GetPropertyInfo() );
1830 SetPageDescAttrs( GetRightPageDesc(), pPageEntry->GetItemSet(),
1831 pPageEntry->GetPropertyInfo() );
1835 pPageEntry = GetPage( "first", true );
1836 if( pPageEntry )
1838 SetPageDescAttrs( GetFirstPageDesc(true), pPageEntry->GetItemSet(),
1839 pPageEntry->GetPropertyInfo() );
1840 bSetFirstPageDesc = true;
1843 pPageEntry = GetPage( "right", true );
1844 if( pPageEntry )
1846 SetPageDescAttrs( GetRightPageDesc(true), pPageEntry->GetItemSet(),
1847 pPageEntry->GetPropertyInfo() );
1848 bSetRightPageDesc = true;
1851 pPageEntry = GetPage( "left", true );
1852 if( pPageEntry )
1853 SetPageDescAttrs( GetLeftPageDesc(true), pPageEntry->GetItemSet(),
1854 pPageEntry->GetPropertyInfo() );
1856 return true;
1859 bool SwHTMLParser::ParseStyleOptions( const OUString &rStyle,
1860 const OUString &rId,
1861 const OUString &rClass,
1862 SfxItemSet &rItemSet,
1863 SvxCSS1PropertyInfo &rPropInfo,
1864 const OUString *pLang,
1865 const OUString *pDir )
1867 bool bRet = false;
1869 if( !rClass.isEmpty() )
1871 OUString aClass( rClass );
1872 SwCSS1Parser::GetScriptFromClass( aClass );
1873 const SvxCSS1MapEntry *pClass = m_pCSS1Parser->GetClass( aClass );
1874 if( pClass )
1876 SvxCSS1Parser::MergeStyles( pClass->GetItemSet(),
1877 pClass->GetPropertyInfo(),
1878 rItemSet, rPropInfo, false );
1879 bRet = true;
1883 if( !rId.isEmpty() )
1885 const SvxCSS1MapEntry *pId = m_pCSS1Parser->GetId( rId );
1886 if( pId )
1887 SvxCSS1Parser::MergeStyles( pId->GetItemSet(),
1888 pId->GetPropertyInfo(),
1889 rItemSet, rPropInfo, !rClass.isEmpty() );
1890 rPropInfo.m_aId = rId;
1891 bRet = true;
1894 if( !rStyle.isEmpty() )
1896 m_pCSS1Parser->ParseStyleOption( rStyle, rItemSet, rPropInfo );
1897 bRet = true;
1900 if( bRet )
1901 rPropInfo.SetBoxItem( rItemSet, MIN_BORDER_DIST );
1903 if( pLang && !pLang->isEmpty() )
1905 LanguageType eLang = LanguageTag::convertToLanguageTypeWithFallback( *pLang );
1906 if( LANGUAGE_DONTKNOW != eLang )
1908 SvxLanguageItem aLang( eLang, RES_CHRATR_LANGUAGE );
1909 rItemSet.Put( aLang );
1910 aLang.SetWhich( RES_CHRATR_CJK_LANGUAGE );
1911 rItemSet.Put( aLang );
1912 aLang.SetWhich( RES_CHRATR_CTL_LANGUAGE );
1913 rItemSet.Put( aLang );
1915 bRet = true;
1918 if( pDir && !pDir->isEmpty() )
1920 OUString aValue( *pDir );
1921 SvxFrameDirection eDir = FRMDIR_ENVIRONMENT;
1922 if (aValue.equalsIgnoreAsciiCase("LTR"))
1923 eDir = FRMDIR_HORI_LEFT_TOP;
1924 else if (aValue.equalsIgnoreAsciiCase("RTL"))
1925 eDir = FRMDIR_HORI_RIGHT_TOP;
1927 if( FRMDIR_ENVIRONMENT != eDir )
1929 SvxFrameDirectionItem aDir( eDir, RES_FRAMEDIR );
1930 rItemSet.Put( aDir );
1932 bRet = true;
1936 return bRet;
1939 void SwHTMLParser::SetAnchorAndAdjustment( const SfxItemSet & /*rItemSet*/,
1940 const SvxCSS1PropertyInfo &rPropInfo,
1941 SfxItemSet &rFrameItemSet )
1943 SwFormatAnchor aAnchor;
1945 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
1946 sal_Int16 eVertOri = text::VertOrientation::NONE;
1947 sal_Int16 eHoriRel = text::RelOrientation::FRAME;
1948 sal_Int16 eVertRel = text::RelOrientation::FRAME;
1949 SwTwips nHoriPos = 0, nVertPos = 0;
1950 SwSurround eSurround = SURROUND_THROUGHT;
1951 if( SVX_CSS1_POS_ABSOLUTE == rPropInfo.m_ePosition )
1953 if( SVX_CSS1_LTYPE_TWIP == rPropInfo.m_eLeftType &&
1954 SVX_CSS1_LTYPE_TWIP == rPropInfo.m_eTopType )
1956 // Absolut positionierte Objekte sind seitengebunden, wenn
1957 // sie nicht schon in einem Rahmen stehen und sonst
1958 // Rahmengebunden.
1959 const SwStartNode *pFlySttNd =
1960 m_pPam->GetPoint()->nNode.GetNode().FindFlyStartNode();
1961 if( pFlySttNd )
1963 aAnchor.SetType( FLY_AT_FLY );
1964 SwPosition aPos( *pFlySttNd );
1965 aAnchor.SetAnchor( &aPos );
1967 else
1969 aAnchor.SetType( FLY_AT_PAGE );
1970 aAnchor.SetPageNum( 1 );
1972 nHoriPos = rPropInfo.m_nLeft;
1973 nVertPos = rPropInfo.m_nTop;
1975 else
1977 aAnchor.SetType( FLY_AT_PARA );
1978 aAnchor.SetAnchor( m_pPam->GetPoint() );
1979 eVertOri = text::VertOrientation::TOP;
1980 eVertRel = text::RelOrientation::CHAR;
1981 if( SVX_CSS1_LTYPE_TWIP == rPropInfo.m_eLeftType )
1983 eHoriOri = text::HoriOrientation::NONE;
1984 eHoriRel = text::RelOrientation::PAGE_FRAME;
1985 nHoriPos = rPropInfo.m_nLeft;
1987 else
1989 eHoriOri = text::HoriOrientation::LEFT;
1990 eHoriRel = text::RelOrientation::FRAME; // wird noch umgeschossen
1994 else
1996 // fliessende Objekte werden Absatzgebunden eingefuegt, wenn
1997 // der Absatz noch leer ist und sonst auto-gebunden.
1998 // Auto-gebundene Rahmen werden zunaechst an der Position davor
1999 // eingefuegt und erst spaeter verschoben.
2000 const sal_Int32 nContent = m_pPam->GetPoint()->nContent.GetIndex();
2001 if( nContent )
2003 aAnchor.SetType( FLY_AT_CHAR );
2004 m_pPam->Move( fnMoveBackward );
2005 eVertOri = text::VertOrientation::CHAR_BOTTOM;
2006 eVertRel = text::RelOrientation::CHAR;
2008 else
2010 aAnchor.SetType( FLY_AT_PARA );
2011 eVertOri = text::VertOrientation::TOP;
2012 eVertRel = text::RelOrientation::PRINT_AREA;
2015 aAnchor.SetAnchor( m_pPam->GetPoint() );
2017 if( nContent )
2018 m_pPam->Move( fnMoveForward );
2020 sal_uInt16 nLeftSpace = 0, nRightSpace = 0;
2021 short nIndent = 0;
2022 GetMarginsFromContextWithNumBul( nLeftSpace, nRightSpace, nIndent );
2024 if( SVX_ADJUST_RIGHT==rPropInfo.m_eFloat )
2026 eHoriOri = text::HoriOrientation::RIGHT;
2027 eHoriRel = nRightSpace ? text::RelOrientation::PRINT_AREA : text::RelOrientation::FRAME;
2028 eSurround = SURROUND_LEFT;
2030 else
2032 eHoriOri = text::HoriOrientation::LEFT;
2033 eHoriRel = nLeftSpace ? text::RelOrientation::PRINT_AREA : text::RelOrientation::FRAME;
2034 eSurround = SURROUND_RIGHT;
2037 rFrameItemSet.Put( aAnchor );
2039 // Absolut Positioniert mit Durchlauf
2040 rFrameItemSet.Put( SwFormatHoriOrient( nHoriPos, eHoriOri, eHoriRel ) );
2041 rFrameItemSet.Put( SwFormatVertOrient( nVertPos, eVertOri, eVertRel ) );
2042 rFrameItemSet.Put( SwFormatSurround( eSurround ) );
2045 void SwHTMLParser::SetVarSize( SfxItemSet & /*rItemSet*/,
2046 SvxCSS1PropertyInfo &rPropInfo,
2047 SfxItemSet &rFrameItemSet,
2048 SwTwips nDfltWidth, sal_uInt8 nDfltPrcWidth )
2050 SwFrameSize eSize = ATT_MIN_SIZE;
2051 SwTwips nWidth = nDfltWidth, nHeight = MINFLY;
2052 sal_uInt8 nPrcWidth = nDfltPrcWidth, nPrcHeight = 0;
2053 switch( rPropInfo.m_eWidthType )
2055 case SVX_CSS1_LTYPE_PERCENTAGE:
2056 nPrcWidth = rPropInfo.m_nWidth > 0 ? (sal_uInt8)rPropInfo.m_nWidth : 1;
2057 nWidth = MINFLY;
2058 break;
2059 case SVX_CSS1_LTYPE_TWIP:
2060 nWidth = rPropInfo.m_nWidth > MINFLY ? rPropInfo.m_nWidth : MINFLY;
2061 nPrcWidth = 0;
2062 break;
2063 default:
2066 switch( rPropInfo.m_eHeightType )
2068 case SVX_CSS1_LTYPE_PERCENTAGE:
2069 nPrcHeight = rPropInfo.m_nHeight > 0 ? (sal_uInt8)rPropInfo.m_nHeight : 1;
2070 break;
2071 case SVX_CSS1_LTYPE_TWIP:
2072 // Netscape und MS-IE interpretieren die Hoehe regelwiedrig
2073 // als Mindest-Hoehe, also machwn wir das auch so.
2074 nHeight = rPropInfo.m_nHeight > MINFLY ? rPropInfo.m_nHeight : MINFLY;
2075 break;
2076 default:
2080 SwFormatFrameSize aFrameSize( eSize, nWidth, nHeight );
2081 aFrameSize.SetWidthPercent( nPrcWidth );
2082 aFrameSize.SetHeightPercent( nPrcHeight );
2083 rFrameItemSet.Put( aFrameSize );
2086 void SwHTMLParser::SetFrameFormatAttrs( SfxItemSet &rItemSet,
2087 SvxCSS1PropertyInfo & /*rPropInfo*/,
2088 HtmlFrameFormatFlags nFlags,
2089 SfxItemSet &rFrameItemSet )
2091 const SfxPoolItem *pItem;
2092 if( (nFlags & HtmlFrameFormatFlags::Box) &&
2093 SfxItemState::SET==rItemSet.GetItemState( RES_BOX, true, &pItem ) )
2095 if( nFlags & HtmlFrameFormatFlags::Padding )
2097 SvxBoxItem aBoxItem( *static_cast<const SvxBoxItem *>(pItem) );
2098 // reset all 4 sides to 0
2099 aBoxItem.SetAllDistances(0);
2100 rFrameItemSet.Put( aBoxItem );
2102 else
2104 rFrameItemSet.Put( *pItem );
2106 rItemSet.ClearItem( RES_BOX );
2109 if( (nFlags & HtmlFrameFormatFlags::Background) &&
2110 SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, true, &pItem ) )
2112 rFrameItemSet.Put( *pItem );
2113 rItemSet.ClearItem( RES_BACKGROUND );
2116 if( (nFlags & HtmlFrameFormatFlags::Direction) &&
2117 SfxItemState::SET==rItemSet.GetItemState( RES_FRAMEDIR, true, &pItem ) )
2119 rFrameItemSet.Put( *pItem );
2120 rItemSet.ClearItem( RES_FRAMEDIR );
2124 HTMLAttrContext *SwHTMLParser::PopContext( sal_uInt16 nToken )
2126 HTMLAttrContexts::size_type nPos = m_aContexts.size();
2127 if( nPos <= m_nContextStMin )
2128 return nullptr;
2130 bool bFound = 0==nToken;
2131 if( nToken )
2133 // Stack-Eintrag zu dem Token suchen
2134 while( nPos > m_nContextStMin )
2136 sal_uInt16 nCntxtToken = m_aContexts[--nPos]->GetToken();
2137 if( nCntxtToken == nToken )
2139 bFound = true;
2140 break;
2142 else if( nCntxtToken == 0 ) // 0 als Token kommt nicht vor
2144 break;
2148 else
2150 nPos--;
2153 HTMLAttrContext *pCntxt = nullptr;
2154 if( bFound )
2156 pCntxt = m_aContexts[nPos];
2157 m_aContexts.erase( m_aContexts.begin() + nPos );
2160 return pCntxt;
2163 bool SwHTMLParser::GetMarginsFromContext( sal_uInt16& nLeft,
2164 sal_uInt16& nRight,
2165 short& nIndent,
2166 bool bIgnoreTopContext ) const
2168 HTMLAttrContexts::size_type nPos = m_aContexts.size();
2169 if( bIgnoreTopContext )
2171 if( !nPos )
2172 return false;
2173 else
2174 nPos--;
2177 while( nPos > m_nContextStAttrMin )
2179 const HTMLAttrContext *pCntxt = m_aContexts[--nPos];
2180 if( pCntxt->IsLRSpaceChanged() )
2182 pCntxt->GetMargins( nLeft, nRight, nIndent );
2183 return true;
2187 return false;
2190 void SwHTMLParser::GetMarginsFromContextWithNumBul( sal_uInt16& nLeft,
2191 sal_uInt16& nRight,
2192 short& nIndent ) const
2194 GetMarginsFromContext( nLeft, nRight, nIndent );
2195 const SwHTMLNumRuleInfo& rInfo = const_cast<SwHTMLParser*>(this)->GetNumInfo();
2196 if( rInfo.GetDepth() )
2198 sal_uInt8 nLevel = (sal_uInt8)( (rInfo.GetDepth() <= MAXLEVEL ? rInfo.GetDepth()
2199 : MAXLEVEL) - 1 );
2200 const SwNumFormat& rNumFormat = rInfo.GetNumRule()->Get(nLevel);
2201 nLeft = nLeft + rNumFormat.GetAbsLSpace();
2202 nIndent = rNumFormat.GetFirstLineOffset();
2206 void SwHTMLParser::GetULSpaceFromContext( sal_uInt16& nUpper,
2207 sal_uInt16& nLower ) const
2209 sal_uInt16 nDfltColl = 0;
2210 OUString aDfltClass;
2212 HTMLAttrContexts::size_type nPos = m_aContexts.size();
2213 while( nPos > m_nContextStAttrMin )
2215 const HTMLAttrContext *pCntxt = m_aContexts[--nPos];
2216 if( pCntxt->IsULSpaceChanged() )
2218 pCntxt->GetULSpace( nUpper, nLower );
2219 return;
2221 else if( !nDfltColl )
2223 nDfltColl = pCntxt->GetDfltTextFormatColl();
2224 if( nDfltColl )
2225 aDfltClass = pCntxt->GetClass();
2229 if( !nDfltColl )
2230 nDfltColl = RES_POOLCOLL_TEXT;
2232 const SwTextFormatColl *pColl =
2233 m_pCSS1Parser->GetTextFormatColl( nDfltColl, aDfltClass );
2234 const SvxULSpaceItem& rULSpace = pColl->GetULSpace();
2235 nUpper = rULSpace.GetUpper();
2236 nLower = rULSpace.GetLower();
2239 void SwHTMLParser::EndContextAttrs( HTMLAttrContext *pContext )
2241 HTMLAttrs &rAttrs = pContext->GetAttrs();
2242 for( auto pAttr : rAttrs )
2244 if( RES_PARATR_DROP==pAttr->GetItem().Which() )
2246 // Fuer DropCaps noch die Anzahl der Zeichen anpassen. Wenn
2247 // es am Ende 0 sind, wird das Attribut invalidiert und dann
2248 // von SetAttr_ gar nicht erst gesetzt.
2249 sal_Int32 nChars = m_pPam->GetPoint()->nContent.GetIndex();
2250 if( nChars < 1 )
2251 pAttr->Invalidate();
2252 else if( nChars > MAX_DROPCAP_CHARS )
2253 nChars = MAX_DROPCAP_CHARS;
2254 static_cast<SwFormatDrop&>(pAttr->GetItem()).GetChars() = (sal_uInt8)nChars;
2257 EndAttr( pAttr );
2261 void SwHTMLParser::InsertParaAttrs( const SfxItemSet& rItemSet )
2263 SfxItemIter aIter( rItemSet );
2265 const SfxPoolItem *pItem = aIter.FirstItem();
2266 while( pItem )
2268 // den zu dem Item gehoehrenden Tabellen-Eintrag ermitteln ...
2269 sal_uInt16 nWhich = pItem->Which();
2270 HTMLAttr **ppAttr = GetAttrTabEntry( nWhich );
2272 if( ppAttr )
2274 NewAttr( ppAttr, *pItem );
2275 if( RES_PARATR_BEGIN > nWhich )
2276 (*ppAttr)->SetLikePara();
2277 m_aParaAttrs.push_back( *ppAttr );
2278 bool bSuccess = EndAttr( *ppAttr, false );
2279 if (!bSuccess)
2280 m_aParaAttrs.pop_back();
2283 pItem = aIter.NextItem();
2287 static void lcl_swcss1_setEncoding( SwFormat& rFormat, rtl_TextEncoding eEnc )
2289 if( RTL_TEXTENCODING_DONTKNOW == eEnc )
2290 return;
2292 const SfxItemSet& rItemSet = rFormat.GetAttrSet();
2293 static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT,
2294 RES_CHRATR_CTL_FONT };
2295 const SfxPoolItem *pItem;
2296 for(sal_uInt16 i : aWhichIds)
2298 if( SfxItemState::SET == rItemSet.GetItemState( i, false,&pItem ) )
2300 const SvxFontItem& rFont = *static_cast<const SvxFontItem *>(pItem);
2301 if( RTL_TEXTENCODING_SYMBOL != rFont.GetCharSet() )
2303 SvxFontItem aFont( rFont.GetFamily(), rFont.GetFamilyName(),
2304 rFont.GetStyleName(), rFont.GetPitch(),
2305 eEnc, i);
2306 rFormat.SetFormatAttr( aFont );
2312 void SwCSS1Parser::SetDfltEncoding( rtl_TextEncoding eEnc )
2314 if( eEnc != GetDfltEncoding() )
2316 if( bIsNewDoc )
2318 // Set new encoding as pool default
2319 static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT,
2320 RES_CHRATR_CTL_FONT };
2321 for(sal_uInt16 i : aWhichIds)
2323 const SvxFontItem& rDfltFont =
2324 static_cast<const SvxFontItem&>(pDoc->GetDefault( i));
2325 SvxFontItem aFont( rDfltFont.GetFamily(),
2326 rDfltFont.GetFamilyName(),
2327 rDfltFont.GetStyleName(),
2328 rDfltFont.GetPitch(),
2329 eEnc, i );
2330 pDoc->SetDefault( aFont );
2333 // Change all paragraph styles that do specify a font.
2334 for( auto pTextFormatColl : *pDoc->GetTextFormatColls() )
2335 lcl_swcss1_setEncoding( *pTextFormatColl, eEnc );
2337 // Change all character styles that do specify a font.
2338 for( auto pCharFormat : *pDoc->GetCharFormats() )
2339 lcl_swcss1_setEncoding( *pCharFormat, eEnc );
2342 SvxCSS1Parser::SetDfltEncoding( eEnc );
2346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */