/* -*- 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 #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 #include #include #include #include #include #include #include #include #include #include #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; //

, , usw. HTMLOptionEnum aHTMLPAlignTable[] = { { OOO_STRING_SVTOOLS_HTML_AL_left, SVX_ADJUST_LEFT }, { OOO_STRING_SVTOOLS_HTML_AL_center, SVX_ADJUST_CENTER }, { OOO_STRING_SVTOOLS_HTML_AL_middle, SVX_ADJUST_CENTER }, // Netscape { OOO_STRING_SVTOOLS_HTML_AL_right, SVX_ADJUST_RIGHT }, { OOO_STRING_SVTOOLS_HTML_AL_justify, SVX_ADJUST_BLOCK }, { OOO_STRING_SVTOOLS_HTML_AL_char, SVX_ADJUST_LEFT }, { nullptr, 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() { bTmplBrowseMode = true; } OUString HTMLReader::GetTemplateName() const { 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( pMedium, "Wo ist das Medium??" ); if( pMedium->IsRemote() || !pMedium->IsStorage() ) { pStrm = pMedium->GetInStream(); return true; } return false; } // Aufruf fuer die allg. Reader-Schnittstelle sal_uLong HTMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, const OUString & rName ) { if( !pStrm ) { OSL_ENSURE( pStrm, "HTML-Read ohne Stream" ); return ERR_SWG_READ_ERROR; } if( !bInsertMode ) { Reader::ResetFrameFormats( rDoc ); // Die HTML-Seitenvorlage setzen, wenn des kein HTML-Dokument ist, // sonst ist sie schon gesetzt. if( !rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ) { rDoc.getIDocumentContentOperations().InsertPoolItem( rPam, SwFormatPageDesc( rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_HTML, false )) ); } } // damit keiner das Doc klaut! rDoc.acquire(); sal_uLong nRet = 0; tools::SvRef xParser = new SwHTMLParser( &rDoc, rPam, *pStrm, rName, rBaseURL, !bInsertMode, pMedium, IsReadUTF8(), bIgnoreHTMLComments ); SvParserState eState = xParser->CallParser(); if( SVPAR_PENDING == eState ) pStrm->ResetError(); else if( SVPAR_ACCEPTED != eState ) { const OUString sErr(OUString::number((sal_Int32)xParser->GetLineNr()) + "," + OUString::number((sal_Int32)xParser->GetLinePos())); // den Stream als Fehlernummer Transporter benutzen nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr, ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR ); } 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_pAppletImpl( nullptr ), m_pCSS1Parser( nullptr ), m_pNumRuleInfo( new SwHTMLNumRuleInfo ), m_pPendStack( nullptr ), m_pDoc( pD ), m_pActionViewShell( nullptr ), m_pSttNdIdx( nullptr ), m_pTable(nullptr), m_pFormImpl( nullptr ), m_pMarquee( nullptr ), m_pField( nullptr ), m_pImageMap( nullptr ), m_pImageMaps(nullptr), m_pFootEndNoteImpl( nullptr ), m_nScriptStartLineNr( 0 ), 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( 0 ), m_eJumpTo( JUMPTO_NONE ), #ifdef DBG_UTIL m_nContinue( 0 ), #endif m_eParaAdjust( SVX_ADJUST_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_bFixSelectHeight( false ), m_bTextArea( false ), m_bSelect( false ), m_bInFootEndNoteAnchor( false ), m_bInFootEndNoteSymbol( false ), m_bIgnoreHTMLComments( bNoHTMLComments ), m_bRemoveHidden( false ), m_pTempViewFrame(nullptr) { m_nEventId = nullptr; m_bUpperSpace = m_bViewCreated = m_bChkJumpMark = m_bSetCursor = false; m_eScriptLang = HTML_SL_UNKNOWN; m_bAnyStarBasic = true; rCursor.DeleteMark(); m_pPam = &rCursor; // re-use existing cursor: avoids spurious ~SwIndexReg assert memset( &m_aAttrTab, 0, sizeof( _HTMLAttrTable )); // Die Font-Groessen 1-7 aus der INI-Datei lesen 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_pDoc->SetDefault( aFontHeight ); SvxFontHeightItem aFontHeightCJK(m_aFontHeights[2], 100, RES_CHRATR_CJK_FONTSIZE); m_pDoc->SetDefault( aFontHeightCJK ); SvxFontHeightItem aFontHeightCTL(m_aFontHeights[2], 100, RES_CHRATR_CTL_FONTSIZE); m_pDoc->SetDefault( aFontHeightCTL ); // #i18732# - adjust default of option 'FollowTextFlow' // TODO: not sure what the appropriate default for HTML should be? m_pDoc->SetDefault( SwFormatFollowTextFlow(true) ); } // Waehrend des Imports in den HTML-Modus schalten, damit die // richrigen Vorlagen angelegt werden m_bOldIsHTMLMode = m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE); m_pDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, true); m_pCSS1Parser = new SwCSS1Parser( m_pDoc, m_aFontHeights, m_sBaseURL, IsNewDoc() ); m_pCSS1Parser->SetIgnoreFontFamily( rHtmlOptions.IsIgnoreFontFamily() ); if( bReadUTF8 ) { SetSrcEncoding( RTL_TEXTENCODING_UTF8 ); } else { SwDocShell *pDocSh = m_pDoc->GetDocShell(); SvKeyValueIterator *pHeaderAttrs = pDocSh->GetHeaderAttributes(); if( pHeaderAttrs ) SetEncodingByHTTPHeader( pHeaderAttrs ); } m_pCSS1Parser->SetDfltEncoding( osl_getThreadTextEncoding() ); // Timer nur bei ganz normalen Dokumenten aufsetzen! SwDocShell* pDocSh = m_pDoc->GetDocShell(); if( pDocSh ) { m_bViewCreated = true; // nicht, synchron laden // es ist ein Sprungziel vorgegeben. 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 = comphelper::string::remove( m_sJmpMark.copy(nPos + 1), ' '); } 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; // das ist nichts gueltiges! else // ansonsten ist das ein normaler (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; } } } } SwHTMLParser::~SwHTMLParser() { #ifdef DBG_UTIL OSL_ENSURE( !m_nContinue, "DTOR im Continue!" ); #endif bool bAsync = m_pDoc->IsInLoadAsynchron(); m_pDoc->SetInLoadAsynchron( false ); m_pDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, m_bOldIsHTMLMode); if( m_pDoc->GetDocShell() && m_nEventId ) Application::RemoveUserEvent( m_nEventId ); // das DocumentDetected kann ggfs. die DocShells loeschen, darum nochmals // abfragen if( m_pDoc->GetDocShell() ) { // Gelinkte Bereiche updaten sal_uInt16 nLinkMode = m_pDoc->getIDocumentSettingAccess().getLinkUpdateMode( true ); if( nLinkMode != NEVER && bAsync && SfxObjectCreateMode::INTERNAL!=m_pDoc->GetDocShell()->GetCreateMode() ) m_pDoc->getIDocumentLinksAdministration().GetLinkManager().UpdateAllLinks( nLinkMode == MANUAL ); if ( m_pDoc->GetDocShell()->IsLoading() ) { // #i59688# m_pDoc->GetDocShell()->LoadingFinished(); } } delete m_pSttNdIdx; if( !m_aSetAttrTab.empty() ) { OSL_ENSURE( m_aSetAttrTab.empty(),"Es stehen noch Attribute auf dem 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_pTable, "Es existiert noch eine offene Tabelle" ); delete m_pImageMaps; OSL_ENSURE( !m_pPendStack, "SwHTMLParser::~SwHTMLParser: Hier sollte es keinen Pending-Stack mehr geben" ); while( m_pPendStack ) { SwPendingStack* pTmp = m_pPendStack; m_pPendStack = m_pPendStack->pNext; delete pTmp->pData; delete pTmp; } if( !m_pDoc->release() ) { // keiner will mehr das Doc haben, also weg damit delete m_pDoc; m_pDoc = nullptr; } 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_pDoc && m_pDoc->GetDocShell() && m_pDoc->GetDocShell()->GetMedium() ) m_pDoc->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN ); } } IMPL_LINK_NOARG_TYPED( SwHTMLParser, AsyncCallback, void*, void ) { m_nEventId=nullptr; // #i47907# - If the document has already been destructed, // the parser should be aware of this: if( ( m_pDoc->GetDocShell() && m_pDoc->GetDocShell()->IsAbortingImport() ) || 1 == m_pDoc->getReferenceCount() ) { // wurde der Import vom SFX abgebrochen? eState = SVPAR_ERROR; } GetAsynchCallLink().Call(nullptr); } SvParserState SwHTMLParser::CallParser() { // einen temporaeren Index anlegen, auf Pos 0 so wird er nicht bewegt! m_pSttNdIdx = new SwNodeIndex( m_pDoc->GetNodes() ); if( !IsNewDoc() ) // in ein Dokument einfuegen ? { const SwPosition* pPos = m_pPam->GetPoint(); m_pDoc->getIDocumentContentOperations().SplitNode( *pPos, false ); *m_pSttNdIdx = pPos->nNode.GetIndex()-1; m_pDoc->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_pDoc->getIDocumentRedlineAccess().SplitRedline( aInsertionRangePam ); m_pDoc->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; } } // Laufbalken anzeigen else if( !GetMedium() || !GetMedium()->IsRemote() ) { rInput.Seek(STREAM_SEEK_TO_END); rInput.ResetError(); ::StartProgress( STR_STATSTR_W4WREAD, 0, rInput.Tell(), m_pDoc->GetDocShell() ); rInput.Seek(STREAM_SEEK_TO_BEGIN); rInput.ResetError(); } m_pDoc->GetPageDesc( 0 ).Add( this ); SvParserState eRet = HTMLParser::CallParser(); return eRet; } void SwHTMLParser::Continue( int nToken ) { #ifdef DBG_UTIL OSL_ENSURE(!m_nContinue, "Continue im Continue - not supposed to happen"); m_nContinue++; #endif // Wenn der Import (vom SFX) abgebrochen wurde, wird ein Fehler // gesetzt aber trotzdem noch weiter gemacht, damit vernuenftig // aufgeraeumt wird. OSL_ENSURE( SVPAR_ERROR!=eState, "SwHTMLParser::Continue: bereits ein Fehler gesetzt" ); if( m_pDoc->GetDocShell() && m_pDoc->GetDocShell()->IsAbortingImport() ) eState = SVPAR_ERROR; // Die SwViewShell vom Dokument holen, merken und als aktuelle setzen. SwViewShell *pInitVSh = CallStartAction(); if( SVPAR_ERROR != eState && GetMedium() && !m_bViewCreated ) { // Beim ersten Aufruf erstmal returnen, Doc anzeigen // und auf Timer Callback warten. // An dieser Stelle wurde im CallParser gerade mal ein Zeichen // gelesen und ein SaveState(0) gerufen. eState = SVPAR_PENDING; m_bViewCreated = true; m_pDoc->SetInLoadAsynchron( true ); #ifdef DBG_UTIL m_nContinue--; #endif return; } m_bSetModEnabled = false; if( m_pDoc->GetDocShell() && (m_bSetModEnabled = m_pDoc->GetDocShell()->IsEnableSetModified()) ) { m_pDoc->GetDocShell()->EnableSetModified( false ); } // waehrend des einlesens kein OLE-Modified rufen Link aOLELink( m_pDoc->GetOle2Link() ); m_pDoc->SetOle2Link( Link() ); bool bModified = m_pDoc->getIDocumentState().IsModified(); bool const bWasUndo = m_pDoc->GetIDocumentUndoRedo().DoesUndo(); m_pDoc->GetIDocumentUndoRedo().DoUndo(false); // Wenn der Import abgebrochen wird, kein Continue mehr rufen. // Falls ein Pending-Stack existiert aber durch einen Aufruf // von NextToken dafuer sorgen, dass der Pending-Stack noch // beendet wird. if( SVPAR_ERROR == eState ) { OSL_ENSURE( !m_pPendStack || m_pPendStack->nToken, "SwHTMLParser::Continue: Pending-Stack ohne Token" ); if( m_pPendStack && m_pPendStack->nToken ) NextToken( m_pPendStack->nToken ); OSL_ENSURE( !m_pPendStack, "SwHTMLParser::Continue: Es gibt wieder einen Pend-Stack" ); } else { HTMLParser::Continue( m_pPendStack ? m_pPendStack->nToken : nToken ); } // Laufbalken wieder abschalten EndProgress( m_pDoc->GetDocShell() ); bool bLFStripped = false; if( SVPAR_PENDING != GetStatus() ) { // noch die letzten Attribute setzen { if( !m_aScriptSource.isEmpty() ) { SwScriptFieldType *pType = static_cast(m_pDoc->getIDocumentFieldsAccess().GetSysFieldType( RES_SCRIPTFLD )); SwScriptField aField( pType, m_aScriptType, m_aScriptSource, false ); InsertAttr( SwFormatField( aField ) ); } if( m_pAppletImpl ) { if( m_pAppletImpl->GetApplet().is() ) EndApplet(); else EndObject(); } // ggf. ein noch vorhandes LF hinter dem letzen Absatz entfernen if( IsNewDoc() ) bLFStripped = StripTrailingLF() > 0; // noch offene Nummerierungen beenden. while( GetNumInfo().GetNumRule() ) EndNumBulList(); OSL_ENSURE( !m_nContextStMin, "Es gibt geschuetzte Kontexte" ); m_nContextStMin = 0; while( m_aContexts.size() ) { _HTMLAttrContext *pCntxt = PopContext(); if( pCntxt ) { EndContext( pCntxt ); delete pCntxt; } } if( !m_aParaAttrs.empty() ) m_aParaAttrs.clear(); SetAttr( false ); // Noch die erst verzoegert gesetzten Styles setzen m_pCSS1Parser->SetDelayedStyles(); } // den Start wieder korrigieren 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(); // wenn der Cursor noch in dem Node steht, dann setze in an das Ende if( m_pPam->GetPoint()->nNode == aNxtIdx ) { m_pPam->GetPoint()->nNode = *m_pSttNdIdx; m_pPam->GetPoint()->nContent.Assign( pTextNode, nStt ); } #if OSL_DEBUG_LEVEL > 0 // !!! sollte nicht moeglich sein, oder ?? OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound().nNode.GetIndex(), "Pam.Bound1 steht noch im Node" ); OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound( false ).nNode.GetIndex(), "Pam.Bound2 steht noch im 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 // Zeichen Attribute beibehalten! SwTextNode* pDelNd = aNxtIdx.GetNode().GetTextNode(); if (pTextNode->GetText().getLength()) pDelNd->FormatToTextAttr( pTextNode ); else pTextNode->ChgFormatColl( pDelNd->GetTextColl() ); pTextNode->JoinNext(); } } } if( SVPAR_ACCEPTED == eState ) { if( m_nMissingImgMaps ) { // es fehlen noch ein paar Image-Map zuordungen. // vielleicht sind die Image-Maps ja jetzt da? ConnectImageMaps(); } // jetzt noch den letzten ueberfluessigen Absatz loeschen SwPosition* pPos = m_pPam->GetPoint(); if( !pPos->nContent.GetIndex() && !bLFStripped ) { SwTextNode* pAktNd; sal_uLong nNodeIdx = pPos->nNode.GetIndex(); bool bHasFlysOrMarks = HasCurrentParaFlys() || HasCurrentParaBookmarks( true ); if( IsNewDoc() ) { const SwNode *pPrev = m_pDoc->GetNodes()[nNodeIdx -1]; if( !m_pPam->GetPoint()->nContent.GetIndex() && ( pPrev->IsContentNode() || (pPrev->IsEndNode() && pPrev->StartOfSectionNode()->IsSectionNode()) ) ) { 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(fnParaPrev, fnParaEnd ); pCursorSh->SetMark(); pCursorSh->ClearMark(); } m_pPam->GetBound().nContent.Assign( nullptr, 0 ); m_pPam->GetBound(false).nContent.Assign( nullptr, 0 ); m_pDoc->GetNodes().Delete( m_pPam->GetPoint()->nNode ); } } } else if( nullptr != ( pAktNd = m_pDoc->GetNodes()[ nNodeIdx ]->GetTextNode()) && !bHasFlysOrMarks ) { if( pAktNd->CanJoinNext( &pPos->nNode )) { SwTextNode* pNextNd = pPos->nNode.GetNode().GetTextNode(); pPos->nContent.Assign( pNextNd, 0 ); m_pPam->SetMark(); m_pPam->DeleteMark(); pNextNd->JoinPrev(); } else if (pAktNd->GetText().isEmpty()) { pPos->nContent.Assign( nullptr, 0 ); m_pPam->SetMark(); m_pPam->DeleteMark(); m_pDoc->GetNodes().Delete( pPos->nNode ); m_pPam->Move( fnMoveBackward ); } } } // nun noch das SplitNode vom Anfang aufheben else if( !IsNewDoc() ) { if( pPos->nContent.GetIndex() ) // dann gabs am Ende kein

, m_pPam->Move( fnMoveForward, fnGoNode ); // als zum naechsten Node SwTextNode* pTextNode = pPos->nNode.GetNode().GetTextNode(); SwNodeIndex aPrvIdx( pPos->nNode ); if( pTextNode && pTextNode->CanJoinPrev( &aPrvIdx ) && *m_pSttNdIdx <= aPrvIdx ) { // eigentlich muss hier ein JoinNext erfolgen, aber alle Cursor // usw. sind im pTextNode angemeldet, so dass der bestehen // bleiben MUSS. // Absatz in Zeichen-Attribute umwandeln, aus dem Prev die // Absatzattribute und die Vorlage uebernehmen! 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_pDoc->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_pDoc->getIDocumentStatistics().UpdateDocStat( false, true ); } } if( SVPAR_PENDING != GetStatus() ) delete m_pSttNdIdx, m_pSttNdIdx = nullptr; // sollte der Parser der Letzte sein, der das Doc haelt, dann braucht // man hier auch nichts mehr tun, Doc wird gleich zerstoert! if( 1 < m_pDoc->getReferenceCount() ) { if( bWasUndo ) { m_pDoc->GetIDocumentUndoRedo().DelAllUndoObj(); m_pDoc->GetIDocumentUndoRedo().DoUndo(true); } else if( !pInitVSh ) { // Wenn zu Beginn des Continue keine Shell vorhanden war, // kann trotzdem mitlerweile eine angelegt worden sein. // In dieses Fall stimmt das bWasUndo-Flag nicht und // wir muessen das Undo noch anschalten. SwViewShell *pTmpVSh = CheckActionViewShell(); if( pTmpVSh ) { m_pDoc->GetIDocumentUndoRedo().DoUndo(true); } } m_pDoc->SetOle2Link( aOLELink ); if( !bModified ) m_pDoc->getIDocumentState().ResetModified(); if( m_bSetModEnabled && m_pDoc->GetDocShell() ) { m_pDoc->GetDocShell()->EnableSetModified(); m_bSetModEnabled = false; // this is unnecessary here } } // Wenn die Dokuemnt-SwViewShell noch existiert und eine Action // offen ist (muss bei Abbruch nicht sein), die Action beenden, // uns von der Shell abmelden und schliesslich die alte Shell // wieder rekonstruieren. 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()) { // dann uns selbst beenden GetRegisteredInNonConst()->Remove( this ); ReleaseRef(); // ansonsten sind wir fertig! } break; } } void SwHTMLParser::DocumentDetected() { OSL_ENSURE( !m_bDocInitalized, "DocumentDetected mehrfach aufgerufen" ); m_bDocInitalized = true; if( IsNewDoc() ) { if( IsInHeader() ) FinishHeader( true ); CallEndAction( true ); m_pDoc->GetIDocumentUndoRedo().DoUndo(false); // Durch das DocumentDetected wurde im allgemeinen eine // SwViewShell angelegt. Es kann aber auch sein, dass sie // erst spaeter angelegt wird, naemlich dann, wenn die UI // gecaptured ist. CallStartAction(); } } // is called for every token that is recognised in CallParser void SwHTMLParser::NextToken( int nToken ) { if( ( m_pDoc->GetDocShell() && m_pDoc->GetDocShell()->IsAbortingImport() ) || 1 == m_pDoc->getReferenceCount() ) { // Was the import cancelled by SFX? If a pending stack // exists, clean it. eState = SVPAR_ERROR; OSL_ENSURE( !m_pPendStack || m_pPendStack->nToken, "SwHTMLParser::NextToken: Pending-Stack without token" ); if( 1 == m_pDoc->getReferenceCount() || !m_pPendStack ) return ; } #if OSL_DEBUG_LEVEL > 0 if( m_pPendStack ) { switch( nToken ) { // tables are read by recursive method calls case HTML_TABLE_ON: // For CSS declarations we might have to wait // for a file download to finish case HTML_LINK: // For controls we might have to set the size. case HTML_INPUT: case HTML_TEXTAREA_ON: case HTML_SELECT_ON: case HTML_SELECT_OFF: break; default: OSL_ENSURE( !m_pPendStack, "Unbekanntes Token fuer 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 HTML_TITLE_OFF: if( IsNewDoc() && !m_sTitle.isEmpty() ) { if( m_pDoc->GetDocShell() ) { uno::Reference xDPS(m_pDoc->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_pDoc->GetDocShell()->SetTitle( m_sTitle ); } } m_bInTitle = false; m_sTitle.clear(); break; case HTML_NONBREAKSPACE: m_sTitle += " "; break; case HTML_SOFTHYPH: m_sTitle += "-"; break; case HTML_TEXTTOKEN: m_sTitle += aToken; break; default: m_sTitle += "<"; if( (HTML_TOKEN_ONOFF & nToken) && (1 & 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 ) { //