/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #if OSL_DEBUG_LEVEL > 0 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "swcss1.hxx" #include #include #include "htmlnum.hxx" #include "swhtml.hxx" #include #include #include #include #include #include #include #include #include #include #include "css1atr.hxx" #define FONTSIZE_MASK 7 #define HTML_ESC_PROP 80 #define HTML_ESC_SUPER DFLT_ESC_SUPER #define HTML_ESC_SUB DFLT_ESC_SUB #define HTML_SPTYPE_BLOCK 1 #define HTML_SPTYPE_HORI 2 #define HTML_SPTYPE_VERT 3 using editeng::SvxBorderLine; using namespace ::com::sun::star; //

, , etc. HTMLOptionEnum aHTMLPAlignTable[] = { { OOO_STRING_SVTOOLS_HTML_AL_left, SvxAdjust::Left }, { OOO_STRING_SVTOOLS_HTML_AL_center, SvxAdjust::Center }, { OOO_STRING_SVTOOLS_HTML_AL_middle, SvxAdjust::Center }, // Netscape { OOO_STRING_SVTOOLS_HTML_AL_right, SvxAdjust::Right }, { OOO_STRING_SVTOOLS_HTML_AL_justify, SvxAdjust::Block }, { OOO_STRING_SVTOOLS_HTML_AL_char, SvxAdjust::Left }, { nullptr, SvxAdjust(0) } }; // static HTMLOptionEnum aHTMLSpacerTypeTable[] = { { OOO_STRING_SVTOOLS_HTML_SPTYPE_block, HTML_SPTYPE_BLOCK }, { OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal, HTML_SPTYPE_HORI }, { OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical, HTML_SPTYPE_VERT }, { nullptr, 0 } }; HTMLReader::HTMLReader() { m_bTemplateBrowseMode = true; } OUString HTMLReader::GetTemplateName(SwDoc& rDoc) const { if (!rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE)) // HTML import into Writer, avoid loading the Writer/Web template. return OUString(); const OUString sTemplateWithoutExt("internal/html"); SvtPathOptions aPathOpt; // first search for OpenDocument Writer/Web template // OpenDocument Writer/Web template (extension .oth) OUString sTemplate( sTemplateWithoutExt + ".oth" ); if (aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE )) return sTemplate; // no OpenDocument Writer/Web template found. // search for OpenOffice.org Writer/Web template sTemplate = sTemplateWithoutExt + ".stw"; if (aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE )) return sTemplate; OSL_ENSURE( false, "The default HTML template cannot be found in the defined template directories!"); return OUString(); } bool HTMLReader::SetStrmStgPtr() { OSL_ENSURE( m_pMedium, "Where is the medium??" ); if( m_pMedium->IsRemote() || !m_pMedium->IsStorage() ) { m_pStream = m_pMedium->GetInStream(); return true; } return false; } // Call for the general Reader-Interface ErrCode HTMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, const OUString & rName ) { if( !m_pStream ) { OSL_ENSURE( m_pStream, "HTML-Read without stream" ); return ERR_SWG_READ_ERROR; } if( !m_bInsertMode ) { Reader::ResetFrameFormats( rDoc ); // Set the HTML page style, when it isn't a HTML document, // otherwise it's already set. if( !rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ) { rDoc.getIDocumentContentOperations().InsertPoolItem( rPam, SwFormatPageDesc( rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML, false )) ); } } // so nobody steals the document! rtl::Reference aHoldRef(&rDoc); ErrCode nRet = ERRCODE_NONE; tools::SvRef xParser = new SwHTMLParser( &rDoc, rPam, *m_pStream, rName, rBaseURL, !m_bInsertMode, m_pMedium, IsReadUTF8(), m_bIgnoreHTMLComments ); SvParserState eState = xParser->CallParser(); if( SvParserState::Pending == eState ) m_pStream->ResetError(); else if( SvParserState::Accepted != eState ) { const OUString sErr(OUString::number(static_cast(xParser->GetLineNr())) + "," + OUString::number(static_cast(xParser->GetLinePos()))); // use the stream as transport for error number nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr, DialogMask::ButtonsOk | DialogMask::MessageError ); } return nRet; } SwHTMLParser::SwHTMLParser( SwDoc* pD, SwPaM& rCursor, SvStream& rIn, const OUString& rPath, const OUString& rBaseURL, bool bReadNewDoc, SfxMedium* pMed, bool bReadUTF8, bool bNoHTMLComments ) : SfxHTMLParser( rIn, bReadNewDoc, pMed ), SwClient( nullptr ), m_aPathToFile( rPath ), m_sBaseURL( rBaseURL ), m_xAttrTab(new HTMLAttrTable), m_pAppletImpl( nullptr ), m_pCSS1Parser( nullptr ), m_pNumRuleInfo( new SwHTMLNumRuleInfo ), m_pPendStack( nullptr ), m_xDoc( pD ), m_pActionViewShell( nullptr ), m_pSttNdIdx( nullptr ), m_pFormImpl( nullptr ), m_pMarquee( nullptr ), m_pImageMap( nullptr ), m_pImageMaps(nullptr), m_pFootEndNoteImpl( nullptr ), m_nBaseFontStMin( 0 ), m_nFontStMin( 0 ), m_nDefListDeep( 0 ), m_nFontStHeadStart( 0 ), m_nSBModuleCnt( 0 ), m_nMissingImgMaps( 0 ), m_nParaCnt( 5 ), // #i83625# m_nContextStMin( 0 ), m_nContextStAttrMin( 0 ), m_nSelectEntryCnt( 0 ), m_nOpenParaToken( HtmlTokenId::NONE ), m_eJumpTo( JUMPTO_NONE ), #ifdef DBG_UTIL m_nContinue( 0 ), #endif m_eParaAdjust( SvxAdjust::End ), m_bDocInitalized( false ), m_bSetModEnabled( false ), m_bInFloatingFrame( false ), m_bInField( false ), m_bCallNextToken( false ), m_bIgnoreRawData( false ), m_bLBEntrySelected ( false ), m_bTAIgnoreNewPara ( false ), m_bFixMarqueeWidth ( false ), m_bNoParSpace( false ), m_bInNoEmbed( false ), m_bInTitle( false ), m_bUpdateDocStat( false ), m_bFixSelectWidth( false ), m_bTextArea( false ), m_bSelect( false ), m_bInFootEndNoteAnchor( false ), m_bInFootEndNoteSymbol( false ), m_bIgnoreHTMLComments( bNoHTMLComments ), m_bRemoveHidden( false ), m_bBodySeen( false ), m_bReadingHeaderOrFooter( false ), m_isInTableStructure(false), m_nTableDepth( 0 ), m_pTempViewFrame(nullptr) { m_nEventId = nullptr; m_bUpperSpace = m_bViewCreated = m_bChkJumpMark = false; m_eScriptLang = HTMLScriptLanguage::Unknown; rCursor.DeleteMark(); m_pPam = &rCursor; // re-use existing cursor: avoids spurious ~SwIndexReg assert memset(m_xAttrTab.get(), 0, sizeof(HTMLAttrTable)); // Read the font sizes 1-7 from the INI file SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); m_aFontHeights[0] = rHtmlOptions.GetFontSize( 0 ) * 20; m_aFontHeights[1] = rHtmlOptions.GetFontSize( 1 ) * 20; m_aFontHeights[2] = rHtmlOptions.GetFontSize( 2 ) * 20; m_aFontHeights[3] = rHtmlOptions.GetFontSize( 3 ) * 20; m_aFontHeights[4] = rHtmlOptions.GetFontSize( 4 ) * 20; m_aFontHeights[5] = rHtmlOptions.GetFontSize( 5 ) * 20; m_aFontHeights[6] = rHtmlOptions.GetFontSize( 6 ) * 20; m_bKeepUnknown = rHtmlOptions.IsImportUnknown(); if(bReadNewDoc) { //CJK has different defaults, so a different object should be used for this //RES_CHARTR_CJK_FONTSIZE is a valid value SvxFontHeightItem aFontHeight(m_aFontHeights[2], 100, RES_CHRATR_FONTSIZE); m_xDoc->SetDefault( aFontHeight ); SvxFontHeightItem aFontHeightCJK(m_aFontHeights[2], 100, RES_CHRATR_CJK_FONTSIZE); m_xDoc->SetDefault( aFontHeightCJK ); SvxFontHeightItem aFontHeightCTL(m_aFontHeights[2], 100, RES_CHRATR_CTL_FONTSIZE); m_xDoc->SetDefault( aFontHeightCTL ); // #i18732# - adjust default of option 'FollowTextFlow' // TODO: not sure what the appropriate default for HTML should be? m_xDoc->SetDefault( SwFormatFollowTextFlow(true) ); } // Change to HTML mode during the import, so that the right styles are created m_bOldIsHTMLMode = m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE); m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, true); m_pCSS1Parser = new SwCSS1Parser( m_xDoc.get(), m_aFontHeights, m_sBaseURL, IsNewDoc() ); m_pCSS1Parser->SetIgnoreFontFamily( rHtmlOptions.IsIgnoreFontFamily() ); if( bReadUTF8 ) { SetSrcEncoding( RTL_TEXTENCODING_UTF8 ); } else { SwDocShell *pDocSh = m_xDoc->GetDocShell(); SvKeyValueIterator *pHeaderAttrs = pDocSh->GetHeaderAttributes(); if( pHeaderAttrs ) SetEncodingByHTTPHeader( pHeaderAttrs ); } m_pCSS1Parser->SetDfltEncoding( osl_getThreadTextEncoding() ); SwDocShell* pDocSh = m_xDoc->GetDocShell(); if( pDocSh ) { m_bViewCreated = true; // not, load synchronous // a jump mark is present if( pMed ) { m_sJmpMark = pMed->GetURLObject().GetMark(); if( !m_sJmpMark.isEmpty() ) { m_eJumpTo = JUMPTO_MARK; sal_Int32 nLastPos = m_sJmpMark.lastIndexOf( cMarkSeparator ); sal_Int32 nPos = nLastPos != -1 ? nLastPos : 0; OUString sCmp; if (nPos) { sCmp = m_sJmpMark.copy(nPos + 1).replaceAll(" ", ""); } if( !sCmp.isEmpty() ) { sCmp = sCmp.toAsciiLowerCase(); if( sCmp == "region" ) m_eJumpTo = JUMPTO_REGION; else if( sCmp == "table" ) m_eJumpTo = JUMPTO_TABLE; else if( sCmp == "graphic" ) m_eJumpTo = JUMPTO_GRAPHIC; else if( sCmp == "outline" || sCmp == "text" || sCmp == "frame" ) m_eJumpTo = JUMPTO_NONE; // this is nothing valid! else // otherwise this is a normal (book)mark nPos = -1; } else nPos = -1; if( nPos != -1 ) m_sJmpMark = m_sJmpMark.copy( 0, nPos ); if( m_sJmpMark.isEmpty() ) m_eJumpTo = JUMPTO_NONE; } } } SetupFilterOptions(); } SwHTMLParser::~SwHTMLParser() { #ifdef DBG_UTIL OSL_ENSURE( !m_nContinue, "DTOR in continue!" ); #endif OSL_ENSURE(m_aContexts.empty(), "There are still contexts on the stack"); OSL_ENSURE(!m_nContextStMin, "There are protected contexts"); m_nContextStMin = 0; while (!m_aContexts.empty()) { std::unique_ptr xCntxt(PopContext()); ClearContext(xCntxt.get()); } bool bAsync = m_xDoc->IsInLoadAsynchron(); m_xDoc->SetInLoadAsynchron( false ); m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, m_bOldIsHTMLMode); if( m_xDoc->GetDocShell() && m_nEventId ) Application::RemoveUserEvent( m_nEventId ); // the DocumentDetected maybe can delete the DocShells, therefore fetch again if( m_xDoc->GetDocShell() ) { // update linked sections sal_uInt16 nLinkMode = m_xDoc->getIDocumentSettingAccess().getLinkUpdateMode( true ); if( nLinkMode != NEVER && bAsync && SfxObjectCreateMode::INTERNAL!=m_xDoc->GetDocShell()->GetCreateMode() ) m_xDoc->getIDocumentLinksAdministration().GetLinkManager().UpdateAllLinks( nLinkMode == MANUAL, false, nullptr ); if ( m_xDoc->GetDocShell()->IsLoading() ) { // #i59688# m_xDoc->GetDocShell()->LoadingFinished(); } } delete m_pSttNdIdx; if( !m_aSetAttrTab.empty() ) { OSL_ENSURE( m_aSetAttrTab.empty(),"There are still attributes on the stack" ); for ( HTMLAttrs::const_iterator it = m_aSetAttrTab.begin(); it != m_aSetAttrTab.end(); ++it ) delete *it; m_aSetAttrTab.clear(); } delete m_pCSS1Parser; delete m_pNumRuleInfo; DeleteFormImpl(); DeleteFootEndNoteImpl(); OSL_ENSURE(!m_xTable.get(), "It exists still a open table"); delete m_pImageMaps; OSL_ENSURE( !m_pPendStack, "SwHTMLParser::~SwHTMLParser: Here should not be Pending-Stack anymore" ); while( m_pPendStack ) { SwPendingStack* pTmp = m_pPendStack; m_pPendStack = m_pPendStack->pNext; delete pTmp->pData; delete pTmp; } m_xDoc.clear(); if ( m_pTempViewFrame ) { m_pTempViewFrame->DoClose(); // the temporary view frame is hidden, so the hidden flag might need to be removed if ( m_bRemoveHidden && m_xDoc.is() && m_xDoc->GetDocShell() && m_xDoc->GetDocShell()->GetMedium() ) m_xDoc->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN ); } } IMPL_LINK_NOARG( SwHTMLParser, AsyncCallback, void*, void ) { m_nEventId=nullptr; // #i47907# - If the document has already been destructed, // the parser should be aware of this: if( ( m_xDoc->GetDocShell() && m_xDoc->GetDocShell()->IsAbortingImport() ) || 1 == m_xDoc->getReferenceCount() ) { // was the import aborted by SFX? eState = SvParserState::Error; } GetAsynchCallLink().Call(nullptr); } SvParserState SwHTMLParser::CallParser() { // create temporary index on position 0, so it won't be moved! m_pSttNdIdx = new SwNodeIndex( m_xDoc->GetNodes() ); if( !IsNewDoc() ) // insert into existing document ? { const SwPosition* pPos = m_pPam->GetPoint(); m_xDoc->getIDocumentContentOperations().SplitNode( *pPos, false ); *m_pSttNdIdx = pPos->nNode.GetIndex()-1; m_xDoc->getIDocumentContentOperations().SplitNode( *pPos, false ); SwPaM aInsertionRangePam( *pPos ); m_pPam->Move( fnMoveBackward ); // split any redline over the insertion point aInsertionRangePam.SetMark(); *aInsertionRangePam.GetPoint() = *m_pPam->GetPoint(); aInsertionRangePam.Move( fnMoveBackward ); m_xDoc->getIDocumentRedlineAccess().SplitRedline( aInsertionRangePam ); m_xDoc->SetTextFormatColl( *m_pPam, m_pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_STANDARD )); } if( GetMedium() ) { if( !m_bViewCreated ) { m_nEventId = Application::PostUserEvent( LINK( this, SwHTMLParser, AsyncCallback ) ); } else { m_bViewCreated = true; m_nEventId = nullptr; } } else // show progress bar { rInput.Seek(STREAM_SEEK_TO_END); rInput.ResetError(); m_xProgress.reset(new ImportProgress(m_xDoc->GetDocShell(), 0, rInput.Tell())); rInput.Seek(STREAM_SEEK_TO_BEGIN); rInput.ResetError(); } m_xDoc->GetPageDesc( 0 ).Add( this ); SvParserState eRet = HTMLParser::CallParser(); return eRet; } bool SwHTMLParser::CanRemoveNode(sal_uLong nNodeIdx) const { const SwNode *pPrev = m_xDoc->GetNodes()[nNodeIdx - 1]; return pPrev->IsContentNode() || (pPrev->IsEndNode() && pPrev->StartOfSectionNode()->IsSectionNode()); } void SwHTMLParser::Continue( HtmlTokenId nToken ) { #ifdef DBG_UTIL OSL_ENSURE(!m_nContinue, "Continue in Continue - not supposed to happen"); m_nContinue++; #endif // When the import (of SFX) is aborted, an error will be set but // we still continue, so that we clean up properly. OSL_ENSURE( SvParserState::Error!=eState, "SwHTMLParser::Continue: already set an error" ); if( m_xDoc->GetDocShell() && m_xDoc->GetDocShell()->IsAbortingImport() ) eState = SvParserState::Error; // Fetch SwViewShell from document, save it and set as current. SwViewShell *pInitVSh = CallStartAction(); if( SvParserState::Error != eState && GetMedium() && !m_bViewCreated ) { // At first call first return, show document and wait for callback // time. // At this point in CallParser only one digit was read and // a SaveState(0) was called. eState = SvParserState::Pending; m_bViewCreated = true; m_xDoc->SetInLoadAsynchron( true ); #ifdef DBG_UTIL m_nContinue--; #endif return; } m_bSetModEnabled = false; if( m_xDoc->GetDocShell() ) { m_bSetModEnabled = m_xDoc->GetDocShell()->IsEnableSetModified(); if( m_bSetModEnabled ) { m_xDoc->GetDocShell()->EnableSetModified( false ); } } // during import don't call OLE-Modified Link aOLELink( m_xDoc->GetOle2Link() ); m_xDoc->SetOle2Link( Link() ); bool bModified = m_xDoc->getIDocumentState().IsModified(); bool const bWasUndo = m_xDoc->GetIDocumentUndoRedo().DoesUndo(); m_xDoc->GetIDocumentUndoRedo().DoUndo(false); // When the import will be aborted, don't call Continue anymore. // If a Pending-Stack exists make sure the stack is ended with a call // of NextToken. if( SvParserState::Error == eState ) { OSL_ENSURE( !m_pPendStack || m_pPendStack->nToken != HtmlTokenId::NONE, "SwHTMLParser::Continue: Pending-Stack without Token" ); if( m_pPendStack && m_pPendStack->nToken != HtmlTokenId::NONE ) NextToken( m_pPendStack->nToken ); OSL_ENSURE( !m_pPendStack, "SwHTMLParser::Continue: There is again a Pending-Stack" ); } else { HTMLParser::Continue( m_pPendStack ? m_pPendStack->nToken : nToken ); } // disable progress bar again m_xProgress.reset(); bool bLFStripped = false; if( SvParserState::Pending != GetStatus() ) { // set the last attributes yet { if( !m_aScriptSource.isEmpty() ) { SwScriptFieldType *pType = static_cast(m_xDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Script )); SwScriptField aField( pType, m_aScriptType, m_aScriptSource, false ); InsertAttr( SwFormatField( aField ), false ); } if( m_pAppletImpl ) { if( m_pAppletImpl->GetApplet().is() ) EndApplet(); else EndObject(); } // maybe remove an existing LF after the last paragraph if( IsNewDoc() ) bLFStripped = StripTrailingLF() > 0; // close still open numbering while( GetNumInfo().GetNumRule() ) EndNumBulList(); OSL_ENSURE( !m_nContextStMin, "There are protected contexts" ); // try this twice, first normally to let m_nContextStMin decrease // naturally and get contexts popped in desired order, and if that // fails force it for (int i = 0; i < 2; ++i) { while (m_aContexts.size() > m_nContextStMin) { std::unique_ptr xCntxt(PopContext()); if (xCntxt) EndContext(xCntxt.get()); } if (!m_nContextStMin) break; OSL_ENSURE(!m_nContextStMin, "There are still protected contexts"); m_nContextStMin = 0; } if( !m_aParaAttrs.empty() ) m_aParaAttrs.clear(); SetAttr( false ); // set the first delayed styles m_pCSS1Parser->SetDelayedStyles(); } // again correct the start if( !IsNewDoc() && m_pSttNdIdx->GetIndex() ) { SwTextNode* pTextNode = m_pSttNdIdx->GetNode().GetTextNode(); SwNodeIndex aNxtIdx( *m_pSttNdIdx ); if( pTextNode && pTextNode->CanJoinNext( &aNxtIdx )) { const sal_Int32 nStt = pTextNode->GetText().getLength(); // when the cursor is still in the node, then set him at the end if( m_pPam->GetPoint()->nNode == aNxtIdx ) { m_pPam->GetPoint()->nNode = *m_pSttNdIdx; m_pPam->GetPoint()->nContent.Assign( pTextNode, nStt ); } #if OSL_DEBUG_LEVEL > 0 // !!! shouldn't be possible, or ?? OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound().nNode.GetIndex(), "Pam.Bound1 is still in the node" ); OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound( false ).nNode.GetIndex(), "Pam.Bound2 is still in the node" ); if( m_pSttNdIdx->GetIndex()+1 == m_pPam->GetBound().nNode.GetIndex() ) { const sal_Int32 nCntPos = m_pPam->GetBound().nContent.GetIndex(); m_pPam->GetBound().nContent.Assign( pTextNode, pTextNode->GetText().getLength() + nCntPos ); } if( m_pSttNdIdx->GetIndex()+1 == m_pPam->GetBound( false ).nNode.GetIndex() ) { const sal_Int32 nCntPos = m_pPam->GetBound( false ).nContent.GetIndex(); m_pPam->GetBound( false ).nContent.Assign( pTextNode, pTextNode->GetText().getLength() + nCntPos ); } #endif // Keep character attribute! SwTextNode* pDelNd = aNxtIdx.GetNode().GetTextNode(); if (pTextNode->GetText().getLength()) pDelNd->FormatToTextAttr( pTextNode ); else pTextNode->ChgFormatColl( pDelNd->GetTextColl() ); pTextNode->JoinNext(); } } } if( SvParserState::Accepted == eState ) { if( m_nMissingImgMaps ) { // Some Image-Map relations are still missing. // Maybe now the Image-Maps are there? ConnectImageMaps(); } // now remove the last useless paragraph SwPosition* pPos = m_pPam->GetPoint(); if( !pPos->nContent.GetIndex() && !bLFStripped ) { SwTextNode* pCurrentNd; sal_uLong nNodeIdx = pPos->nNode.GetIndex(); bool bHasFlysOrMarks = HasCurrentParaFlys() || HasCurrentParaBookmarks( true ); if( IsNewDoc() ) { if (!m_pPam->GetPoint()->nContent.GetIndex() && CanRemoveNode(nNodeIdx)) { SwContentNode* pCNd = m_pPam->GetContentNode(); if( pCNd && pCNd->StartOfSectionIndex()+2 < pCNd->EndOfSectionIndex() && !bHasFlysOrMarks ) { SwViewShell *pVSh = CheckActionViewShell(); SwCursorShell *pCursorSh = pVSh && dynamic_cast< const SwCursorShell *>( pVSh ) != nullptr ? static_cast < SwCursorShell * >( pVSh ) : nullptr; if( pCursorSh && pCursorSh->GetCursor()->GetPoint() ->nNode.GetIndex() == nNodeIdx ) { pCursorSh->MovePara(GoPrevPara, fnParaEnd ); pCursorSh->SetMark(); pCursorSh->ClearMark(); } m_pPam->GetBound().nContent.Assign( nullptr, 0 ); m_pPam->GetBound(false).nContent.Assign( nullptr, 0 ); m_xDoc->GetNodes().Delete( m_pPam->GetPoint()->nNode ); } } } else if( nullptr != ( pCurrentNd = m_xDoc->GetNodes()[ nNodeIdx ]->GetTextNode()) && !bHasFlysOrMarks ) { if( pCurrentNd->CanJoinNext( &pPos->nNode )) { SwTextNode* pNextNd = pPos->nNode.GetNode().GetTextNode(); pPos->nContent.Assign( pNextNd, 0 ); m_pPam->SetMark(); m_pPam->DeleteMark(); pNextNd->JoinPrev(); } else if (pCurrentNd->GetText().isEmpty()) { pPos->nContent.Assign( nullptr, 0 ); m_pPam->SetMark(); m_pPam->DeleteMark(); m_xDoc->GetNodes().Delete( pPos->nNode ); m_pPam->Move( fnMoveBackward ); } } } // annul the SplitNode from the beginning else if( !IsNewDoc() ) { if( pPos->nContent.GetIndex() ) // then there was no

at the end m_pPam->Move( fnMoveForward, GoInNode ); // therefore to the next SwTextNode* pTextNode = pPos->nNode.GetNode().GetTextNode(); SwNodeIndex aPrvIdx( pPos->nNode ); if( pTextNode && pTextNode->CanJoinPrev( &aPrvIdx ) && *m_pSttNdIdx <= aPrvIdx ) { // Normally here should take place a JoinNext, but all cursors and // so are registered in pTextNode, so that it MUST remain. // Convert paragraph to character attribute, from Prev adopt // the paragraph attribute and the template! SwTextNode* pPrev = aPrvIdx.GetNode().GetTextNode(); pTextNode->ChgFormatColl( pPrev->GetTextColl() ); pTextNode->FormatToTextAttr( pPrev ); pTextNode->ResetAllAttr(); if( pPrev->HasSwAttrSet() ) pTextNode->SetAttr( *pPrev->GetpSwAttrSet() ); if( &m_pPam->GetBound().nNode.GetNode() == pPrev ) m_pPam->GetBound().nContent.Assign( pTextNode, 0 ); if( &m_pPam->GetBound(false).nNode.GetNode() == pPrev ) m_pPam->GetBound(false).nContent.Assign( pTextNode, 0 ); pTextNode->JoinPrev(); } } // adjust AutoLoad in DocumentProperties if( IsNewDoc() ) { SwDocShell *pDocShell(m_xDoc->GetDocShell()); OSL_ENSURE(pDocShell, "no SwDocShell"); if (pDocShell) { uno::Reference xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW); uno::Reference xDocProps( xDPS->getDocumentProperties()); OSL_ENSURE(xDocProps.is(), "DocumentProperties is null"); if ( xDocProps.is() && (xDocProps->getAutoloadSecs() > 0) && (xDocProps->getAutoloadURL().isEmpty()) ) { xDocProps->setAutoloadURL(m_aPathToFile); } } } if( m_bUpdateDocStat ) { m_xDoc->getIDocumentStatistics().UpdateDocStat( false, true ); } } if( SvParserState::Pending != GetStatus() ) { delete m_pSttNdIdx; m_pSttNdIdx = nullptr; } // should the parser be the last one who hold the document, then nothing // has to be done anymore, document will be destroyed shortly! if( 1 < m_xDoc->getReferenceCount() ) { if( bWasUndo ) { m_xDoc->GetIDocumentUndoRedo().DelAllUndoObj(); m_xDoc->GetIDocumentUndoRedo().DoUndo(true); } else if( !pInitVSh ) { // When at the beginning of Continue no Shell was available, // it's possible in the meantime one was created. // In that case the bWasUndo flag is wrong and we must // enable Undo. SwViewShell *pTmpVSh = CheckActionViewShell(); if( pTmpVSh ) { m_xDoc->GetIDocumentUndoRedo().DoUndo(true); } } m_xDoc->SetOle2Link( aOLELink ); if( !bModified ) m_xDoc->getIDocumentState().ResetModified(); if( m_bSetModEnabled && m_xDoc->GetDocShell() ) { m_xDoc->GetDocShell()->EnableSetModified(); m_bSetModEnabled = false; // this is unnecessary here } } // When the Document-SwVievShell still exists and an Action is open // (doesn't have to be by abort), end the Action, disconnect from Shell // and finally reconstruct the old Shell. CallEndAction( true ); #ifdef DBG_UTIL m_nContinue--; #endif } void SwHTMLParser::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew ) { switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ) { case RES_OBJECTDYING: if (pOld && static_cast(pOld)->pObject == GetRegisteredIn()) { // then we kill ourself EndListeningAll(); ReleaseRef(); // otherwise we're done! } break; } } void SwHTMLParser::DocumentDetected() { OSL_ENSURE( !m_bDocInitalized, "DocumentDetected called multiple times" ); m_bDocInitalized = true; if( IsNewDoc() ) { if( IsInHeader() ) FinishHeader(); CallEndAction( true ); m_xDoc->GetIDocumentUndoRedo().DoUndo(false); // For DocumentDetected in general a SwViewShell is created. // But it also can be created later, in case the UI is captured. CallStartAction(); } } // is called for every token that is recognised in CallParser void SwHTMLParser::NextToken( HtmlTokenId nToken ) { if( ( m_xDoc->GetDocShell() && m_xDoc->GetDocShell()->IsAbortingImport() ) || 1 == m_xDoc->getReferenceCount() ) { // Was the import cancelled by SFX? If a pending stack // exists, clean it. eState = SvParserState::Error; OSL_ENSURE( !m_pPendStack || m_pPendStack->nToken != HtmlTokenId::NONE, "SwHTMLParser::NextToken: Pending-Stack without token" ); if( 1 == m_xDoc->getReferenceCount() || !m_pPendStack ) return ; } #if OSL_DEBUG_LEVEL > 0 if( m_pPendStack ) { switch( nToken ) { // tables are read by recursive method calls case HtmlTokenId::TABLE_ON: // For CSS declarations we might have to wait // for a file download to finish case HtmlTokenId::LINK: // For controls we might have to set the size. case HtmlTokenId::INPUT: case HtmlTokenId::TEXTAREA_ON: case HtmlTokenId::SELECT_ON: case HtmlTokenId::SELECT_OFF: break; default: OSL_ENSURE( !m_pPendStack, "Unknown token for Pending-Stack" ); break; } } #endif // The following special cases have to be treated before the // filter detection, because Netscape doesn't reference the content // of the title for filter detection either. if( !m_pPendStack ) { if( m_bInTitle ) { switch( nToken ) { case HtmlTokenId::TITLE_OFF: if( IsNewDoc() && !m_sTitle.isEmpty() ) { if( m_xDoc->GetDocShell() ) { uno::Reference xDPS(m_xDoc->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW); uno::Reference xDocProps( xDPS->getDocumentProperties()); OSL_ENSURE(xDocProps.is(), "no DocumentProperties"); if (xDocProps.is()) { xDocProps->setTitle(m_sTitle); } m_xDoc->GetDocShell()->SetTitle( m_sTitle ); } } m_bInTitle = false; m_sTitle.clear(); break; case HtmlTokenId::NONBREAKSPACE: m_sTitle += " "; break; case HtmlTokenId::SOFTHYPH: m_sTitle += "-"; break; case HtmlTokenId::TEXTTOKEN: m_sTitle += aToken; break; default: m_sTitle += "<"; if( (nToken >= HtmlTokenId::ONOFF_START) && isOffToken(nToken) ) m_sTitle += "/"; m_sTitle += sSaveToken; if( !aToken.isEmpty() ) { m_sTitle += " "; m_sTitle += aToken; } m_sTitle += ">"; break; } return; } } // Find out what type of document it is if we don't know already. // For Controls this has to be finished before the control is inserted // because for inserting a View is needed. if( !m_bDocInitalized ) DocumentDetected(); bool bGetIDOption = false, bInsertUnknown = false; bool bUpperSpaceSave = m_bUpperSpace; m_bUpperSpace = false; // The following special cases may or have to be treated after the // filter detection if( !m_pPendStack ) { if( m_bInFloatingFrame ) { //