From c4498251cb7181a9f272b0720f398597c0daef09 Mon Sep 17 00:00:00 2001 From: Oliver-Rainer Wittmann Date: Mon, 17 Sep 2012 11:46:16 +0000 Subject: Resolves: #i119963#, #i120877# import and export actual TOC content Patch by: zhengfan, Oliver Review by: Oliver reintegrate from branch writer001 (cherry picked from commit 8f2a21eac4a904db3cc4c448179e2d2cf5878ef4) Conflicts: sw/inc/tox.hxx sw/source/core/tox/tox.cxx sw/source/filter/ww8/dump/ww8scan.cxx sw/source/filter/ww8/wrtw8nds.cxx sw/source/filter/ww8/wrtww8.cxx sw/source/filter/ww8/ww8atr.cxx sw/source/filter/ww8/ww8par.cxx sw/source/filter/ww8/ww8par.hxx sw/source/filter/ww8/ww8par5.cxx sw/source/filter/ww8/ww8par6.cxx Change-Id: I75b2971f23754afa0bcb0b549bfb820dd5924b3b --- sw/inc/tox.hxx | 13 + sw/source/core/doc/doctxm.cxx | 7 + sw/source/core/tox/tox.cxx | 26 +- sw/source/filter/ww8/attributeoutputbase.hxx | 4 +- sw/source/filter/ww8/writerwordglue.cxx | 4 + sw/source/filter/ww8/wrtw8nds.cxx | 8 +- sw/source/filter/ww8/wrtww8.cxx | 269 ++++++++--------- sw/source/filter/ww8/wrtww8.hxx | 2 +- sw/source/filter/ww8/ww8atr.cxx | 434 ++++++++++++++------------- sw/source/filter/ww8/ww8attributeoutput.hxx | 6 +- sw/source/filter/ww8/ww8par.cxx | 94 ++++-- sw/source/filter/ww8/ww8par.hxx | 11 + sw/source/filter/ww8/ww8par5.cxx | 243 +++++++++------ sw/source/filter/ww8/ww8par6.cxx | 9 + sw/source/filter/ww8/ww8scan.cxx | 14 +- sw/source/filter/ww8/ww8scan.hxx | 2 +- sw/source/ui/index/toxmgr.cxx | 2 + 17 files changed, 653 insertions(+), 495 deletions(-) (limited to 'sw') diff --git a/sw/inc/tox.hxx b/sw/inc/tox.hxx index 8e5a3b746a55..93c6200b31c4 100644 --- a/sw/inc/tox.hxx +++ b/sw/inc/tox.hxx @@ -463,6 +463,13 @@ class SW_DLLPUBLIC SwTOXBase : public SwClient sal_Bool bFromObjectNames : 1; // create a table or object index // from the names rather than the caption sal_Bool bLevelFromChapter : 1; // User index: get the level from the source chapter + +protected: + // Add a data member, for record the TOC field expression of MS Word binary format + // For keeping fedality and may giving a better exporting performance + OUString maMSTOCExpression; + sal_Bool mbKeepExpression; + public: SwTOXBase( const SwTOXType* pTyp, const SwForm& rForm, sal_uInt16 nCreaType, const OUString& rTitle ); @@ -482,6 +489,12 @@ public: OUString GetTOXName() const {return aName;} void SetTOXName(const OUString& rSet) {aName = rSet;} + // for record the TOC field expression of MS Word binary format + const OUString& GetMSTOCExpression() const{return maMSTOCExpression;} + void SetMSTOCExpression(const OUString& rExp) {maMSTOCExpression = rExp;} + void EnableKeepExpression() {mbKeepExpression = sal_True;} + void DisableKeepExpression() {mbKeepExpression = sal_False;} + OUString GetTitle() const; // Title OUString GetTypeName() const; // Name const SwForm& GetTOXForm() const; // description of the lines diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx index a5919b16fb3a..94a2f8afc521 100644 --- a/sw/source/core/doc/doctxm.cxx +++ b/sw/source/core/doc/doctxm.cxx @@ -752,7 +752,14 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr, !GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) || !pSectNd->GetNodes().IsDocNodes() || IsHiddenFlag() ) + { return; + } + + if ( !mbKeepExpression ) + { + maMSTOCExpression = OUString(); + } SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc(); diff --git a/sw/source/core/tox/tox.cxx b/sw/source/core/tox/tox.cxx index c7e177f01c84..d94ec5daddbb 100644 --- a/sw/source/core/tox/tox.cxx +++ b/sw/source/core/tox/tox.cxx @@ -506,17 +506,19 @@ OUString SwForm::GetFormAuth() {return OUString("");} SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm, sal_uInt16 nCreaType, const OUString& rTitle ) - : SwClient((SwModify*)pTyp), - aForm(rForm), - aTitle(rTitle), - eLanguage(::GetAppLanguage()), - nCreateType(nCreaType), - nOLEOptions(0), - eCaptionDisplay(CAPTION_COMPLETE), - bProtected( sal_True ), - bFromChapter(sal_False), - bFromObjectNames(sal_False), - bLevelFromChapter(sal_False) + : SwClient((SwModify*)pTyp) + , aForm(rForm) + , aTitle(rTitle) + , eLanguage((LanguageType)::GetAppLanguage()) + , nCreateType(nCreaType) + , nOLEOptions(0) + , eCaptionDisplay(CAPTION_COMPLETE) + , bProtected( sal_True ) + , bFromChapter(sal_False) + , bFromObjectNames(sal_False) + , bLevelFromChapter(sal_False) + , maMSTOCExpression() + , mbKeepExpression(sal_True) { aData.nOptions = 0; } @@ -524,6 +526,7 @@ SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm, SwTOXBase::SwTOXBase( const SwTOXBase& rSource, SwDoc* pDoc ) : SwClient( rSource.GetRegisteredInNonConst() ) + , mbKeepExpression(sal_True) { CopyTOXBase( pDoc, rSource ); } @@ -535,6 +538,7 @@ void SwTOXBase::RegisterToTOXType( SwTOXType& rType ) SwTOXBase& SwTOXBase::CopyTOXBase( SwDoc* pDoc, const SwTOXBase& rSource ) { + maMSTOCExpression = rSource.maMSTOCExpression; SwTOXType* pType = (SwTOXType*)rSource.GetTOXType(); if( pDoc && USHRT_MAX == pDoc->GetTOXTypes().GetPos( pType )) { diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index 75e847aa9fc6..7e32502d3e78 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -214,7 +214,9 @@ public: void StartTOX( const SwSection& rSect ); - void EndTOX( const SwSection& rSect ); + void EndTOX( const SwSection& rSect,bool bCareEnd=true ); + + virtual void OnTOXEnding() {} virtual void TOXMark( const SwTxtNode& rNode, const SwTOXMark& rAttr ); diff --git a/sw/source/filter/ww8/writerwordglue.cxx b/sw/source/filter/ww8/writerwordglue.cxx index af8c32ea7d37..7fc60611ea1f 100644 --- a/sw/source/filter/ww8/writerwordglue.cxx +++ b/sw/source/filter/ww8/writerwordglue.cxx @@ -494,6 +494,10 @@ namespace sw return true; if (nB == RES_TXTATR_CHARFMT) return false; + if (nA == RES_TXTATR_INETFMT) + return true; + if (nB == RES_TXTATR_INETFMT) + return false; return nA < nB; } diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index 8c608f7e78af..53ced4ed7a1f 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -1974,7 +1974,7 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode ) if ( pTOXSect ) { m_aCurrentCharPropStarts.pop(); - AttrOutput().EndTOX( *pTOXSect ); + AttrOutput().EndTOX( *pTOXSect ,false); } //For i120928,the position of the bullet's graphic is at end of doc if (bLastCR && (!bExported)) @@ -2019,6 +2019,7 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode ) aAttrIter.OutFlys( nEnd ); // insert final bookmarks if any before CR and after flys AppendBookmarks( rNode, nEnd, 1 ); + WriteCR( pTextNodeInfoInner ); // #i120928 - position of the bullet's graphic is at end of doc if (bLastCR && (!bExported)) { @@ -2032,8 +2033,6 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode ) AttrOutput().EndTOX( *pTOXSect ); } - WriteCR( pTextNodeInfoInner ); - if ( bRedlineAtEnd ) { AttrOutput().Redline( aAttrIter.GetRedline( nEnd ) ); @@ -2447,7 +2446,8 @@ void MSWordExportBase::OutputSectionNode( const SwSectionNode& rSectionNode ) SwNodeIndex aIdx( rSectionNode, 1 ); const SwNode& rNd = aIdx.GetNode(); - if ( !rNd.IsSectionNode() && !IsInTable() ) //No sections in table + if ( !rNd.IsSectionNode() && !IsInTable() + && rSection.GetType() != TOX_CONTENT_SECTION && rSection.GetType() != TOX_HEADER_SECTION) //No sections in table { // if the first Node inside the section has an own // PageDesc or PageBreak attribut, then dont write diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx index 95ef3fad8511..e5000919fae6 100644 --- a/sw/source/filter/ww8/wrtww8.cxx +++ b/sw/source/filter/ww8/wrtww8.cxx @@ -26,6 +26,9 @@ #include +#include +#include + #include #include #include @@ -177,41 +180,146 @@ public: WW8_FC GetStartFc() const { return nStartFc; } }; +typedef std::map BKMKNames; +typedef BKMKNames::iterator BKMKNmItr; +typedef std::pair BKMK; +typedef std::pair BKMKCP; +typedef std::multimap BKMKCPs; +typedef BKMKCPs::iterator CPItr; + class WW8_WrtBookmarks { private: - //! Holds information about a single bookmark. - struct BookmarkInfo { - sal_uLong startPos; //!< Starting character position. - sal_uLong endPos; //!< Ending character position. - bool isField; //!< True if the bookmark is in a field result. - OUString name; //!< Name of this bookmark. - inline BookmarkInfo(sal_uLong start, sal_uLong end, bool isFld, const OUString& bkName) : startPos(start), endPos(end), isField(isFld), name(bkName) {}; - //! Operator < is defined purely for sorting. - inline bool operator<(const BookmarkInfo &other) const { return startPos < other.startPos; } - }; - std::vector aBookmarks; - typedef std::vector::iterator BkmIter; - - //! Return the position in aBookmarks where the string rNm can be found. - BkmIter GetPos( const OUString& rNm ); - - //No copying + BKMKCPs aSttCps,aEndCps; + BKMKNames maSwBkmkNms; WW8_WrtBookmarks(const WW8_WrtBookmarks&); WW8_WrtBookmarks& operator=(const WW8_WrtBookmarks&); + public: WW8_WrtBookmarks(); ~WW8_WrtBookmarks(); - //! Add a new bookmark to the list OR add an end position to an existing bookmark. void Append( WW8_CP nStartCp, const OUString& rNm, const ::sw::mark::IMark* pBkmk=NULL ); //! Write out bookmarks to file. void Write( WW8Export& rWrt ); //! Move existing field marks from one position to another. - void MoveFieldMarks(sal_uLong nFrom,sal_uLong nTo); - + void MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo); }; +WW8_WrtBookmarks::WW8_WrtBookmarks() +{} + +WW8_WrtBookmarks::~WW8_WrtBookmarks() +{ + CPItr aEnd = aSttCps.end(); + for (CPItr aItr = aSttCps.begin();aItr!=aEnd;aItr++) + { + if (aItr->second) + { + delete aItr->second; + aItr->second = NULL; + } + } +} + +void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const OUString& rNm, const ::sw::mark::IMark*) +{ + std::pair aResult = maSwBkmkNms.insert(std::pair(rNm,0L)); + if (aResult.second) + { + BKMK aBK(false,rNm); + BKMKCP* pBKCP = new BKMKCP((long)nStartCp,aBK); + aSttCps.insert(std::pair(nStartCp,pBKCP)); + aResult.first->second = (long)nStartCp; + } + else + { + std::pair aRange = aSttCps.equal_range(aResult.first->second); + for (CPItr aItr = aRange.first;aItr != aRange.second;aItr++) + { + if (aItr->second && aItr->second->second.second == rNm) + { + if (aItr->second->second.first) + nStartCp--; + aItr->second->first = (long)nStartCp; + break; + } + } + } +} + +void WW8_WrtBookmarks::Write( WW8Export& rWrt) +{ + if (!aSttCps.size()) + return; + CPItr aItr; + long n; + std::vector aNames; + SvMemoryStream aTempStrm1(65535,65535); + SvMemoryStream aTempStrm2(65535,65535); + for (aItr = aSttCps.begin();aItr!=aSttCps.end();aItr++) + { + if (aItr->second) + { + aEndCps.insert(std::pair(aItr->second->first,aItr->second)); + aNames.push_back(aItr->second->second.second); + SwWW8Writer::WriteLong( aTempStrm1, aItr->first); + } + } + + aTempStrm1.Seek(0L); + for (aItr = aEndCps.begin(), n = 0;aItr != aEndCps.end();aItr++,n++) + { + if (aItr->second) + { + aItr->second->first = n; + SwWW8Writer::WriteLong( aTempStrm2, aItr->first); + } + } + + aTempStrm2.Seek(0L); + rWrt.WriteAsStringTable(aNames, rWrt.pFib->fcSttbfbkmk,rWrt.pFib->lcbSttbfbkmk); + SvStream& rStrm = rWrt.bWrtWW8 ? *rWrt.pTableStrm : rWrt.Strm(); + rWrt.pFib->fcPlcfbkf = rStrm.Tell(); + rStrm<ccpText + rWrt.pFib->ccpTxbx); + for (aItr = aSttCps.begin();aItr!=aSttCps.end();aItr++) + { + if (aItr->second) + { + SwWW8Writer::WriteLong(rStrm, aItr->second->first); + } + } + rWrt.pFib->lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->fcPlcfbkf; + rWrt.pFib->fcPlcfbkl = rStrm.Tell(); + rStrm<ccpText + rWrt.pFib->ccpTxbx); + rWrt.pFib->lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->fcPlcfbkl; +} + +void WW8_WrtBookmarks::MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo) +{ + std::pair aRange = aSttCps.equal_range(nFrom); + CPItr aItr = aRange.first; + while (aItr != aRange.second) + { + if (aItr->second) + { + if (aItr->second->first == nFrom) + { + aItr->second->second.first = true; + aItr->second->first = nTo; + } + aSttCps.insert(std::pair(nTo,aItr->second)); + aItr->second = NULL; + aRange = aSttCps.equal_range(nFrom); + aItr = aRange.first; + continue; + } + aItr++; + } +} + #define ANZ_DEFAULT_STYLES 16 // Names of the storage streams @@ -1237,122 +1345,6 @@ WW8_CP WW8_WrPct::Fc2Cp( sal_uLong nFc ) const return nFc + aPcts.back().GetStartCp(); } -//-------------------------------------------------------------------------- - -WW8_WrtBookmarks::WW8_WrtBookmarks() -{ -} - -WW8_WrtBookmarks::~WW8_WrtBookmarks() -{ -} - -void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const OUString& rNm, const ::sw::mark::IMark* ) -{ - BkmIter bkIter = GetPos( rNm ); - if( bkIter == aBookmarks.end() ) - { - // new bookmark -> insert with start==end - aBookmarks.push_back( BookmarkInfo(nStartCp, nStartCp, false, rNm) ); - } - else - { - // old bookmark -> this should be the end position - OSL_ENSURE( bkIter->endPos == bkIter->startPos, "end position is valid" ); - - //If this bookmark was around a field in writer, then we want to move - //it to the field result in word. The end is therefore one cp - //backwards from the 0x15 end mark that was inserted. - if (bkIter->isField) - --nStartCp; - bkIter->endPos = nStartCp; - } -} - - -void WW8_WrtBookmarks::Write( WW8Export& rWrt ) -{ - if (!aBookmarks.empty()) - { - //Make sure the bookmarks are sorted in order of start position. - std::sort(aBookmarks.begin(), aBookmarks.end()); - - // First write the Bookmark Name Stringtable - std::vector aNames; - aNames.reserve(aBookmarks.size()); - for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt) - aNames.push_back(bIt->name); - rWrt.WriteAsStringTable(aNames, rWrt.pFib->fcSttbfbkmk, rWrt.pFib->lcbSttbfbkmk); - - // Second write the Bookmark start positions as pcf of longs - SvStream& rStrm = rWrt.bWrtWW8 ? *rWrt.pTableStrm : rWrt.Strm(); - rWrt.pFib->fcPlcfbkf = rStrm.Tell(); - for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt) - SwWW8Writer::WriteLong( rStrm, bIt->startPos ); - SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx); - - //Lastly, need to write out the end positions (sorted by end position). But - //before that we need a lookup table (sorted by start position) to link - //start and end positions. - // Start by sorting the end positions. - std::vector aEndSortTab; - aEndSortTab.reserve(aBookmarks.size()); - for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt) - aEndSortTab.push_back(bIt->endPos); - std::sort(aEndSortTab.begin(), aEndSortTab.end()); - - //Now write out the lookups. - //Note that in most cases, the positions in both vectors will be very close. - for( sal_uLong i = 0; i < aBookmarks.size(); ++i ) - { - sal_uLong nEndCP = aBookmarks[ i ].endPos; - sal_uInt16 nPos = i; - if( aEndSortTab[ nPos ] > nEndCP ) - { - while( aEndSortTab[ --nPos ] != nEndCP ) - ; - } - else if( aEndSortTab[ nPos ] < nEndCP ) - while( aEndSortTab[ ++nPos ] != nEndCP ) - ; - SwWW8Writer::WriteLong( rStrm, nPos ); - } - rWrt.pFib->lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->fcPlcfbkf; - - // Finally, the actual Bookmark end positions. - rWrt.pFib->fcPlcfbkl = rStrm.Tell(); - for(sal_uLong i = 0; i < aEndSortTab.size(); ++i ) - SwWW8Writer::WriteLong( rStrm, aEndSortTab[ i ] ); - SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx); - rWrt.pFib->lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->fcPlcfbkl; - } -} - -WW8_WrtBookmarks::BkmIter WW8_WrtBookmarks::GetPos( const OUString& rNm ) -{ - for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt) { - if (rNm == bIt->name) - return bIt; - } - return aBookmarks.end(); -} - -void WW8_WrtBookmarks::MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo) -{ - for (BkmIter i = aBookmarks.begin(); i < aBookmarks.end(); ++i) - { - if (i->startPos == nFrom) - { - i->startPos = nTo; - if (i->endPos == nFrom) - { - i->isField = true; - i->endPos = nTo; - } - } - } -} - void WW8Export::AppendBookmarks( const SwTxtNode& rNd, xub_StrLen nAktPos, xub_StrLen nLen ) { @@ -1397,7 +1389,7 @@ void WW8Export::AppendBookmarks( const SwTxtNode& rNd, } } -void WW8Export::MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo) +void WW8Export::MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo) { pBkmks->MoveFieldMarks(nFrom, nTo); } @@ -2540,7 +2532,8 @@ void MSWordExportBase::WriteText() ; else if ( aIdx.GetNode().IsSectionNode() ) ; - else if ( !IsInTable() ) //No sections in table + else if ( !IsInTable() + && (rSect.GetType() != TOX_CONTENT_SECTION && rSect.GetType() != TOX_HEADER_SECTION )) //No sections in table { //#120140# Do not need to insert a page/section break after a section end. Check this case first sal_Bool bNeedExportBreakHere = sal_True; diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index ec9eb54f08b7..4185437d53ea 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -1018,7 +1018,7 @@ public: virtual void ExportGrfBullet(const SwTxtNode& rNd); void OutGrfBullets(const sw::Frame &rFrame); - void MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo); + void MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo); void WriteAsStringTable(const ::std::vector&, sal_Int32& rfcSttbf, sal_Int32& rlcbSttbf, sal_uInt16 nExtraLen = 0); diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index ca57cf27d2fa..1d01bf4c2ffe 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -923,7 +923,8 @@ void WW8AttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript ) void WW8AttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) { - m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() ); + m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() - (mbOnTOXEnding?2:0), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() ); + mbOnTOXEnding = false; m_rWW8Export.pO->clear(); if ( pTextNodeInfoInner.get() != NULL ) @@ -968,6 +969,11 @@ void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bSi } } +void WW8AttributeOutput::OnTOXEnding() +{ + mbOnTOXEnding = true; +} + void WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData ) { Redline( pRedlineData ); @@ -2034,260 +2040,268 @@ void AttributeOutputBase::StartTOX( const SwSection& rSect ) static const sal_Char sEntryEnd[] = "\" "; ww::eField eCode = ww::eTOC; - OUString sStr; - switch (pTOX->GetType()) + OUString sStr = pTOX->GetMSTOCExpression(); + if ( sStr.isEmpty() ) { - case TOX_INDEX: - eCode = ww::eINDEX; - sStr = FieldString(eCode); + switch (pTOX->GetType()) + { + case TOX_INDEX: + eCode = ww::eINDEX; + sStr = FieldString(eCode); - if (pTOX->GetTOXForm().IsCommaSeparated()) - sStr += "\\r "; + if (pTOX->GetTOXForm().IsCommaSeparated()) + sStr += "\\r "; - if (nsSwTOIOptions::TOI_ALPHA_DELIMITTER & pTOX->GetOptions()) - sStr += "\\h \"A\" "; + if (nsSwTOIOptions::TOI_ALPHA_DELIMITTER & pTOX->GetOptions()) + sStr += "\\h \"A\" "; - { - OUString aFillTxt; - for (sal_uInt8 n = 1; n <= 3; ++n) { - OUString aTxt; - int nRet = ::lcl_CheckForm(pTOX->GetTOXForm(), n, aTxt); + OUString aFillTxt; + for (sal_uInt8 n = 1; n <= 3; ++n) + { + OUString aTxt; + int nRet = ::lcl_CheckForm(pTOX->GetTOXForm(), n, aTxt); - if( 3 == nRet ) - aFillTxt = aTxt; - else if ((4 == nRet) || (2 == nRet)) - aFillTxt = "\t"; - else - aFillTxt = ""; + if( 3 == nRet ) + aFillTxt = aTxt; + else if ((4 == nRet) || (2 == nRet)) //#109414# + aFillTxt = "\t"; + else + aFillTxt = ""; + } + sStr += "\\e \""; + sStr += aFillTxt; + sStr += sEntryEnd; } - sStr += "\\e \""; - sStr += aFillTxt; - sStr += sEntryEnd; - } - break; - - case TOX_ILLUSTRATIONS: - case TOX_OBJECTS: - case TOX_TABLES: - if (!pTOX->IsFromObjectNames()) - { - sStr = FieldString(eCode); - - sStr += "\\c \""; - sStr += pTOX->GetSequenceName(); - sStr += sEntryEnd; + break; - OUString aTxt; - int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), 1, aTxt ); - if (1 == nRet) - sStr += "\\n "; - else if( 3 == nRet || 4 == nRet ) + // case TOX_AUTHORITIES: eCode = eTOA; sStr = ???; break; + case TOX_ILLUSTRATIONS: + case TOX_OBJECTS: + case TOX_TABLES: + if (!pTOX->IsFromObjectNames()) { - sStr += "\\p \""; - sStr += aTxt; - sStr += sEntryEnd; - } - } - break; + sStr = FieldString(eCode); - default: - { - sStr = FieldString(eCode); + sStr += "\\c \""; + sStr += pTOX->GetSequenceName(); + sStr += sEntryEnd; - OUString sTOption; - sal_uInt16 n, nTOXLvl = pTOX->GetLevel(); - if( !nTOXLvl ) - ++nTOXLvl; + OUString aTxt; + int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), 1, aTxt ); + if (1 == nRet) + sStr += "\\n "; + else if( 3 == nRet || 4 == nRet ) + { + sStr += "\\p \""; + sStr += aTxt; + sStr += sEntryEnd; + } + } + break; - if( nsSwTOXElement::TOX_MARK & pTOX->GetCreateType() ) + // case TOX_USER: + // case TOX_CONTENT: + default: { - sStr += "\\f "; + sStr = FieldString(eCode); - if( TOX_USER == pTOX->GetType() ) - { - sStr += "\""; - sStr += OUString((sal_Char)( 'A' + GetExport( ).GetId( *pTOX->GetTOXType() ) )); - sStr += sEntryEnd; - } + OUString sTOption; + sal_uInt16 n, nTOXLvl = pTOX->GetLevel(); + if( !nTOXLvl ) + ++nTOXLvl; - if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() ) + if( nsSwTOXElement::TOX_MARK & pTOX->GetCreateType() ) { - const int nMinLvl = nTOXLvl; + sStr += "\\f "; - if ( nMinLvl > 0 ) + if( TOX_USER == pTOX->GetType() ) { - int nTmpLvl = nMinLvl; - if (nTmpLvl > WW8ListManager::nMaxLevel) - nTmpLvl = WW8ListManager::nMaxLevel; - - sStr += "\\o \"1-"; - sStr += OUString::number( nTmpLvl ); + sStr += "\""; + sStr += OUString((sal_Char)( 'A' + GetExport( ).GetId( *pTOX->GetTOXType() ) )); sStr += sEntryEnd; } - } - if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() ) - { - // Take the TOC value of the max level to evaluate to as - // the starting point for the \o flag, but reduce it to the - // value of the highest outline level filled by a *standard* - // Heading 1 - 9 style because \o "Builds a table of - // contents from paragraphs formatted with built-in heading - // styles". And afterward fill in any outline styles left - // uncovered by that range to the \t flag - // - // i.e. for - // Heading 1 - // Heading 2 - // custom-style - // Heading 4 - // output - // \o 1-2 \tcustom-style,3,Heading 3,4 - - // Search over all the outline styles used and figure out - // what is the minimum outline level (if any) filled by a - // non-standard style for that level, i.e. ignore headline - // styles 1-9 and find the lowest valid outline level - sal_uInt8 nPosOfLowestNonStandardLvl = MAXLEVEL; - const SwTxtFmtColls& rColls = *GetExport().pDoc->GetTxtFmtColls(); - for( n = rColls.size(); n; ) + if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() ) { - const SwTxtFmtColl* pColl = rColls[ --n ]; - sal_uInt16 nPoolId = pColl->GetPoolFmtId(); - if ( - //Is a Non-Standard Outline Style - (RES_POOLCOLL_HEADLINE1 > nPoolId || RES_POOLCOLL_HEADLINE9 < nPoolId) && - //Has a valid outline level - (pColl->IsAssignedToListLevelOfOutlineStyle()) && - // Is less than the lowest known non-standard level - (pColl->GetAssignedOutlineStyleLevel() < nPosOfLowestNonStandardLvl) - ) + const int nMinLvl = nTOXLvl; + if ( nMinLvl > 0 ) { - nPosOfLowestNonStandardLvl = ::sal::static_int_cast(pColl->GetAssignedOutlineStyleLevel()); - } - } + int nTmpLvl = nMinLvl; + if (nTmpLvl > WW8ListManager::nMaxLevel) + nTmpLvl = WW8ListManager::nMaxLevel; - sal_uInt8 nMaxMSAutoEvaluate = nPosOfLowestNonStandardLvl < nTOXLvl ? nPosOfLowestNonStandardLvl : (sal_uInt8)nTOXLvl; + sStr += "\\o \"1-"; + sStr += OUString::number(nTmpLvl); + sStr += sEntryEnd; - //output \o 1-X where X is the highest normal outline style to be included in the toc - if ( nMaxMSAutoEvaluate ) - { - if (nMaxMSAutoEvaluate > WW8ListManager::nMaxLevel) - nMaxMSAutoEvaluate = WW8ListManager::nMaxLevel; - - sStr += "\\o \"1-"; - sStr += OUString::number( nMaxMSAutoEvaluate ); - sStr += sEntryEnd; + } } - //collect up any other styles in the writer TOC which will - //not already appear in the MS TOC and place then into the - //\t option - if( nMaxMSAutoEvaluate < nTOXLvl ) + if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() ) { - // collect this templates into the \t otion - for( n = rColls.size(); n;) + // Take the TOC value of the max level to evaluate to as + // the starting point for the \o flag, but reduce it to the + // value of the highest outline level filled by a *standard* + // Heading 1 - 9 style because \o "Builds a table of + // contents from paragraphs formatted with built-in heading + // styles". And afterward fill in any outline styles left + // uncovered by that range to the \t flag + // + // i.e. for + // Heading 1 + // Heading 2 + // custom-style + // Heading 4 + // output + // \o 1-2 \tcustom-style,3,Heading 3,4 + + // Search over all the outline styles used and figure out + // what is the minimum outline level (if any) filled by a + // non-standard style for that level, i.e. ignore headline + // styles 1-9 and find the lowest valid outline level + sal_uInt8 nPosOfLowestNonStandardLvl = MAXLEVEL; + const SwTxtFmtColls& rColls = *GetExport().pDoc->GetTxtFmtColls(); + for( n = rColls.size(); n; ) { const SwTxtFmtColl* pColl = rColls[ --n ]; - if (!pColl->IsAssignedToListLevelOfOutlineStyle()) - continue; - sal_uInt8 nTestLvl = ::sal::static_int_cast(pColl->GetAssignedOutlineStyleLevel()); - if (nTestLvl < nTOXLvl && nTestLvl >= nMaxMSAutoEvaluate) + sal_uInt16 nPoolId = pColl->GetPoolFmtId(); + if ( + //Is a Non-Standard Outline Style + (RES_POOLCOLL_HEADLINE1 > nPoolId || RES_POOLCOLL_HEADLINE9 < nPoolId) && + //Has a valid outline level + (pColl->IsAssignedToListLevelOfOutlineStyle()) && + // Is less than the lowest known non-standard level + (pColl->GetAssignedOutlineStyleLevel() < nPosOfLowestNonStandardLvl) + ) + { + nPosOfLowestNonStandardLvl = ::sal::static_int_cast(pColl->GetAssignedOutlineStyleLevel()); + } + } + + sal_uInt8 nMaxMSAutoEvaluate = nPosOfLowestNonStandardLvl < nTOXLvl ? nPosOfLowestNonStandardLvl : (sal_uInt8)nTOXLvl; + + //output \o 1-X where X is the highest normal outline style to be included in the toc + if ( nMaxMSAutoEvaluate ) + { + if (nMaxMSAutoEvaluate > WW8ListManager::nMaxLevel) + nMaxMSAutoEvaluate = WW8ListManager::nMaxLevel; + + sStr += "\\o \"1-"; + sStr += OUString::number(nMaxMSAutoEvaluate); + sStr += sEntryEnd; + } + + //collect up any other styles in the writer TOC which will + //not already appear in the MS TOC and place then into the + //\t option + if( nMaxMSAutoEvaluate < nTOXLvl ) + { + // collect this templates into the \t otion + for( n = rColls.size(); n;) { - if( !sTOption.isEmpty() ) - sTOption += ","; - sTOption += pColl->GetName() + "," + OUString::number( nTestLvl + 1 ); + const SwTxtFmtColl* pColl = rColls[ --n ]; + if (!pColl->IsAssignedToListLevelOfOutlineStyle()) + continue; + sal_uInt8 nTestLvl = ::sal::static_int_cast(pColl->GetAssignedOutlineStyleLevel()); + if (nTestLvl < nTOXLvl && nTestLvl >= nMaxMSAutoEvaluate) + { + if (!sTOption.isEmpty()) + sTOption += ","; + sTOption += pColl->GetName() + "," + OUString::number( nTestLvl + 1 ); + } } } } - } - if( nsSwTOXElement::TOX_TEMPLATE & pTOX->GetCreateType() ) - // #i99641# - Consider additional styles regardless of TOX-outlinelevel - for( n = 0; n < MAXLEVEL; ++n ) - { - const OUString& rStyles = pTOX->GetStyleNames( n ); - if( !rStyles.isEmpty() ) + if( nsSwTOXElement::TOX_TEMPLATE & pTOX->GetCreateType() ) + // #i99641# - Consider additional styles regardless of TOX-outlinelevel + for( n = 0; n < MAXLEVEL; ++n ) + { + const OUString& rStyles = pTOX->GetStyleNames( n ); + if( !rStyles.isEmpty() ) + { + sal_Int32 nPos = 0; + OUString sLvl = OUString(','); + sLvl += OUString::number( n + 1 ); + do { + OUString sStyle( rStyles.getToken( 0, TOX_STYLE_DELIMITER, nPos )); + if( !sStyle.isEmpty() ) + { + SwTxtFmtColl* pColl = GetExport().pDoc->FindTxtFmtCollByName(sStyle); + if (!pColl->IsAssignedToListLevelOfOutlineStyle() || pColl->GetAssignedOutlineStyleLevel() < nTOXLvl) + { + if( !sTOption.isEmpty() ) + sTOption += ","; + sTOption += sStyle + sLvl; + } + } + } while( -1 != nPos ); + } + } + { - sal_Int32 nPos = 0; - OUString sLvl = OUString(','); - sLvl += OUString::number( n + 1 ); - do { - OUString sStyle( rStyles.getToken( 0, TOX_STYLE_DELIMITER, nPos )); - if( !sStyle.isEmpty() ) + OUString aFillTxt; + sal_uInt8 nNoPgStt = MAXLEVEL, nNoPgEnd = MAXLEVEL; + bool bFirstFillTxt = true, bOnlyText = true; + for( n = 0; n < nTOXLvl; ++n ) + { + OUString aTxt; + int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), + static_cast< sal_uInt8 >(n+1), aTxt ); + if( 1 == nRet ) { - SwTxtFmtColl* pColl = GetExport().pDoc->FindTxtFmtCollByName(sStyle); - if (!pColl || !pColl->IsAssignedToListLevelOfOutlineStyle() || pColl->GetAssignedOutlineStyleLevel() < nTOXLvl) + bOnlyText = false; + if( MAXLEVEL == nNoPgStt ) + nNoPgStt = static_cast< sal_uInt8 >(n+1); + } + else + { + if( MAXLEVEL != nNoPgStt && + MAXLEVEL == nNoPgEnd ) + nNoPgEnd = sal_uInt8(n); + + bOnlyText = bOnlyText && 3 == nRet; + if( 3 == nRet || 4 == nRet ) { - if( !sTOption.isEmpty() ) - sTOption += ","; - ( sTOption += sStyle ) += sLvl; + if( bFirstFillTxt ) + aFillTxt = aTxt; + else if( aFillTxt != aTxt ) + aFillTxt = ""; + bFirstFillTxt = false; } } - } while( -1 != nPos ); + } + if( MAXLEVEL != nNoPgStt ) + { + if (WW8ListManager::nMaxLevel < nNoPgEnd) + nNoPgEnd = WW8ListManager::nMaxLevel; + sStr += "\\n "; + sStr += OUString::number( nNoPgStt ); + sStr += "-"; + sStr += OUString::number( nNoPgEnd ); + sStr += " "; + } + if( bOnlyText ) + { + sStr += "\\p \""; + sStr += aFillTxt; + sStr += sEntryEnd; + } } - } - OUString aFillTxt; - sal_uInt8 nNoPgStt = MAXLEVEL, nNoPgEnd = MAXLEVEL; - bool bFirstFillTxt = true, bOnlyText = true; - for( n = 0; n < nTOXLvl; ++n ) - { - OUString aTxt; - int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), - static_cast< sal_uInt8 >(n+1), aTxt ); - if( 1 == nRet ) - { - bOnlyText = false; - if( MAXLEVEL == nNoPgStt ) - nNoPgStt = static_cast< sal_uInt8 >(n+1); - } - else - { - if( MAXLEVEL != nNoPgStt && - MAXLEVEL == nNoPgEnd ) - nNoPgEnd = sal_uInt8(n); - - bOnlyText = bOnlyText && 3 == nRet; - if( 3 == nRet || 4 == nRet ) + if( !sTOption.isEmpty() ) { - if( bFirstFillTxt ) - aFillTxt = aTxt; - else if( aFillTxt != aTxt ) - aFillTxt = ""; - bFirstFillTxt = false; + sStr += "\\t \""; + sStr += sTOption; + sStr += sEntryEnd; } - } - } - if( MAXLEVEL != nNoPgStt ) - { - if (WW8ListManager::nMaxLevel < nNoPgEnd) - nNoPgEnd = WW8ListManager::nMaxLevel; - sStr += "\\n "; - sStr += OUString::number( nNoPgStt ); - sStr += "-"; - sStr += OUString::number( nNoPgEnd ); - sStr += " "; - } - if( bOnlyText ) - { - sStr += "\\p \""; - sStr += aFillTxt; - sStr += sEntryEnd; - } - if( !sTOption.isEmpty() ) - { - sStr += "\\t \""; - sStr += sTOption; - sStr += sEntryEnd; + if (lcl_IsHyperlinked(pTOX->GetTOXForm(), nTOXLvl)) + sStr += "\\h"; } - - if (lcl_IsHyperlinked(pTOX->GetTOXForm(), nTOXLvl)) - sStr += "\\h"; + break; } - break; } } @@ -2302,7 +2316,7 @@ void AttributeOutputBase::StartTOX( const SwSection& rSect ) GetExport( ).bStartTOX = false; } -void AttributeOutputBase::EndTOX( const SwSection& rSect ) +void AttributeOutputBase::EndTOX( const SwSection& rSect,bool bCareEnd ) { const SwTOXBase* pTOX = rSect.GetTOXBase(); if ( pTOX ) @@ -2311,6 +2325,8 @@ void AttributeOutputBase::EndTOX( const SwSection& rSect ) GetExport( ).OutputField( 0, eCode, aEmptyOUStr, WRITEFIELD_CLOSE ); } GetExport( ).bInWriteTOX = false; + if (bCareEnd) + OnTOXEnding(); } bool MSWordExportBase::GetNumberFmt(const SwField& rFld, OUString& rStr) diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx index 81691cb508f7..2fc8dbda526c 100644 --- a/sw/source/filter/ww8/ww8attributeoutput.hxx +++ b/sw/source/filter/ww8/ww8attributeoutput.hxx @@ -51,6 +51,8 @@ public: /// virtual void StartRun( const SwRedlineData* pRedlineData, bool bSingleEmptyRun = false ); + virtual void OnTOXEnding(); + /// End of the text run. /// /// No-op for binary filters. @@ -441,8 +443,10 @@ protected: /// of the field results if we were forced to split text. sal_uInt16 m_nFieldResults; + bool mbOnTOXEnding; + public: - WW8AttributeOutput( WW8Export &rWW8Export ) : AttributeOutputBase(), m_rWW8Export( rWW8Export ) {} + WW8AttributeOutput( WW8Export &rWW8Export ) : AttributeOutputBase(), m_rWW8Export( rWW8Export ),mbOnTOXEnding(false) {} virtual ~WW8AttributeOutput() {} /// Return the right export class. diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx index b3d3426a5cd3..160b9e5d1088 100644 --- a/sw/source/filter/ww8/ww8par.cxx +++ b/sw/source/filter/ww8/ww8par.cxx @@ -3165,8 +3165,14 @@ bool SwWW8ImplReader::ReadChar(long nPosCp, long nCpOfs) cInsert = '\xb5'; break; case 0x15: - if( !bSpec ) // Section sign - cInsert = '\xa7'; + if( !bSpec ) // Juristenparagraph + { + cp_set::iterator aItr = maTOXEndCps.find((WW8_CP)nPosCp); + if (aItr == maTOXEndCps.end()) + cInsert = '\xa7'; + else + maTOXEndCps.erase(aItr); + } break; case 0x9: cInsert = '\x9'; // Tab @@ -3576,10 +3582,26 @@ bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType) // create a new txtnode and join the two paragraphs together if (bStartLine && !pPreviousNode) // Line end { - // We will record the CP of a paragraph end ('0x0D'), if current loading contents is from main stream; - if (mbOnLoadingMain) - maEndParaPos.push_back(l-1); - AppendTxtNode(*pPaM->GetPoint()); + bool bSplit = true; + if (mbCareFirstParaEndInToc) + { + mbCareFirstParaEndInToc = false; + if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() && pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0) + bSplit = false; + } + if (mbCareLastParaEndInToc) + { + mbCareLastParaEndInToc = false; + if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() && pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0) + bSplit = false; + } + if (bSplit) + { + // We will record the CP of a paragraph end ('0x0D'), if current loading contents is from main stream; + if (mbOnLoadingMain) + maEndParaPos.push_back(l-1); + AppendTxtNode(*pPaM->GetPoint()); + } } if (pPreviousNode && bStartLine) @@ -3714,33 +3736,39 @@ bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType) * class SwWW8ImplReader */ SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara, SvStorage* pStorage, - SvStream* pSt, SwDoc& rD, const OUString& rBaseURL, bool bNewDoc) : - mpDocShell(rD.GetDocShell()), - pStg(pStorage), - pStrm(pSt), - pTableStream(0), - pDataStream(0), - rDoc(rD), - maSectionManager(*this), - m_aExtraneousParas(rD), - maInsertedTables(rD), - maSectionNameGenerator(rD, OUString("WW")), - maGrfNameGenerator(bNewDoc, OUString('G')), - maParaStyleMapper(rD), - maCharStyleMapper(rD), - maTxtNodesHavingFirstLineOfstSet(), // #i103711# - maTxtNodesHavingLeftIndentSet(), // #i105414# - pMSDffManager(0), - mpAtnNames(0), - sBaseURL(rBaseURL), - m_bRegardHindiDigits( false ), - mbNewDoc(bNewDoc), - nDropCap(0), - nIdctHint(0), - bBidi(false), - bReadTable(false), - maCurrAttrCP(-1), - mbOnLoadingMain(false) + SvStream* pSt, SwDoc& rD, const OUString& rBaseURL, bool bNewDoc) + : mpDocShell(rD.GetDocShell()) + , pStg(pStorage) + , pStrm(pSt) + , pTableStream(0) + , pDataStream(0) + , rDoc(rD) + , maSectionManager(*this) + , m_aExtraneousParas(rD) + , maInsertedTables(rD) + , maSectionNameGenerator(rD, OUString("WW")) + , maGrfNameGenerator(bNewDoc, OUString('G')) + , maParaStyleMapper(rD) + , maCharStyleMapper(rD) + , maTxtNodesHavingFirstLineOfstSet() + , maTxtNodesHavingLeftIndentSet() + , pMSDffManager(0) + , mpAtnNames(0) + , sBaseURL(rBaseURL) + , m_bRegardHindiDigits( false ) + , mbNewDoc(bNewDoc) + , nDropCap(0) + , nIdctHint(0) + , bBidi(false) + , bReadTable(false) + , mbLoadingTOCCache(false) + , mbLoadingTOCHyperlink(false) + , mpPosAfterTOC(0) + , mbCareFirstParaEndInToc(false) + , mbCareLastParaEndInToc(false) + , maTOXEndCps() + , maCurrAttrCP(-1) + , mbOnLoadingMain(false) { pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); nWantedVersion = nVersionPara; diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx index ffe4317e8112..30ae35f87300 100644 --- a/sw/source/filter/ww8/ww8par.hxx +++ b/sw/source/filter/ww8/ww8par.hxx @@ -974,6 +974,7 @@ struct WW8TabBandDesc //----------------------------------------- // Storage-Reader //----------------------------------------- +typedef std::set cp_set; typedef std::vector cp_vector; class SwWW8ImplReader @@ -1276,6 +1277,16 @@ private: bool bBidi; bool bReadTable; boost::shared_ptr mpTableEndPaM; + // Indicate that currently on loading a TOC, managed by Read_F_TOX() and End_Field() + bool mbLoadingTOCCache; + // Indicate that current on loading a hyperlink, which is inside a TOC; Managed by Read_F_Hyperlink() and End_Field() + bool mbLoadingTOCHyperlink; + // a document position recorded the after-position of TOC section, managed by Read_F_TOX() and End_Field() + SwPaM* mpPosAfterTOC; + + bool mbCareFirstParaEndInToc; + bool mbCareLastParaEndInToc; + cp_set maTOXEndCps; cp_vector maEndParaPos; WW8_CP maCurrAttrCP; diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx index 2ce43f289269..23265881d525 100644 --- a/sw/source/filter/ww8/ww8par5.cxx +++ b/sw/source/filter/ww8/ww8par5.cxx @@ -116,13 +116,15 @@ long SwWW8ImplReader::Read_Book(WW8PLCFManResult*) return 0; } - //"_Toc*" and "_Hlt*" are unnecessary + // "_Hlt*" are unnecessary const OUString* pName = pB->GetName(); -#if !defined(WW_NATIVE_TOC) - if( !pName || pName->startsWithIgnoreAsciiCase( "_Toc" ) - || pName->startsWithIgnoreAsciiCase( "_Hlt" ) ) + // Now, as we read the TOC field completely, we also need the hyperlinks inside keep available. + // So the hidden bookmarks inside for hyperlink jumping also should be kept. + if ( !pName || + pName->startsWithIgnoreAsciiCase( "_Hlt" ) ) + { return 0; -#endif + } // do NOT call ToUpper as the bookmark name can also be a hyperlink target! @@ -455,7 +457,8 @@ sal_uInt16 SwWW8ImplReader::End_Field() sal_uInt16 nRet = 0; WW8PLCFx_FLD* pF = pPlcxMan->GetFld(); OSL_ENSURE(pF, "WW8PLCFx_FLD - Pointer nicht da"); - if (!pF || !pF->EndPosIsFieldEnd()) + WW8_CP nCP = 0; + if (!pF || !pF->EndPosIsFieldEnd(nCP)) return nRet; const SvtFilterOptions &rOpt = SvtFilterOptions::Get(); @@ -486,28 +489,43 @@ sal_uInt16 SwWW8ImplReader::End_Field() } } break; -#if defined(WW_NATIVE_TOC) - case 8: // TOX_INDEX - case 13: // TOX_CONTENT - case 88: // HYPERLINK - case 37: // REF - if (pPaM!=NULL && pPaM->GetPoint()!=NULL) { + // Doing corresponding status management for TOC field, index field, hyperlink field and page reference field + case 13://TOX + case 8://index + if (mbLoadingTOCCache) + { + maTOXEndCps.insert(nCP); + mbLoadingTOCCache = false; + if ( pPaM->End() && + pPaM->End()->nNode.GetNode().GetTxtNode() && + pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0 ) + { + JoinNode(*pPaM); + } + else + { + mbCareLastParaEndInToc = true; + } - SwPosition aEndPos = *pPaM->GetPoint(); - SwPaM aFldPam( maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex()); - SwFieldBookmark *pFieldmark=(SwFieldBookmark*)rDoc.makeFieldBookmark(aFldPam, maFieldStack.back().GetBookmarkName(), maFieldStack.back().GetBookmarkType()); - OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?"); - if (pFieldmark!=NULL) { - const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters(); - pFieldmark->GetParameters()->insert(pParameters.begin(), pParameters.end()); - } - } - break; -#else + if (mpPosAfterTOC) + { + *pPaM = *mpPosAfterTOC; + delete mpPosAfterTOC; + mpPosAfterTOC = 0; + } + } + break; + case 37://REF + if (mbLoadingTOCCache && !mbLoadingTOCHyperlink) + { + pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT); + } + break; case 88: + if (mbLoadingTOCHyperlink) + mbLoadingTOCHyperlink = false; pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT); - break; -#endif + break; case 36: case 68: //Move outside the section associated with this type of field @@ -592,10 +610,8 @@ bool AcceptableNestedField(sal_uInt16 nFieldCode) { switch (nFieldCode) { -#if defined(WW_NATIVE_TOC) - case 8: // allow recursive field in TOC... - case 13: // allow recursive field in TOC... -#endif + case 8: // allow recursive field in TOC... + case 13: // allow recursive field in TOC... case 36: case 68: case 79: @@ -2017,27 +2033,36 @@ eF_ResT SwWW8ImplReader::Read_F_PgRef( WW8FieldDesc*, OUString& rStr ) const sal_Int32 nRet = aReadParam.SkipToNextToken(); if ( nRet==-1 ) break; - switch( nRet ) + else if ( nRet == -2 && sOrigName.isEmpty() ) { - case -2: - if( sOrigName.isEmpty() ) - sOrigName = aReadParam.GetResult(); - break; + sOrigName = aReadParam.GetResult(); } } OUString sName(GetMappedBookmark(sOrigName)); -#if defined(WW_NATIVE_TOC) - if (1) { - OUString aBookmarkName("_REF"); - maFieldStack.back().SetBookmarkName(aBookmarkName); - maFieldStack.back().SetBookmarkType(ODF_PAGEREF); - maFieldStack.back().AddParam(OUString(), sName); - return FLD_TEXT; + //loading page reference field in TOC + if (mbLoadingTOCCache ) + { + //Step 1. Insert page ref representation as plain text + //Step 2. If there is no hyperlink settings for current toc, assign link to current ref area + if ( !mbLoadingTOCHyperlink) + { + OUString sURL, sTarget; + if (!sName.isEmpty()) + sURL += OUString(INET_MARK_TOKEN) + sName; + SwFmtINetFmt aURL( sURL, sTarget ); + OUString sLinkStyle("Index Link"); + sal_uInt16 nPoolId = + SwStyleNameMapper::GetPoolIdFromUIName( sLinkStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT ); + aURL.SetVisitedFmt(sLinkStyle); + aURL.SetINetFmt(sLinkStyle); + aURL.SetVisitedFmtId(nPoolId); + aURL.SetINetFmtId(nPoolId); + pCtrlStck->NewAttr( *pPaM->GetPoint(), aURL ); + } + return FLD_TEXT; } -#endif - SwGetRefField aFld( (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ), sName, @@ -2771,14 +2796,7 @@ static sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm) eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) { -#if defined(WW_NATIVE_TOC) - if (1) { - OUString aBookmarkName("_TOC"); - maFieldStack.back().SetBookmarkName(aBookmarkName); - maFieldStack.back().SetBookmarkType(ODF_TOC); - return FLD_TEXT; - } -#endif + mbLoadingTOCCache = true; if (pF->nLRes < 3) return FLD_TEXT; // ignore (#i25440#) @@ -2906,6 +2924,7 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) case TOX_CONTENT: { bool bIsHyperlink = false; + bool bShowPage = true; // TOX_OUTLINELEVEL setzen wir genau dann, wenn // die Parameter \o in 1 bis 9 liegen // oder der Parameter \f existiert @@ -3076,27 +3095,37 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) } } - if (bIsHyperlink) - { - SwForm aForm(pBase->GetTOXForm()); - sal_uInt16 nEnd = aForm.GetFormMax()-1; - SwFormToken aLinkStart(TOKEN_LINK_START); - SwFormToken aLinkEnd(TOKEN_LINK_END); + // For loading the expression of TOC field, we need to mapping its parameters to TOX entries tokens + // also include the hyperlinks and page references + SwFormToken aLinkStart(TOKEN_LINK_START); + SwFormToken aLinkEnd(TOKEN_LINK_END); + aLinkStart.sCharStyleName = "Index Link"; + aLinkEnd.sCharStyleName = "Index Link"; + SwForm aForm(pBase->GetTOXForm()); + sal_uInt16 nEnd = aForm.GetFormMax()-1; - // -> #i21237# - for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel) + for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel) + { + SwFormTokens aPattern = aForm.GetPattern(nLevel); + if ( bIsHyperlink ) { - SwFormTokens aPattern = aForm.GetPattern(nLevel); - aPattern.insert(aPattern.begin(), aLinkStart); - aPattern.push_back(aLinkEnd); - - aForm.SetPattern(nLevel, aPattern); - } - // <- #i21237# - pBase->SetTOXForm(aForm); + else if ( bShowPage ) + { + for (SwFormTokens::iterator aItr = aPattern.begin();aItr!= aPattern.end();aItr++) + { + if (aItr->eTokenType == TOKEN_PAGE_NUMS) + { + aPattern.insert(aItr,aLinkStart); + break; + } + } + } + aPattern.push_back(aLinkEnd); + aForm.SetPattern(nLevel, aPattern); } + pBase->SetTOXForm(aForm); if (!nMaxLevel) nMaxLevel = WW8ListManager::nMaxLevel; @@ -3177,11 +3206,11 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) pattern which do not apply to illustration indices */ SwForm aOldForm( pBase->GetTOXForm() ); - SwForm aForm( eType ); - sal_uInt16 nEnd = aForm.GetFormMax()-1; + SwForm aNewForm( eType ); + sal_uInt16 nNewEnd = aNewForm.GetFormMax()-1; // #i21237# - for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel) + for(sal_uInt16 nLevel = 1; nLevel <= nNewEnd; ++nLevel) { SwFormTokens aPattern = aOldForm.GetPattern(nLevel); @@ -3191,13 +3220,13 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) // table index imported with wrong page number format aPattern.erase (new_end, aPattern.end() ); - aForm.SetPattern(nLevel, aPattern); + aNewForm.SetPattern(nLevel, aPattern); - aForm.SetTemplate( nLevel, + aNewForm.SetTemplate( nLevel, aOldForm.GetTemplate(nLevel)); } - pBase->SetTOXForm( aForm ); + pBase->SetTOXForm( aNewForm ); } break; default: @@ -3213,15 +3242,23 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) break; } // ToxBase fertig - // Update fuer TOX anstossen - rDoc.SetUpdateTOX(true); + // no Update of TOC anymore as its actual content is imported and kept. + //rDoc.SetUpdateTOX(true); // #i21237# - propagate tab stops from paragraph styles // used in TOX to patterns of the TOX pBase->AdjustTabStops(rDoc, sal_True); - // #i10028# - inserting a toc implicltly acts like a parabreak in word and writer + // #i10028# - inserting a toc implictly acts like a parabreak in word and writer + + if ( pPaM->End() && + pPaM->End()->nNode.GetNode().GetTxtNode() && + pPaM->End()->nNode.GetNode().GetTxtNode()->Len() != 0 ) + { + mbCareFirstParaEndInToc = true; + } + if (pPaM->GetPoint()->nContent.GetIndex()) AppendTxtNode(*pPaM->GetPoint()); @@ -3252,14 +3289,22 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) rDoc.InsertTableOf(*pPaM->GetPoint(), *aFltTOX.GetBase()); - //inserting a toc inserts a section before this point, so adjust pos - //for future page/section segment insertion + //The TOC field representation contents should be inserted into TOC section, but not after TOC section. + //So we need update the document position when loading TOC representation and after loading TOC; + if (mpPosAfterTOC) + { + delete mpPosAfterTOC; + } + mpPosAfterTOC = new SwPaM(*pPaM); + (*pPaM).Move(fnMoveBackward); SwPaM aRegion(*pPaM); - aRegion.Move(fnMoveBackward); + OSL_ENSURE(rDoc.GetCurTOX(*aRegion.GetPoint()), "Misunderstood how toc works"); if (SwTOXBase* pBase2 = (SwTOXBase*)rDoc.GetCurTOX(*aRegion.GetPoint())) { - if(nIndexCols>1) + pBase2->SetMSTOCExpression(rStr); + + if ( nIndexCols > 1 ) { // Set the column number for index SfxItemSet aSet( rDoc.GetAttrPool(), RES_COL, RES_COL ); @@ -3269,8 +3314,9 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) pBase2->SetAttrSet( aSet ); } - maSectionManager.PrependedInlineNode(*pPaM->GetPoint(), - *aRegion.GetNode()); + // inserting a toc inserts a section before this point, so adjust pos + // for future page/section segment insertion + maSectionManager.PrependedInlineNode( *mpPosAfterTOC->GetPoint(), *aRegion.GetNode() ); } // Setze Ende in Stack @@ -3278,7 +3324,11 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr ) if (!maApos.back()) //a para end in apo doesn't count bWasParaEnd = true; - return FLD_OK; + + //Return FLD_TEXT, instead of FLD_OK + //FLD_TEXT means the following content, commonly indicate the field representation content should be parsed + //FLD_OK means the current field loading is finished. The rest part should be ignored. + return FLD_TEXT; } eF_ResT SwWW8ImplReader::Read_F_Shape(WW8FieldDesc* /*pF*/, OUString& /*rStr*/) @@ -3293,17 +3343,7 @@ eF_ResT SwWW8ImplReader::Read_F_Shape(WW8FieldDesc* /*pF*/, OUString& /*rStr*/) eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, OUString& rStr ) { -#if defined(WW_NATIVE_TOC) - if (1) { - OUString aBookmarkName("_HYPERLINK"); - maFieldStack.back().SetBookmarkName(aBookmarkName); - maFieldStack.back().SetBookmarkType(ODF_HYPERLINK); - return FLD_TEXT; - } -#endif - - OUString sURL, sMark; - OUString sTarget; + OUString sURL, sTarget, sMark; bool bDataImport = false; //HYPERLINK "filename" [switches] @@ -3338,6 +3378,10 @@ eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, OUString& rStr if( sMark.endsWith("\"")) sMark = sMark.copy( 0, sMark.getLength() - 1 ); + if (mbLoadingTOCCache) + { + mbLoadingTOCHyperlink = true;//on loading a TOC field nested hyperlink field + } } break; case 't': @@ -3362,6 +3406,17 @@ eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, OUString& rStr ( sURL += OUString(INET_MARK_TOKEN) ) += sMark; SwFmtINetFmt aURL( sURL, sTarget ); + // If on loading TOC field, change the default style into the "index link" + if (mbLoadingTOCCache) + { + OUString sLinkStyle("Index Link"); + sal_uInt16 nPoolId = + SwStyleNameMapper::GetPoolIdFromUIName( sLinkStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT ); + aURL.SetVisitedFmt(sLinkStyle); + aURL.SetINetFmt(sLinkStyle); + aURL.SetVisitedFmtId(nPoolId); + aURL.SetINetFmtId(nPoolId); + } //As an attribute this needs to be closed, and that'll happen from //EndExtSprm in conjunction with the maFieldStack If there are are flyfrms diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx index 3e13770f71b6..14e9cdfd711b 100644 --- a/sw/source/filter/ww8/ww8par6.cxx +++ b/sw/source/filter/ww8/ww8par6.cxx @@ -3723,6 +3723,15 @@ void SwWW8ImplReader::Read_CColl( sal_uInt16, const sal_uInt8* pData, short nLen || vColl[nId].bColl ) // oder Para-Style ? return; // dann ignorieren + // if current on loading a TOC field, and current trying to apply a hyperlink character style, + // just ignore. For the hyperlinks inside TOC in MS Word is not same with a common hyperlink + // Character styles: without underline and blue font color. And such type style will be applied in others + // processes. + if (mbLoadingTOCCache && vColl[nId].GetWWStyleId() == ww::stiHyperlink) + { + return; + } + NewAttr( SwFmtCharFmt( (SwCharFmt*)vColl[nId].pFmt ) ); nCharFmt = (short) nId; } diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx index c89faf7f1852..5a6d79c546f5 100644 --- a/sw/source/filter/ww8/ww8scan.cxx +++ b/sw/source/filter/ww8/ww8scan.cxx @@ -3703,7 +3703,7 @@ bool WW8PLCFx_FLD::StartPosIsFieldStart() return true; } -bool WW8PLCFx_FLD::EndPosIsFieldEnd() +bool WW8PLCFx_FLD::EndPosIsFieldEnd(WW8_CP& nCP) { bool bRet = false; @@ -3716,7 +3716,10 @@ bool WW8PLCFx_FLD::EndPosIsFieldEnd() void* pData; sal_Int32 nTest; if ( pPLCF->Get(nTest, pData) && ((((sal_uInt8*)pData)[0] & 0x1f) == 0x15) ) + { + nCP = nTest; bRet = true; + } pPLCF->SetIdx(n); } @@ -4026,7 +4029,14 @@ void WW8PLCFx_Book::advance() else if( l1 < l0 ) nIsEnd = 1; else - nIsEnd = ( nIsEnd ) ? 0 : 1; + { + const void * p = pBook[0]->GetData(pBook[0]->GetIdx()); + long nPairFor = (p == NULL)? 0L : SVBT16ToShort(*((SVBT16*) p)); + if (nPairFor == pBook[1]->GetIdx()) + nIsEnd = 0; + else + nIsEnd = ( nIsEnd ) ? 0 : 1; + } } } diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx index e6fa8c2eba62..4f7e06e92bd5 100644 --- a/sw/source/filter/ww8/ww8scan.hxx +++ b/sw/source/filter/ww8/ww8scan.hxx @@ -706,7 +706,7 @@ public: virtual void GetSprms(WW8PLCFxDesc* p); virtual void advance(); bool StartPosIsFieldStart(); - bool EndPosIsFieldEnd(); + bool EndPosIsFieldEnd(WW8_CP&); bool GetPara(long nIdx, WW8FieldDesc& rF); }; diff --git a/sw/source/ui/index/toxmgr.cxx b/sw/source/ui/index/toxmgr.cxx index f0223022dcac..eb8fdf0166f5 100644 --- a/sw/source/ui/index/toxmgr.cxx +++ b/sw/source/ui/index/toxmgr.cxx @@ -449,7 +449,9 @@ sal_Bool SwTOXMgr::UpdateOrInsertTOX(const SwTOXDescription& rDesc, if (pNewTOX != NULL) // => pTOX != NULL pDoc->ChgTOX(*pTOX, *pNewTOX); + pTOX->DisableKeepExpression(); bRet = pSh->UpdateTableOf(*pTOX, pSet); + pTOX->EnableKeepExpression(); if (pDoc->GetIDocumentUndoRedo().DoesUndo()) { -- cgit