diff options
author | Miklos Vajna <vmiklos@suse.cz> | 2013-01-21 09:31:26 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@suse.cz> | 2013-01-21 09:32:28 +0100 |
commit | 7907cc0ef9751d553014bd3bab49be9e7fc31bca (patch) | |
tree | 0578a57307f9cf167641684aa1ccd61b1db0769f | |
parent | af1d3c83a372b096b4c425a2bc976e7ef0cd7ed9 (diff) |
fdo#59530 WW8 import of commented text ranges
Change-Id: I3e2928922ebcec8188c1b5416108373c4f26dd62
-rwxr-xr-x | sw/qa/extras/ww8import/data/fdo59530.doc | bin | 0 -> 22528 bytes | |||
-rw-r--r-- | sw/qa/extras/ww8import/ww8import.cxx | 26 | ||||
-rw-r--r-- | sw/source/filter/ww8/ww8par.cxx | 89 | ||||
-rw-r--r-- | sw/source/filter/ww8/ww8par.hxx | 6 | ||||
-rw-r--r-- | sw/source/filter/ww8/ww8struc.hxx | 8 |
5 files changed, 125 insertions, 4 deletions
diff --git a/sw/qa/extras/ww8import/data/fdo59530.doc b/sw/qa/extras/ww8import/data/fdo59530.doc Binary files differnew file mode 100755 index 000000000000..4e41cb8ecef6 --- /dev/null +++ b/sw/qa/extras/ww8import/data/fdo59530.doc diff --git a/sw/qa/extras/ww8import/ww8import.cxx b/sw/qa/extras/ww8import/ww8import.cxx index d650e114d019..d471b7bb8b6c 100644 --- a/sw/qa/extras/ww8import/ww8import.cxx +++ b/sw/qa/extras/ww8import/ww8import.cxx @@ -47,6 +47,7 @@ public: void testN757118(); void testN757905(); void testAllGapsWord(); + void testFdo59530(); CPPUNIT_TEST_SUITE(Test); #if !defined(MACOSX) && !defined(WNT) @@ -68,6 +69,7 @@ void Test::run() {"n757118.doc", &Test::testN757118}, {"n757905.doc", &Test::testN757905}, {"all_gaps_word.doc", &Test::testAllGapsWord}, + {"fdo59530.doc", &Test::testFdo59530}, }; header(); for (unsigned int i = 0; i < SAL_N_ELEMENTS(aMethods); ++i) @@ -226,6 +228,30 @@ void Test::testAllGapsWord() borderTest.testTheBorders(mxComponent); } +void Test::testFdo59530() +{ + // See ooxmlexport's testFdo38244(). + // Test comment range feature. + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); + xRunEnum->nextElement(); + uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("TextFieldStart"), getProperty<OUString>(xPropertySet, "TextPortionType")); + xRunEnum->nextElement(); + xPropertySet.set(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("TextFieldEnd"), getProperty<OUString>(xPropertySet, "TextPortionType")); + + // Test initials. + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); + uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); + xPropertySet.set(xFields->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("346376201"), getProperty<OUString>(xPropertySet, "Name")); + CPPUNIT_ASSERT_EQUAL(OUString("M"), getProperty<OUString>(xPropertySet, "Initials")); +} CPPUNIT_TEST_SUITE_REGISTRATION(Test); diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx index 7705aae2cb37..acfecb2eef4a 100644 --- a/sw/source/filter/ww8/ww8par.cxx +++ b/sw/source/filter/ww8/ww8par.cxx @@ -1761,6 +1761,8 @@ long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes) return 0; String sAuthor; + String sInitials; + String sName; if( bVer67 ) { const WW67_ATRD* pDescri = (const WW67_ATRD*)pSD->GetData(); @@ -1775,13 +1777,35 @@ long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes) { const WW8_ATRD* pDescri = (const WW8_ATRD*)pSD->GetData(); + { + sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]); + for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx) + sInitials += SVBT16ToShort(pDescri->xstUsrInitl[nIdx]); + } + if (const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst))) sAuthor = *pA; else + sAuthor = sInitials; + + // If there is a bookmark tag, a text range should be commented. + sal_uInt32 nTagBkmk = SVBT32ToUInt32(pDescri->ITagBkmk); + if (nTagBkmk != 0xFFFFFFFF) { - sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]); - for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx) - sAuthor += SVBT16ToShort(pDescri->xstUsrInitl[nIdx]); + sName = OUString::valueOf(sal_Int32(nTagBkmk)); + int nAtnIndex = GetAnnotationIndex(nTagBkmk); + if (nAtnIndex != -1) + { + WW8_CP nStart = GetAnnotationStart(nAtnIndex); + WW8_CP nEnd = GetAnnotationEnd(nAtnIndex); + sal_Int32 nLen = nEnd - nStart; + // Don't support ranges affecting multiple SwTxtNode for now. + if (nLen && pPaM->GetPoint()->nContent.GetIndex() >= nLen) + { + pPaM->SetMark(); + pPaM->GetPoint()->nContent -= nLen; + } + } } } @@ -1803,9 +1827,18 @@ long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes) this->pFmtOfJustInsertedApo = 0; SwPostItField aPostIt( (SwPostItFieldType*)rDoc.GetSysFldType(RES_POSTITFLD), sAuthor, - sTxt, aEmptyStr, aEmptyStr, aDate ); + sTxt, sInitials, sName, aDate ); aPostIt.SetTextObject(pOutliner); + // If this is a range, create the associated fieldmark. + if (pPaM->HasMark()) + { + IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess(); + pMarksAccess->makeFieldBookmark(*pPaM, aPostIt.GetName(), ODF_COMMENTRANGE); + pPaM->Exchange(); + pPaM->DeleteMark(); + } + pCtrlStck->NewAttr(*pPaM->GetPoint(), SvxCharHiddenItem(false, RES_CHRATR_HIDDEN)); rDoc.InsertPoolItem(*pPaM, SwFmtFld(aPostIt), 0); pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_HIDDEN); @@ -5367,6 +5400,54 @@ const String* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx) return pRet; } +int SwWW8ImplReader::GetAnnotationIndex(sal_uInt32 nTag) +{ + if (!mpAtnIndexes.get() && pWwFib->lcbSttbfAtnbkmk) + { + mpAtnIndexes.reset(new std::map<sal_uInt32, int>()); + std::vector<String> aStrings; + std::vector<ww::bytes> aEntries; + WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbfAtnbkmk, pWwFib->lcbSttbfAtnbkmk, sizeof(struct WW8_ATNBE), eStructCharSet, aStrings, &aEntries); + for (size_t i = 0; i < aStrings.size() && i < aEntries.size(); ++i) + { + ww::bytes aEntry = aEntries[i]; + WW8_ATNBE* pAtnbeStruct = (WW8_ATNBE*)(&aEntry[0]); + mpAtnIndexes->insert(std::pair<sal_uInt32, int>(SVBT32ToUInt32(pAtnbeStruct->nTag), i)); + } + } + if (mpAtnIndexes.get()) + { + std::map<sal_uInt32, int>::iterator it = mpAtnIndexes->find(nTag); + if (it != mpAtnIndexes->end()) + return it->second; + } + return -1; +} + +WW8_CP SwWW8ImplReader::GetAnnotationStart(int nIndex) +{ + if (!mpAtnStarts.get() && pWwFib->lcbPlcfAtnbkf) + // A PLCFBKF is a PLC whose data elements are FBKF structures (4 bytes each). + mpAtnStarts.reset(new WW8PLCFspecial(pTableStream, pWwFib->fcPlcfAtnbkf, pWwFib->lcbPlcfAtnbkf, 4)); + + if (mpAtnStarts.get()) + return mpAtnStarts->GetPos(nIndex); + else + return SAL_MAX_INT32; +} + +WW8_CP SwWW8ImplReader::GetAnnotationEnd(int nIndex) +{ + if (!mpAtnEnds.get() && pWwFib->lcbPlcfAtnbkl) + // The Plcfbkl structure is a PLC that contains only CPs and no additional data. + mpAtnEnds.reset(new WW8PLCFspecial(pTableStream, pWwFib->fcPlcfAtnbkl, pWwFib->lcbPlcfAtnbkl, 0)); + + if (mpAtnEnds.get()) + return mpAtnEnds->GetPos(nIndex); + else + return SAL_MAX_INT32; +} + sal_uLong SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss) { sal_uLong nErrRet = 0; diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx index 31321f763668..485cc34e3764 100644 --- a/sw/source/filter/ww8/ww8par.hxx +++ b/sw/source/filter/ww8/ww8par.hxx @@ -1101,6 +1101,9 @@ private: SwMSDffManager* pMSDffManager; std::vector<String>* mpAtnNames; + boost::shared_ptr< std::map<sal_uInt32, int> > mpAtnIndexes; + boost::shared_ptr<WW8PLCFspecial> mpAtnStarts; + boost::shared_ptr<WW8PLCFspecial> mpAtnEnds; sw::util::AuthorInfos m_aAuthorInfos; String sBaseURL; @@ -1484,6 +1487,9 @@ private: // spaeter zu ersetzen durch Aufruf in entsprechend erweiterten SvxMSDffManager const String* GetAnnotationAuthor(sal_uInt16 nIdx); + int GetAnnotationIndex(sal_uInt32 nTag); + WW8_CP GetAnnotationStart(int nIndex); + WW8_CP GetAnnotationEnd(int nIndex); // Schnittstellen fuer die Toggle-Attribute void SetToggleAttr(sal_uInt8 nAttrId, bool bOn); diff --git a/sw/source/filter/ww8/ww8struc.hxx b/sw/source/filter/ww8/ww8struc.hxx index 9bb467dfa4aa..56d39d99c69f 100644 --- a/sw/source/filter/ww8/ww8struc.hxx +++ b/sw/source/filter/ww8/ww8struc.hxx @@ -878,6 +878,14 @@ struct WW8_STRINGID SVBT16 reserved3; }; +/// The ATNBE structure contains information about an annotation bookmark in the document. +struct WW8_ATNBE +{ + SVBT16 nBmc; + SVBT32 nTag; + SVBT32 nTagOld; +}; + struct WW8_WKB { // M.M. This is the WkbPLCF struct |