[Libreoffice-commits] core.git: 2 commits - editeng/Library_editeng.mk editeng/qa editeng/source include/editeng sc/inc sc/Library_sc.mk sc/qa sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Tue Aug 20 19:59:12 PDT 2013
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.yoshida at 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.yoshida at 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: */
More information about the Libreoffice-commits
mailing list