summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-08-20 17:23:12 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-08-20 22:57:13 -0400
commit6c4bedffb98a33b202692b225fc250b858ff9f65 (patch)
tree3d1d30ff0c7dd352d2c39737a4ce38f7e93176c5
parent9ca5e3da5ca5f68ced1917cf38773fd1060bede4 (diff)
Add edit text iterator that iterates through only edit text cells.
Change-Id: I898d7a2d3f0ea472daddb9dd32f772a5d7268773
-rw-r--r--sc/Library_sc.mk1
-rw-r--r--sc/inc/column.hxx2
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/edittextiterator.hxx61
-rw-r--r--sc/inc/table.hxx1
-rw-r--r--sc/qa/unit/ucalc.cxx94
-rw-r--r--sc/qa/unit/ucalc.hxx2
-rw-r--r--sc/source/core/data/edittextiterator.cxx86
8 files changed, 249 insertions, 0 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 83e335856bdc..1ef9a82ea717 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 49cc24aa8f38..4322c247ff81 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 c74c6c8349d3..ab84d4c10b06 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 000000000000..f160b63f58c3
--- /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 06e8151ddda8..99c506bec405 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 468d7c694a02..4ed2092491dd 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 5e8933c90b2c..fba750f8c488 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 000000000000..e563f04ae562
--- /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: */