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 <config_features.h>
22 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
23 #include <com/sun/star/document/XDocumentProperties.hpp>
24 #include <com/sun/star/i18n/ScriptType.hpp>
25 #include <comphelper/string.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <sfx2/sfx.hrc>
28 #include <svx/svxids.hrc>
29 #if OSL_DEBUG_LEVEL > 0
32 #include <hintids.hxx>
34 #include <svl/stritem.hxx>
35 #include <svtools/imap.hxx>
36 #include <svtools/htmltokn.h>
37 #include <svtools/htmlkywd.hxx>
38 #include <svtools/ctrltool.hxx>
39 #include <unotools/pathoptions.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/wrkwin.hxx>
42 #include <sfx2/fcontnr.hxx>
43 #include <sfx2/docfile.hxx>
45 #include <svtools/htmlcfg.hxx>
46 #include <sfx2/linkmgr.hxx>
47 #include <editeng/kernitem.hxx>
48 #include <editeng/boxitem.hxx>
49 #include <editeng/fhgtitem.hxx>
50 #include <editeng/formatbreakitem.hxx>
51 #include <editeng/postitem.hxx>
52 #include <editeng/wghtitem.hxx>
53 #include <editeng/crossedoutitem.hxx>
54 #include <editeng/udlnitem.hxx>
55 #include <editeng/escapementitem.hxx>
56 #include <editeng/blinkitem.hxx>
57 #include <editeng/ulspitem.hxx>
58 #include <editeng/colritem.hxx>
59 #include <editeng/fontitem.hxx>
60 #include <editeng/adjustitem.hxx>
61 #include <editeng/lrspitem.hxx>
62 #include <editeng/protitem.hxx>
63 #include <editeng/flstitem.hxx>
64 #include <svx/unobrushitemhelper.hxx>
67 #include <charatr.hxx>
69 #include <fmtpdsc.hxx>
71 #include <fmtanchr.hxx>
72 #include <fmtsrnd.hxx>
73 #include <fmtfsize.hxx>
74 #include <fmtclds.hxx>
75 #include <fchrfmt.hxx>
76 #include <fmtinfmt.hxx>
77 #include <fmtfollowtextflow.hxx>
79 #include <docstat.hxx>
81 #include <IDocumentUndoRedo.hxx>
82 #include <IDocumentSettingAccess.hxx>
83 #include <IDocumentLayoutAccess.hxx>
84 #include <IDocumentLinksAdministration.hxx>
85 #include <IDocumentRedlineAccess.hxx>
86 #include <IDocumentFieldsAccess.hxx>
87 #include <IDocumentStylePoolAccess.hxx>
88 #include <IDocumentStatistics.hxx>
89 #include <IDocumentState.hxx>
94 #include <poolfmt.hxx>
95 #include <pagedesc.hxx>
99 #include <docufld.hxx>
100 #include <swcss1.hxx>
101 #include <fltini.hxx>
102 #include <htmltbl.hxx>
103 #include <htmlnum.hxx>
104 #include <swhtml.hxx>
105 #include <linkenum.hxx>
106 #include <breakit.hxx>
107 #include <SwAppletImpl.hxx>
109 #include <sfx2/viewfrm.hxx>
111 #include <statstr.hrc>
113 #include <css1atr.hxx>
115 #define FONTSIZE_MASK 7
117 #define HTML_ESC_PROP 80
118 #define HTML_ESC_SUPER DFLT_ESC_SUPER
119 #define HTML_ESC_SUB DFLT_ESC_SUB
121 #define HTML_SPTYPE_BLOCK 1
122 #define HTML_SPTYPE_HORI 2
123 #define HTML_SPTYPE_VERT 3
125 using editeng::SvxBorderLine
;
126 using namespace ::com::sun::star
;
128 // <P ALIGN=xxx>, <Hn ALIGN=xxx>, <TD ALIGN=xxx> usw.
129 HTMLOptionEnum aHTMLPAlignTable
[] =
131 { OOO_STRING_SVTOOLS_HTML_AL_left
, SVX_ADJUST_LEFT
},
132 { OOO_STRING_SVTOOLS_HTML_AL_center
, SVX_ADJUST_CENTER
},
133 { OOO_STRING_SVTOOLS_HTML_AL_middle
, SVX_ADJUST_CENTER
}, // Netscape
134 { OOO_STRING_SVTOOLS_HTML_AL_right
, SVX_ADJUST_RIGHT
},
135 { OOO_STRING_SVTOOLS_HTML_AL_justify
, SVX_ADJUST_BLOCK
},
136 { OOO_STRING_SVTOOLS_HTML_AL_char
, SVX_ADJUST_LEFT
},
141 static HTMLOptionEnum aHTMLSpacerTypeTable
[] =
143 { OOO_STRING_SVTOOLS_HTML_SPTYPE_block
, HTML_SPTYPE_BLOCK
},
144 { OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal
, HTML_SPTYPE_HORI
},
145 { OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical
, HTML_SPTYPE_VERT
},
149 HTMLReader::HTMLReader()
151 bTmplBrowseMode
= true;
154 OUString
HTMLReader::GetTemplateName() const
156 const OUString
sTemplateWithoutExt("internal/html");
157 SvtPathOptions aPathOpt
;
159 // first search for OpenDocument Writer/Web template
160 // OpenDocument Writer/Web template (extension .oth)
161 OUString
sTemplate( sTemplateWithoutExt
+ ".oth" );
162 if (aPathOpt
.SearchFile( sTemplate
, SvtPathOptions::PATH_TEMPLATE
))
165 // no OpenDocument Writer/Web template found.
166 // search for OpenOffice.org Writer/Web template
167 sTemplate
= sTemplateWithoutExt
+ ".stw";
168 if (aPathOpt
.SearchFile( sTemplate
, SvtPathOptions::PATH_TEMPLATE
))
171 OSL_ENSURE( false, "The default HTML template cannot be found in the defined template directories!");
176 bool HTMLReader::SetStrmStgPtr()
178 OSL_ENSURE( pMedium
, "Wo ist das Medium??" );
180 if( pMedium
->IsRemote() || !pMedium
->IsStorage() )
182 pStrm
= pMedium
->GetInStream();
189 // Aufruf fuer die allg. Reader-Schnittstelle
190 sal_uLong
HTMLReader::Read( SwDoc
&rDoc
, const OUString
& rBaseURL
, SwPaM
&rPam
, const OUString
& rName
)
194 OSL_ENSURE( pStrm
, "HTML-Read ohne Stream" );
195 return ERR_SWG_READ_ERROR
;
200 Reader::ResetFrameFormats( rDoc
);
202 // Die HTML-Seitenvorlage setzen, wenn des kein HTML-Dokument ist,
203 // sonst ist sie schon gesetzt.
204 if( !rDoc
.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE
) )
206 rDoc
.getIDocumentContentOperations().InsertPoolItem( rPam
, SwFormatPageDesc(
207 rDoc
.getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML
, false )) );
211 // damit keiner das Doc klaut!
214 tools::SvRef
<SvParser
> xParser
= new SwHTMLParser( &rDoc
, rPam
, *pStrm
,
215 rName
, rBaseURL
, !bInsertMode
, pMedium
,
217 bIgnoreHTMLComments
);
219 SvParserState eState
= xParser
->CallParser();
221 if( SVPAR_PENDING
== eState
)
223 else if( SVPAR_ACCEPTED
!= eState
)
225 const OUString
sErr(OUString::number((sal_Int32
)xParser
->GetLineNr())
226 + "," + OUString::number((sal_Int32
)xParser
->GetLinePos()));
228 // den Stream als Fehlernummer Transporter benutzen
229 nRet
= *new StringErrorInfo( ERR_FORMAT_ROWCOL
, sErr
,
230 ERRCODE_BUTTON_OK
| ERRCODE_MSG_ERROR
);
236 SwHTMLParser::SwHTMLParser( SwDoc
* pD
, SwPaM
& rCursor
, SvStream
& rIn
,
237 const OUString
& rPath
,
238 const OUString
& rBaseURL
,
240 SfxMedium
* pMed
, bool bReadUTF8
,
241 bool bNoHTMLComments
)
242 : SfxHTMLParser( rIn
, bReadNewDoc
, pMed
),
244 m_aPathToFile( rPath
),
245 m_sBaseURL( rBaseURL
),
246 m_pAppletImpl( nullptr ),
247 m_pCSS1Parser( nullptr ),
248 m_pNumRuleInfo( new SwHTMLNumRuleInfo
),
249 m_pPendStack( nullptr ),
251 m_pActionViewShell( nullptr ),
252 m_pSttNdIdx( nullptr ),
254 m_pFormImpl( nullptr ),
255 m_pMarquee( nullptr ),
257 m_pImageMap( nullptr ),
258 m_pImageMaps(nullptr),
259 m_pFootEndNoteImpl( nullptr ),
260 m_nScriptStartLineNr( 0 ),
261 m_nBaseFontStMin( 0 ),
264 m_nFontStHeadStart( 0 ),
266 m_nMissingImgMaps( 0 ),
269 m_nContextStMin( 0 ),
270 m_nContextStAttrMin( 0 ),
271 m_nSelectEntryCnt( 0 ),
272 m_nOpenParaToken( 0 ),
273 m_eJumpTo( JUMPTO_NONE
),
277 m_eParaAdjust( SVX_ADJUST_END
),
278 m_bDocInitalized( false ),
279 m_bSetModEnabled( false ),
280 m_bInFloatingFrame( false ),
282 m_bCallNextToken( false ),
283 m_bIgnoreRawData( false ),
284 m_bLBEntrySelected ( false ),
285 m_bTAIgnoreNewPara ( false ),
286 m_bFixMarqueeWidth ( false ),
287 m_bNoParSpace( false ),
288 m_bInNoEmbed( false ),
290 m_bUpdateDocStat( false ),
291 m_bFixSelectWidth( false ),
292 m_bFixSelectHeight( false ),
293 m_bTextArea( false ),
295 m_bInFootEndNoteAnchor( false ),
296 m_bInFootEndNoteSymbol( false ),
297 m_bIgnoreHTMLComments( bNoHTMLComments
),
298 m_bRemoveHidden( false ),
299 m_isInTableStructure(false),
300 m_pTempViewFrame(nullptr)
302 m_nEventId
= nullptr;
303 m_bUpperSpace
= m_bViewCreated
= m_bChkJumpMark
= false;
305 m_eScriptLang
= HTML_SL_UNKNOWN
;
307 rCursor
.DeleteMark();
308 m_pPam
= &rCursor
; // re-use existing cursor: avoids spurious ~SwIndexReg assert
309 memset( &m_aAttrTab
, 0, sizeof( HTMLAttrTable
));
311 // Die Font-Groessen 1-7 aus der INI-Datei lesen
312 SvxHtmlOptions
& rHtmlOptions
= SvxHtmlOptions::Get();
313 m_aFontHeights
[0] = rHtmlOptions
.GetFontSize( 0 ) * 20;
314 m_aFontHeights
[1] = rHtmlOptions
.GetFontSize( 1 ) * 20;
315 m_aFontHeights
[2] = rHtmlOptions
.GetFontSize( 2 ) * 20;
316 m_aFontHeights
[3] = rHtmlOptions
.GetFontSize( 3 ) * 20;
317 m_aFontHeights
[4] = rHtmlOptions
.GetFontSize( 4 ) * 20;
318 m_aFontHeights
[5] = rHtmlOptions
.GetFontSize( 5 ) * 20;
319 m_aFontHeights
[6] = rHtmlOptions
.GetFontSize( 6 ) * 20;
321 m_bKeepUnknown
= rHtmlOptions
.IsImportUnknown();
325 //CJK has different defaults, so a different object should be used for this
326 //RES_CHARTR_CJK_FONTSIZE is a valid value
327 SvxFontHeightItem
aFontHeight(m_aFontHeights
[2], 100, RES_CHRATR_FONTSIZE
);
328 m_pDoc
->SetDefault( aFontHeight
);
329 SvxFontHeightItem
aFontHeightCJK(m_aFontHeights
[2], 100, RES_CHRATR_CJK_FONTSIZE
);
330 m_pDoc
->SetDefault( aFontHeightCJK
);
331 SvxFontHeightItem
aFontHeightCTL(m_aFontHeights
[2], 100, RES_CHRATR_CTL_FONTSIZE
);
332 m_pDoc
->SetDefault( aFontHeightCTL
);
334 // #i18732# - adjust default of option 'FollowTextFlow'
335 // TODO: not sure what the appropriate default for HTML should be?
336 m_pDoc
->SetDefault( SwFormatFollowTextFlow(true) );
339 // Waehrend des Imports in den HTML-Modus schalten, damit die
340 // richrigen Vorlagen angelegt werden
341 m_bOldIsHTMLMode
= m_pDoc
->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE
);
342 m_pDoc
->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE
, true);
344 m_pCSS1Parser
= new SwCSS1Parser( m_pDoc
, m_aFontHeights
, m_sBaseURL
, IsNewDoc() );
345 m_pCSS1Parser
->SetIgnoreFontFamily( rHtmlOptions
.IsIgnoreFontFamily() );
349 SetSrcEncoding( RTL_TEXTENCODING_UTF8
);
353 SwDocShell
*pDocSh
= m_pDoc
->GetDocShell();
354 SvKeyValueIterator
*pHeaderAttrs
=
355 pDocSh
->GetHeaderAttributes();
357 SetEncodingByHTTPHeader( pHeaderAttrs
);
359 m_pCSS1Parser
->SetDfltEncoding( osl_getThreadTextEncoding() );
361 // Timer nur bei ganz normalen Dokumenten aufsetzen!
362 SwDocShell
* pDocSh
= m_pDoc
->GetDocShell();
365 m_bViewCreated
= true; // nicht, synchron laden
367 // es ist ein Sprungziel vorgegeben.
371 m_sJmpMark
= pMed
->GetURLObject().GetMark();
372 if( !m_sJmpMark
.isEmpty() )
374 m_eJumpTo
= JUMPTO_MARK
;
375 sal_Int32 nLastPos
= m_sJmpMark
.lastIndexOf( cMarkSeparator
);
376 sal_Int32 nPos
= nLastPos
!= -1 ? nLastPos
: 0;
381 sCmp
= m_sJmpMark
.copy(nPos
+ 1).replaceAll(" ", "");
384 if( !sCmp
.isEmpty() )
386 sCmp
= sCmp
.toAsciiLowerCase();
387 if( sCmp
== "region" )
388 m_eJumpTo
= JUMPTO_REGION
;
389 else if( sCmp
== "table" )
390 m_eJumpTo
= JUMPTO_TABLE
;
391 else if( sCmp
== "graphic" )
392 m_eJumpTo
= JUMPTO_GRAPHIC
;
393 else if( sCmp
== "outline" ||
396 m_eJumpTo
= JUMPTO_NONE
; // das ist nichts gueltiges!
398 // ansonsten ist das ein normaler (Book)Mark
405 m_sJmpMark
= m_sJmpMark
.copy( 0, nPos
);
406 if( m_sJmpMark
.isEmpty() )
407 m_eJumpTo
= JUMPTO_NONE
;
413 SwHTMLParser::~SwHTMLParser()
416 OSL_ENSURE( !m_nContinue
, "DTOR im Continue!" );
418 bool bAsync
= m_pDoc
->IsInLoadAsynchron();
419 m_pDoc
->SetInLoadAsynchron( false );
420 m_pDoc
->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE
, m_bOldIsHTMLMode
);
422 if( m_pDoc
->GetDocShell() && m_nEventId
)
423 Application::RemoveUserEvent( m_nEventId
);
425 // das DocumentDetected kann ggfs. die DocShells loeschen, darum nochmals
427 if( m_pDoc
->GetDocShell() )
429 // Gelinkte Bereiche updaten
430 sal_uInt16 nLinkMode
= m_pDoc
->getIDocumentSettingAccess().getLinkUpdateMode( true );
431 if( nLinkMode
!= NEVER
&& bAsync
&&
432 SfxObjectCreateMode::INTERNAL
!=m_pDoc
->GetDocShell()->GetCreateMode() )
433 m_pDoc
->getIDocumentLinksAdministration().GetLinkManager().UpdateAllLinks( nLinkMode
== MANUAL
);
435 if ( m_pDoc
->GetDocShell()->IsLoading() )
438 m_pDoc
->GetDocShell()->LoadingFinished();
444 if( !m_aSetAttrTab
.empty() )
446 OSL_ENSURE( m_aSetAttrTab
.empty(),"Es stehen noch Attribute auf dem Stack" );
447 for ( HTMLAttrs::const_iterator it
= m_aSetAttrTab
.begin();
448 it
!= m_aSetAttrTab
.end(); ++it
)
450 m_aSetAttrTab
.clear();
453 delete m_pCSS1Parser
;
454 delete m_pNumRuleInfo
;
456 DeleteFootEndNoteImpl();
458 OSL_ENSURE( !m_pTable
, "Es existiert noch eine offene Tabelle" );
461 OSL_ENSURE( !m_pPendStack
,
462 "SwHTMLParser::~SwHTMLParser: Hier sollte es keinen Pending-Stack mehr geben" );
463 while( m_pPendStack
)
465 SwPendingStack
* pTmp
= m_pPendStack
;
466 m_pPendStack
= m_pPendStack
->pNext
;
471 if( !m_pDoc
->release() )
473 // keiner will mehr das Doc haben, also weg damit
478 if ( m_pTempViewFrame
)
480 m_pTempViewFrame
->DoClose();
482 // the temporary view frame is hidden, so the hidden flag might need to be removed
483 if ( m_bRemoveHidden
&& m_pDoc
&& m_pDoc
->GetDocShell() && m_pDoc
->GetDocShell()->GetMedium() )
484 m_pDoc
->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN
);
488 IMPL_LINK_NOARG( SwHTMLParser
, AsyncCallback
, void*, void )
492 // #i47907# - If the document has already been destructed,
493 // the parser should be aware of this:
494 if( ( m_pDoc
->GetDocShell() && m_pDoc
->GetDocShell()->IsAbortingImport() )
495 || 1 == m_pDoc
->getReferenceCount() )
497 // wurde der Import vom SFX abgebrochen?
498 eState
= SVPAR_ERROR
;
501 GetAsynchCallLink().Call(nullptr);
504 SvParserState
SwHTMLParser::CallParser()
506 // einen temporaeren Index anlegen, auf Pos 0 so wird er nicht bewegt!
507 m_pSttNdIdx
= new SwNodeIndex( m_pDoc
->GetNodes() );
508 if( !IsNewDoc() ) // in ein Dokument einfuegen ?
510 const SwPosition
* pPos
= m_pPam
->GetPoint();
512 m_pDoc
->getIDocumentContentOperations().SplitNode( *pPos
, false );
514 *m_pSttNdIdx
= pPos
->nNode
.GetIndex()-1;
515 m_pDoc
->getIDocumentContentOperations().SplitNode( *pPos
, false );
517 SwPaM
aInsertionRangePam( *pPos
);
519 m_pPam
->Move( fnMoveBackward
);
521 // split any redline over the insertion point
522 aInsertionRangePam
.SetMark();
523 *aInsertionRangePam
.GetPoint() = *m_pPam
->GetPoint();
524 aInsertionRangePam
.Move( fnMoveBackward
);
525 m_pDoc
->getIDocumentRedlineAccess().SplitRedline( aInsertionRangePam
);
527 m_pDoc
->SetTextFormatColl( *m_pPam
,
528 m_pCSS1Parser
->GetTextCollFromPool( RES_POOLCOLL_STANDARD
));
533 if( !m_bViewCreated
)
535 m_nEventId
= Application::PostUserEvent( LINK( this, SwHTMLParser
, AsyncCallback
) );
539 m_bViewCreated
= true;
540 m_nEventId
= nullptr;
544 // Laufbalken anzeigen
545 else if( !GetMedium() || !GetMedium()->IsRemote() )
547 rInput
.Seek(STREAM_SEEK_TO_END
);
549 ::StartProgress( STR_STATSTR_W4WREAD
, 0, rInput
.Tell(),
550 m_pDoc
->GetDocShell() );
551 rInput
.Seek(STREAM_SEEK_TO_BEGIN
);
555 m_pDoc
->GetPageDesc( 0 ).Add( this );
557 SvParserState eRet
= HTMLParser::CallParser();
561 void SwHTMLParser::Continue( int nToken
)
564 OSL_ENSURE(!m_nContinue
, "Continue im Continue - not supposed to happen");
568 // Wenn der Import (vom SFX) abgebrochen wurde, wird ein Fehler
569 // gesetzt aber trotzdem noch weiter gemacht, damit vernuenftig
571 OSL_ENSURE( SVPAR_ERROR
!=eState
,
572 "SwHTMLParser::Continue: bereits ein Fehler gesetzt" );
573 if( m_pDoc
->GetDocShell() && m_pDoc
->GetDocShell()->IsAbortingImport() )
574 eState
= SVPAR_ERROR
;
576 // Die SwViewShell vom Dokument holen, merken und als aktuelle setzen.
577 SwViewShell
*pInitVSh
= CallStartAction();
579 if( SVPAR_ERROR
!= eState
&& GetMedium() && !m_bViewCreated
)
581 // Beim ersten Aufruf erstmal returnen, Doc anzeigen
582 // und auf Timer Callback warten.
583 // An dieser Stelle wurde im CallParser gerade mal ein Zeichen
584 // gelesen und ein SaveState(0) gerufen.
585 eState
= SVPAR_PENDING
;
586 m_bViewCreated
= true;
587 m_pDoc
->SetInLoadAsynchron( true );
596 m_bSetModEnabled
= false;
597 if( m_pDoc
->GetDocShell() &&
598 (m_bSetModEnabled
= m_pDoc
->GetDocShell()->IsEnableSetModified()) )
600 m_pDoc
->GetDocShell()->EnableSetModified( false );
603 // waehrend des einlesens kein OLE-Modified rufen
604 Link
<bool,void> aOLELink( m_pDoc
->GetOle2Link() );
605 m_pDoc
->SetOle2Link( Link
<bool,void>() );
607 bool bModified
= m_pDoc
->getIDocumentState().IsModified();
608 bool const bWasUndo
= m_pDoc
->GetIDocumentUndoRedo().DoesUndo();
609 m_pDoc
->GetIDocumentUndoRedo().DoUndo(false);
611 // Wenn der Import abgebrochen wird, kein Continue mehr rufen.
612 // Falls ein Pending-Stack existiert aber durch einen Aufruf
613 // von NextToken dafuer sorgen, dass der Pending-Stack noch
615 if( SVPAR_ERROR
== eState
)
617 OSL_ENSURE( !m_pPendStack
|| m_pPendStack
->nToken
,
618 "SwHTMLParser::Continue: Pending-Stack ohne Token" );
619 if( m_pPendStack
&& m_pPendStack
->nToken
)
620 NextToken( m_pPendStack
->nToken
);
621 OSL_ENSURE( !m_pPendStack
,
622 "SwHTMLParser::Continue: Es gibt wieder einen Pend-Stack" );
626 HTMLParser::Continue( m_pPendStack
? m_pPendStack
->nToken
: nToken
);
629 // Laufbalken wieder abschalten
630 EndProgress( m_pDoc
->GetDocShell() );
632 bool bLFStripped
= false;
633 if( SVPAR_PENDING
!= GetStatus() )
635 // noch die letzten Attribute setzen
637 if( !m_aScriptSource
.isEmpty() )
639 SwScriptFieldType
*pType
=
640 static_cast<SwScriptFieldType
*>(m_pDoc
->getIDocumentFieldsAccess().GetSysFieldType( RES_SCRIPTFLD
));
642 SwScriptField
aField( pType
, m_aScriptType
, m_aScriptSource
,
644 InsertAttr( SwFormatField( aField
), false );
649 if( m_pAppletImpl
->GetApplet().is() )
655 // ggf. ein noch vorhandes LF hinter dem letzen Absatz entfernen
657 bLFStripped
= StripTrailingLF() > 0;
659 // noch offene Nummerierungen beenden.
660 while( GetNumInfo().GetNumRule() )
663 OSL_ENSURE( !m_nContextStMin
, "Es gibt geschuetzte Kontexte" );
665 while( m_aContexts
.size() )
667 HTMLAttrContext
*pCntxt
= PopContext();
670 EndContext( pCntxt
);
675 if( !m_aParaAttrs
.empty() )
676 m_aParaAttrs
.clear();
680 // Noch die erst verzoegert gesetzten Styles setzen
681 m_pCSS1Parser
->SetDelayedStyles();
684 // den Start wieder korrigieren
685 if( !IsNewDoc() && m_pSttNdIdx
->GetIndex() )
687 SwTextNode
* pTextNode
= m_pSttNdIdx
->GetNode().GetTextNode();
688 SwNodeIndex
aNxtIdx( *m_pSttNdIdx
);
689 if( pTextNode
&& pTextNode
->CanJoinNext( &aNxtIdx
))
691 const sal_Int32 nStt
= pTextNode
->GetText().getLength();
692 // wenn der Cursor noch in dem Node steht, dann setze in an das Ende
693 if( m_pPam
->GetPoint()->nNode
== aNxtIdx
)
695 m_pPam
->GetPoint()->nNode
= *m_pSttNdIdx
;
696 m_pPam
->GetPoint()->nContent
.Assign( pTextNode
, nStt
);
699 #if OSL_DEBUG_LEVEL > 0
700 // !!! sollte nicht moeglich sein, oder ??
701 OSL_ENSURE( m_pSttNdIdx
->GetIndex()+1 != m_pPam
->GetBound().nNode
.GetIndex(),
702 "Pam.Bound1 steht noch im Node" );
703 OSL_ENSURE( m_pSttNdIdx
->GetIndex()+1 != m_pPam
->GetBound( false ).nNode
.GetIndex(),
704 "Pam.Bound2 steht noch im Node" );
706 if( m_pSttNdIdx
->GetIndex()+1 == m_pPam
->GetBound().nNode
.GetIndex() )
708 const sal_Int32 nCntPos
= m_pPam
->GetBound().nContent
.GetIndex();
709 m_pPam
->GetBound().nContent
.Assign( pTextNode
,
710 pTextNode
->GetText().getLength() + nCntPos
);
712 if( m_pSttNdIdx
->GetIndex()+1 == m_pPam
->GetBound( false ).nNode
.GetIndex() )
714 const sal_Int32 nCntPos
= m_pPam
->GetBound( false ).nContent
.GetIndex();
715 m_pPam
->GetBound( false ).nContent
.Assign( pTextNode
,
716 pTextNode
->GetText().getLength() + nCntPos
);
719 // Zeichen Attribute beibehalten!
720 SwTextNode
* pDelNd
= aNxtIdx
.GetNode().GetTextNode();
721 if (pTextNode
->GetText().getLength())
722 pDelNd
->FormatToTextAttr( pTextNode
);
724 pTextNode
->ChgFormatColl( pDelNd
->GetTextColl() );
725 pTextNode
->JoinNext();
730 if( SVPAR_ACCEPTED
== eState
)
732 if( m_nMissingImgMaps
)
734 // es fehlen noch ein paar Image-Map zuordungen.
735 // vielleicht sind die Image-Maps ja jetzt da?
739 // jetzt noch den letzten ueberfluessigen Absatz loeschen
740 SwPosition
* pPos
= m_pPam
->GetPoint();
741 if( !pPos
->nContent
.GetIndex() && !bLFStripped
)
744 sal_uLong nNodeIdx
= pPos
->nNode
.GetIndex();
746 bool bHasFlysOrMarks
=
747 HasCurrentParaFlys() || HasCurrentParaBookmarks( true );
751 const SwNode
*pPrev
= m_pDoc
->GetNodes()[nNodeIdx
-1];
752 if( !m_pPam
->GetPoint()->nContent
.GetIndex() &&
753 ( pPrev
->IsContentNode() ||
754 (pPrev
->IsEndNode() &&
755 pPrev
->StartOfSectionNode()->IsSectionNode()) ) )
757 SwContentNode
* pCNd
= m_pPam
->GetContentNode();
758 if( pCNd
&& pCNd
->StartOfSectionIndex()+2 <
759 pCNd
->EndOfSectionIndex() && !bHasFlysOrMarks
)
761 SwViewShell
*pVSh
= CheckActionViewShell();
762 SwCursorShell
*pCursorSh
= pVSh
&& dynamic_cast< const SwCursorShell
*>( pVSh
) != nullptr
763 ? static_cast < SwCursorShell
* >( pVSh
)
766 pCursorSh
->GetCursor()->GetPoint()
767 ->nNode
.GetIndex() == nNodeIdx
)
769 pCursorSh
->MovePara(GoPrevPara
, fnParaEnd
);
770 pCursorSh
->SetMark();
771 pCursorSh
->ClearMark();
773 m_pPam
->GetBound().nContent
.Assign( nullptr, 0 );
774 m_pPam
->GetBound(false).nContent
.Assign( nullptr, 0 );
775 m_pDoc
->GetNodes().Delete( m_pPam
->GetPoint()->nNode
);
779 else if( nullptr != ( pAktNd
= m_pDoc
->GetNodes()[ nNodeIdx
]->GetTextNode()) && !bHasFlysOrMarks
)
781 if( pAktNd
->CanJoinNext( &pPos
->nNode
))
783 SwTextNode
* pNextNd
= pPos
->nNode
.GetNode().GetTextNode();
784 pPos
->nContent
.Assign( pNextNd
, 0 );
785 m_pPam
->SetMark(); m_pPam
->DeleteMark();
788 else if (pAktNd
->GetText().isEmpty())
790 pPos
->nContent
.Assign( nullptr, 0 );
791 m_pPam
->SetMark(); m_pPam
->DeleteMark();
792 m_pDoc
->GetNodes().Delete( pPos
->nNode
);
793 m_pPam
->Move( fnMoveBackward
);
798 // nun noch das SplitNode vom Anfang aufheben
799 else if( !IsNewDoc() )
801 if( pPos
->nContent
.GetIndex() ) // dann gabs am Ende kein <P>,
802 m_pPam
->Move( fnMoveForward
, GoInNode
); // als zum naechsten Node
803 SwTextNode
* pTextNode
= pPos
->nNode
.GetNode().GetTextNode();
804 SwNodeIndex
aPrvIdx( pPos
->nNode
);
805 if( pTextNode
&& pTextNode
->CanJoinPrev( &aPrvIdx
) &&
806 *m_pSttNdIdx
<= aPrvIdx
)
808 // eigentlich muss hier ein JoinNext erfolgen, aber alle Cursor
809 // usw. sind im pTextNode angemeldet, so dass der bestehen
812 // Absatz in Zeichen-Attribute umwandeln, aus dem Prev die
813 // Absatzattribute und die Vorlage uebernehmen!
814 SwTextNode
* pPrev
= aPrvIdx
.GetNode().GetTextNode();
815 pTextNode
->ChgFormatColl( pPrev
->GetTextColl() );
816 pTextNode
->FormatToTextAttr( pPrev
);
817 pTextNode
->ResetAllAttr();
819 if( pPrev
->HasSwAttrSet() )
820 pTextNode
->SetAttr( *pPrev
->GetpSwAttrSet() );
822 if( &m_pPam
->GetBound().nNode
.GetNode() == pPrev
)
823 m_pPam
->GetBound().nContent
.Assign( pTextNode
, 0 );
824 if( &m_pPam
->GetBound(false).nNode
.GetNode() == pPrev
)
825 m_pPam
->GetBound(false).nContent
.Assign( pTextNode
, 0 );
827 pTextNode
->JoinPrev();
831 // adjust AutoLoad in DocumentProperties
834 SwDocShell
*pDocShell(m_pDoc
->GetDocShell());
835 OSL_ENSURE(pDocShell
, "no SwDocShell");
837 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
838 pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
839 uno::Reference
<document::XDocumentProperties
> xDocProps(
840 xDPS
->getDocumentProperties());
841 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
842 if ( xDocProps
.is() && (xDocProps
->getAutoloadSecs() > 0) &&
843 (xDocProps
->getAutoloadURL().isEmpty()) )
845 xDocProps
->setAutoloadURL(m_aPathToFile
);
850 if( m_bUpdateDocStat
)
852 m_pDoc
->getIDocumentStatistics().UpdateDocStat( false, true );
856 if( SVPAR_PENDING
!= GetStatus() )
859 m_pSttNdIdx
= nullptr;
862 // sollte der Parser der Letzte sein, der das Doc haelt, dann braucht
863 // man hier auch nichts mehr tun, Doc wird gleich zerstoert!
864 if( 1 < m_pDoc
->getReferenceCount() )
868 m_pDoc
->GetIDocumentUndoRedo().DelAllUndoObj();
869 m_pDoc
->GetIDocumentUndoRedo().DoUndo(true);
873 // Wenn zu Beginn des Continue keine Shell vorhanden war,
874 // kann trotzdem mitlerweile eine angelegt worden sein.
875 // In dieses Fall stimmt das bWasUndo-Flag nicht und
876 // wir muessen das Undo noch anschalten.
877 SwViewShell
*pTmpVSh
= CheckActionViewShell();
880 m_pDoc
->GetIDocumentUndoRedo().DoUndo(true);
884 m_pDoc
->SetOle2Link( aOLELink
);
886 m_pDoc
->getIDocumentState().ResetModified();
887 if( m_bSetModEnabled
&& m_pDoc
->GetDocShell() )
889 m_pDoc
->GetDocShell()->EnableSetModified();
890 m_bSetModEnabled
= false; // this is unnecessary here
894 // Wenn die Dokuemnt-SwViewShell noch existiert und eine Action
895 // offen ist (muss bei Abbruch nicht sein), die Action beenden,
896 // uns von der Shell abmelden und schliesslich die alte Shell
897 // wieder rekonstruieren.
898 CallEndAction( true );
905 void SwHTMLParser::Modify( const SfxPoolItem
* pOld
, const SfxPoolItem
*pNew
)
907 switch( pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0 )
909 case RES_OBJECTDYING
:
910 if (pOld
&& static_cast<const SwPtrMsgPoolItem
*>(pOld
)->pObject
== GetRegisteredIn())
912 // dann uns selbst beenden
913 GetRegisteredInNonConst()->Remove( this );
914 ReleaseRef(); // ansonsten sind wir fertig!
920 void SwHTMLParser::DocumentDetected()
922 OSL_ENSURE( !m_bDocInitalized
, "DocumentDetected mehrfach aufgerufen" );
923 m_bDocInitalized
= true;
927 FinishHeader( true );
929 CallEndAction( true );
931 m_pDoc
->GetIDocumentUndoRedo().DoUndo(false);
932 // Durch das DocumentDetected wurde im allgemeinen eine
933 // SwViewShell angelegt. Es kann aber auch sein, dass sie
934 // erst spaeter angelegt wird, naemlich dann, wenn die UI
940 // is called for every token that is recognised in CallParser
941 void SwHTMLParser::NextToken( int nToken
)
943 if( ( m_pDoc
->GetDocShell() && m_pDoc
->GetDocShell()->IsAbortingImport() )
944 || 1 == m_pDoc
->getReferenceCount() )
946 // Was the import cancelled by SFX? If a pending stack
948 eState
= SVPAR_ERROR
;
949 OSL_ENSURE( !m_pPendStack
|| m_pPendStack
->nToken
,
950 "SwHTMLParser::NextToken: Pending-Stack without token" );
951 if( 1 == m_pDoc
->getReferenceCount() || !m_pPendStack
)
955 #if OSL_DEBUG_LEVEL > 0
960 // tables are read by recursive method calls
962 // For CSS declarations we might have to wait
963 // for a file download to finish
965 // For controls we might have to set the size.
967 case HTML_TEXTAREA_ON
:
969 case HTML_SELECT_OFF
:
972 OSL_ENSURE( !m_pPendStack
, "Unbekanntes Token fuer Pending-Stack" );
978 // The following special cases have to be treated before the
979 // filter detection, because Netscape doesn't reference the content
980 // of the title for filter detection either.
988 if( IsNewDoc() && !m_sTitle
.isEmpty() )
990 if( m_pDoc
->GetDocShell() ) {
991 uno::Reference
<document::XDocumentPropertiesSupplier
>
992 xDPS(m_pDoc
->GetDocShell()->GetModel(),
993 uno::UNO_QUERY_THROW
);
994 uno::Reference
<document::XDocumentProperties
> xDocProps(
995 xDPS
->getDocumentProperties());
996 OSL_ENSURE(xDocProps
.is(), "no DocumentProperties");
997 if (xDocProps
.is()) {
998 xDocProps
->setTitle(m_sTitle
);
1001 m_pDoc
->GetDocShell()->SetTitle( m_sTitle
);
1008 case HTML_NONBREAKSPACE
:
1016 case HTML_TEXTTOKEN
:
1022 if( (HTML_TOKEN_ONOFF
& nToken
) && (1 & nToken
) )
1024 m_sTitle
+= sSaveToken
;
1025 if( !aToken
.isEmpty() )
1038 // Find out what type of document it is if we don't know already.
1039 // For Controls this has to be finished before the control is inserted
1040 // because for inserting a View is needed.
1041 if( !m_bDocInitalized
)
1044 bool bGetIDOption
= false, bInsertUnknown
= false;
1045 bool bUpperSpaceSave
= m_bUpperSpace
;
1046 m_bUpperSpace
= false;
1048 // The following special cases may or have to be treated after the
1052 if( m_bInFloatingFrame
)
1054 // <SCRIPT> is ignored here (from us), because it is ignored in
1056 if( HTML_IFRAME_OFF
== nToken
)
1058 m_bCallNextToken
= false;
1059 m_bInFloatingFrame
= false;
1064 else if( m_bInNoEmbed
)
1068 case HTML_NOEMBED_OFF
:
1069 m_aContents
= convertLineEnd(m_aContents
, GetSystemLineEnd());
1070 InsertComment( m_aContents
, OOO_STRING_SVTOOLS_HTML_noembed
);
1071 m_aContents
.clear();
1072 m_bCallNextToken
= false;
1073 m_bInNoEmbed
= false;
1077 InsertCommentText( OOO_STRING_SVTOOLS_HTML_noembed
);
1081 OSL_ENSURE( false, "SwHTMLParser::NextToken: invalid tag" );
1087 else if( m_pAppletImpl
)
1089 // in an applet only <PARAM> tags and the </APPLET> tag
1090 // are of interest for us (for the moment)
1091 // <SCRIPT> is ignored here (from Netscape)!
1095 case HTML_APPLET_OFF
:
1096 m_bCallNextToken
= false;
1099 case HTML_OBJECT_OFF
:
1100 m_bCallNextToken
= false;
1111 else if( m_bTextArea
)
1113 // in a TextArea everything up to </TEXTAREA> is inserted as text.
1114 // <SCRIPT> is ignored here (from Netscape)!
1118 case HTML_TEXTAREA_OFF
:
1119 m_bCallNextToken
= false;
1124 InsertTextAreaText( static_cast< sal_uInt16
>(nToken
) );
1130 else if( m_bSelect
)
1132 // HAS to be treated after bNoScript!
1135 case HTML_SELECT_OFF
:
1136 m_bCallNextToken
= false;
1141 InsertSelectOption();
1144 case HTML_TEXTTOKEN
:
1149 case HTML_SCRIPT_ON
:
1150 case HTML_SCRIPT_OFF
:
1151 case HTML_NOSCRIPT_ON
:
1152 case HTML_NOSCRIPT_OFF
:
1154 // treat in normal switch
1162 else if( m_pMarquee
)
1164 // in a TextArea everything up to </TEXTAREA> is inserted as text.
1165 // The <SCRIPT> tags are ignored from MS-IE, we ignore the whole
1169 case HTML_MARQUEE_OFF
:
1170 m_bCallNextToken
= false;
1174 case HTML_TEXTTOKEN
:
1175 InsertMarqueeText();
1181 else if( m_bInField
)
1185 case HTML_SDFIELD_OFF
:
1186 m_bCallNextToken
= false;
1190 case HTML_TEXTTOKEN
:
1197 else if( m_bInFootEndNoteAnchor
|| m_bInFootEndNoteSymbol
)
1201 case HTML_ANCHOR_OFF
:
1203 m_bCallNextToken
= false;
1206 case HTML_TEXTTOKEN
:
1207 InsertFootEndNoteText();
1212 else if( !m_aUnknownToken
.isEmpty() )
1214 // Paste content of unknown tags.
1215 // (but surely if we are not in the header section) fdo#36080 fdo#34666
1216 if (!aToken
.isEmpty() && !IsInHeader() )
1218 if( !m_bDocInitalized
)
1220 m_pDoc
->getIDocumentContentOperations().InsertString( *m_pPam
, aToken
);
1222 // if there are temporary paragraph attributes and the
1223 // paragraph isn't empty then the paragraph attributes
1225 if( !m_aParaAttrs
.empty() )
1226 m_aParaAttrs
.clear();
1231 // Unknown token in the header are only closed by a matching
1232 // end-token, </HEAD> or <BODY>. Text inside is ignored.
1235 case HTML_UNKNOWNCONTROL_OFF
:
1236 if( m_aUnknownToken
!= sSaveToken
)
1239 case HTML_FRAMESET_ON
:
1242 case HTML_IMAGE
: // Don't know why Netscape acts this way.
1243 m_aUnknownToken
.clear();
1245 case HTML_TEXTTOKEN
:
1248 m_aUnknownToken
.clear();
1257 if( !m_aStyleSource
.isEmpty() )
1259 m_pCSS1Parser
->ParseStyleSheet( m_aStyleSource
);
1260 m_aStyleSource
.clear();
1264 InsertBodyOptions();
1265 // If there is a template for the first or the right page,
1267 const SwPageDesc
*pPageDesc
= nullptr;
1268 if( m_pCSS1Parser
->IsSetFirstPageDesc() )
1269 pPageDesc
= m_pCSS1Parser
->GetFirstPageDesc();
1270 else if( m_pCSS1Parser
->IsSetRightPageDesc() )
1271 pPageDesc
= m_pCSS1Parser
->GetRightPageDesc();
1275 m_pDoc
->getIDocumentContentOperations().InsertPoolItem( *m_pPam
, SwFormatPageDesc( pPageDesc
) );
1286 const HTMLOptions
& rHTMLOptions
= GetOptions();
1287 for (size_t i
= rHTMLOptions
.size(); i
; )
1289 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
1290 switch( rOption
.GetToken() )
1293 m_sBaseURL
= rOption
.GetString();
1298 SwDocShell
*pDocShell(m_pDoc
->GetDocShell());
1299 OSL_ENSURE(pDocShell
, "no SwDocShell");
1301 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1302 pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
1303 uno::Reference
<document::XDocumentProperties
>
1304 xDocProps(xDPS
->getDocumentProperties());
1305 OSL_ENSURE(xDocProps
.is(),"no DocumentProperties");
1306 if (xDocProps
.is()) {
1307 xDocProps
->setDefaultTarget(
1308 rOption
.GetString());
1320 SvKeyValueIterator
*pHTTPHeader
= nullptr;
1323 SwDocShell
*pDocSh
= m_pDoc
->GetDocShell();
1325 pHTTPHeader
= pDocSh
->GetHeaderAttributes();
1327 SwDocShell
*pDocShell(m_pDoc
->GetDocShell());
1328 OSL_ENSURE(pDocShell
, "no SwDocShell");
1331 uno::Reference
<document::XDocumentProperties
> xDocProps
;
1334 const uno::Reference
<document::XDocumentPropertiesSupplier
>
1335 xDPS( pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
1336 xDocProps
= xDPS
->getDocumentProperties();
1337 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
1339 ParseMetaOptions( xDocProps
, pHTTPHeader
);
1348 case HTML_SCRIPT_ON
:
1352 case HTML_SCRIPT_OFF
:
1356 case HTML_NOSCRIPT_ON
:
1357 case HTML_NOSCRIPT_OFF
:
1358 bInsertUnknown
= true;
1365 case HTML_STYLE_OFF
:
1370 if( !m_bIgnoreRawData
)
1372 if( IsReadScript() )
1376 else if( IsReadStyle() )
1378 if( !m_aStyleSource
.isEmpty() )
1379 m_aStyleSource
+= "\n";
1380 m_aStyleSource
+= aToken
;
1385 case HTML_OBJECT_ON
:
1386 #if HAVE_FEATURE_JAVA
1388 m_bCallNextToken
= m_pAppletImpl
!=nullptr && m_pTable
!=nullptr;
1392 case HTML_APPLET_ON
:
1393 #if HAVE_FEATURE_JAVA
1395 m_bCallNextToken
= m_pAppletImpl
!=nullptr && m_pTable
!=nullptr;
1399 case HTML_IFRAME_ON
:
1400 InsertFloatingFrame();
1401 m_bCallNextToken
= m_bInFloatingFrame
&& m_pTable
!=nullptr;
1404 case HTML_LINEBREAK
:
1411 bGetIDOption
= true;
1412 // <BR>s in <PRE> resemble true LFs, hence no break
1416 // CR in PRE/LISTING/XMP
1418 if( HTML_NEWPARA
==nToken
||
1419 m_pPam
->GetPoint()->nContent
.GetIndex() )
1421 AppendTextNode(); // there is no LF at this place
1422 // therefore it will cause no problems
1426 if( !GetMedium() || !GetMedium()->IsRemote() )
1427 ::SetProgressState( rInput
.Tell(), m_pDoc
->GetDocShell() );
1431 case HTML_NONBREAKSPACE
:
1432 m_pDoc
->getIDocumentContentOperations().InsertString( *m_pPam
, OUString(CHAR_HARDBLANK
) );
1436 m_pDoc
->getIDocumentContentOperations().InsertString( *m_pPam
, OUString(CHAR_SOFTHYPHEN
) );
1439 case HTML_LINEFEEDCHAR
:
1440 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
1442 if( !m_pTable
&& !m_pDoc
->IsInHeaderFooter( m_pPam
->GetPoint()->nNode
) )
1444 NewAttr( &m_aAttrTab
.pBreak
, SvxFormatBreakItem(SvxBreak::PageBefore
, RES_BREAK
) );
1445 EndAttr( m_aAttrTab
.pBreak
, false );
1449 case HTML_TEXTTOKEN
:
1450 // insert string without spanning attributes at the end.
1451 if( !aToken
.isEmpty() && ' '==aToken
[0] && !IsReadPRE() )
1453 sal_Int32 nPos
= m_pPam
->GetPoint()->nContent
.GetIndex();
1456 const OUString
& rText
=
1457 m_pPam
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText();
1458 sal_Unicode cLast
= rText
[--nPos
];
1459 if( ' ' == cLast
|| '\x0a' == cLast
)
1460 aToken
= aToken
.copy(1);
1463 aToken
= aToken
.copy(1);
1465 if( aToken
.isEmpty() )
1467 m_bUpperSpace
= bUpperSpaceSave
;
1472 if( !aToken
.isEmpty() )
1474 if( !m_bDocInitalized
)
1476 m_pDoc
->getIDocumentContentOperations().InsertString( *m_pPam
, aToken
);
1478 // if there are temporary paragraph attributes and the
1479 // paragraph isn't empty then the paragraph attributes
1481 if( !m_aParaAttrs
.empty() )
1482 m_aParaAttrs
.clear();
1494 // if only the parser references the doc, we can break and set
1496 if( 1 == m_pDoc
->getReferenceCount() )
1498 eState
= SVPAR_ERROR
;
1510 case HTML_NOEMBED_ON
:
1511 m_bInNoEmbed
= true;
1512 m_bCallNextToken
= m_pTable
!=nullptr;
1513 ReadRawData( OOO_STRING_SVTOOLS_HTML_noembed
);
1516 case HTML_DEFLIST_ON
:
1517 if( m_nOpenParaToken
)
1521 case HTML_DEFLIST_OFF
:
1522 if( m_nOpenParaToken
)
1524 EndDefListItem( 0, 1==m_nDefListDeep
);
1530 if( m_nOpenParaToken
)
1532 EndDefListItem();// close <DD>/<DT> and set no template
1533 NewDefListItem( nToken
);
1539 // Actually we should close a DD/DT now.
1540 // But neither Netscape nor Microsoft do this and so don't we.
1541 EndDefListItem( nToken
);
1545 case HTML_DIVISION_ON
:
1546 case HTML_CENTER_ON
:
1547 if (!m_isInTableStructure
)
1549 if( m_nOpenParaToken
)
1552 m_nOpenParaToken
= 0;
1556 NewDivision( nToken
);
1560 case HTML_DIVISION_OFF
:
1561 case HTML_CENTER_OFF
:
1562 if (!m_isInTableStructure
)
1564 if( m_nOpenParaToken
)
1567 m_nOpenParaToken
= 0;
1571 EndDivision( nToken
);
1575 case HTML_MULTICOL_ON
:
1576 if( m_nOpenParaToken
)
1581 case HTML_MULTICOL_OFF
:
1582 if( m_nOpenParaToken
)
1584 EndTag( HTML_MULTICOL_ON
);
1587 case HTML_MARQUEE_ON
:
1589 m_bCallNextToken
= m_pMarquee
!=nullptr && m_pTable
!=nullptr;
1600 case HTML_PARABREAK_ON
:
1601 if( m_nOpenParaToken
)
1606 case HTML_PARABREAK_OFF
:
1610 case HTML_ADDRESS_ON
:
1611 if( m_nOpenParaToken
)
1613 NewTextFormatColl( HTML_ADDRESS_ON
, RES_POOLCOLL_SENDADRESS
);
1616 case HTML_ADDRESS_OFF
:
1617 if( m_nOpenParaToken
)
1619 EndTextFormatColl( HTML_ADDRESS_OFF
);
1622 case HTML_BLOCKQUOTE_ON
:
1623 case HTML_BLOCKQUOTE30_ON
:
1624 if( m_nOpenParaToken
)
1626 NewTextFormatColl( HTML_BLOCKQUOTE_ON
, RES_POOLCOLL_HTML_BLOCKQUOTE
);
1629 case HTML_BLOCKQUOTE_OFF
:
1630 case HTML_BLOCKQUOTE30_OFF
:
1631 if( m_nOpenParaToken
)
1633 EndTextFormatColl( HTML_BLOCKQUOTE_ON
);
1636 case HTML_PREFORMTXT_ON
:
1637 case HTML_LISTING_ON
:
1639 if( m_nOpenParaToken
)
1641 NewTextFormatColl( nToken
, RES_POOLCOLL_HTML_PRE
);
1644 case HTML_PREFORMTXT_OFF
:
1645 m_bNoParSpace
= true; // the last PRE-paragraph gets a spacing
1646 EndTextFormatColl( HTML_PREFORMTXT_OFF
);
1649 case HTML_LISTING_OFF
:
1651 EndTextFormatColl( nToken
);
1660 if( m_nOpenParaToken
)
1663 m_nOpenParaToken
= 0;
1667 NewHeading( nToken
);
1670 case HTML_HEAD1_OFF
:
1671 case HTML_HEAD2_OFF
:
1672 case HTML_HEAD3_OFF
:
1673 case HTML_HEAD4_OFF
:
1674 case HTML_HEAD5_OFF
:
1675 case HTML_HEAD6_OFF
:
1681 BuildTable( SVX_ADJUST_END
);
1684 if( m_nOpenParaToken
)
1686 OSL_ENSURE( !m_pTable
, "table in table not allowed here" );
1687 if( !m_pTable
&& (IsNewDoc() || !m_pPam
->GetNode().FindTableNode()) &&
1688 (m_pPam
->GetPoint()->nNode
.GetIndex() >
1689 m_pDoc
->GetNodes().GetEndOfExtras().GetIndex() ||
1690 !m_pPam
->GetNode().FindFootnoteStartNode() ) )
1692 if ( m_nParaCnt
< 5 )
1693 Show(); // show what we have up to here
1695 SvxAdjust eAdjust
= m_aAttrTab
.pAdjust
1696 ? static_cast<const SvxAdjustItem
&>(m_aAttrTab
.pAdjust
->GetItem()).
1699 BuildTable( eAdjust
);
1702 bInsertUnknown
= m_bKeepUnknown
;
1707 case HTML_DIRLIST_ON
:
1708 case HTML_MENULIST_ON
:
1709 case HTML_ORDERLIST_ON
:
1710 case HTML_UNORDERLIST_ON
:
1711 if( m_nOpenParaToken
)
1713 NewNumBulList( nToken
);
1716 case HTML_DIRLIST_OFF
:
1717 case HTML_MENULIST_OFF
:
1718 case HTML_ORDERLIST_OFF
:
1719 case HTML_UNORDERLIST_OFF
:
1720 if( m_nOpenParaToken
)
1722 EndNumBulListItem( 0, true, GetNumInfo().GetDepth()==1 );
1723 EndNumBulList( nToken
);
1727 case HTML_LISTHEADER_ON
:
1728 if( m_nOpenParaToken
&&
1729 (m_pPam
->GetPoint()->nContent
.GetIndex()
1730 || HTML_PARABREAK_ON
==m_nOpenParaToken
) )
1732 // only finish paragraph for <P><LI>, not for <DD><LI>
1736 EndNumBulListItem( 0, false );// close <LI>/<LH> and don't set a template
1737 NewNumBulListItem( nToken
);
1741 case HTML_LISTHEADER_OFF
:
1742 EndNumBulListItem( nToken
, false );
1746 case HTML_ITALIC_ON
:
1748 SvxPostureItem
aPosture( ITALIC_NORMAL
, RES_CHRATR_POSTURE
);
1749 SvxPostureItem
aPostureCJK( ITALIC_NORMAL
, RES_CHRATR_CJK_POSTURE
);
1750 SvxPostureItem
aPostureCTL( ITALIC_NORMAL
, RES_CHRATR_CTL_POSTURE
);
1751 NewStdAttr( HTML_ITALIC_ON
,
1752 &m_aAttrTab
.pItalic
, aPosture
,
1753 &m_aAttrTab
.pItalicCJK
, &aPostureCJK
,
1754 &m_aAttrTab
.pItalicCTL
, &aPostureCTL
);
1760 SvxWeightItem
aWeight( WEIGHT_BOLD
, RES_CHRATR_WEIGHT
);
1761 SvxWeightItem
aWeightCJK( WEIGHT_BOLD
, RES_CHRATR_CJK_WEIGHT
);
1762 SvxWeightItem
aWeightCTL( WEIGHT_BOLD
, RES_CHRATR_CTL_WEIGHT
);
1763 NewStdAttr( HTML_BOLD_ON
,
1764 &m_aAttrTab
.pBold
, aWeight
,
1765 &m_aAttrTab
.pBoldCJK
, &aWeightCJK
,
1766 &m_aAttrTab
.pBoldCTL
, &aWeightCTL
);
1770 case HTML_STRIKE_ON
:
1771 case HTML_STRIKETHROUGH_ON
:
1773 NewStdAttr( HTML_STRIKE_ON
, &m_aAttrTab
.pStrike
,
1774 SvxCrossedOutItem(STRIKEOUT_SINGLE
, RES_CHRATR_CROSSEDOUT
) );
1778 case HTML_UNDERLINE_ON
:
1780 NewStdAttr( HTML_UNDERLINE_ON
, &m_aAttrTab
.pUnderline
,
1781 SvxUnderlineItem(LINESTYLE_SINGLE
, RES_CHRATR_UNDERLINE
) );
1785 case HTML_SUPERSCRIPT_ON
:
1787 NewStdAttr( HTML_SUPERSCRIPT_ON
, &m_aAttrTab
.pEscapement
,
1788 SvxEscapementItem(HTML_ESC_SUPER
,HTML_ESC_PROP
, RES_CHRATR_ESCAPEMENT
) );
1792 case HTML_SUBSCRIPT_ON
:
1794 NewStdAttr( HTML_SUBSCRIPT_ON
, &m_aAttrTab
.pEscapement
,
1795 SvxEscapementItem(HTML_ESC_SUB
,HTML_ESC_PROP
, RES_CHRATR_ESCAPEMENT
) );
1801 NewStdAttr( HTML_BLINK_ON
, &m_aAttrTab
.pBlink
,
1802 SvxBlinkItem( true, RES_CHRATR_BLINK
) );
1807 NewStdAttr( HTML_SPAN_ON
);
1810 case HTML_ITALIC_OFF
:
1812 case HTML_STRIKE_OFF
:
1813 case HTML_UNDERLINE_OFF
:
1814 case HTML_SUPERSCRIPT_OFF
:
1815 case HTML_SUBSCRIPT_OFF
:
1816 case HTML_BLINK_OFF
:
1821 case HTML_STRIKETHROUGH_OFF
:
1822 EndTag( HTML_STRIKE_OFF
);
1825 case HTML_BASEFONT_ON
:
1828 case HTML_BASEFONT_OFF
:
1832 case HTML_BIGPRINT_ON
:
1833 case HTML_SMALLPRINT_ON
:
1834 NewFontAttr( nToken
);
1837 case HTML_BIGPRINT_OFF
:
1838 case HTML_SMALLPRINT_OFF
:
1839 EndFontAttr( nToken
);
1842 case HTML_EMPHASIS_ON
:
1843 case HTML_CITIATION_ON
:
1844 case HTML_STRONG_ON
:
1846 case HTML_SAMPLE_ON
:
1847 case HTML_KEYBOARD_ON
:
1848 case HTML_VARIABLE_ON
:
1849 case HTML_DEFINSTANCE_ON
:
1850 case HTML_SHORTQUOTE_ON
:
1851 case HTML_LANGUAGE_ON
:
1852 case HTML_AUTHOR_ON
:
1853 case HTML_PERSON_ON
:
1854 case HTML_ACRONYM_ON
:
1855 case HTML_ABBREVIATION_ON
:
1856 case HTML_INSERTEDTEXT_ON
:
1857 case HTML_DELETEDTEXT_ON
:
1859 case HTML_TELETYPE_ON
:
1860 NewCharFormat( nToken
);
1863 case HTML_SDFIELD_ON
:
1865 m_bCallNextToken
= m_bInField
&& m_pTable
!=nullptr;
1868 case HTML_EMPHASIS_OFF
:
1869 case HTML_CITIATION_OFF
:
1870 case HTML_STRONG_OFF
:
1872 case HTML_SAMPLE_OFF
:
1873 case HTML_KEYBOARD_OFF
:
1874 case HTML_VARIABLE_OFF
:
1875 case HTML_DEFINSTANCE_OFF
:
1876 case HTML_SHORTQUOTE_OFF
:
1877 case HTML_LANGUAGE_OFF
:
1878 case HTML_AUTHOR_OFF
:
1879 case HTML_PERSON_OFF
:
1880 case HTML_ACRONYM_OFF
:
1881 case HTML_ABBREVIATION_OFF
:
1882 case HTML_INSERTEDTEXT_OFF
:
1883 case HTML_DELETEDTEXT_OFF
:
1885 case HTML_TELETYPE_OFF
:
1890 if( !m_aStyleSource
.isEmpty() )
1892 m_pCSS1Parser
->ParseStyleSheet( m_aStyleSource
);
1893 m_aStyleSource
.clear();
1901 case HTML_TITLE_OFF
:
1902 break; // don't evaluate further???
1905 const HTMLOptions
& rHTMLOptions
= GetOptions();
1906 for (size_t i
= rHTMLOptions
.size(); i
; )
1908 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
1909 if( HTML_O_DIR
== rOption
.GetToken() )
1911 const OUString
& rDir
= rOption
.GetString();
1912 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(),
1913 m_pCSS1Parser
->GetWhichMap() );
1914 SvxCSS1PropertyInfo aPropInfo
;
1916 ParseStyleOptions( aDummy
, aDummy
, aDummy
, aItemSet
,
1917 aPropInfo
, nullptr, &rDir
);
1919 m_pCSS1Parser
->SetPageDescAttrs( nullptr, &aItemSet
);
1930 case HTML_TEXTAREA_ON
:
1932 m_bCallNextToken
= m_bTextArea
&& m_pTable
!=nullptr;
1935 case HTML_SELECT_ON
:
1937 m_bCallNextToken
= m_bSelect
&& m_pTable
!=nullptr;
1940 case HTML_ANCHOR_ON
:
1944 case HTML_ANCHOR_OFF
:
1949 if( ( aToken
.getLength() > 5 ) && ( ! m_bIgnoreHTMLComments
) )
1951 // insert as Post-It
1952 // If there are no space characters right behind
1953 // the <!-- and on front of the -->, leave the comment untouched.
1954 if( ' ' == aToken
[ 3 ] &&
1955 ' ' == aToken
[ aToken
.getLength()-3 ] )
1957 OUString
aComment( aToken
.copy( 3, aToken
.getLength()-5 ) );
1958 InsertComment(comphelper::string::strip(aComment
, ' '));
1962 OUStringBuffer aComment
;
1963 aComment
.append('<').append(aToken
).append('>');
1964 InsertComment( aComment
.makeStringAndClear() );
1970 // Image Maps are read asynchronously: At first only an image map is created
1971 // Areas are processed later. Nevertheless the
1972 // ImageMap is inserted into the IMap-Array, because it might be used
1974 m_pImageMap
= new ImageMap
;
1975 if( ParseMapOptions( m_pImageMap
) )
1978 m_pImageMaps
= new ImageMaps
;
1979 m_pImageMaps
->push_back(std::unique_ptr
<ImageMap
>(m_pImageMap
));
1984 m_pImageMap
= nullptr;
1989 // there is no ImageMap anymore (don't delete IMap, because it's
1990 // already contained in the array!)
1991 m_pImageMap
= nullptr;
1996 ParseAreaOptions( m_pImageMap
, m_sBaseURL
, SFX_EVENT_MOUSEOVER_OBJECT
,
1997 SFX_EVENT_MOUSEOUT_OBJECT
);
2000 case HTML_FRAMESET_ON
:
2001 bInsertUnknown
= m_bKeepUnknown
;
2004 case HTML_NOFRAMES_ON
:
2006 FinishHeader( true );
2007 bInsertUnknown
= m_bKeepUnknown
;
2010 case HTML_UNKNOWNCONTROL_ON
:
2011 // Ignore content of unknown token in the header, if the token
2012 // does not start with a '!'.
2013 // (but judging from the code, also if does not start with a '%')
2014 // (and also if we're not somewhere we consider PRE)
2015 if( IsInHeader() && !IsReadPRE() && m_aUnknownToken
.isEmpty() &&
2016 !sSaveToken
.isEmpty() && '!' != sSaveToken
[0] &&
2017 '%' != sSaveToken
[0] )
2018 m_aUnknownToken
= sSaveToken
;
2022 bInsertUnknown
= m_bKeepUnknown
;
2029 if( bInsertUnknown
)
2031 OUString
aComment("HTML: <");
2032 if( (HTML_TOKEN_ONOFF
& nToken
) != 0 && (1 & nToken
) != 0 )
2034 aComment
+= sSaveToken
;
2035 if( !aToken
.isEmpty() )
2038 (aComment
+= " ") += aToken
;
2041 InsertComment( aComment
);
2044 // if there are temporary paragraph attributes and the
2045 // paragraph isn't empty then the paragraph attributes are final.
2046 if( !m_aParaAttrs
.empty() && m_pPam
->GetPoint()->nContent
.GetIndex() )
2047 m_aParaAttrs
.clear();
2050 static void lcl_swhtml_getItemInfo( const HTMLAttr
& rAttr
,
2051 bool& rScriptDependent
, bool& rFont
,
2052 sal_uInt16
& rScriptType
)
2054 switch( rAttr
.GetItem().Which() )
2056 case RES_CHRATR_FONT
:
2059 case RES_CHRATR_FONTSIZE
:
2060 case RES_CHRATR_LANGUAGE
:
2061 case RES_CHRATR_POSTURE
:
2062 case RES_CHRATR_WEIGHT
:
2063 rScriptType
= i18n::ScriptType::LATIN
;
2064 rScriptDependent
= true;
2066 case RES_CHRATR_CJK_FONT
:
2069 case RES_CHRATR_CJK_FONTSIZE
:
2070 case RES_CHRATR_CJK_LANGUAGE
:
2071 case RES_CHRATR_CJK_POSTURE
:
2072 case RES_CHRATR_CJK_WEIGHT
:
2073 rScriptType
= i18n::ScriptType::ASIAN
;
2074 rScriptDependent
= true;
2076 case RES_CHRATR_CTL_FONT
:
2079 case RES_CHRATR_CTL_FONTSIZE
:
2080 case RES_CHRATR_CTL_LANGUAGE
:
2081 case RES_CHRATR_CTL_POSTURE
:
2082 case RES_CHRATR_CTL_WEIGHT
:
2083 rScriptType
= i18n::ScriptType::COMPLEX
;
2084 rScriptDependent
= true;
2087 rScriptDependent
= false;
2093 bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode
, bool bUpdateNum
)
2095 // Ein harter Zeilen-Umbruch am Ende muss immer entfernt werden.
2096 // Einen zweiten ersetzen wir durch einen Absatz-Abstand.
2097 sal_Int32 nLFStripped
= StripTrailingLF();
2098 if( (AM_NOSPACE
==eMode
|| AM_SOFTNOSPACE
==eMode
) && nLFStripped
> 1 )
2101 // die harten Attribute an diesem Absatz werden nie mehr ungueltig
2102 if( !m_aParaAttrs
.empty() )
2103 m_aParaAttrs
.clear();
2105 if( AM_SPACE
==eMode
|| AM_NOSPACE
==eMode
)
2107 SwTextNode
*pTextNode
=
2108 m_pPam
->GetPoint()->nNode
.GetNode().GetTextNode();
2110 const SvxULSpaceItem
& rULSpace
=
2111 static_cast<const SvxULSpaceItem
&>(pTextNode
->SwContentNode::GetAttr( RES_UL_SPACE
));
2113 bool bChange
= AM_NOSPACE
==eMode
? rULSpace
.GetLower() > 0
2114 : rULSpace
.GetLower() == 0;
2118 const SvxULSpaceItem
& rCollULSpace
=
2119 pTextNode
->GetAnyFormatColl().GetULSpace();
2121 bool bMayReset
= AM_NOSPACE
==eMode
? rCollULSpace
.GetLower() == 0
2122 : rCollULSpace
.GetLower() > 0;
2125 rCollULSpace
.GetUpper() == rULSpace
.GetUpper() )
2127 pTextNode
->ResetAttr( RES_UL_SPACE
);
2132 SvxULSpaceItem( rULSpace
.GetUpper(),
2133 AM_NOSPACE
==eMode
? 0 : HTML_PARSPACE
, RES_UL_SPACE
) );
2137 m_bNoParSpace
= AM_NOSPACE
==eMode
|| AM_SOFTNOSPACE
==eMode
;
2139 SwPosition
aOldPos( *m_pPam
->GetPoint() );
2141 bool bRet
= m_pDoc
->getIDocumentContentOperations().AppendTextNode( *m_pPam
->GetPoint() );
2143 // Zeichen-Attribute aufspalten und ggf keine setzen, die ueber den
2144 // ganzen Absatz gesetzt sind
2145 const SwNodeIndex
& rEndIdx
= aOldPos
.nNode
;
2146 const sal_Int32 nEndCnt
= aOldPos
.nContent
.GetIndex();
2147 const SwPosition
& rPos
= *m_pPam
->GetPoint();
2149 HTMLAttr
** pHTMLAttributes
= reinterpret_cast<HTMLAttr
**>(&m_aAttrTab
);
2150 for (auto nCnt
= sizeof(HTMLAttrTable
) / sizeof(HTMLAttr
*); nCnt
--; ++pHTMLAttributes
)
2152 HTMLAttr
*pAttr
= *pHTMLAttributes
;
2153 if( pAttr
&& pAttr
->GetItem().Which() < RES_PARATR_BEGIN
)
2155 bool bWholePara
= false;
2159 HTMLAttr
*pNext
= pAttr
->GetNext();
2160 if( pAttr
->GetSttParaIdx() < rEndIdx
.GetIndex() ||
2162 pAttr
->GetSttPara() == rEndIdx
&&
2163 pAttr
->GetSttCnt() != nEndCnt
) )
2166 pAttr
->GetSttPara() == rEndIdx
&&
2167 pAttr
->GetSttCnt() == 0;
2169 sal_Int32 nStt
= pAttr
->nSttContent
;
2170 bool bScript
= false, bFont
= false;
2171 sal_uInt16 nScriptItem
;
2172 bool bInsert
= true;
2173 lcl_swhtml_getItemInfo( *pAttr
, bScript
, bFont
,
2175 // den besehrigen Teil setzen
2176 if( bInsert
&& bScript
)
2178 const SwTextNode
*pTextNd
=
2179 pAttr
->GetSttPara().GetNode().GetTextNode();
2180 OSL_ENSURE( pTextNd
, "No text node" );
2183 const OUString
& rText
= pTextNd
->GetText();
2184 sal_uInt16 nScriptText
=
2185 g_pBreakIt
->GetBreakIter()->getScriptType(
2186 rText
, pAttr
->GetSttCnt() );
2187 sal_Int32 nScriptEnd
= g_pBreakIt
->GetBreakIter()
2188 ->endOfScript( rText
, nStt
, nScriptText
);
2189 while (nScriptEnd
< nEndCnt
&& nScriptEnd
!= -1)
2191 if( nScriptItem
== nScriptText
)
2193 HTMLAttr
*pSetAttr
=
2194 pAttr
->Clone( rEndIdx
, nScriptEnd
);
2195 pSetAttr
->nSttContent
= nStt
;
2196 pSetAttr
->ClearPrev();
2197 if( !pNext
|| bWholePara
)
2199 if (pSetAttr
->bInsAtStart
)
2200 m_aSetAttrTab
.push_front( pSetAttr
);
2202 m_aSetAttrTab
.push_back( pSetAttr
);
2205 pNext
->InsertPrev( pSetAttr
);
2208 nScriptText
= g_pBreakIt
->GetBreakIter()->getScriptType(
2210 nScriptEnd
= g_pBreakIt
->GetBreakIter()
2211 ->endOfScript( rText
, nStt
, nScriptText
);
2213 bInsert
= nScriptItem
== nScriptText
;
2218 HTMLAttr
*pSetAttr
=
2219 pAttr
->Clone( rEndIdx
, nEndCnt
);
2220 pSetAttr
->nSttContent
= nStt
;
2222 // Wenn das Attribut den gesamten Absatz umspannt, werden
2223 // alle auesseren Attribute nicht mehr beachtet. Deshalb
2224 // darf es auch nicht in die Prev-Liste eines ausseren
2225 // Attributs eingetragen werden, denn dieses wird ja
2226 // erstmal nicht gesetzt. Das fuehrt zu verschiebenungen,
2227 // wenn Felder ins Rennen kommen
2228 if( !pNext
|| bWholePara
)
2230 if (pSetAttr
->bInsAtStart
)
2231 m_aSetAttrTab
.push_front( pSetAttr
);
2233 m_aSetAttrTab
.push_back( pSetAttr
);
2236 pNext
->InsertPrev( pSetAttr
);
2240 HTMLAttr
*pPrev
= pAttr
->GetPrev();
2243 // Die Previous-Attribute muessen trotzdem gesetzt werden.
2244 if( !pNext
|| bWholePara
)
2246 if (pPrev
->bInsAtStart
)
2247 m_aSetAttrTab
.push_front( pPrev
);
2249 m_aSetAttrTab
.push_back( pPrev
);
2252 pNext
->InsertPrev( pPrev
);
2258 pAttr
->SetStart( rPos
);
2266 if( GetNumInfo().GetDepth() )
2268 sal_uInt8 nLvl
= GetNumInfo().GetLevel();
2272 m_pPam
->GetNode().GetTextNode()->ResetAttr( RES_PARATR_NUMRULE
);
2275 // We must set the attribute of the paragraph before now (because of JavaScript)
2278 // Now it is time to get rid of all script dependent hints that are
2279 // equal to the settings in the style
2280 SwTextNode
*pTextNd
= rEndIdx
.GetNode().GetTextNode();
2281 OSL_ENSURE( pTextNd
, "There is the txt node" );
2282 size_t nCntAttr
= (pTextNd
&& pTextNd
->GetpSwpHints())
2283 ? pTextNd
->GetSwpHints().Count() : 0;
2286 // These are the end position of all script dependent hints.
2287 // If we find a hint that starts before the current end position,
2288 // we have to set it. If we find a hint that start behind or at
2289 // that position, we have to take the hint value into account.
2290 // If it is equal to the style, or in fact the paragarph value
2291 // for that hint, the hint is removed. Otherwise its end position
2293 sal_Int32 aEndPos
[15] =
2294 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2295 SwpHints
& rHints
= pTextNd
->GetSwpHints();
2296 for( size_t i
=0; i
< nCntAttr
; i
++ )
2298 SwTextAttr
*pHt
= rHints
.Get( i
);
2299 sal_uInt16 nWhich
= pHt
->Which();
2304 case RES_CHRATR_FONT
:
2308 case RES_CHRATR_FONTSIZE
:
2311 case RES_CHRATR_LANGUAGE
:
2314 case RES_CHRATR_POSTURE
:
2317 case RES_CHRATR_WEIGHT
:
2320 case RES_CHRATR_CJK_FONT
:
2324 case RES_CHRATR_CJK_FONTSIZE
:
2327 case RES_CHRATR_CJK_LANGUAGE
:
2330 case RES_CHRATR_CJK_POSTURE
:
2333 case RES_CHRATR_CJK_WEIGHT
:
2336 case RES_CHRATR_CTL_FONT
:
2340 case RES_CHRATR_CTL_FONTSIZE
:
2343 case RES_CHRATR_CTL_LANGUAGE
:
2346 case RES_CHRATR_CTL_POSTURE
:
2349 case RES_CHRATR_CTL_WEIGHT
:
2353 // Skip to next attribute
2356 const sal_Int32 nStt
= pHt
->GetStart();
2357 if( nStt
>= aEndPos
[nIdx
] )
2359 const SfxPoolItem
& rItem
=
2360 static_cast<const SwContentNode
*>(pTextNd
)->GetAttr( nWhich
);
2361 if( bFont
? swhtml_css1atr_equalFontItems(rItem
,pHt
->GetAttr())
2362 : rItem
== pHt
->GetAttr() )
2364 // The hint is the same as set in the paragraph and
2365 // therefore, it can be deleted
2366 // CAUTION!!! This WILL delete the hint and it MAY
2367 // also delete the SwpHints!!! To avoid any trouble
2368 // we leave the loop immediately if this is the last
2370 pTextNd
->DeleteAttribute( pHt
);
2378 // The hint is different. Therefore all hints within that
2379 // hint have to be ignored.
2380 aEndPos
[nIdx
] = pHt
->GetEnd() ? *pHt
->GetEnd() : nStt
;
2385 // The hint starts before another one ends.
2386 // The hint in this case is not deleted
2387 OSL_ENSURE( pHt
->GetEnd() && *pHt
->GetEnd() <= aEndPos
[nIdx
],
2388 "hints aren't nested properly!" );
2393 if( !m_pTable
&& !--m_nParaCnt
)
2399 void SwHTMLParser::AddParSpace()
2401 //If it already has ParSpace, return
2402 if( !m_bNoParSpace
)
2405 m_bNoParSpace
= false;
2407 sal_uLong nNdIdx
= m_pPam
->GetPoint()->nNode
.GetIndex() - 1;
2409 SwTextNode
*pTextNode
= m_pDoc
->GetNodes()[nNdIdx
]->GetTextNode();
2413 SvxULSpaceItem rULSpace
=
2414 static_cast<const SvxULSpaceItem
&>(pTextNode
->SwContentNode::GetAttr( RES_UL_SPACE
));
2415 if( !rULSpace
.GetLower() )
2417 const SvxULSpaceItem
& rCollULSpace
=
2418 pTextNode
->GetAnyFormatColl().GetULSpace();
2419 if( rCollULSpace
.GetLower() &&
2420 rCollULSpace
.GetUpper() == rULSpace
.GetUpper() )
2422 pTextNode
->ResetAttr( RES_UL_SPACE
);
2426 //What I do here, is that I examine the attributes, and if
2427 //I find out, that it's CJK/CTL, then I set the paragraph space
2428 //to the value set in HTML_CJK_PARSPACE/HTML_CTL_PARSPACE.
2430 bool bIsCJK
= false;
2431 bool bIsCTL
= false;
2433 const size_t nCntAttr
= (pTextNode
&& pTextNode
->GetpSwpHints())
2434 ? pTextNode
->GetSwpHints().Count() : 0;
2436 for(size_t i
= 0; i
< nCntAttr
; ++i
)
2438 SwTextAttr
*const pHt
= pTextNode
->GetSwpHints().Get(i
);
2439 sal_uInt16
const nWhich
= pHt
->Which();
2440 if (RES_CHRATR_CJK_FONT
== nWhich
||
2441 RES_CHRATR_CJK_FONTSIZE
== nWhich
||
2442 RES_CHRATR_CJK_LANGUAGE
== nWhich
||
2443 RES_CHRATR_CJK_POSTURE
== nWhich
||
2444 RES_CHRATR_CJK_WEIGHT
== nWhich
)
2449 if (RES_CHRATR_CTL_FONT
== nWhich
||
2450 RES_CHRATR_CTL_FONTSIZE
== nWhich
||
2451 RES_CHRATR_CTL_LANGUAGE
== nWhich
||
2452 RES_CHRATR_CTL_POSTURE
== nWhich
||
2453 RES_CHRATR_CTL_WEIGHT
== nWhich
)
2463 SvxULSpaceItem( rULSpace
.GetUpper(), HTML_CTL_PARSPACE
, RES_UL_SPACE
) );
2468 SvxULSpaceItem( rULSpace
.GetUpper(), HTML_CJK_PARSPACE
, RES_UL_SPACE
) );
2471 SvxULSpaceItem( rULSpace
.GetUpper(), HTML_PARSPACE
, RES_UL_SPACE
) );
2477 void SwHTMLParser::Show()
2480 // - ein EndAction gerufen, damit formatiert wird
2481 // - ein Reschedule gerufen,
2482 // - die eiegen View-Shell wieder gesetzt
2483 // - und Start-Action gerufen
2485 OSL_ENSURE( SVPAR_WORKING
==eState
, "Show nicht im Working-State - Das kann ins Auge gehen" );
2486 SwViewShell
*pOldVSh
= CallEndAction();
2488 Application::Reschedule();
2490 if( ( m_pDoc
->GetDocShell() && m_pDoc
->GetDocShell()->IsAbortingImport() )
2491 || 1 == m_pDoc
->getReferenceCount() )
2493 // wurde der Import vom SFX abgebrochen?
2494 eState
= SVPAR_ERROR
;
2497 // Die SwViewShell nochmal holen, denn sie koennte im Reschedule
2498 // zerstoert wirden sein.
2499 SwViewShell
*pVSh
= CallStartAction( pOldVSh
);
2501 // ist der aktuelle Node nicht mehr sichtbar, dann benutzen wir
2502 // eine groessere Schrittweite
2505 m_nParaCnt
= (m_pPam
->GetPoint()->nNode
.GetNode().IsInVisibleArea(pVSh
))
2510 void SwHTMLParser::ShowStatline()
2513 // - ein Reschedule gerufen, damit gescrollt werden kann
2514 // - die eiegen View-Shell wieder gesetzt
2515 // - ein Start/End-Action gerufen, wenn gescrollt wurde.
2517 OSL_ENSURE( SVPAR_WORKING
==eState
, "ShowStatLine nicht im Working-State - Das kann ins Auge gehen" );
2519 // Laufbalkenanzeige
2520 if( !GetMedium() || !GetMedium()->IsRemote() )
2522 ::SetProgressState( rInput
.Tell(), m_pDoc
->GetDocShell() );
2523 CheckActionViewShell();
2527 Application::Reschedule();
2529 if( ( m_pDoc
->GetDocShell() && m_pDoc
->GetDocShell()->IsAbortingImport() )
2530 || 1 == m_pDoc
->getReferenceCount() )
2531 // wurde der Import vom SFX abgebrochen?
2532 eState
= SVPAR_ERROR
;
2534 SwViewShell
*pVSh
= CheckActionViewShell();
2535 if( pVSh
&& pVSh
->HasInvalidRect() )
2537 CallEndAction( false, false );
2538 CallStartAction( pVSh
, false );
2543 SwViewShell
*SwHTMLParser::CallStartAction( SwViewShell
*pVSh
, bool bChkPtr
)
2545 OSL_ENSURE( !m_pActionViewShell
, "CallStartAction: SwViewShell schon gesetzt" );
2547 if( !pVSh
|| bChkPtr
)
2549 #if OSL_DEBUG_LEVEL > 0
2550 SwViewShell
*pOldVSh
= pVSh
;
2552 pVSh
= m_pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell();
2553 #if OSL_DEBUG_LEVEL > 0
2554 OSL_ENSURE( !pVSh
|| !pOldVSh
|| pOldVSh
== pVSh
, "CallStartAction: Wer hat die SwViewShell ausgetauscht?" );
2555 if( pOldVSh
&& !pVSh
)
2559 m_pActionViewShell
= pVSh
;
2561 if( m_pActionViewShell
)
2563 if( dynamic_cast< const SwEditShell
*>( m_pActionViewShell
) != nullptr )
2564 static_cast<SwEditShell
*>(m_pActionViewShell
)->StartAction();
2566 m_pActionViewShell
->StartAction();
2569 return m_pActionViewShell
;
2572 SwViewShell
*SwHTMLParser::CallEndAction( bool bChkAction
, bool bChkPtr
)
2576 SwViewShell
*pVSh
= m_pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell();
2577 OSL_ENSURE( !pVSh
|| m_pActionViewShell
== pVSh
,
2578 "CallEndAction: Wer hat die SwViewShell ausgetauscht?" );
2579 #if OSL_DEBUG_LEVEL > 0
2580 if( m_pActionViewShell
&& !pVSh
)
2583 if( pVSh
!= m_pActionViewShell
)
2584 m_pActionViewShell
= nullptr;
2587 if( !m_pActionViewShell
|| (bChkAction
&& !m_pActionViewShell
->ActionPend()) )
2588 return m_pActionViewShell
;
2590 if( dynamic_cast< const SwEditShell
*>( m_pActionViewShell
) != nullptr )
2592 //Schon gescrollt?, dann dafuer sorgen, dass die View sich nicht bewegt!
2593 const bool bOldLock
= m_pActionViewShell
->IsViewLocked();
2594 m_pActionViewShell
->LockView( true );
2595 const bool bOldEndActionByVirDev
= m_pActionViewShell
->IsEndActionByVirDev();
2596 m_pActionViewShell
->SetEndActionByVirDev( true );
2597 static_cast<SwEditShell
*>(m_pActionViewShell
)->EndAction();
2598 m_pActionViewShell
->SetEndActionByVirDev( bOldEndActionByVirDev
);
2599 m_pActionViewShell
->LockView( bOldLock
);
2601 // bChkJumpMark ist nur gesetzt, wenn das Object auch gefunden wurde
2602 if( m_bChkJumpMark
)
2604 const Point
aVisSttPos( DOCUMENTBORDER
, DOCUMENTBORDER
);
2605 if( GetMedium() && aVisSttPos
== m_pActionViewShell
->VisArea().Pos() )
2606 ::JumpToSwMark( m_pActionViewShell
,
2607 GetMedium()->GetURLObject().GetMark() );
2608 m_bChkJumpMark
= false;
2612 m_pActionViewShell
->EndAction();
2614 // sollte der Parser der Letzte sein, der das Doc haelt, dann kann
2615 // man hier abbrechen und einen Fehler setzen.
2616 if( 1 == m_pDoc
->getReferenceCount() )
2618 eState
= SVPAR_ERROR
;
2621 SwViewShell
*pVSh
= m_pActionViewShell
;
2622 m_pActionViewShell
= nullptr;
2627 SwViewShell
*SwHTMLParser::CheckActionViewShell()
2629 SwViewShell
*pVSh
= m_pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell();
2630 OSL_ENSURE( !pVSh
|| m_pActionViewShell
== pVSh
,
2631 "CheckActionViewShell: Wer hat die SwViewShell ausgetauscht?" );
2632 #if OSL_DEBUG_LEVEL > 0
2633 if( m_pActionViewShell
&& !pVSh
)
2636 if( pVSh
!= m_pActionViewShell
)
2637 m_pActionViewShell
= nullptr;
2639 return m_pActionViewShell
;
2642 void SwHTMLParser::SetAttr_( bool bChkEnd
, bool bBeforeTable
,
2643 HTMLAttrs
*pPostIts
)
2645 std::unique_ptr
<SwPaM
> pAttrPam( new SwPaM( *m_pPam
->GetPoint() ) );
2646 const SwNodeIndex
& rEndIdx
= m_pPam
->GetPoint()->nNode
;
2647 const sal_Int32 nEndCnt
= m_pPam
->GetPoint()->nContent
.GetIndex();
2649 SwContentNode
* pCNd
;
2653 for( auto n
= m_aSetAttrTab
.size(); n
; )
2655 pAttr
= m_aSetAttrTab
[ --n
];
2656 sal_uInt16 nWhich
= pAttr
->pItem
->Which();
2658 sal_uLong nEndParaIdx
= pAttr
->GetEndParaIdx();
2662 // Zechen-Attribute mit Ende moeglich frueh,
2663 // also noch im aktuellen Absatz setzen (wegen JavaScript
2664 // und diversen Chats). das darf man aber nicht fuer Attribute,
2665 // die ueber den ganzen Absatz aufgspannt werden sollen, weil
2666 // sie aus Absatzvorlgen stammen, die nicht gesetzt werden
2667 // koennen. Weil die Attribute mit SETATTR_DONTREPLACE
2668 // eingefuegt werden, sollte man sie auch anchtraeglich
2669 // noch setzen koennen.
2670 bSetAttr
= ( nEndParaIdx
< rEndIdx
.GetIndex() &&
2671 (RES_LR_SPACE
!= nWhich
|| !GetNumInfo().GetNumRule()) ) ||
2672 ( !pAttr
->IsLikePara() &&
2673 nEndParaIdx
== rEndIdx
.GetIndex() &&
2674 pAttr
->GetEndCnt() < nEndCnt
&&
2675 (isCHRATR(nWhich
) || isTXTATR_WITHEND(nWhich
)) ) ||
2677 nEndParaIdx
== rEndIdx
.GetIndex() &&
2678 !pAttr
->GetEndCnt() );
2682 // Attribute im Content-Bereich duerfen nicht gesetzt
2683 // werden, wenn wir in einem Sonderbereich stehen, aber
2684 // umgekekehrt schon.
2685 sal_uLong nEndOfIcons
= m_pDoc
->GetNodes().GetEndOfExtras().GetIndex();
2686 bSetAttr
= nEndParaIdx
< rEndIdx
.GetIndex() ||
2687 rEndIdx
.GetIndex() > nEndOfIcons
||
2688 nEndParaIdx
<= nEndOfIcons
;
2693 // Das Attribute darf nicht in der liste der vorlaeufigen
2694 // Absatz-Attribute stehen, weil es sonst geloescht wurde.
2695 while( !m_aParaAttrs
.empty() )
2697 OSL_ENSURE( pAttr
!= m_aParaAttrs
.back(),
2698 "SetAttr: Attribut duerfte noch nicht gesetzt werden" );
2699 m_aParaAttrs
.pop_back();
2703 m_aSetAttrTab
.erase( m_aSetAttrTab
.begin() + n
);
2707 HTMLAttr
*pPrev
= pAttr
->GetPrev();
2708 if( !pAttr
->bValid
)
2710 // ungueltige Attribute koennen gloescht werden
2716 pCNd
= pAttr
->nSttPara
.GetNode().GetContentNode();
2719 // durch die elende Loescherei von Nodes kann auch mal
2720 // ein Index auf einen End-Node zeigen :-(
2721 if ( (pAttr
->GetSttPara() == pAttr
->GetEndPara()) &&
2722 !isTXTATR_NOEND(nWhich
) )
2724 // wenn der End-Index auch auf den Node zeigt
2725 // brauchen wir auch kein Attribut mehr zu setzen,
2726 // es sei denn, es ist ein Text-Attribut.
2731 pCNd
= m_pDoc
->GetNodes().GoNext( &(pAttr
->nSttPara
) );
2733 pAttr
->nSttContent
= 0;
2736 OSL_ENSURE( false, "SetAttr: GoNext() failed!" );
2742 pAttrPam
->GetPoint()->nNode
= pAttr
->nSttPara
;
2744 // durch das Loeschen von BRs kann der Start-Index
2745 // auch mal hinter das Ende des Textes zeigen
2746 if( pAttr
->nSttContent
> pCNd
->Len() )
2747 pAttr
->nSttContent
= pCNd
->Len();
2748 pAttrPam
->GetPoint()->nContent
.Assign( pCNd
, pAttr
->nSttContent
);
2750 pAttrPam
->SetMark();
2751 if ( (pAttr
->GetSttPara() != pAttr
->GetEndPara()) &&
2752 !isTXTATR_NOEND(nWhich
) )
2754 pCNd
= pAttr
->nEndPara
.GetNode().GetContentNode();
2757 pCNd
= SwNodes::GoPrevious( &(pAttr
->nEndPara
) );
2759 pAttr
->nEndContent
= pCNd
->Len();
2762 OSL_ENSURE( false, "SetAttr: GoPrevious() failed!" );
2763 pAttrPam
->DeleteMark();
2770 pAttrPam
->GetPoint()->nNode
= pAttr
->nEndPara
;
2772 else if( pAttr
->IsLikePara() )
2774 pAttr
->nEndContent
= pCNd
->Len();
2777 // durch das Loeschen von BRs kann der End-Index
2778 // auch mal hinter das Ende des Textes zeigen
2779 if( pAttr
->nEndContent
> pCNd
->Len() )
2780 pAttr
->nEndContent
= pCNd
->Len();
2782 pAttrPam
->GetPoint()->nContent
.Assign( pCNd
, pAttr
->nEndContent
);
2784 pAttrPam
->GetPoint()->nNode
.GetIndex() ==
2785 rEndIdx
.GetIndex() )
2787 // wenn wir vor dem Einfuegen einer Tabelle stehen
2788 // und das Attribut im aktuellen Node beendet wird,
2789 // muessen wir es im Node davor beenden oder wegschmeissen,
2790 // wenn es erst in dem Node beginnt
2791 if( nWhich
!= RES_BREAK
&& nWhich
!= RES_PAGEDESC
&&
2792 !isTXTATR_NOEND(nWhich
) )
2794 if( pAttrPam
->GetMark()->nNode
.GetIndex() !=
2795 rEndIdx
.GetIndex() )
2797 OSL_ENSURE( !pAttrPam
->GetPoint()->nContent
.GetIndex(),
2798 "Content-Position vor Tabelle nicht 0???" );
2799 pAttrPam
->Move( fnMoveBackward
);
2803 pAttrPam
->DeleteMark();
2813 case RES_FLTR_BOOKMARK
: // insert bookmark
2815 const OUString
sName( static_cast<SfxStringItem
*>(pAttr
->pItem
)->GetValue() );
2816 IDocumentMarkAccess
* const pMarkAccess
= m_pDoc
->getIDocumentMarkAccess();
2817 IDocumentMarkAccess::const_iterator_t ppBkmk
= pMarkAccess
->findMark( sName
);
2818 if( ppBkmk
!= pMarkAccess
->getAllMarksEnd() &&
2819 ppBkmk
->get()->GetMarkStart() == *pAttrPam
->GetPoint() )
2820 break; // do not generate duplicates on this position
2821 pAttrPam
->DeleteMark();
2822 const ::sw::mark::IMark
* const pNewMark
= pMarkAccess
->makeMark(
2825 IDocumentMarkAccess::MarkType::BOOKMARK
,
2826 ::sw::mark::InsertMode::New
);
2829 if( JUMPTO_MARK
== m_eJumpTo
&& pNewMark
->GetName() == m_sJmpMark
)
2831 m_bChkJumpMark
= true;
2832 m_eJumpTo
= JUMPTO_NONE
;
2836 case RES_TXTATR_FIELD
:
2837 case RES_TXTATR_ANNOTATION
:
2838 case RES_TXTATR_INPUTFIELD
:
2840 sal_uInt16 nFieldWhich
=
2842 ? static_cast<const SwFormatField
*>(pAttr
->pItem
)->GetField()->GetTyp()->Which()
2844 if( pPostIts
&& (RES_POSTITFLD
== nFieldWhich
||
2845 RES_SCRIPTFLD
== nFieldWhich
) )
2847 pPostIts
->push_front( pAttr
);
2851 aFields
.push_back( pAttr
);
2854 pAttrPam
->DeleteMark();
2859 if( pAttrPam
->GetPoint()->nNode
.GetIndex() ==
2860 pAttrPam
->GetMark()->nNode
.GetIndex() &&
2863 // wegen Numerierungen dieses Attribut direkt
2865 pCNd
->SetAttr( *pAttr
->pItem
);
2869 "LRSpace ueber mehrere Absaetze gesetzt!" );
2870 SAL_FALLTHROUGH
; // (shouldn't reach this point anyway)
2872 // tdf#94088 expand RES_BACKGROUND to the new fill attribute
2873 // definitions in the range [XATTR_FILL_FIRST .. XATTR_FILL_LAST].
2874 // This is the right place in the future if the adapted fill attributes
2875 // may be handled more directly in HTML import to handle them.
2876 case RES_BACKGROUND
:
2878 const SvxBrushItem
& rBrush
= static_cast< SvxBrushItem
& >(*pAttr
->pItem
);
2879 SfxItemSet
aNewSet(m_pDoc
->GetAttrPool(), XATTR_FILL_FIRST
, XATTR_FILL_LAST
);
2881 setSvxBrushItemAsFillAttributesToTargetSet(rBrush
, aNewSet
);
2882 m_pDoc
->getIDocumentContentOperations().InsertItemSet(*pAttrPam
, aNewSet
, SetAttrMode::DONTREPLACE
);
2887 // ggfs. ein Bookmark anspringen
2888 if( RES_TXTATR_INETFMT
== nWhich
&&
2889 JUMPTO_MARK
== m_eJumpTo
&&
2890 m_sJmpMark
== static_cast<SwFormatINetFormat
*>(pAttr
->pItem
)->GetName() )
2892 m_bChkJumpMark
= true;
2893 m_eJumpTo
= JUMPTO_NONE
;
2896 m_pDoc
->getIDocumentContentOperations().InsertPoolItem( *pAttrPam
, *pAttr
->pItem
, SetAttrMode::DONTREPLACE
);
2898 pAttrPam
->DeleteMark();
2906 for( auto n
= m_aMoveFlyFrames
.size(); n
; )
2908 SwFrameFormat
*pFrameFormat
= m_aMoveFlyFrames
[ --n
];
2910 const SwFormatAnchor
& rAnchor
= pFrameFormat
->GetAnchor();
2911 OSL_ENSURE( FLY_AT_PARA
== rAnchor
.GetAnchorId(),
2912 "Nur Auto-Rahmen brauchen eine Spezialbehandlung" );
2913 const SwPosition
*pFlyPos
= rAnchor
.GetContentAnchor();
2914 sal_uLong nFlyParaIdx
= pFlyPos
->nNode
.GetIndex();
2918 bMoveFly
= nFlyParaIdx
< rEndIdx
.GetIndex() ||
2919 ( nFlyParaIdx
== rEndIdx
.GetIndex() &&
2920 m_aMoveFlyCnts
[n
] < nEndCnt
);
2924 sal_uLong nEndOfIcons
= m_pDoc
->GetNodes().GetEndOfExtras().GetIndex();
2925 bMoveFly
= nFlyParaIdx
< rEndIdx
.GetIndex() ||
2926 rEndIdx
.GetIndex() > nEndOfIcons
||
2927 nFlyParaIdx
<= nEndOfIcons
;
2931 pFrameFormat
->DelFrames();
2932 *pAttrPam
->GetPoint() = *pFlyPos
;
2933 pAttrPam
->GetPoint()->nContent
.Assign( pAttrPam
->GetContentNode(),
2934 m_aMoveFlyCnts
[n
] );
2935 SwFormatAnchor
aAnchor( rAnchor
);
2936 aAnchor
.SetType( FLY_AT_CHAR
);
2937 aAnchor
.SetAnchor( pAttrPam
->GetPoint() );
2938 pFrameFormat
->SetFormatAttr( aAnchor
);
2940 const SwFormatHoriOrient
& rHoriOri
= pFrameFormat
->GetHoriOrient();
2941 if( text::HoriOrientation::LEFT
== rHoriOri
.GetHoriOrient() )
2943 SwFormatHoriOrient
aHoriOri( rHoriOri
);
2944 aHoriOri
.SetRelationOrient( text::RelOrientation::CHAR
);
2945 pFrameFormat
->SetFormatAttr( aHoriOri
);
2947 const SwFormatVertOrient
& rVertOri
= pFrameFormat
->GetVertOrient();
2948 if( text::VertOrientation::TOP
== rVertOri
.GetVertOrient() )
2950 SwFormatVertOrient
aVertOri( rVertOri
);
2951 aVertOri
.SetRelationOrient( text::RelOrientation::CHAR
);
2952 pFrameFormat
->SetFormatAttr( aVertOri
);
2955 pFrameFormat
->MakeFrames();
2956 m_aMoveFlyFrames
.erase( m_aMoveFlyFrames
.begin() + n
);
2957 m_aMoveFlyCnts
.erase( m_aMoveFlyCnts
.begin() + n
);
2960 while( !aFields
.empty() )
2964 pCNd
= pAttr
->nSttPara
.GetNode().GetContentNode();
2965 pAttrPam
->GetPoint()->nNode
= pAttr
->nSttPara
;
2966 pAttrPam
->GetPoint()->nContent
.Assign( pCNd
, pAttr
->nSttContent
);
2969 pAttrPam
->GetPoint()->nNode
.GetIndex() == rEndIdx
.GetIndex() )
2971 OSL_ENSURE( !bBeforeTable
, "Aha, der Fall tritt also doch ein" );
2972 OSL_ENSURE( !pAttrPam
->GetPoint()->nContent
.GetIndex(),
2973 "Content-Position vor Tabelle nicht 0???" );
2975 pAttrPam
->Move( fnMoveBackward
);
2978 m_pDoc
->getIDocumentContentOperations().InsertPoolItem( *pAttrPam
, *pAttr
->pItem
);
2980 aFields
.pop_front();
2985 void SwHTMLParser::NewAttr( HTMLAttr
**ppAttr
, const SfxPoolItem
& rItem
)
2987 // Font-Hoehen und -Farben- sowie Escapement-Attribute duerfen nicht
2988 // zusammengefasst werden. Sie werden deshalb in einer Liste gespeichert,
2989 // in der das zuletzt aufgespannte Attribut vorne steht und der Count
2990 // immer 1 ist. Fuer alle anderen Attribute wird der Count einfach
2994 HTMLAttr
*pAttr
= new HTMLAttr( *m_pPam
->GetPoint(), rItem
,
2996 pAttr
->InsertNext( *ppAttr
);
3000 (*ppAttr
) = new HTMLAttr( *m_pPam
->GetPoint(), rItem
, ppAttr
);
3003 bool SwHTMLParser::EndAttr( HTMLAttr
* pAttr
, bool bChkEmpty
)
3007 // Der Listenkopf ist im Attribut gespeichert
3008 HTMLAttr
**ppHead
= pAttr
->ppHead
;
3010 OSL_ENSURE( ppHead
, "keinen Attributs-Listenkopf gefunden!" );
3012 // die aktuelle Position als Ende-Position merken
3013 const SwNodeIndex
* pEndIdx
= &m_pPam
->GetPoint()->nNode
;
3014 sal_Int32 nEndCnt
= m_pPam
->GetPoint()->nContent
.GetIndex();
3016 // WIrd das zueltzt gestartete oder ein frueher gestartetes Attribut
3018 HTMLAttr
*pLast
= nullptr;
3019 if( ppHead
&& pAttr
!= *ppHead
)
3021 // Es wird nicht das zuletzt gestartete Attribut beendet
3023 // Dann suche wir das unmittelbar danach gestartete Attribut, das
3024 // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
3025 // mehr in der Liste
3027 while( pLast
&& pLast
->GetNext() != pAttr
)
3028 pLast
= pLast
->GetNext();
3030 OSL_ENSURE( pLast
, "Attribut nicht in eigener Liste gefunden!" );
3033 bool bMoveBack
= false;
3034 sal_uInt16 nWhich
= pAttr
->pItem
->Which();
3035 if( !nEndCnt
&& RES_PARATR_BEGIN
<= nWhich
&&
3036 *pEndIdx
!= pAttr
->GetSttPara() )
3038 // dann eine Contentnt Position zurueck!
3039 bMoveBack
= m_pPam
->Move( fnMoveBackward
);
3040 nEndCnt
= m_pPam
->GetPoint()->nContent
.GetIndex();
3043 // nun das Attrubut beenden
3044 HTMLAttr
*pNext
= pAttr
->GetNext();
3047 sal_uInt16 nScriptItem
= 0;
3048 bool bScript
= false;
3050 if( !bChkEmpty
|| (RES_PARATR_BEGIN
<= nWhich
&& bMoveBack
) ||
3051 RES_PAGEDESC
== nWhich
|| RES_BREAK
== nWhich
||
3052 *pEndIdx
!= pAttr
->GetSttPara() ||
3053 nEndCnt
!= pAttr
->GetSttCnt() )
3056 // We do some optimization for script dependent attributes here.
3057 if( *pEndIdx
== pAttr
->GetSttPara() )
3060 lcl_swhtml_getItemInfo( *pAttr
, bScript
, bFont
, nScriptItem
);
3068 if( bInsert
&& bScript
)
3070 const SwTextNode
*pTextNd
= pAttr
->GetSttPara().GetNode()
3072 OSL_ENSURE( pTextNd
, "No text node" );
3073 const OUString
& rText
= pTextNd
->GetText();
3074 sal_uInt16 nScriptText
= g_pBreakIt
->GetBreakIter()->getScriptType(
3075 rText
, pAttr
->GetSttCnt() );
3076 sal_Int32 nScriptEnd
= g_pBreakIt
->GetBreakIter()
3077 ->endOfScript( rText
, pAttr
->GetSttCnt(), nScriptText
);
3078 while (nScriptEnd
< nEndCnt
&& nScriptEnd
!= -1)
3080 if( nScriptItem
== nScriptText
)
3082 HTMLAttr
*pSetAttr
= pAttr
->Clone( *pEndIdx
, nScriptEnd
);
3083 pSetAttr
->ClearPrev();
3085 pNext
->InsertPrev( pSetAttr
);
3088 if (pSetAttr
->bInsAtStart
)
3089 m_aSetAttrTab
.push_front( pSetAttr
);
3091 m_aSetAttrTab
.push_back( pSetAttr
);
3094 pAttr
->nSttContent
= nScriptEnd
;
3095 nScriptText
= g_pBreakIt
->GetBreakIter()->getScriptType(
3096 rText
, nScriptEnd
);
3097 nScriptEnd
= g_pBreakIt
->GetBreakIter()
3098 ->endOfScript( rText
, nScriptEnd
, nScriptText
);
3100 bInsert
= nScriptItem
== nScriptText
;
3104 pAttr
->nEndPara
= *pEndIdx
;
3105 pAttr
->nEndContent
= nEndCnt
;
3106 pAttr
->bInsAtStart
= RES_TXTATR_INETFMT
!= nWhich
&&
3107 RES_TXTATR_CHARFMT
!= nWhich
;
3111 // keine offenen Attribute dieses Typs mehr da,
3112 // dann koennen alle gesetzt werden, es sei denn
3113 // sie haengen noch von einem anderen Attribut ab,
3114 // dann werden sie dort angehaengt
3115 if (pAttr
->bInsAtStart
)
3116 m_aSetAttrTab
.push_front( pAttr
);
3118 m_aSetAttrTab
.push_back( pAttr
);
3122 // es gibt noch andere offene Attribute des Typs,
3123 // daher muss das Setzen zurueckgestellt werden.
3124 // das aktuelle Attribut wird deshalb hinten an die
3125 // Previous-Liste des Nachfolgers angehaengt
3126 pNext
->InsertPrev( pAttr
);
3131 // dann nicht einfuegen, sondern Loeschen. Durch das "tuerken" von
3132 // Vorlagen durch harte Attributierung koennen sich auch mal andere
3133 // leere Attribute in der Prev-Liste befinden, die dann trotzdem
3134 // gesetzt werden muessen
3135 HTMLAttr
*pPrev
= pAttr
->GetPrev();
3141 // Die Previous-Attribute muessen trotzdem gesetzt werden.
3143 pNext
->InsertPrev( pPrev
);
3146 if (pPrev
->bInsAtStart
)
3147 m_aSetAttrTab
.push_front( pPrev
);
3149 m_aSetAttrTab
.push_back( pPrev
);
3155 // wenn das erste Attribut der Liste gesetzt wurde muss noch der
3156 // Listenkopf korrigiert werden.
3158 pLast
->pNext
= pNext
;
3163 m_pPam
->Move( fnMoveForward
);
3168 void SwHTMLParser::DeleteAttr( HTMLAttr
* pAttr
)
3170 // preliminary paragraph attributes are not allowed here, they could
3171 // be set here and then the pointers become invalid!
3172 OSL_ENSURE(m_aParaAttrs
.empty(),
3173 "Danger: there are non-final paragraph attributes");
3174 if( !m_aParaAttrs
.empty() )
3175 m_aParaAttrs
.clear();
3177 // Der Listenkopf ist im Attribut gespeichert
3178 HTMLAttr
**ppHead
= pAttr
->ppHead
;
3180 OSL_ENSURE( ppHead
, "keinen Attributs-Listenkopf gefunden!" );
3182 // Wird das zueltzt gestartete oder ein frueher gestartetes Attribut
3184 HTMLAttr
*pLast
= nullptr;
3185 if( ppHead
&& pAttr
!= *ppHead
)
3187 // Es wird nicht das zuletzt gestartete Attribut beendet
3189 // Dann suche wir das unmittelbar danach gestartete Attribut, das
3190 // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
3191 // mehr in der Liste
3193 while( pLast
&& pLast
->GetNext() != pAttr
)
3194 pLast
= pLast
->GetNext();
3196 OSL_ENSURE( pLast
, "Attribut nicht in eigener Liste gefunden!" );
3199 // nun das Attrubut entfernen
3200 HTMLAttr
*pNext
= pAttr
->GetNext();
3201 HTMLAttr
*pPrev
= pAttr
->GetPrev();
3206 // Die Previous-Attribute muessen trotzdem gesetzt werden.
3208 pNext
->InsertPrev( pPrev
);
3211 if (pPrev
->bInsAtStart
)
3212 m_aSetAttrTab
.push_front( pPrev
);
3214 m_aSetAttrTab
.push_back( pPrev
);
3218 // wenn das erste Attribut der Liste entfernt wurde muss noch der
3219 // Listenkopf korrigiert werden.
3221 pLast
->pNext
= pNext
;
3226 void SwHTMLParser::SaveAttrTab( HTMLAttrTable
& rNewAttrTab
)
3228 // preliminary paragraph attributes are not allowed here, they could
3229 // be set here and then the pointers become invalid!
3230 OSL_ENSURE(m_aParaAttrs
.empty(),
3231 "Danger: there are non-final paragraph attributes");
3232 if( !m_aParaAttrs
.empty() )
3233 m_aParaAttrs
.clear();
3235 HTMLAttr
** pHTMLAttributes
= reinterpret_cast<HTMLAttr
**>(&m_aAttrTab
);
3236 HTMLAttr
** pSaveAttributes
= reinterpret_cast<HTMLAttr
**>(&rNewAttrTab
);
3238 for (auto nCnt
= sizeof(HTMLAttrTable
) / sizeof(HTMLAttr
*); nCnt
--; ++pHTMLAttributes
, ++pSaveAttributes
)
3240 *pSaveAttributes
= *pHTMLAttributes
;
3242 HTMLAttr
*pAttr
= *pSaveAttributes
;
3245 pAttr
->SetHead(pSaveAttributes
);
3246 pAttr
= pAttr
->GetNext();
3249 *pHTMLAttributes
= nullptr;
3253 void SwHTMLParser::SplitAttrTab( HTMLAttrTable
& rNewAttrTab
,
3256 // preliminary paragraph attributes are not allowed here, they could
3257 // be set here and then the pointers become invalid!
3258 OSL_ENSURE(m_aParaAttrs
.empty(),
3259 "Danger: there are non-final paragraph attributes");
3260 if( !m_aParaAttrs
.empty() )
3261 m_aParaAttrs
.clear();
3263 const SwNodeIndex
& nSttIdx
= m_pPam
->GetPoint()->nNode
;
3264 SwNodeIndex
nEndIdx( nSttIdx
);
3266 // alle noch offenen Attribute beenden und hinter der Tabelle
3268 HTMLAttr
** pHTMLAttributes
= reinterpret_cast<HTMLAttr
**>(&m_aAttrTab
);
3269 HTMLAttr
** pSaveAttributes
= reinterpret_cast<HTMLAttr
**>(&rNewAttrTab
);
3270 bool bSetAttr
= true;
3271 const sal_Int32 nSttCnt
= m_pPam
->GetPoint()->nContent
.GetIndex();
3272 sal_Int32 nEndCnt
= nSttCnt
;
3276 sal_uLong nOldEnd
= nEndIdx
.GetIndex();
3278 if( ( nTmpIdx
= m_pDoc
->GetNodes().GetEndOfExtras().GetIndex()) >= nOldEnd
||
3279 ( nTmpIdx
= m_pDoc
->GetNodes().GetEndOfAutotext().GetIndex()) >= nOldEnd
)
3281 nTmpIdx
= m_pDoc
->GetNodes().GetEndOfInserts().GetIndex();
3283 SwContentNode
* pCNd
= SwNodes::GoPrevious(&nEndIdx
);
3285 // keine Attribute setzen, wenn der PaM aus dem Content-Bereich
3286 // herausgeschoben wurde.
3287 bSetAttr
= pCNd
&& nTmpIdx
< nEndIdx
.GetIndex();
3289 nEndCnt
= (bSetAttr
? pCNd
->Len() : 0);
3291 for (auto nCnt
= sizeof(HTMLAttrTable
) / sizeof(HTMLAttr
*); nCnt
--; (++pHTMLAttributes
, ++pSaveAttributes
))
3293 HTMLAttr
*pAttr
= *pHTMLAttributes
;
3294 *pSaveAttributes
= nullptr;
3297 HTMLAttr
*pNext
= pAttr
->GetNext();
3298 HTMLAttr
*pPrev
= pAttr
->GetPrev();
3301 ( pAttr
->GetSttParaIdx() < nEndIdx
.GetIndex() ||
3302 (pAttr
->GetSttPara() == nEndIdx
&&
3303 pAttr
->GetSttCnt() != nEndCnt
) ) )
3305 // das Attribut muss vor der Liste gesetzt werden. Da wir
3306 // das Original noch brauchen, weil Zeiger auf das Attribut
3307 // noch in den Kontexten existieren, muessen wir es clonen.
3308 // Die Next-Liste geht dabei verloren, aber die
3309 // Previous-Liste bleibt erhalten
3310 HTMLAttr
*pSetAttr
= pAttr
->Clone( nEndIdx
, nEndCnt
);
3313 pNext
->InsertPrev( pSetAttr
);
3316 if (pSetAttr
->bInsAtStart
)
3317 m_aSetAttrTab
.push_front( pSetAttr
);
3319 m_aSetAttrTab
.push_back( pSetAttr
);
3324 // Wenn das Attribut nicht gesetzt vor der Tabelle
3325 // gesetzt werden muss, muessen der Previous-Attribute
3326 // trotzdem gesetzt werden.
3328 pNext
->InsertPrev( pPrev
);
3331 if (pPrev
->bInsAtStart
)
3332 m_aSetAttrTab
.push_front( pPrev
);
3334 m_aSetAttrTab
.push_back( pPrev
);
3338 // den Start des Attributs neu setzen und die Verkettungen
3340 pAttr
->Reset(nSttIdx
, nSttCnt
, pSaveAttributes
);
3342 if (*pSaveAttributes
)
3344 HTMLAttr
*pSAttr
= *pSaveAttributes
;
3345 while( pSAttr
->GetNext() )
3346 pSAttr
= pSAttr
->GetNext();
3347 pSAttr
->InsertNext( pAttr
);
3350 *pSaveAttributes
= pAttr
;
3355 *pHTMLAttributes
= nullptr;
3359 void SwHTMLParser::RestoreAttrTab( HTMLAttrTable
& rNewAttrTab
)
3361 // preliminary paragraph attributes are not allowed here, they could
3362 // be set here and then the pointers become invalid!
3363 OSL_ENSURE(m_aParaAttrs
.empty(),
3364 "Danger: there are non-final paragraph attributes");
3365 if( !m_aParaAttrs
.empty() )
3366 m_aParaAttrs
.clear();
3368 HTMLAttr
** pHTMLAttributes
= reinterpret_cast<HTMLAttr
**>(&m_aAttrTab
);
3369 HTMLAttr
** pSaveAttributes
= reinterpret_cast<HTMLAttr
**>(&rNewAttrTab
);
3371 for (auto nCnt
= sizeof(HTMLAttrTable
) / sizeof(HTMLAttr
*); nCnt
--; ++pHTMLAttributes
, ++pSaveAttributes
)
3373 OSL_ENSURE(!*pHTMLAttributes
, "Die Attribut-Tabelle ist nicht leer!");
3375 *pHTMLAttributes
= *pSaveAttributes
;
3377 HTMLAttr
*pAttr
= *pHTMLAttributes
;
3380 OSL_ENSURE( !pAttr
->GetPrev() || !pAttr
->GetPrev()->ppHead
,
3381 "Previous-Attribut hat noch einen Header" );
3382 pAttr
->SetHead(pHTMLAttributes
);
3383 pAttr
= pAttr
->GetNext();
3386 *pSaveAttributes
= nullptr;
3390 void SwHTMLParser::InsertAttr( const SfxPoolItem
& rItem
, bool bInsAtStart
)
3392 HTMLAttr
* pTmp
= new HTMLAttr( *m_pPam
->GetPoint(),
3395 m_aSetAttrTab
.push_front( pTmp
);
3397 m_aSetAttrTab
.push_back( pTmp
);
3400 void SwHTMLParser::InsertAttrs( HTMLAttrs
& rAttrs
)
3402 while( !rAttrs
.empty() )
3404 HTMLAttr
*pAttr
= rAttrs
.front();
3405 InsertAttr( pAttr
->GetItem(), false );
3411 void SwHTMLParser::NewStdAttr( int nToken
)
3413 OUString aId
, aStyle
, aLang
, aDir
;
3416 const HTMLOptions
& rHTMLOptions
= GetOptions();
3417 for (size_t i
= rHTMLOptions
.size(); i
; )
3419 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
3420 switch( rOption
.GetToken() )
3423 aId
= rOption
.GetString();
3426 aStyle
= rOption
.GetString();
3429 aClass
= rOption
.GetString();
3432 aLang
= rOption
.GetString();
3435 aDir
= rOption
.GetString();
3440 // einen neuen Kontext anlegen
3441 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( static_cast< sal_uInt16
>(nToken
) );
3444 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
3446 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
3447 SvxCSS1PropertyInfo aPropInfo
;
3449 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
3451 if( HTML_SPAN_ON
!= nToken
|| aClass
.isEmpty() ||
3452 !CreateContainer( aClass
, aItemSet
, aPropInfo
, pCntxt
) )
3453 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
3454 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
, true );
3458 // den Kontext merken
3459 PushContext( pCntxt
);
3462 void SwHTMLParser::NewStdAttr( int nToken
,
3463 HTMLAttr
**ppAttr
, const SfxPoolItem
& rItem
,
3464 HTMLAttr
**ppAttr2
, const SfxPoolItem
*pItem2
,
3465 HTMLAttr
**ppAttr3
, const SfxPoolItem
*pItem3
)
3467 OUString aId
, aStyle
, aClass
, aLang
, aDir
;
3469 const HTMLOptions
& rHTMLOptions
= GetOptions();
3470 for (size_t i
= rHTMLOptions
.size(); i
; )
3472 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
3473 switch( rOption
.GetToken() )
3476 aId
= rOption
.GetString();
3479 aStyle
= rOption
.GetString();
3482 aClass
= rOption
.GetString();
3485 aLang
= rOption
.GetString();
3488 aDir
= rOption
.GetString();
3493 // einen neuen Kontext anlegen
3494 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( static_cast< sal_uInt16
>(nToken
) );
3497 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
3499 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
3500 SvxCSS1PropertyInfo aPropInfo
;
3502 aItemSet
.Put( rItem
);
3504 aItemSet
.Put( *pItem2
);
3506 aItemSet
.Put( *pItem3
);
3508 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
3509 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
3511 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
, true );
3515 InsertAttr( ppAttr
,rItem
, pCntxt
);
3518 OSL_ENSURE( ppAttr2
, "missing table entry for item2" );
3519 InsertAttr( ppAttr2
, *pItem2
, pCntxt
);
3523 OSL_ENSURE( ppAttr3
, "missing table entry for item3" );
3524 InsertAttr( ppAttr3
, *pItem3
, pCntxt
);
3528 // den Kontext merken
3529 PushContext( pCntxt
);
3532 void SwHTMLParser::EndTag( int nToken
)
3534 // den Kontext holen
3535 HTMLAttrContext
*pCntxt
= PopContext( static_cast< sal_uInt16
>(nToken
& ~1) );
3538 // und ggf. die Attribute beenden
3539 EndContext( pCntxt
);
3544 void SwHTMLParser::NewBasefontAttr()
3546 OUString aId
, aStyle
, aClass
, aLang
, aDir
;
3547 sal_uInt16 nSize
= 3;
3549 const HTMLOptions
& rHTMLOptions
= GetOptions();
3550 for (size_t i
= rHTMLOptions
.size(); i
; )
3552 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
3553 switch( rOption
.GetToken() )
3556 nSize
= (sal_uInt16
)rOption
.GetNumber();
3559 aId
= rOption
.GetString();
3562 aStyle
= rOption
.GetString();
3565 aClass
= rOption
.GetString();
3568 aLang
= rOption
.GetString();
3571 aDir
= rOption
.GetString();
3582 // einen neuen Kontext anlegen
3583 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( HTML_BASEFONT_ON
);
3586 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
3588 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
3589 SvxCSS1PropertyInfo aPropInfo
;
3591 //CJK has different defaults
3592 SvxFontHeightItem
aFontHeight( m_aFontHeights
[nSize
-1], 100, RES_CHRATR_FONTSIZE
);
3593 aItemSet
.Put( aFontHeight
);
3594 SvxFontHeightItem
aFontHeightCJK( m_aFontHeights
[nSize
-1], 100, RES_CHRATR_CJK_FONTSIZE
);
3595 aItemSet
.Put( aFontHeightCJK
);
3596 //Complex type can contain so many types of letters,
3597 //that it's not really worthy to bother, IMO.
3598 //Still, I have set a default.
3599 SvxFontHeightItem
aFontHeightCTL( m_aFontHeights
[nSize
-1], 100, RES_CHRATR_CTL_FONTSIZE
);
3600 aItemSet
.Put( aFontHeightCTL
);
3602 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
3603 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
3605 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
, true );
3609 SvxFontHeightItem
aFontHeight( m_aFontHeights
[nSize
-1], 100, RES_CHRATR_FONTSIZE
);
3610 InsertAttr( &m_aAttrTab
.pFontHeight
, aFontHeight
, pCntxt
);
3611 SvxFontHeightItem
aFontHeightCJK( m_aFontHeights
[nSize
-1], 100, RES_CHRATR_CJK_FONTSIZE
);
3612 InsertAttr( &m_aAttrTab
.pFontHeightCJK
, aFontHeightCJK
, pCntxt
);
3613 SvxFontHeightItem
aFontHeightCTL( m_aFontHeights
[nSize
-1], 100, RES_CHRATR_CTL_FONTSIZE
);
3614 InsertAttr( &m_aAttrTab
.pFontHeightCTL
, aFontHeightCTL
, pCntxt
);
3617 // den Kontext merken
3618 PushContext( pCntxt
);
3620 // die Font-Size merken
3621 m_aBaseFontStack
.push_back( nSize
);
3624 void SwHTMLParser::EndBasefontAttr()
3626 EndTag( HTML_BASEFONT_ON
);
3628 // Stack-Unterlauf in Tabellen vermeiden
3629 if( m_aBaseFontStack
.size() > m_nBaseFontStMin
)
3630 m_aBaseFontStack
.erase( m_aBaseFontStack
.begin() + m_aBaseFontStack
.size() - 1 );
3633 void SwHTMLParser::NewFontAttr( int nToken
)
3635 sal_uInt16 nBaseSize
=
3636 ( m_aBaseFontStack
.size() > m_nBaseFontStMin
3637 ? (m_aBaseFontStack
[m_aBaseFontStack
.size()-1] & FONTSIZE_MASK
)
3639 sal_uInt16 nFontSize
=
3640 ( m_aFontStack
.size() > m_nFontStMin
3641 ? (m_aFontStack
[m_aFontStack
.size()-1] & FONTSIZE_MASK
)
3644 OUString aFace
, aId
, aStyle
, aClass
, aLang
, aDir
;
3646 sal_uLong nFontHeight
= 0; // tatsaechlich einzustellende Font-Hoehe
3647 sal_uInt16 nSize
= 0; // Fontgroesse in Netscape-Notation (1-7)
3648 bool bColor
= false;
3650 const HTMLOptions
& rHTMLOptions
= GetOptions();
3651 for (size_t i
= rHTMLOptions
.size(); i
; )
3653 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
3654 switch( rOption
.GetToken() )
3657 if( HTML_FONT_ON
==nToken
&& !rOption
.GetString().isEmpty() )
3660 if( '+' == rOption
.GetString()[0] ||
3661 '-' == rOption
.GetString()[0] )
3662 nSSize
= nBaseSize
+ rOption
.GetSNumber();
3664 nSSize
= (sal_Int32
)rOption
.GetNumber();
3668 else if( nSSize
> 7 )
3671 nSize
= (sal_uInt16
)nSSize
;
3672 nFontHeight
= m_aFontHeights
[nSize
-1];
3676 if( HTML_FONT_ON
==nToken
)
3678 rOption
.GetColor( aColor
);
3683 if( HTML_FONT_ON
==nToken
)
3684 aFace
= rOption
.GetString();
3687 aId
= rOption
.GetString();
3690 aStyle
= rOption
.GetString();
3693 aClass
= rOption
.GetString();
3696 aLang
= rOption
.GetString();
3699 aDir
= rOption
.GetString();
3704 if( HTML_FONT_ON
!= nToken
)
3706 // HTML_BIGPRINT_ON oder HTML_SMALLPRINT_ON
3708 // in Ueberschriften bestimmt die aktuelle Ueberschrift
3709 // die Font-Hoehe und nicht BASEFONT
3710 sal_uInt16 nPoolId
= GetCurrFormatColl()->GetPoolFormatId();
3711 if( (nPoolId
>=RES_POOLCOLL_HEADLINE1
&&
3712 nPoolId
<=RES_POOLCOLL_HEADLINE6
) )
3714 // wenn die Schriftgroesse in der Ueberschrift noch
3715 // nicht veraendert ist, die aus der Vorlage nehmen
3716 if( m_nFontStHeadStart
==m_aFontStack
.size() )
3717 nFontSize
= static_cast< sal_uInt16
>(6 - (nPoolId
- RES_POOLCOLL_HEADLINE1
));
3722 if( HTML_BIGPRINT_ON
== nToken
)
3723 nSize
= ( nFontSize
<7 ? nFontSize
+1 : 7 );
3725 nSize
= ( nFontSize
>1 ? nFontSize
-1 : 1 );
3727 // in Ueberschriften wird die neue Fonthoehe wenn moeglich aus
3728 // den Vorlagen geholt.
3729 if( nPoolId
&& nSize
>=1 && nSize
<=6 )
3731 m_pCSS1Parser
->GetTextCollFromPool(
3732 RES_POOLCOLL_HEADLINE1
+6-nSize
)->GetSize().GetHeight();
3734 nFontHeight
= m_aFontHeights
[nSize
-1];
3737 OSL_ENSURE( !nSize
== !nFontHeight
, "HTML-Font-Size != Font-Height" );
3739 OUString aFontName
, aStyleName
;
3740 FontFamily eFamily
= FAMILY_DONTKNOW
; // Family und Pitch,
3741 FontPitch ePitch
= PITCH_DONTKNOW
; // falls nicht gefunden
3742 rtl_TextEncoding eEnc
= osl_getThreadTextEncoding();
3744 if( !aFace
.isEmpty() && !m_pCSS1Parser
->IsIgnoreFontFamily() )
3746 const FontList
*pFList
= nullptr;
3747 SwDocShell
*pDocSh
= m_pDoc
->GetDocShell();
3750 const SvxFontListItem
*pFListItem
=
3751 static_cast<const SvxFontListItem
*>(pDocSh
->GetItem(SID_ATTR_CHAR_FONTLIST
));
3753 pFList
= pFListItem
->GetFontList();
3756 bool bFound
= false;
3757 sal_Int32 nStrPos
= 0;
3758 while( nStrPos
!= -1 )
3760 OUString aFName
= aFace
.getToken( 0, ',', nStrPos
);
3761 aFName
= comphelper::string::strip(aFName
, ' ');
3762 if( !aFName
.isEmpty() )
3764 if( !bFound
&& pFList
)
3766 sal_Handle hFont
= pFList
->GetFirstFontMetric( aFName
);
3767 if( nullptr != hFont
)
3769 const FontMetric
& rFMetric
= FontList::GetFontMetric( hFont
);
3770 if( RTL_TEXTENCODING_DONTKNOW
!= rFMetric
.GetCharSet() )
3773 if( RTL_TEXTENCODING_SYMBOL
== rFMetric
.GetCharSet() )
3774 eEnc
= RTL_TEXTENCODING_SYMBOL
;
3778 if( !aFontName
.isEmpty() )
3780 aFontName
+= aFName
;
3785 // einen neuen Kontext anlegen
3786 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( static_cast< sal_uInt16
>(nToken
) );
3789 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
3791 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
3792 SvxCSS1PropertyInfo aPropInfo
;
3796 SvxFontHeightItem
aFontHeight( nFontHeight
, 100, RES_CHRATR_FONTSIZE
);
3797 aItemSet
.Put( aFontHeight
);
3798 SvxFontHeightItem
aFontHeightCJK( nFontHeight
, 100, RES_CHRATR_CJK_FONTSIZE
);
3799 aItemSet
.Put( aFontHeightCJK
);
3800 SvxFontHeightItem
aFontHeightCTL( nFontHeight
, 100, RES_CHRATR_CTL_FONTSIZE
);
3801 aItemSet
.Put( aFontHeightCTL
);
3804 aItemSet
.Put( SvxColorItem(aColor
, RES_CHRATR_COLOR
) );
3805 if( !aFontName
.isEmpty() )
3807 SvxFontItem
aFont( eFamily
, aFontName
, aStyleName
, ePitch
, eEnc
, RES_CHRATR_FONT
);
3808 aItemSet
.Put( aFont
);
3809 SvxFontItem
aFontCJK( eFamily
, aFontName
, aStyleName
, ePitch
, eEnc
, RES_CHRATR_CJK_FONT
);
3810 aItemSet
.Put( aFontCJK
);
3811 SvxFontItem
aFontCTL( eFamily
, aFontName
, aStyleName
, ePitch
, eEnc
, RES_CHRATR_CTL_FONT
);
3812 aItemSet
.Put( aFontCTL
);
3815 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
3816 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
3818 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
, true );
3824 SvxFontHeightItem
aFontHeight( nFontHeight
, 100, RES_CHRATR_FONTSIZE
);
3825 InsertAttr( &m_aAttrTab
.pFontHeight
, aFontHeight
, pCntxt
);
3826 SvxFontHeightItem
aFontHeightCJK( nFontHeight
, 100, RES_CHRATR_CJK_FONTSIZE
);
3827 InsertAttr( &m_aAttrTab
.pFontHeight
, aFontHeightCJK
, pCntxt
);
3828 SvxFontHeightItem
aFontHeightCTL( nFontHeight
, 100, RES_CHRATR_CTL_FONTSIZE
);
3829 InsertAttr( &m_aAttrTab
.pFontHeight
, aFontHeightCTL
, pCntxt
);
3832 InsertAttr( &m_aAttrTab
.pFontColor
, SvxColorItem(aColor
, RES_CHRATR_COLOR
), pCntxt
);
3833 if( !aFontName
.isEmpty() )
3835 SvxFontItem
aFont( eFamily
, aFontName
, aStyleName
, ePitch
, eEnc
, RES_CHRATR_FONT
);
3836 InsertAttr( &m_aAttrTab
.pFont
, aFont
, pCntxt
);
3837 SvxFontItem
aFontCJK( eFamily
, aFontName
, aStyleName
, ePitch
, eEnc
, RES_CHRATR_CJK_FONT
);
3838 InsertAttr( &m_aAttrTab
.pFont
, aFontCJK
, pCntxt
);
3839 SvxFontItem
aFontCTL( eFamily
, aFontName
, aStyleName
, ePitch
, eEnc
, RES_CHRATR_CTL_FONT
);
3840 InsertAttr( &m_aAttrTab
.pFont
, aFontCTL
, pCntxt
);
3844 // den Kontext merken
3845 PushContext( pCntxt
);
3847 m_aFontStack
.push_back( nSize
);
3850 void SwHTMLParser::EndFontAttr( int nToken
)
3854 // Stack-Unterlauf in Tabellen vermeiden
3855 if( m_aFontStack
.size() > m_nFontStMin
)
3856 m_aFontStack
.erase( m_aFontStack
.begin() + m_aFontStack
.size() - 1 );
3859 void SwHTMLParser::NewPara()
3861 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
3862 AppendTextNode( AM_SPACE
);
3866 m_eParaAdjust
= SVX_ADJUST_END
;
3867 OUString aId
, aStyle
, aClass
, aLang
, aDir
;
3869 const HTMLOptions
& rHTMLOptions
= GetOptions();
3870 for (size_t i
= rHTMLOptions
.size(); i
; )
3872 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
3873 switch( rOption
.GetToken() )
3876 aId
= rOption
.GetString();
3879 m_eParaAdjust
= (SvxAdjust
)rOption
.GetEnum( aHTMLPAlignTable
, static_cast< sal_uInt16
>(m_eParaAdjust
) );
3882 aStyle
= rOption
.GetString();
3885 aClass
= rOption
.GetString();
3888 aLang
= rOption
.GetString();
3891 aDir
= rOption
.GetString();
3896 // einen neuen Kontext anlegen
3897 HTMLAttrContext
*pCntxt
=
3898 !aClass
.isEmpty() ? new HTMLAttrContext( HTML_PARABREAK_ON
,
3899 RES_POOLCOLL_TEXT
, aClass
)
3900 : new HTMLAttrContext( HTML_PARABREAK_ON
);
3902 // Styles parsen (Class nicht beruecksichtigen. Das geht nur, solange
3903 // keine der CSS1-Properties der Klasse hart formatiert werden muss!!!)
3904 if( HasStyleOptions( aStyle
, aId
, aEmptyOUStr
, &aLang
, &aDir
) )
3906 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
3907 SvxCSS1PropertyInfo aPropInfo
;
3909 if( ParseStyleOptions( aStyle
, aId
, aEmptyOUStr
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
3911 OSL_ENSURE( aClass
.isEmpty() || !m_pCSS1Parser
->GetClass( aClass
),
3912 "Class wird nicht beruecksichtigt" );
3913 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
3914 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
);
3918 if( SVX_ADJUST_END
!= m_eParaAdjust
)
3919 InsertAttr( &m_aAttrTab
.pAdjust
, SvxAdjustItem(m_eParaAdjust
, RES_PARATR_ADJUST
), pCntxt
);
3921 // und auf den Stack packen
3922 PushContext( pCntxt
);
3924 // die aktuelle Vorlage oder deren Attribute setzen
3925 SetTextCollAttrs( !aClass
.isEmpty() ? pCntxt
: nullptr );
3927 // Laufbalkenanzeige
3930 OSL_ENSURE( !m_nOpenParaToken
, "Jetzt geht ein offenes Absatz-Element verloren" );
3931 m_nOpenParaToken
= HTML_PARABREAK_ON
;
3934 void SwHTMLParser::EndPara( bool bReal
)
3936 if( HTML_LI_ON
==m_nOpenParaToken
&& m_pTable
)
3938 #if OSL_DEBUG_LEVEL > 0
3939 const SwNumRule
*pNumRule
= m_pPam
->GetNode().GetTextNode()->GetNumRule();
3940 OSL_ENSURE( pNumRule
, "Wo ist die Numrule geblieben" );
3944 // leere Absaetze werden von Netscape uebersprungen, von uns jetzt auch
3947 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
3948 AppendTextNode( AM_SPACE
);
3953 // wenn ein DD oder DT offen war, handelt es sich um eine
3954 // implizite Def-Liste, die jetzt beendet werden muss
3955 if( (m_nOpenParaToken
==HTML_DT_ON
|| m_nOpenParaToken
==HTML_DD_ON
) &&
3961 // den Kontext vom Stack holen. Er kann auch von einer implizit
3962 // geoeffneten Definitionsliste kommen
3963 HTMLAttrContext
*pCntxt
=
3964 PopContext( static_cast< sal_uInt16
>(m_nOpenParaToken
? (m_nOpenParaToken
& ~1)
3965 : HTML_PARABREAK_ON
) );
3967 // Attribute beenden
3970 EndContext( pCntxt
);
3971 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
3975 // und die bisherige Vorlage neu setzen
3979 m_nOpenParaToken
= 0;
3982 void SwHTMLParser::NewHeading( int nToken
)
3984 m_eParaAdjust
= SVX_ADJUST_END
;
3986 OUString aId
, aStyle
, aClass
, aLang
, aDir
;
3988 const HTMLOptions
& rHTMLOptions
= GetOptions();
3989 for (size_t i
= rHTMLOptions
.size(); i
; )
3991 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
3992 switch( rOption
.GetToken() )
3995 aId
= rOption
.GetString();
3998 m_eParaAdjust
= (SvxAdjust
)rOption
.GetEnum( aHTMLPAlignTable
, static_cast< sal_uInt16
>(m_eParaAdjust
) );
4001 aStyle
= rOption
.GetString();
4004 aClass
= rOption
.GetString();
4007 aLang
= rOption
.GetString();
4010 aDir
= rOption
.GetString();
4015 // einen neuen Absatz aufmachen
4016 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
4017 AppendTextNode( AM_SPACE
);
4021 // die passende Vorlage suchen
4022 sal_uInt16 nTextColl
;
4025 case HTML_HEAD1_ON
: nTextColl
= RES_POOLCOLL_HEADLINE1
; break;
4026 case HTML_HEAD2_ON
: nTextColl
= RES_POOLCOLL_HEADLINE2
; break;
4027 case HTML_HEAD3_ON
: nTextColl
= RES_POOLCOLL_HEADLINE3
; break;
4028 case HTML_HEAD4_ON
: nTextColl
= RES_POOLCOLL_HEADLINE4
; break;
4029 case HTML_HEAD5_ON
: nTextColl
= RES_POOLCOLL_HEADLINE5
; break;
4030 case HTML_HEAD6_ON
: nTextColl
= RES_POOLCOLL_HEADLINE6
; break;
4031 default: nTextColl
= RES_POOLCOLL_STANDARD
; break;
4034 // den Kontext anlegen
4035 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( static_cast< sal_uInt16
>(nToken
), nTextColl
, aClass
);
4037 // Styles parsen (zu Class siehe auch NewPara)
4038 if( HasStyleOptions( aStyle
, aId
, aEmptyOUStr
, &aLang
, &aDir
) )
4040 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
4041 SvxCSS1PropertyInfo aPropInfo
;
4043 if( ParseStyleOptions( aStyle
, aId
, aEmptyOUStr
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
4045 OSL_ENSURE( aClass
.isEmpty() || !m_pCSS1Parser
->GetClass( aClass
),
4046 "Class wird nicht beruecksichtigt" );
4047 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
4048 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
);
4052 if( SVX_ADJUST_END
!= m_eParaAdjust
)
4053 InsertAttr( &m_aAttrTab
.pAdjust
, SvxAdjustItem(m_eParaAdjust
, RES_PARATR_ADJUST
), pCntxt
);
4055 // udn auf den Stack packen
4056 PushContext( pCntxt
);
4058 // und die Vorlage oder deren Attribute setzen
4059 SetTextCollAttrs( pCntxt
);
4061 m_nFontStHeadStart
= m_aFontStack
.size();
4063 // Laufbalkenanzeige
4067 void SwHTMLParser::EndHeading()
4069 // einen neuen Absatz aufmachen
4070 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
4071 AppendTextNode( AM_SPACE
);
4075 // Kontext zu dem Token suchen und vom Stack holen
4076 HTMLAttrContext
*pCntxt
= nullptr;
4077 auto nPos
= m_aContexts
.size();
4078 while( !pCntxt
&& nPos
>m_nContextStMin
)
4080 switch( m_aContexts
[--nPos
]->GetToken() )
4088 pCntxt
= m_aContexts
[nPos
];
4089 m_aContexts
.erase( m_aContexts
.begin() + nPos
);
4094 // und noch Attribute beenden
4097 EndContext( pCntxt
);
4098 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4102 // die bisherige Vorlage neu setzen
4105 m_nFontStHeadStart
= m_nFontStMin
;
4108 void SwHTMLParser::NewTextFormatColl( int nToken
, sal_uInt16 nColl
)
4110 OUString aId
, aStyle
, aClass
, aLang
, aDir
;
4112 const HTMLOptions
& rHTMLOptions
= GetOptions();
4113 for (size_t i
= rHTMLOptions
.size(); i
; )
4115 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
4116 switch( rOption
.GetToken() )
4119 aId
= rOption
.GetString();
4122 aStyle
= rOption
.GetString();
4125 aClass
= rOption
.GetString();
4128 aLang
= rOption
.GetString();
4131 aDir
= rOption
.GetString();
4136 // einen neuen Absatz aufmachen
4137 SwHTMLAppendMode eMode
= AM_NORMAL
;
4140 case HTML_LISTING_ON
:
4142 // Diese beiden Tags werden jetzt auf die PRE-Vorlage gemappt.
4143 // Fuer dem Fall, dass ein CLASS angegeben ist, loeschen wir
4144 // es damit wir nicht die CLASS der PRE-Vorlage bekommen.
4145 aClass
= aEmptyOUStr
;
4147 case HTML_BLOCKQUOTE_ON
:
4148 case HTML_BLOCKQUOTE30_ON
:
4149 case HTML_PREFORMTXT_ON
:
4152 case HTML_ADDRESS_ON
:
4153 eMode
= AM_NOSPACE
; // ADDRESS kann auf einen <P> ohne </P> folgen
4157 eMode
= AM_SOFTNOSPACE
;
4160 OSL_ENSURE( false, "unbekannte Vorlage" );
4163 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
4164 AppendTextNode( eMode
);
4165 else if( AM_SPACE
==eMode
)
4168 // ... und in einem Kontext merken
4169 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( static_cast< sal_uInt16
>(nToken
), nColl
, aClass
);
4171 // Styles parsen (zu Class siehe auch NewPara)
4172 if( HasStyleOptions( aStyle
, aId
, aEmptyOUStr
, &aLang
, &aDir
) )
4174 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
4175 SvxCSS1PropertyInfo aPropInfo
;
4177 if( ParseStyleOptions( aStyle
, aId
, aEmptyOUStr
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
4179 OSL_ENSURE( aClass
.isEmpty() || !m_pCSS1Parser
->GetClass( aClass
),
4180 "Class wird nicht beruecksichtigt" );
4181 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
4182 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
);
4186 PushContext( pCntxt
);
4188 // die neue Vorlage setzen
4189 SetTextCollAttrs( pCntxt
);
4191 // Laufbalkenanzeige aktualisieren
4195 void SwHTMLParser::EndTextFormatColl( int nToken
)
4197 SwHTMLAppendMode eMode
= AM_NORMAL
;
4198 switch( nToken
& ~1 )
4200 case HTML_BLOCKQUOTE_ON
:
4201 case HTML_BLOCKQUOTE30_ON
:
4202 case HTML_PREFORMTXT_ON
:
4203 case HTML_LISTING_ON
:
4207 case HTML_ADDRESS_ON
:
4210 eMode
= AM_SOFTNOSPACE
;
4213 OSL_ENSURE( false, "unbekannte Vorlage" );
4216 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
4217 AppendTextNode( eMode
);
4218 else if( AM_SPACE
==eMode
)
4221 // den aktuellen Kontext vom Stack holen
4222 HTMLAttrContext
*pCntxt
= PopContext( static_cast< sal_uInt16
>(nToken
& ~1) );
4224 // und noch Attribute beenden
4227 EndContext( pCntxt
);
4228 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4232 // und die bisherige Vorlage setzen
4236 void SwHTMLParser::NewDefList()
4238 OUString aId
, aStyle
, aClass
, aLang
, aDir
;
4240 const HTMLOptions
& rHTMLOptions
= GetOptions();
4241 for (size_t i
= rHTMLOptions
.size(); i
; )
4243 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
4244 switch( rOption
.GetToken() )
4247 aId
= rOption
.GetString();
4250 aStyle
= rOption
.GetString();
4253 aClass
= rOption
.GetString();
4256 aLang
= rOption
.GetString();
4259 aDir
= rOption
.GetString();
4264 // einen neuen Absatz aufmachen
4265 bool bSpace
= (GetNumInfo().GetDepth() + m_nDefListDeep
) == 0;
4266 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
4267 AppendTextNode( bSpace
? AM_SPACE
: AM_SOFTNOSPACE
);
4274 bool bInDD
= false, bNotInDD
= false;
4275 auto nPos
= m_aContexts
.size();
4276 while( !bInDD
&& !bNotInDD
&& nPos
>m_nContextStMin
)
4278 sal_uInt16 nCntxtToken
= m_aContexts
[--nPos
]->GetToken();
4279 switch( nCntxtToken
)
4281 case HTML_DEFLIST_ON
:
4282 case HTML_DIRLIST_ON
:
4283 case HTML_MENULIST_ON
:
4284 case HTML_ORDERLIST_ON
:
4285 case HTML_UNORDERLIST_ON
:
4294 // ... und in einem Kontext merken
4295 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( HTML_DEFLIST_ON
);
4297 // darin auch die Raender merken
4298 sal_uInt16 nLeft
=0, nRight
=0;
4300 GetMarginsFromContext( nLeft
, nRight
, nIndent
);
4302 // Die Einrueckung, die sich schon aus einem DL-ergibt, entspricht der
4303 // eines DT auf dem aktuellen Level, und die entspricht der eines
4304 // DD auf dem Level davor. Fue einen Level >=2 muss also ein DD-Abstand
4305 // hinzugefuegt werden
4306 if( !bInDD
&& m_nDefListDeep
> 1 )
4309 // und den der DT-Vorlage des aktuellen Levels
4310 SvxLRSpaceItem rLRSpace
=
4311 m_pCSS1Parser
->GetTextFormatColl( RES_POOLCOLL_HTML_DD
, aEmptyOUStr
)
4313 nLeft
= nLeft
+ static_cast< sal_uInt16
>(rLRSpace
.GetTextLeft());
4316 pCntxt
->SetMargins( nLeft
, nRight
, nIndent
);
4319 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
4321 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
4322 SvxCSS1PropertyInfo aPropInfo
;
4324 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
4326 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
4327 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
);
4331 PushContext( pCntxt
);
4333 // die Attribute der neuen Vorlage setzen
4334 if( m_nDefListDeep
> 1 )
4335 SetTextCollAttrs( pCntxt
);
4338 void SwHTMLParser::EndDefList()
4340 bool bSpace
= (GetNumInfo().GetDepth() + m_nDefListDeep
) == 1;
4341 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
4342 AppendTextNode( bSpace
? AM_SPACE
: AM_SOFTNOSPACE
);
4346 // ein Level weniger
4347 if( m_nDefListDeep
> 0 )
4350 // den aktuellen Kontext vom Stack holen
4351 HTMLAttrContext
*pCntxt
= PopContext( HTML_DEFLIST_ON
);
4353 // und noch Attribute beenden
4356 EndContext( pCntxt
);
4357 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4361 // und Vorlage setzen
4365 void SwHTMLParser::NewDefListItem( int nToken
)
4367 // festellen, ob das DD/DT in einer DL vorkommt
4368 bool bInDefList
= false, bNotInDefList
= false;
4369 auto nPos
= m_aContexts
.size();
4370 while( !bInDefList
&& !bNotInDefList
&& nPos
>m_nContextStMin
)
4372 sal_uInt16 nCntxtToken
= m_aContexts
[--nPos
]->GetToken();
4373 switch( nCntxtToken
)
4375 case HTML_DEFLIST_ON
:
4378 case HTML_DIRLIST_ON
:
4379 case HTML_MENULIST_ON
:
4380 case HTML_ORDERLIST_ON
:
4381 case HTML_UNORDERLIST_ON
:
4382 bNotInDefList
= true;
4387 // wenn nicht, implizit eine neue DL aufmachen
4391 OSL_ENSURE( !m_nOpenParaToken
,
4392 "Jetzt geht ein offenes Absatz-Element verloren" );
4393 m_nOpenParaToken
= static_cast< sal_uInt16
>(nToken
);
4396 NewTextFormatColl( nToken
, static_cast< sal_uInt16
>(nToken
==HTML_DD_ON
? RES_POOLCOLL_HTML_DD
4397 : RES_POOLCOLL_HTML_DT
) );
4400 void SwHTMLParser::EndDefListItem( int nToken
, bool /*bLastPara*/ )
4402 // einen neuen Absatz aufmachen
4403 if( !nToken
&& m_pPam
->GetPoint()->nContent
.GetIndex() )
4404 AppendTextNode( AM_SOFTNOSPACE
);
4406 // Kontext zu dem Token suchen und vom Stack holen
4408 HTMLAttrContext
*pCntxt
= nullptr;
4409 auto nPos
= m_aContexts
.size();
4410 while( !pCntxt
&& nPos
>m_nContextStMin
)
4412 sal_uInt16 nCntxtToken
= m_aContexts
[--nPos
]->GetToken();
4413 switch( nCntxtToken
)
4417 if( !nToken
|| nToken
== nCntxtToken
)
4419 pCntxt
= m_aContexts
[nPos
];
4420 m_aContexts
.erase( m_aContexts
.begin() + nPos
);
4423 case HTML_DEFLIST_ON
:
4424 // keine DD/DT ausserhalb der aktuelen DefListe betrachten
4425 case HTML_DIRLIST_ON
:
4426 case HTML_MENULIST_ON
:
4427 case HTML_ORDERLIST_ON
:
4428 case HTML_UNORDERLIST_ON
:
4429 // und auch nicht ausserhalb einer anderen Liste
4430 nPos
= m_nContextStMin
;
4435 // und noch Attribute beenden
4438 EndContext( pCntxt
);
4439 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4444 bool SwHTMLParser::HasCurrentParaFlys( bool bNoSurroundOnly
,
4445 bool bSurroundOnly
) const
4447 // bNoSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
4449 // bSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
4450 // mit Umlauf aber keinen ohne Umlauf
4451 // sonst: Der Absatz enthaelt irgendeinen Rahmen
4452 SwNodeIndex
& rNodeIdx
= m_pPam
->GetPoint()->nNode
;
4454 const SwFrameFormats
& rFrameFormatTable
= *m_pDoc
->GetSpzFrameFormats();
4456 bool bFound
= false;
4457 for ( size_t i
=0; i
<rFrameFormatTable
.size(); i
++ )
4459 const SwFrameFormat
*const pFormat
= rFrameFormatTable
[i
];
4460 SwFormatAnchor
const*const pAnchor
= &pFormat
->GetAnchor();
4461 // Ein Rahmen wurde gefunden, wenn
4462 // - er absatzgebunden ist, und
4463 // - im aktuellen Absatz verankert ist, und
4464 // - jeder absatzgebunene Rahmen zaehlt, oder
4465 // - (nur Rahmen oder umlauf zaehlen und ) der Rahmen keinen
4467 SwPosition
const*const pAPos
= pAnchor
->GetContentAnchor();
4469 ((FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
4470 (FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
4471 pAPos
->nNode
== rNodeIdx
)
4473 if( !(bNoSurroundOnly
|| bSurroundOnly
) )
4480 // Wenn Rahmen mit Umlauf gesucht sind,
4481 // auch keine mit Durchlauf beachten. Dabei handelt es
4482 // sich (noch) um HIDDEN-Controls, und denen weicht man
4483 // besser auch nicht aus.
4484 SwSurround eSurround
= pFormat
->GetSurround().GetSurround();
4485 if( bNoSurroundOnly
)
4487 if( SURROUND_NONE
==eSurround
)
4495 if( SURROUND_NONE
==eSurround
)
4500 else if( SURROUND_THROUGHT
!=eSurround
)
4503 // weitersuchen: Es koennten ja noch welche ohne
4504 // Umlauf kommen ...
4514 // die speziellen Methoden zum Einfuegen von Objecten
4516 const SwFormatColl
*SwHTMLParser::GetCurrFormatColl() const
4518 const SwContentNode
* pCNd
= m_pPam
->GetContentNode();
4519 return &pCNd
->GetAnyFormatColl();
4522 void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext
*pContext
)
4524 SwTextFormatColl
*pCollToSet
= nullptr; // die zu setzende Vorlage
4525 SfxItemSet
*pItemSet
= nullptr; // der Set fuer harte Attrs
4526 sal_uInt16 nTopColl
= pContext
? pContext
->GetTextFormatColl() : 0;
4527 const OUString
& rTopClass
= pContext
? pContext
->GetClass() : aEmptyOUStr
;
4528 sal_uInt16 nDfltColl
= RES_POOLCOLL_TEXT
;
4530 bool bInPRE
=false; // etwas Kontext Info
4532 sal_uInt16 nLeftMargin
= 0, nRightMargin
= 0; // die Einzuege und
4533 short nFirstLineIndent
= 0; // Abstaende
4535 for( auto i
= m_nContextStAttrMin
; i
< m_aContexts
.size(); ++i
)
4537 const HTMLAttrContext
*pCntxt
= m_aContexts
[i
];
4539 sal_uInt16 nColl
= pCntxt
->GetTextFormatColl();
4542 // Es gibt eine Vorlage, die zu setzen ist. Dann
4543 // muss zunaechst einmal entschieden werden,
4544 // ob die Vorlage auch gesetzt werden kann
4545 bool bSetThis
= true;
4548 case RES_POOLCOLL_HTML_PRE
:
4551 case RES_POOLCOLL_TEXT
:
4552 // <TD><P CLASS=xxx> muss TD.xxx werden
4553 if( nDfltColl
==RES_POOLCOLL_TABLE
||
4554 nDfltColl
==RES_POOLCOLL_TABLE_HDLN
)
4557 case RES_POOLCOLL_HTML_HR
:
4558 // <HR> auch in <PRE> als Vorlage setzen, sonst kann man sie
4559 // nicht mehr exportieren
4567 SwTextFormatColl
*pNewColl
=
4568 m_pCSS1Parser
->GetTextFormatColl( nColl
, pCntxt
->GetClass() );
4572 // wenn jetzt eine andere Vorlage gesetzt werden soll als
4573 // bisher, muss die bishere Vorlage durch harte Attributierung
4578 // die Attribute, die bisherige Vorlage setzt
4581 pItemSet
= new SfxItemSet( pCollToSet
->GetAttrSet() );
4584 const SfxItemSet
& rCollSet
= pCollToSet
->GetAttrSet();
4585 SfxItemSet
aItemSet( *rCollSet
.GetPool(),
4586 rCollSet
.GetRanges() );
4587 aItemSet
.Set( rCollSet
);
4588 pItemSet
->Put( aItemSet
);
4590 // aber die Attribute, die aktuelle Vorlage setzt
4591 // entfernen, weil sie sonst spaeter ueberschrieben
4593 pItemSet
->Differentiate( pNewColl
->GetAttrSet() );
4596 pCollToSet
= pNewColl
;
4600 // hart Attributieren
4602 pItemSet
= new SfxItemSet( pNewColl
->GetAttrSet() );
4605 const SfxItemSet
& rCollSet
= pNewColl
->GetAttrSet();
4606 SfxItemSet
aItemSet( *rCollSet
.GetPool(),
4607 rCollSet
.GetRanges() );
4608 aItemSet
.Set( rCollSet
);
4609 pItemSet
->Put( aItemSet
);
4615 // vielliecht gibt es ja eine Default-Vorlage?
4616 nColl
= pCntxt
->GetDfltTextFormatColl();
4621 // ggf. neue Absatz-Einzuege holen
4622 if( pCntxt
->IsLRSpaceChanged() )
4624 sal_uInt16 nLeft
=0, nRight
=0;
4626 pCntxt
->GetMargins( nLeft
, nRight
, nFirstLineIndent
);
4627 nLeftMargin
= nLeft
;
4628 nRightMargin
= nRight
;
4632 // wenn im aktuellen Kontext eine neue Vorlage gesetzt werden soll,
4633 // muessen deren Absatz-Abstaende noch in den Kontext eingetragen werden
4634 if( pContext
&& nTopColl
)
4636 // <TD><P CLASS=xxx> muss TD.xxx werden
4637 if( nTopColl
==RES_POOLCOLL_TEXT
&&
4638 (nDfltColl
==RES_POOLCOLL_TABLE
||
4639 nDfltColl
==RES_POOLCOLL_TABLE_HDLN
) )
4640 nTopColl
= nDfltColl
;
4642 const SwTextFormatColl
*pTopColl
=
4643 m_pCSS1Parser
->GetTextFormatColl( nTopColl
, rTopClass
);
4644 const SfxItemSet
& rItemSet
= pTopColl
->GetAttrSet();
4645 const SfxPoolItem
*pItem
;
4646 if( SfxItemState::SET
== rItemSet
.GetItemState(RES_LR_SPACE
,true, &pItem
) )
4648 const SvxLRSpaceItem
*pLRItem
=
4649 static_cast<const SvxLRSpaceItem
*>(pItem
);
4651 sal_Int32 nLeft
= pLRItem
->GetTextLeft();
4652 sal_Int32 nRight
= pLRItem
->GetRight();
4653 nFirstLineIndent
= pLRItem
->GetTextFirstLineOfst();
4655 // In Definitions-Listen enthalten die Abstaende auch die der
4656 // vorhergehenden Level
4657 if( RES_POOLCOLL_HTML_DD
== nTopColl
)
4659 const SvxLRSpaceItem
& rDTLRSpace
= m_pCSS1Parser
4660 ->GetTextFormatColl( RES_POOLCOLL_HTML_DT
, aEmptyOUStr
)
4662 nLeft
-= rDTLRSpace
.GetTextLeft();
4663 nRight
-= rDTLRSpace
.GetRight();
4665 else if( RES_POOLCOLL_HTML_DT
== nTopColl
)
4671 // die Absatz-Abstaende addieren sich
4672 nLeftMargin
= nLeftMargin
+ static_cast< sal_uInt16
>(nLeft
);
4673 nRightMargin
= nRightMargin
+ static_cast< sal_uInt16
>(nRight
);
4675 pContext
->SetMargins( nLeftMargin
, nRightMargin
,
4678 if( SfxItemState::SET
== rItemSet
.GetItemState(RES_UL_SPACE
,true, &pItem
) )
4680 const SvxULSpaceItem
*pULItem
=
4681 static_cast<const SvxULSpaceItem
*>(pItem
);
4682 pContext
->SetULSpace( pULItem
->GetUpper(), pULItem
->GetLower() );
4686 // wenn gar keine Vorlage im Kontext gesetzt ist, Textkoerper nehmen
4689 pCollToSet
= m_pCSS1Parser
->GetTextCollFromPool( nDfltColl
);
4690 const SvxLRSpaceItem
& rLRItem
= pCollToSet
->GetLRSpace();
4692 nLeftMargin
= static_cast< sal_uInt16
>(rLRItem
.GetTextLeft());
4694 nRightMargin
= static_cast< sal_uInt16
>(rLRItem
.GetRight());
4695 if( !nFirstLineIndent
)
4696 nFirstLineIndent
= rLRItem
.GetTextFirstLineOfst();
4699 // bisherige harte Attributierung des Absatzes entfernen
4700 if( !m_aParaAttrs
.empty() )
4702 for( auto pParaAttr
: m_aParaAttrs
)
4703 pParaAttr
->Invalidate();
4705 m_aParaAttrs
.clear();
4708 // Die Vorlage setzen
4709 m_pDoc
->SetTextFormatColl( *m_pPam
, pCollToSet
);
4711 // ggf. noch den Absatz-Einzug korrigieren
4712 const SvxLRSpaceItem
& rLRItem
= pCollToSet
->GetLRSpace();
4715 bSetLRSpace
= nLeftMargin
!= rLRItem
.GetTextLeft() ||
4716 nFirstLineIndent
!= rLRItem
.GetTextFirstLineOfst() ||
4717 nRightMargin
!= rLRItem
.GetRight();
4721 SvxLRSpaceItem
aLRItem( rLRItem
);
4722 aLRItem
.SetTextLeft( nLeftMargin
);
4723 aLRItem
.SetRight( nRightMargin
);
4724 aLRItem
.SetTextFirstLineOfst( nFirstLineIndent
);
4726 pItemSet
->Put( aLRItem
);
4729 NewAttr( &m_aAttrTab
.pLRSpace
, aLRItem
);
4730 m_aAttrTab
.pLRSpace
->SetLikePara();
4731 m_aParaAttrs
.push_back( m_aAttrTab
.pLRSpace
);
4732 EndAttr( m_aAttrTab
.pLRSpace
, false );
4736 // und nun noch die Attribute setzen
4739 InsertParaAttrs( *pItemSet
);
4744 void SwHTMLParser::NewCharFormat( int nToken
)
4746 OUString aId
, aStyle
, aLang
, aDir
;
4749 const HTMLOptions
& rHTMLOptions
= GetOptions();
4750 for (size_t i
= rHTMLOptions
.size(); i
; )
4752 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
4753 switch( rOption
.GetToken() )
4756 aId
= rOption
.GetString();
4759 aStyle
= rOption
.GetString();
4762 aClass
= rOption
.GetString();
4765 aLang
= rOption
.GetString();
4768 aDir
= rOption
.GetString();
4773 // einen neuen Kontext anlegen
4774 HTMLAttrContext
*pCntxt
= new HTMLAttrContext( static_cast< sal_uInt16
>(nToken
) );
4776 // die Vorlage setzen und im Kontext merken
4777 SwCharFormat
* pCFormat
= m_pCSS1Parser
->GetChrFormat( static_cast< sal_uInt16
>(nToken
), aClass
);
4778 OSL_ENSURE( pCFormat
, "keine Zeichenvorlage zu Token gefunden" );
4780 // Styles parsen (zu Class siehe auch NewPara)
4781 if( HasStyleOptions( aStyle
, aId
, aEmptyOUStr
, &aLang
, &aDir
) )
4783 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
4784 SvxCSS1PropertyInfo aPropInfo
;
4786 if( ParseStyleOptions( aStyle
, aId
, aEmptyOUStr
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
4788 OSL_ENSURE( aClass
.isEmpty() || !m_pCSS1Parser
->GetClass( aClass
),
4789 "Class wird nicht beruecksichtigt" );
4790 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
4791 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
, true );
4795 // Zeichen-Vorlagen werden in einem eigenen Stack gehalten und
4796 // koennen nie durch Styles eingefuegt werden. Das Attribut ist deshalb
4797 // auch gar nicht im CSS1-Which-Range enthalten
4799 InsertAttr( &m_aAttrTab
.pCharFormats
, SwFormatCharFormat( pCFormat
), pCntxt
);
4801 // den Kontext merken
4802 PushContext( pCntxt
);
4805 void SwHTMLParser::InsertSpacer()
4807 // und es ggf. durch die Optionen veraendern
4809 sal_Int16 eVertOri
= text::VertOrientation::TOP
;
4810 sal_Int16 eHoriOri
= text::HoriOrientation::NONE
;
4813 bool bPrcWidth
= false;
4814 bool bPrcHeight
= false;
4815 sal_uInt16 nType
= HTML_SPTYPE_HORI
;
4817 const HTMLOptions
& rHTMLOptions
= GetOptions();
4818 for (size_t i
= rHTMLOptions
.size(); i
; )
4820 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
4821 switch( rOption
.GetToken() )
4824 aId
= rOption
.GetString();
4827 rOption
.GetEnum( nType
, aHTMLSpacerTypeTable
);
4831 rOption
.GetEnum( aHTMLImgVAlignTable
,
4834 rOption
.GetEnum( aHTMLImgHAlignTable
,
4838 // erstmal nur als Pixelwerte merken!
4839 bPrcWidth
= (rOption
.GetString().indexOf('%') != -1);
4840 aSize
.Width() = (long)rOption
.GetNumber();
4843 // erstmal nur als Pixelwerte merken!
4844 bPrcHeight
= (rOption
.GetString().indexOf('%') != -1);
4845 aSize
.Height() = (long)rOption
.GetNumber();
4848 // erstmal nur als Pixelwerte merken!
4849 nSize
= rOption
.GetNumber();
4856 case HTML_SPTYPE_BLOCK
:
4858 // einen leeren Textrahmen anlegen
4860 // den Itemset holen
4861 SfxItemSet
aFrameSet( m_pDoc
->GetAttrPool(),
4862 RES_FRMATR_BEGIN
, RES_FRMATR_END
-1 );
4864 Reader::ResetFrameFormatAttrs( aFrameSet
);
4866 // den Anker und die Ausrichtung setzen
4867 SetAnchorAndAdjustment( eVertOri
, eHoriOri
, aFrameSet
);
4869 // und noch die Groesse des Rahmens
4870 Size
aDfltSz( MINFLY
, MINFLY
);
4871 Size
aSpace( 0, 0 );
4872 SfxItemSet
aDummyItemSet( m_pDoc
->GetAttrPool(),
4873 m_pCSS1Parser
->GetWhichMap() );
4874 SvxCSS1PropertyInfo aDummyPropInfo
;
4876 SetFixSize( aSize
, aDfltSz
, bPrcWidth
, bPrcHeight
,
4877 aDummyItemSet
, aDummyPropInfo
, aFrameSet
);
4878 SetSpace( aSpace
, aDummyItemSet
, aDummyPropInfo
, aFrameSet
);
4880 // den Inhalt schuetzen
4881 SvxProtectItem
aProtectItem( RES_PROTECT
) ;
4882 aProtectItem
.SetContentProtect( true );
4883 aFrameSet
.Put( aProtectItem
);
4885 // der Rahmen anlegen
4886 RndStdIds eAnchorId
=
4887 static_cast<const SwFormatAnchor
&>(aFrameSet
.Get(RES_ANCHOR
)).GetAnchorId();
4888 SwFrameFormat
*pFlyFormat
= m_pDoc
->MakeFlySection( eAnchorId
,
4889 m_pPam
->GetPoint(), &aFrameSet
);
4890 // Ggf Frames anlegen und auto-geb. Rahmen registrieren
4891 RegisterFlyFrame( pFlyFormat
);
4894 case HTML_SPTYPE_VERT
:
4897 if( nSize
&& Application::GetDefaultDevice() )
4899 nSize
= Application::GetDefaultDevice()
4900 ->PixelToLogic( Size(0,nSize
),
4901 MapMode(MapUnit::MapTwip
) ).Height();
4904 // einen Absatz-Abstand setzen
4905 SwTextNode
*pTextNode
= nullptr;
4906 if( !m_pPam
->GetPoint()->nContent
.GetIndex() )
4908 // den unteren Absatz-Abstand des vorherigen Nodes aendern,
4911 SetAttr(); // noch offene Absatz-Attribute setzen
4913 pTextNode
= m_pDoc
->GetNodes()[m_pPam
->GetPoint()->nNode
.GetIndex()-1]
4916 // Wenn der Abstz davor kein Textenode ist, dann wird jetzt
4917 // ein leere Absatz angelegt, der eh schon eine Zeilenhoehe
4920 nSize
= nSize
>HTML_PARSPACE
? nSize
-HTML_PARSPACE
: 0;
4925 SvxULSpaceItem
aULSpace( static_cast<const SvxULSpaceItem
&>(pTextNode
4926 ->SwContentNode::GetAttr( RES_UL_SPACE
)) );
4927 aULSpace
.SetLower( aULSpace
.GetLower() + (sal_uInt16
)nSize
);
4928 pTextNode
->SetAttr( aULSpace
);
4932 NewAttr( &m_aAttrTab
.pULSpace
, SvxULSpaceItem( 0, (sal_uInt16
)nSize
, RES_UL_SPACE
) );
4933 EndAttr( m_aAttrTab
.pULSpace
, false );
4935 AppendTextNode(); // nicht am Abstand drehen!
4939 case HTML_SPTYPE_HORI
:
4942 // wenn der Absatz noch leer ist, einen Erstzeilen-Einzug
4943 // setzen, sondern Sperrschrift ueber einem Space aufspannen
4945 if( nSize
&& Application::GetDefaultDevice() )
4947 nSize
= Application::GetDefaultDevice()
4948 ->PixelToLogic( Size(nSize
,0),
4949 MapMode(MapUnit::MapTwip
) ).Width();
4952 if( !m_pPam
->GetPoint()->nContent
.GetIndex() )
4954 sal_uInt16 nLeft
=0, nRight
=0;
4957 GetMarginsFromContextWithNumBul( nLeft
, nRight
, nIndent
);
4958 nIndent
= nIndent
+ (short)nSize
;
4960 SvxLRSpaceItem
aLRItem( RES_LR_SPACE
);
4961 aLRItem
.SetTextLeft( nLeft
);
4962 aLRItem
.SetRight( nRight
);
4963 aLRItem
.SetTextFirstLineOfst( nIndent
);
4965 NewAttr( &m_aAttrTab
.pLRSpace
, aLRItem
);
4966 EndAttr( m_aAttrTab
.pLRSpace
, false );
4970 NewAttr( &m_aAttrTab
.pKerning
, SvxKerningItem( (short)nSize
, RES_CHRATR_KERNING
) );
4971 OUString
aTmp( ' ' );
4972 m_pDoc
->getIDocumentContentOperations().InsertString( *m_pPam
, aTmp
);
4973 EndAttr( m_aAttrTab
.pKerning
);
4979 sal_uInt16
SwHTMLParser::ToTwips( sal_uInt16 nPixel
)
4981 if( nPixel
&& Application::GetDefaultDevice() )
4983 long nTwips
= Application::GetDefaultDevice()->PixelToLogic(
4984 Size( nPixel
, nPixel
), MapMode( MapUnit::MapTwip
) ).Width();
4985 return nTwips
<= USHRT_MAX
? (sal_uInt16
)nTwips
: USHRT_MAX
;
4991 SwTwips
SwHTMLParser::GetCurrentBrowseWidth()
4993 const SwTwips nWidth
= SwHTMLTableLayout::GetBrowseWidth( *m_pDoc
);
4997 if( !m_aHTMLPageSize
.Width() )
4999 const SwFrameFormat
& rPgFormat
= m_pCSS1Parser
->GetMasterPageDesc()->GetMaster();
5001 const SwFormatFrameSize
& rSz
= rPgFormat
.GetFrameSize();
5002 const SvxLRSpaceItem
& rLR
= rPgFormat
.GetLRSpace();
5003 const SvxULSpaceItem
& rUL
= rPgFormat
.GetULSpace();
5004 const SwFormatCol
& rCol
= rPgFormat
.GetCol();
5006 m_aHTMLPageSize
.Width() = rSz
.GetWidth() - rLR
.GetLeft() - rLR
.GetRight();
5007 m_aHTMLPageSize
.Height() = rSz
.GetHeight() - rUL
.GetUpper() - rUL
.GetLower();
5009 if( 1 < rCol
.GetNumCols() )
5010 m_aHTMLPageSize
.Width() /= rCol
.GetNumCols();
5013 return m_aHTMLPageSize
.Width();
5016 void SwHTMLParser::InsertIDOption()
5019 const HTMLOptions
& rHTMLOptions
= GetOptions();
5020 for (size_t i
= rHTMLOptions
.size(); i
; )
5022 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
5023 if( HTML_O_ID
==rOption
.GetToken() )
5025 aId
= rOption
.GetString();
5030 if( !aId
.isEmpty() )
5031 InsertBookmark( aId
);
5034 void SwHTMLParser::InsertLineBreak()
5036 // <BR CLEAR=xxx> wird wie folgt behandelt:
5037 // 1.) Es werden nur nur absatzgebundene Rahmen betrachtet, die
5038 // im aktuellen Absatz verankert sind.
5039 // 2.) Fuer linksbuendig ausgerichtete Rahmen wird bei CLEAR=LEFT
5040 // oder ALL und auf rechtsbuendige ausgerichtete Rahmen bei
5041 // CLEAR=RIGHT oder ALL der Durchlauf wie folgt geaendert:
5042 // 3.) Wenn der Absatz keinen Text enthaelt, bekommt der Rahmen keinen
5044 // 4.) sonst erhaelt ein links ausgerichteter Rahmen eine rechten
5045 // "nur Anker" Umlauf und recht rechst ausg. Rahmen einen linken
5046 // "nur Anker" Umlauf.
5047 // 5.) wenn in einem nicht-leeren Absatz der Umlauf eines Rahmens
5048 // geaendert wird, wird ein neuer Absatz aufgemacht
5049 // 6.) Wenn von keinem Rahmen der Umlauf geaendert wird, wird ein
5050 // harter Zeilenumbruch eingefuegt
5052 OUString aId
, aStyle
, aClass
; // die ID der Bookmark
5053 bool bClearLeft
= false, bClearRight
= false;
5054 bool bCleared
= false; // wurde ein CLEAR ausgefuehrt?
5056 // dann holen wir mal die Optionen
5057 const HTMLOptions
& rHTMLOptions
= GetOptions();
5058 for (size_t i
= rHTMLOptions
.size(); i
; )
5060 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
5061 switch( rOption
.GetToken() )
5065 const OUString
&rClear
= rOption
.GetString();
5066 if( rClear
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_all
) )
5071 else if( rClear
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_left
) )
5073 else if( rClear
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_right
) )
5078 aId
= rOption
.GetString();
5081 aStyle
= rOption
.GetString();
5084 aClass
= rOption
.GetString();
5089 // CLEAR wird nur fuer den aktuellen Absaetz unterstuetzt
5090 if( bClearLeft
|| bClearRight
)
5092 SwNodeIndex
& rNodeIdx
= m_pPam
->GetPoint()->nNode
;
5093 SwTextNode
* pTextNd
= rNodeIdx
.GetNode().GetTextNode();
5096 const SwFrameFormats
& rFrameFormatTable
= *m_pDoc
->GetSpzFrameFormats();
5098 for( size_t i
=0; i
<rFrameFormatTable
.size(); i
++ )
5100 SwFrameFormat
*const pFormat
= rFrameFormatTable
[i
];
5101 SwFormatAnchor
const*const pAnchor
= &pFormat
->GetAnchor();
5102 SwPosition
const*const pAPos
= pAnchor
->GetContentAnchor();
5104 ((FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
5105 (FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
5106 pAPos
->nNode
== rNodeIdx
&&
5107 pFormat
->GetSurround().GetSurround() != SURROUND_NONE
)
5109 sal_Int16 eHori
= RES_DRAWFRMFMT
== pFormat
->Which()
5110 ? text::HoriOrientation::LEFT
5111 : pFormat
->GetHoriOrient().GetHoriOrient();
5113 SwSurround eSurround
= SURROUND_PARALLEL
;
5114 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
5116 if( bClearLeft
&& text::HoriOrientation::LEFT
==eHori
)
5117 eSurround
= SURROUND_RIGHT
;
5118 else if( bClearRight
&& text::HoriOrientation::RIGHT
==eHori
)
5119 eSurround
= SURROUND_LEFT
;
5121 else if( (bClearLeft
&& text::HoriOrientation::LEFT
==eHori
) ||
5122 (bClearRight
&& text::HoriOrientation::RIGHT
==eHori
) )
5124 eSurround
= SURROUND_NONE
;
5127 if( SURROUND_PARALLEL
!= eSurround
)
5129 SwFormatSurround
aSurround( eSurround
);
5130 if( SURROUND_NONE
!= eSurround
)
5131 aSurround
.SetAnchorOnly( true );
5132 pFormat
->SetFormatAttr( aSurround
);
5135 } // Anker ist nicht im Node
5136 } // Schleife ueber Fly-Frames
5141 SvxFormatBreakItem
aBreakItem( SvxBreak::NONE
, RES_BREAK
);
5142 bool bBreakItem
= false;
5143 if( HasStyleOptions( aStyle
, aId
, aClass
) )
5145 SfxItemSet
aItemSet( m_pDoc
->GetAttrPool(), m_pCSS1Parser
->GetWhichMap() );
5146 SvxCSS1PropertyInfo aPropInfo
;
5148 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
) )
5150 if( m_pCSS1Parser
->SetFormatBreak( aItemSet
, aPropInfo
) )
5152 aBreakItem
= static_cast<const SvxFormatBreakItem
&>(aItemSet
.Get( RES_BREAK
));
5155 if( !aPropInfo
.m_aId
.isEmpty() )
5156 InsertBookmark( aPropInfo
.m_aId
);
5160 if( bBreakItem
&& SvxBreak::PageAfter
==aBreakItem
.GetBreak() )
5162 NewAttr( &m_aAttrTab
.pBreak
, aBreakItem
);
5163 EndAttr( m_aAttrTab
.pBreak
, false );
5166 if( !bCleared
&& !bBreakItem
)
5168 // wenn kein CLEAR ausgefuehrt werden sollte oder konnte, wird
5169 // ein Zeilenumbruch eingef?gt
5170 OUString
sTmp( (sal_Unicode
)0x0a ); // make the Mac happy :-)
5171 m_pDoc
->getIDocumentContentOperations().InsertString( *m_pPam
, sTmp
);
5173 else if( m_pPam
->GetPoint()->nContent
.GetIndex() )
5175 // wenn ein clear in einem nicht-leeren Absatz ausgefuehrt wurde,
5176 // muss anschliessen ein neuer Absatz aufgemacht werden
5177 // MIB 21.02.97: Eigentlich muesste man hier den unteren Absatz-
5178 // Absatnd auf 0 drehen. Das geht aber bei sowas wie <BR ..><P>
5179 // schief (>Netscape). Deshalb lassen wir das erstmal.
5180 AppendTextNode( AM_NOSPACE
);
5182 if( bBreakItem
&& SvxBreak::PageBefore
==aBreakItem
.GetBreak() )
5184 NewAttr( &m_aAttrTab
.pBreak
, aBreakItem
);
5185 EndAttr( m_aAttrTab
.pBreak
, false );
5189 void SwHTMLParser::InsertHorzRule()
5191 sal_uInt16 nSize
= 0;
5192 sal_uInt16 nWidth
= 0;
5194 SvxAdjust eAdjust
= SVX_ADJUST_END
;
5196 bool bPrcWidth
= false;
5197 bool bNoShade
= false;
5198 bool bColor
= false;
5203 // dann holen wir mal die Optionen
5204 const HTMLOptions
& rHTMLOptions
= GetOptions();
5205 for (size_t i
= rHTMLOptions
.size(); i
; )
5207 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
5208 switch( rOption
.GetToken() )
5211 aId
= rOption
.GetString();
5214 nSize
= (sal_uInt16
)rOption
.GetNumber();
5217 bPrcWidth
= (rOption
.GetString().indexOf('%') != -1);
5218 nWidth
= (sal_uInt16
)rOption
.GetNumber();
5219 if( bPrcWidth
&& nWidth
>=100 )
5221 // 100%-Linien sind der default-Fall (keine Attrs neotig)
5228 (SvxAdjust
)rOption
.GetEnum( aHTMLPAlignTable
, static_cast< sal_uInt16
>(eAdjust
) );
5230 case HTML_O_NOSHADE
:
5234 rOption
.GetColor( aColor
);
5240 if( m_pPam
->GetPoint()->nContent
.GetIndex() )
5241 AppendTextNode( AM_NOSPACE
);
5242 if( m_nOpenParaToken
)
5245 m_pPam
->Move( fnMoveBackward
);
5247 // ... und in einem Kontext merken
5248 HTMLAttrContext
*pCntxt
=
5249 new HTMLAttrContext( HTML_HORZRULE
, RES_POOLCOLL_HTML_HR
, aEmptyOUStr
);
5251 PushContext( pCntxt
);
5253 // die neue Vorlage setzen
5254 SetTextCollAttrs( pCntxt
);
5256 // die harten Attribute an diesem Absatz werden nie mehr ungueltig
5257 if( !m_aParaAttrs
.empty() )
5258 m_aParaAttrs
.clear();
5260 if( nSize
>0 || bColor
|| bNoShade
)
5262 // Farbe und/oder Breite der Linie setzen
5264 aColor
.SetColor( COL_GRAY
);
5266 SvxBorderLine
aBorderLine( &aColor
);
5270 long nPHeight
= (long)nSize
;
5271 SvxCSS1Parser::PixelToTwip( nPWidth
, nPHeight
);
5274 aBorderLine
.SetBorderLineStyle(table::BorderLineStyle::DOUBLE
);
5276 aBorderLine
.SetWidth( nPHeight
);
5280 aBorderLine
.SetWidth( DEF_LINE_WIDTH_2
);
5284 aBorderLine
.SetBorderLineStyle(table::BorderLineStyle::DOUBLE
);
5285 aBorderLine
.SetWidth( DEF_LINE_WIDTH_0
);
5288 SvxBoxItem
aBoxItem(RES_BOX
);
5289 aBoxItem
.SetLine( &aBorderLine
, SvxBoxItemLine::BOTTOM
);
5290 HTMLAttr
* pTmp
= new HTMLAttr( *m_pPam
->GetPoint(), aBoxItem
);
5291 m_aSetAttrTab
.push_back( pTmp
);
5295 // Wenn wir in keiner Tabelle sind, wird die Breitenangabe durch
5296 // Absatz-Einzuege "getuerkt". In einer Tabelle macht das wenig
5297 // Sinn. Um zu Vermeiden, dass die Linie bei der Breitenberechnung
5298 // beruecksichtigt wird, bekommt sie aber trotzdem entsprechendes
5299 // LRSpace-Item verpasst.
5302 // Laenge und Ausrichtung der Linie ueber Absatz-Einzuege "tuerken"
5303 long nBrowseWidth
= GetCurrentBrowseWidth();
5304 nWidth
= bPrcWidth
? (sal_uInt16
)((nWidth
*nBrowseWidth
) / 100)
5305 : ToTwips( (sal_uInt16
)nBrowseWidth
);
5306 if( nWidth
< MINLAY
)
5309 if( (long)nWidth
< nBrowseWidth
)
5311 const SwFormatColl
*pColl
= GetCurrFormatColl();
5312 SvxLRSpaceItem
aLRItem( pColl
->GetLRSpace() );
5313 long nDist
= nBrowseWidth
- nWidth
;
5317 case SVX_ADJUST_RIGHT
:
5318 aLRItem
.SetTextLeft( (sal_uInt16
)nDist
);
5320 case SVX_ADJUST_LEFT
:
5321 aLRItem
.SetRight( (sal_uInt16
)nDist
);
5323 case SVX_ADJUST_CENTER
:
5326 aLRItem
.SetTextLeft( (sal_uInt16
)nDist
);
5327 aLRItem
.SetRight( (sal_uInt16
)nDist
);
5331 HTMLAttr
* pTmp
= new HTMLAttr( *m_pPam
->GetPoint(), aLRItem
);
5332 m_aSetAttrTab
.push_back( pTmp
);
5337 // Bookmarks koennen nicht in Hyperlinks eingefueht werden
5338 if( !aId
.isEmpty() )
5339 InsertBookmark( aId
);
5341 // den aktuellen Kontext vom Stack holen
5342 HTMLAttrContext
*pPoppedContext
= PopContext( HTML_HORZRULE
);
5343 OSL_ENSURE( pPoppedContext
==pCntxt
, "wo kommt denn da ein HR-Kontext her?" );
5344 delete pPoppedContext
;
5346 m_pPam
->Move( fnMoveForward
);
5348 // und im Absatz danach die dort aktuelle Vorlage setzen
5352 void SwHTMLParser::ParseMoreMetaOptions()
5354 OUString aName
, aContent
;
5355 bool bHTTPEquiv
= false;
5357 const HTMLOptions
& rHTMLOptions
= GetOptions();
5358 for (size_t i
= rHTMLOptions
.size(); i
; )
5360 const HTMLOption
& rOption
= rHTMLOptions
[--i
];
5361 switch( rOption
.GetToken() )
5364 aName
= rOption
.GetString();
5367 case HTML_O_HTTPEQUIV
:
5368 aName
= rOption
.GetString();
5371 case HTML_O_CONTENT
:
5372 aContent
= rOption
.GetString();
5377 // Hier wird es etwas tricky: Wir wissen genau, da? die Dok-Info
5378 // nicht geaendert wurde. Deshalb genuegt es, auf Generator und
5379 // auf refresh abzufragen, um noch nicht verarbeitete Token zu finden,
5380 // denn das sind die einzigen, die die Dok-Info nicht modifizieren.
5381 if( aName
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_META_generator
) ||
5382 aName
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_META_refresh
) ||
5383 aName
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_META_content_type
) ||
5384 aName
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_META_content_script_type
) )
5387 aContent
= aContent
.replaceAll("\r", "").replaceAll("\n", "");
5389 if( aName
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_META_sdendnote
) )
5391 FillEndNoteInfo( aContent
);
5395 if( aName
.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_META_sdfootnote
) )
5397 FillFootNoteInfo( aContent
);
5401 OUStringBuffer sText
;
5402 sText
.append("HTML: <");
5403 sText
.append(OOO_STRING_SVTOOLS_HTML_meta
);
5406 sText
.append(OOO_STRING_SVTOOLS_HTML_O_httpequiv
);
5408 sText
.append(OOO_STRING_SVTOOLS_HTML_O_name
);
5409 sText
.append("=\"");
5410 sText
.append(aName
);
5411 sText
.append("\" ");
5412 sText
.append(OOO_STRING_SVTOOLS_HTML_O_content
);
5413 sText
.append("=\"");
5414 sText
.append(aContent
);
5415 sText
.append("\">");
5417 SwPostItField
aPostItField(
5418 static_cast<SwPostItFieldType
*>(m_pDoc
->getIDocumentFieldsAccess().GetSysFieldType( RES_POSTITFLD
)),
5419 aEmptyOUStr
, sText
.makeStringAndClear(), aEmptyOUStr
, aEmptyOUStr
, DateTime( DateTime::SYSTEM
) );
5420 SwFormatField
aFormatField( aPostItField
);
5421 InsertAttr( aFormatField
, false );
5424 HTMLAttr::HTMLAttr( const SwPosition
& rPos
, const SfxPoolItem
& rItem
,
5426 nSttPara( rPos
.nNode
),
5427 nEndPara( rPos
.nNode
),
5428 nSttContent( rPos
.nContent
.GetIndex() ),
5429 nEndContent(rPos
.nContent
.GetIndex() ),
5430 bInsAtStart( true ),
5437 pItem
= rItem
.Clone();
5440 HTMLAttr::HTMLAttr( const HTMLAttr
&rAttr
, const SwNodeIndex
&rEndPara
,
5441 sal_Int32 nEndCnt
, HTMLAttr
**ppHd
) :
5442 nSttPara( rAttr
.nSttPara
),
5443 nEndPara( rEndPara
),
5444 nSttContent( rAttr
.nSttContent
),
5445 nEndContent( nEndCnt
),
5446 bInsAtStart( rAttr
.bInsAtStart
),
5447 bLikePara( rAttr
.bLikePara
),
5448 bValid( rAttr
.bValid
),
5453 pItem
= rAttr
.pItem
->Clone();
5456 HTMLAttr::~HTMLAttr()
5461 HTMLAttr
*HTMLAttr::Clone(const SwNodeIndex
& rEndPara
, sal_Int32 nEndCnt
) const
5463 // das Attribut mit der alten Start-Position neu anlegen
5464 HTMLAttr
*pNew
= new HTMLAttr( *this, rEndPara
, nEndCnt
, ppHead
);
5466 // die Previous-Liste muss uebernommen werden, die Next-Liste nicht!
5467 pNew
->pPrev
= pPrev
;
5472 void HTMLAttr::Reset(const SwNodeIndex
& rSttPara
, sal_Int32 nSttCnt
,
5475 // den Anfang (und das Ende) neu setzen
5476 nSttPara
= rSttPara
;
5477 nSttContent
= nSttCnt
;
5478 nEndPara
= rSttPara
;
5479 nEndContent
= nSttCnt
;
5481 // den Head korrigieren und die Verkettungen aufheben
5487 void HTMLAttr::InsertPrev( HTMLAttr
*pPrv
)
5489 OSL_ENSURE( !pPrv
->pNext
|| pPrv
->pNext
== this,
5490 "HTMLAttr::InsertPrev: pNext falsch" );
5491 pPrv
->pNext
= nullptr;
5493 OSL_ENSURE( nullptr == pPrv
->ppHead
|| ppHead
== pPrv
->ppHead
,
5494 "HTMLAttr::InsertPrev: ppHead falsch" );
5495 pPrv
->ppHead
= nullptr;
5497 HTMLAttr
*pAttr
= this;
5498 while( pAttr
->GetPrev() )
5499 pAttr
= pAttr
->GetPrev();
5501 pAttr
->pPrev
= pPrv
;
5504 bool SwHTMLParser::ParseMetaOptions(
5505 const uno::Reference
<document::XDocumentProperties
> & i_xDocProps
,
5506 SvKeyValueIterator
*i_pHeader
)
5508 // always call base ParseMetaOptions, it sets the encoding (#i96700#)
5509 bool ret( HTMLParser::ParseMetaOptions(i_xDocProps
, i_pHeader
) );
5510 if (!ret
&& IsNewDoc())
5512 ParseMoreMetaOptions();
5517 // override so we can parse DOCINFO field subtypes INFO[1-4]
5518 void SwHTMLParser::AddMetaUserDefined( OUString
const & i_rMetaName
)
5520 // unless we already have 4 names, append the argument to m_InfoNames
5521 OUString
* pName
// the first empty string in m_InfoNames
5522 (m_InfoNames
[0].isEmpty() ? &m_InfoNames
[0] :
5523 (m_InfoNames
[1].isEmpty() ? &m_InfoNames
[1] :
5524 (m_InfoNames
[2].isEmpty() ? &m_InfoNames
[2] :
5525 (m_InfoNames
[3].isEmpty() ? &m_InfoNames
[3] : nullptr ))));
5528 (*pName
) = i_rMetaName
;
5532 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */