editeng/Library_editeng.mk | 1 editeng/qa/unit/core-test.cxx | 93 +++++++++++++++++ editeng/source/editeng/editobj.cxx | 149 ++++++++++++++++++++++++++++ editeng/source/editeng/editobj2.hxx | 8 + editeng/source/editeng/sectionattribute.cxx | 21 +++ include/editeng/editobj.hxx | 13 ++ include/editeng/sectionattribute.hxx | 37 ++++++ sc/Library_sc.mk | 1 sc/inc/column.hxx | 2 sc/inc/document.hxx | 2 sc/inc/edittextiterator.hxx | 61 +++++++++++ sc/inc/table.hxx | 1 sc/qa/unit/ucalc.cxx | 94 +++++++++++++++++ sc/qa/unit/ucalc.hxx | 2 sc/source/core/data/edittextiterator.cxx | 86 ++++++++++++++++ 15 files changed, 571 insertions(+)
New commits: commit 6c4bedffb98a33b202692b225fc250b858ff9f65 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Tue Aug 20 17:23:12 2013 -0400 Add edit text iterator that iterates through only edit text cells. Change-Id: I898d7a2d3f0ea472daddb9dd32f772a5d7268773 diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 83e3358..1ef9a82 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -147,6 +147,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/data/dputil \ sc/source/core/data/drawpage \ sc/source/core/data/drwlayer \ + sc/source/core/data/edittextiterator \ sc/source/core/data/fillinfo \ sc/source/core/data/formulacell \ sc/source/core/data/formulaiter \ diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 49cc24a..4322c24 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -51,6 +51,7 @@ namespace sc { struct RefUpdateInsertTabContext; struct RefUpdateDeleteTabContext; struct RefUpdateMoveTabContext; + class EditTextIterator; } class Fraction; @@ -132,6 +133,7 @@ friend class ScColumnTextWidthIterator; friend class ScDocumentImport; friend class sc::SingleColumnSpanSet; friend class sc::ColumnSpanSet; +friend class sc::EditTextIterator; ScColumn(const ScColumn&); // disabled ScColumn& operator= (const ScColumn&); // disabled diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index c74c6c8..ab84d4c 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -56,6 +56,7 @@ namespace sc { class ColumnSpanSet; struct ColumnBlockPosition; struct RefUpdateContext; + class EditTextIterator; } class SvxFontItem; @@ -231,6 +232,7 @@ friend class ScTable; friend struct ScRefCellValue; friend class ScDocumentImport; friend class sc::ColumnSpanSet; +friend class sc::EditTextIterator; typedef ::std::vector<ScTable*> TableContainer; private: diff --git a/sc/inc/edittextiterator.hxx b/sc/inc/edittextiterator.hxx new file mode 100644 index 0000000..f160b63 --- /dev/null +++ b/sc/inc/edittextiterator.hxx @@ -0,0 +1,61 @@ +/* -*- 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/. + */ + +#ifndef SC_EDITTEXTITERATOR_HXX +#define SC_EDITTEXTITERATOR_HXX + +#include "address.hxx" +#include "mtvelements.hxx" + +class ScColumn; +class ScTable; +class ScDocument; +class EditTextObject; + +namespace sc { + +/** + * Iterate through all edit text cells in a given sheet. The caller must + * check the validity of the sheet index passed to its constructor. + * + * It iterates from top to bottom, and then left to right order. + */ +class EditTextIterator +{ + const ScTable& mrTable; + const ScColumn* mpCol; + const ScColumn* mpColEnd; + const CellStoreType* mpCells; + CellStoreType::const_position_type maPos; + CellStoreType::const_iterator miEnd; + + /** + * Move to the next edit text cell position if the current position is not + * an edit text. + */ + const EditTextObject* seek(); + + /** + * Increment current position by one. + */ + void incPos(); + void incBlock(); + +public: + EditTextIterator( const ScDocument& rDoc, SCTAB nTab ); + + const EditTextObject* first(); + const EditTextObject* next(); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 06e8151..99c506b 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -210,6 +210,7 @@ friend class ScAttrRectIterator; friend class ScColumnTextWidthIterator; friend class ScDocumentImport; friend class sc::ColumnSpanSet; +friend class sc::EditTextIterator; public: ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName, diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 468d7c6..4ed2092 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -49,6 +49,8 @@ #include "dociter.hxx" #include "docsh.hxx" #include "queryparam.hxx" +#include "edittextiterator.hxx" +#include "editutil.hxx" #include "formula/IFunctionDescription.hxx" @@ -4022,6 +4024,98 @@ void Test::testCellTextWidth() m_pDoc->DeleteTab(0); } +bool checkEditTextIterator(sc::EditTextIterator& rIter, const char** pChecks) +{ + const EditTextObject* pText = rIter.first(); + const char* p = *pChecks; + + for (int i = 0; i < 100; ++i) // cap it to 100 loops. + { + if (!pText) + // No more edit cells. The check string array should end too. + return p == NULL; + + if (!p) + // More edit cell, but no more check string. Bad. + return false; + + if (pText->GetParagraphCount() != 1) + // For this test, we don't handle multi-paragraph text. + return false; + + if (pText->GetText(0) != OUString::createFromAscii(p)) + // Text differs from what's expected. + return false; + + pText = rIter.next(); + ++pChecks; + p = *pChecks; + } + + return false; +} + +void Test::testEditTextIterator() +{ + m_pDoc->InsertTab(0, "Test"); + + { + // First, try with an empty sheet. + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + ScFieldEditEngine& rEditEngine = m_pDoc->GetEditEngine(); + + { + // Only set one edit cell. + rEditEngine.SetText("A2"); + m_pDoc->SetEditText(ScAddress(0,1,0), rEditEngine.CreateTextObject()); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + { + // Add a series of edit cells. + rEditEngine.SetText("A5"); + m_pDoc->SetEditText(ScAddress(0,4,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("A6"); + m_pDoc->SetEditText(ScAddress(0,5,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("A7"); + m_pDoc->SetEditText(ScAddress(0,6,0), rEditEngine.CreateTextObject()); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", "A5", "A6", "A7", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + { + // Add more edit cells to column C. Skip column B. + rEditEngine.SetText("C1"); + m_pDoc->SetEditText(ScAddress(2,0,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("C3"); + m_pDoc->SetEditText(ScAddress(2,2,0), rEditEngine.CreateTextObject()); + rEditEngine.SetText("C4"); + m_pDoc->SetEditText(ScAddress(2,3,0), rEditEngine.CreateTextObject()); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", "A5", "A6", "A7", "C1", "C3", "C4", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + { + // Add some numeric, string and formula cells. This shouldn't affect the outcome. + m_pDoc->SetString(ScAddress(0,99,0), "=ROW()"); + m_pDoc->SetValue(ScAddress(1,3,0), 1.2); + m_pDoc->SetString(ScAddress(2,4,0), "Simple string"); + sc::EditTextIterator aIter(*m_pDoc,0); + const char* pChecks[] = { "A2", "A5", "A6", "A7", "C1", "C3", "C4", NULL }; + CPPUNIT_ASSERT_MESSAGE("Wrong iterator behavior.", checkEditTextIterator(aIter, pChecks)); + } + + m_pDoc->DeleteTab(0); +} + void Test::testCondFormatINSDEL() { // fdo#62206 diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx index 5e8933c..fba750f 100644 --- a/sc/qa/unit/ucalc.hxx +++ b/sc/qa/unit/ucalc.hxx @@ -268,6 +268,7 @@ public: void testDeleteCol(); void testAnchoredRotatedShape(); void testCellTextWidth(); + void testEditTextIterator(); void testCondFormatINSDEL(); @@ -364,6 +365,7 @@ public: CPPUNIT_TEST(testDeleteCol); CPPUNIT_TEST(testAnchoredRotatedShape); CPPUNIT_TEST(testCellTextWidth); + CPPUNIT_TEST(testEditTextIterator); CPPUNIT_TEST(testCondFormatINSDEL); CPPUNIT_TEST_SUITE_END(); diff --git a/sc/source/core/data/edittextiterator.cxx b/sc/source/core/data/edittextiterator.cxx new file mode 100644 index 0000000..e563f04 --- /dev/null +++ b/sc/source/core/data/edittextiterator.cxx @@ -0,0 +1,86 @@ +/* -*- 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/. + */ + +#include "edittextiterator.hxx" +#include "document.hxx" +#include "table.hxx" +#include "column.hxx" + +namespace sc { + +EditTextIterator::EditTextIterator( const ScDocument& rDoc, SCTAB nTab ) : + mrTable(*rDoc.maTabs.at(nTab)), + mpCol(&mrTable.aCol[0]), + mpColEnd(mpCol + static_cast<size_t>(MAXCOLCOUNT)), + mpCells(&mpCol->maCells), + maPos(mpCells->position(0)), + miEnd(mpCells->end()) +{ +} + +const EditTextObject* EditTextIterator::seek() +{ + while (maPos.first->type != sc::element_type_edittext) + { + incBlock(); + if (maPos.first == miEnd) + { + // Move to the next column. + ++mpCol; + if (mpCol == mpColEnd) + // No more columns. + return NULL; + + mpCells = &mpCol->maCells; + maPos = mpCells->position(0); + miEnd = mpCells->end(); + } + } + + // We are on the right block type. + return sc::edittext_block::at(*maPos.first->data, maPos.second); +} + +void EditTextIterator::incPos() +{ + if (maPos.second + 1 < maPos.first->size) + // Increment within the block. + ++maPos.second; + else + incBlock(); +} + +void EditTextIterator::incBlock() +{ + ++maPos.first; + maPos.second = 0; +} + +const EditTextObject* EditTextIterator::first() +{ + mpCol = &mrTable.aCol[0]; + mpColEnd = mpCol + static_cast<size_t>(MAXCOLCOUNT); + mpCells = &mpCol->maCells; + maPos = mpCells->position(0); + miEnd = mpCells->end(); + return seek(); +} + +const EditTextObject* EditTextIterator::next() +{ + if (maPos.first == miEnd) + return NULL; + + incPos(); + return seek(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 9ca5e3da5ca5f68ced1917cf38773fd1060bede4 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Tue Aug 20 14:56:27 2013 -0400 Add a means to retrieve all formatting attributes in non-overlapping sections. Change-Id: Id04dffc135fad6bb66ea157cd280dd481cb80117 diff --git a/editeng/Library_editeng.mk b/editeng/Library_editeng.mk index e9c5b4b..c4a9fbe 100644 --- a/editeng/Library_editeng.mk +++ b/editeng/Library_editeng.mk @@ -60,6 +60,7 @@ $(eval $(call gb_Library_add_exception_objects,editeng,\ editeng/source/editeng/impedit3 \ editeng/source/editeng/impedit4 \ editeng/source/editeng/impedit5 \ + editeng/source/editeng/sectionattribute \ editeng/source/editeng/textconv \ editeng/source/items/borderline \ editeng/source/items/bulitem \ diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx index ae3749c..86f5eb8 100644 --- a/editeng/qa/unit/core-test.cxx +++ b/editeng/qa/unit/core-test.cxx @@ -21,9 +21,15 @@ #include "editeng/editdoc.hxx" #include "editeng/svxacorr.hxx" #include "editeng/unofield.hxx" +#include "editeng/wghtitem.hxx" +#include "editeng/postitem.hxx" +#include "editeng/sectionattribute.hxx" +#include "editeng/editobj.hxx" #include <com/sun/star/text/textfield/Type.hpp> +#include <boost/scoped_ptr.hpp> + using namespace com::sun::star; namespace { @@ -48,10 +54,13 @@ public: */ void testAutocorrect(); + void testSectionAttributes(); + CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testConstruction); CPPUNIT_TEST(testUnoTextFields); CPPUNIT_TEST(testAutocorrect); + CPPUNIT_TEST(testSectionAttributes); CPPUNIT_TEST_SUITE_END(); private: @@ -331,7 +340,91 @@ void Test::testAutocorrect() CPPUNIT_ASSERT_EQUAL(sExpected, aFoo.getResult()); } +} + +bool hasBold(const editeng::SectionAttribute& rSecAttr) +{ + std::vector<const SfxPoolItem*>::const_iterator it = rSecAttr.maAttributes.begin(), itEnd = rSecAttr.maAttributes.end(); + for (; it != itEnd; ++it) + { + const SfxPoolItem* p = *it; + if (p->Which() != EE_CHAR_WEIGHT) + continue; + + if (static_cast<const SvxWeightItem*>(p)->GetWeight() != WEIGHT_BOLD) + continue; + + return true; + } + return false; +} + +bool hasItalic(const editeng::SectionAttribute& rSecAttr) +{ + std::vector<const SfxPoolItem*>::const_iterator it = rSecAttr.maAttributes.begin(), itEnd = rSecAttr.maAttributes.end(); + for (; it != itEnd; ++it) + { + const SfxPoolItem* p = *it; + if (p->Which() != EE_CHAR_ITALIC) + continue; + + if (static_cast<const SvxPostureItem*>(p)->GetPosture() != ITALIC_NORMAL) + continue; + + return true; + } + return false; +} + +void Test::testSectionAttributes() +{ + EditEngine aEngine(mpItemPool); + + boost::scoped_ptr<SfxItemSet> pSet(new SfxItemSet(aEngine.GetEmptyItemSet())); + SvxWeightItem aBold(WEIGHT_BOLD, EE_CHAR_WEIGHT); + SvxPostureItem aItalic(ITALIC_NORMAL, EE_CHAR_ITALIC); + OUString aParaText = "aaabbbccc"; + aEngine.SetText(aParaText); + pSet->Put(aBold); + CPPUNIT_ASSERT_MESSAGE("There should be exactly one item.", pSet->Count() == 1); + aEngine.QuickSetAttribs(*pSet, ESelection(0,0,0,6)); // 'aaabbb' - end point is not inclusive. + pSet.reset(new SfxItemSet(aEngine.GetEmptyItemSet())); + pSet->Put(aItalic); + CPPUNIT_ASSERT_MESSAGE("There should be exactly one item.", pSet->Count() == 1); + + aEngine.QuickSetAttribs(*pSet, ESelection(0,3,0,9)); // 'bbbccc' + boost::scoped_ptr<EditTextObject> pEditText(aEngine.CreateTextObject()); + CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText.get()); + std::vector<editeng::SectionAttribute> aAttrs; + pEditText->GetAllSectionAttributes(aAttrs); + + // Now, we should have a total of 3 sections. + CPPUNIT_ASSERT_MESSAGE("There should be 3 sections.", aAttrs.size() == 3); + + // First section should be 0-3 of paragraph 0, and it should only have boldness applied. + const editeng::SectionAttribute* pSecAttr = &aAttrs[0]; + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pSecAttr->mnParagraph); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pSecAttr->mnStart); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pSecAttr->mnEnd); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pSecAttr->maAttributes.size()); + CPPUNIT_ASSERT_MESSAGE("This section must be bold.", hasBold(*pSecAttr)); + + // Second section should be 3-6, and it should be both bold and italic. + pSecAttr = &aAttrs[1]; + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pSecAttr->mnParagraph); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pSecAttr->mnStart); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), pSecAttr->mnEnd); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pSecAttr->maAttributes.size()); + CPPUNIT_ASSERT_MESSAGE("This section must be bold and italic.", hasBold(*pSecAttr) && hasItalic(*pSecAttr)); + + // Third section should be 6-9, and it should be only italic. + pSecAttr = &aAttrs[2]; + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pSecAttr->mnParagraph); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), pSecAttr->mnStart); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(9), pSecAttr->mnEnd); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pSecAttr->maAttributes.size()); + CPPUNIT_ASSERT_MESSAGE("This section must be italic.", hasItalic(*pSecAttr)); } CPPUNIT_TEST_SUITE_REGISTRATION(Test); diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx index bcbef1e..dbfd833 100644 --- a/editeng/source/editeng/editobj.cxx +++ b/editeng/source/editeng/editobj.cxx @@ -28,6 +28,7 @@ #include "editeng/fieldupdater.hxx" #include "editeng/macros.hxx" +#include "editeng/sectionattribute.hxx" #include <editobj2.hxx> #include <editeng/editdata.hxx> #include <editattr.hxx> @@ -276,6 +277,11 @@ bool EditTextObject::RemoveCharAttribs( sal_uInt16 nWhich ) return mpImpl->RemoveCharAttribs(nWhich); } +void EditTextObject::GetAllSectionAttributes( std::vector<editeng::SectionAttribute>& rAttrs ) const +{ + mpImpl->GetAllSectionAttributes(rAttrs); +} + void EditTextObject::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const { mpImpl->GetStyleSheet(nPara, rName, eFamily); @@ -824,6 +830,149 @@ bool EditTextObjectImpl::RemoveCharAttribs( sal_uInt16 _nWhich ) return bChanged; } +namespace { + +class FindByParagraph : std::unary_function<editeng::SectionAttribute, bool> +{ + size_t mnPara; +public: + FindByParagraph(size_t nPara) : mnPara(nPara) {} + bool operator() (const editeng::SectionAttribute& rAttr) const + { + return rAttr.mnParagraph == mnPara; + } +}; + +class FindBySectionStart : std::unary_function<editeng::SectionAttribute, bool> +{ + size_t mnPara; + size_t mnStart; +public: + FindBySectionStart(size_t nPara, size_t nStart) : mnPara(nPara), mnStart(nStart) {} + bool operator() (const editeng::SectionAttribute& rAttr) const + { + return rAttr.mnParagraph == mnPara && rAttr.mnStart == mnStart; + } +}; + +} + +void EditTextObjectImpl::GetAllSectionAttributes( std::vector<editeng::SectionAttribute>& rAttrs ) const +{ + typedef std::vector<size_t> SectionBordersType; + typedef std::map<size_t, SectionBordersType> ParagraphsType; + ParagraphsType aParaBorders; + + // First pass: determine section borders for each paragraph. + for (size_t nPara = 0; nPara < aContents.size(); ++nPara) + { + const ContentInfo& rC = aContents[nPara]; + for (size_t nAttr = 0; nAttr < rC.aAttribs.size(); ++nAttr) + { + const XEditAttribute& rAttr = rC.aAttribs[nAttr]; + const SfxPoolItem* pItem = rAttr.GetItem(); + if (!pItem || pItem->Which() == EE_FEATURE_FIELD) + continue; + + ParagraphsType::iterator it = aParaBorders.lower_bound(nPara); + SectionBordersType* pBorders = NULL; + if (it != aParaBorders.end() && !aParaBorders.key_comp()(nPara, it->first)) + { + // Container for this paragraph already exists. + pBorders = &it->second; + } + else + { + it = aParaBorders.insert(it, ParagraphsType::value_type(nPara, SectionBordersType())); + pBorders = &it->second; + } + + pBorders->push_back(rAttr.GetStart()); + pBorders->push_back(rAttr.GetEnd()); + } + } + + // Sort and remove duplicates for each paragraph. + ParagraphsType::iterator it = aParaBorders.begin(), itEnd = aParaBorders.end(); + for (; it != itEnd; ++it) + { + SectionBordersType& rBorders = it->second; + std::sort(rBorders.begin(), rBorders.end()); + SectionBordersType::iterator itUniqueEnd = std::unique(rBorders.begin(), rBorders.end()); + rBorders.erase(itUniqueEnd, rBorders.end()); + } + + std::vector<editeng::SectionAttribute> aAttrs; + + // Create storage for each section. Note that this creates storage even + // for unformatted sections. The entries are sorted first by paragraph, + // then by section positions. They don't overlap with each other. + it = aParaBorders.begin(); + for (; it != itEnd; ++it) + { + size_t nPara = it->first; + const SectionBordersType& rBorders = it->second; + if (rBorders.empty()) + continue; + + SectionBordersType::const_iterator itBorder = rBorders.begin(), itBorderEnd = rBorders.end(); + size_t nPrev = *itBorder; + size_t nCur; + for (++itBorder; itBorder != itBorderEnd; ++itBorder, nPrev = nCur) + { + nCur = *itBorder; + aAttrs.push_back(editeng::SectionAttribute(nPara, nPrev, nCur)); + } + } + + if (aAttrs.empty()) + return; + + // Go through all formatted paragraphs, and store format items. + it = aParaBorders.begin(); + std::vector<editeng::SectionAttribute>::iterator itAttr = aAttrs.begin(); + for (; it != itEnd; ++it) + { + size_t nPara = it->first; + const ContentInfo& rC = aContents[nPara]; + if (itAttr->mnParagraph != nPara) + // Find the first container for the current paragraph. + itAttr = std::find_if(itAttr, aAttrs.end(), FindByParagraph(nPara)); + + if (itAttr == aAttrs.end()) + // This should never happen. There is a logic error somewhere... + return; + + // Remember this position. + std::vector<editeng::SectionAttribute>::iterator itAttrHead = itAttr; + + for (size_t i = 0; i < rC.aAttribs.size(); ++i) + { + const XEditAttribute& rAttr = rC.aAttribs[i]; + const SfxPoolItem* pItem = rAttr.GetItem(); + if (!pItem || pItem->Which() == EE_FEATURE_FIELD) + continue; + + size_t nStart = rAttr.GetStart(), nEnd = rAttr.GetEnd(); + itAttr = itAttrHead; + + // Find the container whose start position matches. + itAttr = std::find_if(itAttr, aAttrs.end(), FindBySectionStart(nPara, nStart)); + if (itAttr == aAttrs.end()) + // This should never happen. There is a logic error somewhere... + return; + + for (; itAttr != aAttrs.end() && itAttr->mnEnd <= nEnd; ++itAttr) + { + editeng::SectionAttribute& rSecAttr = *itAttr; + rSecAttr.maAttributes.push_back(pItem); + } + } + } + + rAttrs.swap(aAttrs); +} + void EditTextObjectImpl::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& rFamily) const { if (nPara < 0 || static_cast<size_t>(nPara) >= aContents.size()) diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx index d602753..b243647 100644 --- a/editeng/source/editeng/editobj2.hxx +++ b/editeng/source/editeng/editobj2.hxx @@ -28,6 +28,12 @@ #include <boost/ptr_container/ptr_vector.hpp> #include <boost/noncopyable.hpp> +namespace editeng { + +struct SectionAttribute; + +} + class XEditAttribute { private: @@ -219,6 +225,8 @@ public: bool RemoveCharAttribs( sal_uInt16 nWhich = 0 ); + void GetAllSectionAttributes( std::vector<editeng::SectionAttribute>& rAttrs ) const; + bool IsFieldObject() const; const SvxFieldItem* GetField() const; const SvxFieldData* GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const; diff --git a/editeng/source/editeng/sectionattribute.cxx b/editeng/source/editeng/sectionattribute.cxx new file mode 100644 index 0000000..d8e0e57 --- /dev/null +++ b/editeng/source/editeng/sectionattribute.cxx @@ -0,0 +1,21 @@ +/* -*- 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/. + */ + +#include "editeng/sectionattribute.hxx" + +namespace editeng { + +SectionAttribute::SectionAttribute() : mnParagraph(0), mnStart(0), mnEnd(0) {} + +SectionAttribute::SectionAttribute(size_t nPara, size_t nStart, size_t nEnd) : + mnParagraph(nPara), mnStart(nStart), mnEnd(nEnd){} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/editeng/editobj.hxx b/include/editeng/editobj.hxx index 570615f..c61f682 100644 --- a/include/editeng/editobj.hxx +++ b/include/editeng/editobj.hxx @@ -45,6 +45,7 @@ namespace editeng { class FieldUpdater; class FieldUpdaterImpl; +struct SectionAttribute; } @@ -99,6 +100,18 @@ public: bool RemoveCharAttribs( sal_uInt16 nWhich = 0 ); + /** + * Get all attributes that are applied to this content, separated by + * sections. If multiple attributes are applied to the same section, the + * object representing that section will store multiple attributes. + * Sections never overlap each other; if an attribute was applied to [0-6] + * and another applied to [3-10], you would get 3 sections that are [0-3], + * [3-6] and [6-10]. + * + * <p>Note that this method skips field attributes.</p> + */ + void GetAllSectionAttributes( std::vector<editeng::SectionAttribute>& rAttrs ) const; + bool IsFieldObject() const; const SvxFieldItem* GetField() const; const SvxFieldData* GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const; diff --git a/include/editeng/sectionattribute.hxx b/include/editeng/sectionattribute.hxx new file mode 100644 index 0000000..eafd4e2 --- /dev/null +++ b/include/editeng/sectionattribute.hxx @@ -0,0 +1,37 @@ +/* -*- 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/. + */ + +#ifndef EDITENG_SECTIONATTRIBUTE_HXX +#define EDITENG_SECTIONATTRIBUTE_HXX + +#include "editeng/editengdllapi.h" + +#include <vector> + +class SfxPoolItem; + +namespace editeng { + +struct EDITENG_DLLPUBLIC SectionAttribute +{ + size_t mnParagraph; + size_t mnStart; + size_t mnEnd; + + std::vector<const SfxPoolItem*> maAttributes; + + SectionAttribute(); + SectionAttribute(size_t nPara, size_t nStart, size_t nEnd); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits