]> git.lyx.org Git - lyx.git/blobdiff - src/iterators.C
the spellcheck cleanup
[lyx.git] / src / iterators.C
index e94479dd049e60c8ed05430734ffe06bfaaa8e4c..609f6e6bbad3863183e3c777fa27dbd486fc9cd0 100644 (file)
+/* \file iterators.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author unknown
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+
 #include <config.h>
 
 #include "iterators.h"
+#include "paragraph.h"
+#include "PosIterator.h"
+#include "cursor.h"
+#include "BufferView.h"
+#include "funcrequest.h"
+#include "dispatchresult.h"
+
+
+
+#include "insets/inset.h"
+#include "insets/updatableinset.h"
+#include "insets/insettext.h"
+
+#include <boost/next_prior.hpp>
+#include <boost/optional.hpp>
 
-ParIterator  & ParIterator::operator++()
+using boost::next;
+using boost::optional;
+using std::vector;
+
+///
+/// ParPosition
+///
+
+class ParPosition {
+public:
+       ///
+       ParPosition(ParagraphList::iterator p, ParagraphList const & pl);
+       ///
+       ParagraphList::iterator pit;
+       ///
+       ParagraphList const * plist;
+       ///
+       optional<InsetList::iterator> it;
+       ///
+       optional<int> index;
+};
+
+
+ParPosition::ParPosition(ParagraphList::iterator p, ParagraphList const & pl)
+       : pit(p), plist(&pl)
 {
-       while (!positions.empty()) {
-               ParPosition & p = positions.back();
+       if (p != const_cast<ParagraphList&>(pl).end()) {
+               it.reset(p->insetlist.begin());
+       }
+}
+
+
+bool operator==(ParPosition const & pos1, ParPosition const & pos2)
+{
+       return pos1.pit == pos2.pit;
+}
+
+
+bool operator!=(ParPosition const & pos1, ParPosition const & pos2)
+{
+       return !(pos1 == pos2);
+}
+
+
+///
+/// ParIterator
+///
+
+struct ParIterator::Pimpl {
+       typedef vector<ParPosition> PosHolder;
+       PosHolder positions;
+};
+
+ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl)
+       : pimpl_(new Pimpl)
+{
+       pimpl_->positions.push_back(ParPosition(pit, pl));
+}
+
+
+ParIterator::~ParIterator()
+{}
+
+
+ParIterator::ParIterator(ParIterator const & pi)
+       : pimpl_(new Pimpl(*pi.pimpl_))
+{}
+
+
+void ParIterator::operator=(ParIterator const & pi)
+{
+       ParIterator tmp(pi);
+       pimpl_.swap(tmp.pimpl_);
+}
+
+
+ParIterator & ParIterator::operator++()
+{
+       while (!pimpl_->positions.empty()) {
+               ParPosition & p = pimpl_->positions.back();
 
                // Does the current inset contain more "cells" ?
-               if (p.index >= 0) {
-                       ++p.index;
-                       Paragraph * par = (*p.it)->getFirstParagraph(p.index);
-                       if (par) {
-                               positions.push_back(ParPosition(par));
+               if (p.index) {
+                       ++(*p.index);
+                       ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
+                       if (plist && !plist->empty()) {
+                               pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
+                               return *this;
+                       }
+                       ++(*p.it);
+               } else
+                       // The following line is needed because the value of
+                       // p.it may be invalid if inset was added/removed to
+                       // the paragraph pointed by the iterator
+                       p.it.reset(p.pit->insetlist.begin());
+
+               // Try to find the next inset that contains paragraphs
+               InsetList::iterator end = p.pit->insetlist.end();
+               for (; *p.it != end; ++(*p.it)) {
+                       ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
+                       if (plist && !plist->empty()) {
+                               p.index.reset(0);
+                               pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
                                return *this;
                        }
-                       ++p.it;
                }
 
+               // Try to go to the next paragarph
+               if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
+                   || pimpl_->positions.size() == 1) {
+                       ++p.pit;
+                       p.index.reset();
+                       p.it.reset();
+
+                       return *this;
+               }
+
+               // Drop end and move up in the stack.
+               pimpl_->positions.pop_back();
+       }
+       return *this;
+}
+
+
+LyXText * ParIterator::text() const
+{
+       //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
+       if (pimpl_->positions.size() <= 1)
+               return 0;
+
+       ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
+       return (*pos.it)->inset->getText(*pos.index);
+}
+
+
+InsetOld * ParIterator::inset() const
+{
+       //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
+       if (pimpl_->positions.size() <= 1)
+               return 0;
+
+       ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
+       return (*pos.it)->inset;
+}
+
+
+int ParIterator::index() const
+{
+       if (pimpl_->positions.size() <= 1)
+               return 0;
+
+       return *(pimpl_->positions[pimpl_->positions.size() - 2].index);
+}
+
+
+void ParIterator::asCursor(Cursor & cursor) const
+{
+       cursor.data_.clear();
+       for (size_t i = 1, n = size(); i < n; ++i) {
+               ParPosition const & pos = pimpl_->positions[i - 1];
+               CursorItem item;
+               item.inset_ = (*pos.it)->inset;
+               item.idx_   = (*pos.index);
+               item.text_  = (*pos.it)->inset->getText(*pos.index);
+               item.par_   = 0;
+               item.pos_   = 0;
+               cursor.data_.push_back(item);
+       }
+}
+
+
+Paragraph & ParIterator::operator*() const
+{
+       return *pimpl_->positions.back().pit;
+}
+
+
+ParagraphList::iterator ParIterator::pit() const
+{
+       return pimpl_->positions.back().pit;
+}
+
+
+ParagraphList::iterator ParIterator::operator->() const
+{
+       return pimpl_->positions.back().pit;
+}
+
+
+ParagraphList::iterator ParIterator::outerPar() const
+{
+       return pimpl_->positions[0].pit;
+}
+
+
+size_t ParIterator::size() const
+{
+       return pimpl_->positions.size();
+}
+
+
+ParagraphList & ParIterator::plist() const
+{
+       return *const_cast<ParagraphList*>(pimpl_->positions.back().plist);
+}
+
+
+bool operator==(ParIterator const & iter1, ParIterator const & iter2)
+{
+       return iter1.pimpl_->positions == iter2.pimpl_->positions;
+}
+
+
+bool operator!=(ParIterator const & iter1, ParIterator const & iter2)
+{
+       return !(iter1 == iter2);
+}
+
+
+///
+/// ParConstIterator
+///
+
+
+struct ParConstIterator::Pimpl {
+       typedef vector<ParPosition> PosHolder;
+       PosHolder positions;
+};
+
+
+ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
+                                  ParagraphList const & pl)
+       : pimpl_(new Pimpl)
+{
+       pimpl_->positions.push_back(ParPosition(pit, pl));
+}
+
+
+ParConstIterator::~ParConstIterator()
+{}
+
+
+ParConstIterator::ParConstIterator(ParConstIterator const & pi)
+       : pimpl_(new Pimpl(*pi.pimpl_))
+{}
+
+
+ParConstIterator & ParConstIterator::operator++()
+{
+       while (!pimpl_->positions.empty()) {
+               ParPosition & p = pimpl_->positions.back();
+
+               // Does the current inset contain more "cells" ?
+               if (p.index) {
+                       ++(*p.index);
+                       ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
+                       if (plist && !plist->empty()) {
+                               pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
+                               return *this;
+                       }
+                       ++(*p.it);
+               } else
+                       // The following line is needed because the value of
+                       // p.it may be invalid if inset was added/removed to
+                       // the paragraph pointed by the iterator
+                       p.it.reset(p.pit->insetlist.begin());
+
                // Try to find the next inset that contains paragraphs
-               for ( ; p.it != p.par->inset_iterator_end(); ++p.it) {
-                       Paragraph * par = (*p.it)->getFirstParagraph(0);
-                       if (par) {
-                               p.index = 0;
-                               positions.push_back(ParPosition(par));
+               InsetList::iterator end = p.pit->insetlist.end();
+               for (; *p.it != end; ++(*p.it)) {
+                       ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
+                       if (plist && !plist->empty()) {
+                               p.index.reset(0);
+                               pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
                                return *this;
                        }
                }
+
                // Try to go to the next paragarph
-               if (p.par->next()) {
-                       p = ParPosition(p.par->next());
+               if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
+                   || pimpl_->positions.size() == 1) {
+                       ++p.pit;
+                       p.index.reset();
+                       p.it.reset();
+
                        return *this;
                }
 
-               positions.pop_back();
+               // Drop end and move up in the stack.
+               pimpl_->positions.pop_back();
        }
+
        return *this;
 }
+
+
+Paragraph const & ParConstIterator::operator*() const
+{
+       return *pimpl_->positions.back().pit;
+}
+
+
+ParagraphList::const_iterator ParConstIterator::pit() const
+{
+       return pimpl_->positions.back().pit;
+}
+
+
+ParagraphList::const_iterator ParConstIterator::operator->() const
+{
+       return pimpl_->positions.back().pit;
+}
+
+
+ParagraphList const & ParConstIterator::plist() const
+{
+       return *pimpl_->positions.back().plist;
+}
+
+
+size_t ParConstIterator::size() const
+{
+       return pimpl_->positions.size();
+}
+
+
+bool operator==(ParConstIterator const & iter1, ParConstIterator const & iter2)
+{
+       return iter1.pimpl_->positions == iter2.pimpl_->positions;
+}
+
+
+bool operator!=(ParConstIterator const & iter1, ParConstIterator const & iter2)
+{
+       return !(iter1 == iter2);
+}
+
+
+PosIterator ParIterator::asPosIterator(lyx::pos_type pos) const
+{
+       PosIterator p;
+
+       int const last = size() - 1;
+       for (int i = 0; i < last; ++i) {
+               ParPosition & pp = pimpl_->positions[i];
+               p.stack_.push(PosIteratorItem(const_cast<ParagraphList *>(pp.plist), pp.pit, (*pp.it)->pos, *pp.index + 1));
+       }
+       ParPosition const & pp = pimpl_->positions[last];
+       p.stack_.push(PosIteratorItem(const_cast<ParagraphList *>(pp.plist),
+                                     pp.pit, pos, 0));
+       return p;
+}
+
+
+void ParIterator::lockPath(BufferView * bv) const
+{
+       bv->insetUnlock();
+       int last = size() - 1;
+       for (int i = 0; i < last; ++i) {
+               UpdatableInset * outer = dynamic_cast<UpdatableInset *>((*pimpl_->positions[i].it)->inset);
+               FuncRequest cmd(bv, LFUN_INSET_EDIT);
+               outer->dispatch(cmd);
+               LyXText * txt = outer->getText(*pimpl_->positions[i].index);
+               InsetText * inner = txt->inset_owner;
+               // deep vodoo magic: on a table, the edit call locks the first
+               // cell and further lock calls get lost there.
+               // We have to unlock it to then lock the correct one.
+               if (outer != inner) {
+                       outer->insetUnlock(bv);
+                       outer->lockInsetInInset(bv, inner);
+                       inner->dispatch(FuncRequest(bv, LFUN_INSET_EDIT));
+               }
+       }
+}