2003-05-21 21:20:50 +00:00
|
|
|
|
/* \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<EFBFBD>nnes
|
|
|
|
|
*
|
2003-08-23 00:17:00 +00:00
|
|
|
|
* Full author contact details are available in file CREDITS.
|
2003-05-21 21:20:50 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2001-09-01 21:26:34 +00:00
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
|
|
#include "iterators.h"
|
2003-09-06 12:36:58 +00:00
|
|
|
|
#include "paragraph.h"
|
2003-11-02 17:56:26 +00:00
|
|
|
|
#include "PosIterator.h"
|
2003-10-29 12:18:08 +00:00
|
|
|
|
#include "cursor.h"
|
2003-11-03 09:23:23 +00:00
|
|
|
|
#include "BufferView.h"
|
|
|
|
|
#include "funcrequest.h"
|
|
|
|
|
#include "dispatchresult.h"
|
|
|
|
|
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|
2003-11-02 17:56:26 +00:00
|
|
|
|
|
2003-09-18 10:52:29 +00:00
|
|
|
|
#include "insets/inset.h"
|
2003-11-03 09:23:23 +00:00
|
|
|
|
#include "insets/updatableinset.h"
|
|
|
|
|
#include "insets/insettext.h"
|
2003-09-18 10:52:29 +00:00
|
|
|
|
|
2003-05-21 21:20:50 +00:00
|
|
|
|
#include <boost/next_prior.hpp>
|
|
|
|
|
#include <boost/optional.hpp>
|
|
|
|
|
|
|
|
|
|
using boost::next;
|
|
|
|
|
using boost::optional;
|
2003-06-04 12:45:26 +00:00
|
|
|
|
using std::vector;
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// 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)
|
|
|
|
|
{
|
2003-06-16 14:21:52 +00:00
|
|
|
|
if (p != const_cast<ParagraphList&>(pl).end()) {
|
2003-05-21 21:20:50 +00:00
|
|
|
|
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 {
|
2003-06-04 12:45:26 +00:00
|
|
|
|
typedef vector<ParPosition> PosHolder;
|
2003-05-21 21:20:50 +00:00
|
|
|
|
PosHolder positions;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ParIterator::ParIterator(ParagraphList::iterator pit, ParagraphList const & pl)
|
|
|
|
|
: pimpl_(new Pimpl)
|
|
|
|
|
{
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.push_back(ParPosition(pit, pl));
|
2003-05-21 21:20:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParIterator::~ParIterator()
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParIterator::ParIterator(ParIterator const & pi)
|
|
|
|
|
: pimpl_(new Pimpl(*pi.pimpl_))
|
|
|
|
|
{}
|
|
|
|
|
|
2001-09-01 21:26:34 +00:00
|
|
|
|
|
2003-05-22 15:16:58 +00:00
|
|
|
|
void ParIterator::operator=(ParIterator const & pi)
|
|
|
|
|
{
|
|
|
|
|
ParIterator tmp(pi);
|
|
|
|
|
pimpl_.swap(tmp.pimpl_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-12-07 18:40:24 +00:00
|
|
|
|
ParIterator & ParIterator::operator++()
|
2001-09-01 21:26:34 +00:00
|
|
|
|
{
|
2003-05-21 21:20:50 +00:00
|
|
|
|
while (!pimpl_->positions.empty()) {
|
2003-06-04 12:45:26 +00:00
|
|
|
|
ParPosition & p = pimpl_->positions.back();
|
2001-09-01 21:26:34 +00:00
|
|
|
|
|
|
|
|
|
// Does the current inset contain more "cells" ?
|
2003-05-21 21:20:50 +00:00
|
|
|
|
if (p.index) {
|
|
|
|
|
++(*p.index);
|
2003-05-29 01:13:18 +00:00
|
|
|
|
ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
|
2003-05-05 15:39:48 +00:00
|
|
|
|
if (plist && !plist->empty()) {
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
|
2001-09-01 21:26:34 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
2003-05-21 21:20:50 +00:00
|
|
|
|
++(*p.it);
|
2001-12-07 18:40:24 +00:00
|
|
|
|
} 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
|
2003-05-21 21:20:50 +00:00
|
|
|
|
p.it.reset(p.pit->insetlist.begin());
|
2001-09-01 21:26:34 +00:00
|
|
|
|
|
|
|
|
|
// Try to find the next inset that contains paragraphs
|
2003-05-21 21:20:50 +00:00
|
|
|
|
InsetList::iterator end = p.pit->insetlist.end();
|
|
|
|
|
for (; *p.it != end; ++(*p.it)) {
|
2003-05-29 01:13:18 +00:00
|
|
|
|
ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
|
2003-05-05 15:39:48 +00:00
|
|
|
|
if (plist && !plist->empty()) {
|
2003-05-21 21:20:50 +00:00
|
|
|
|
p.index.reset(0);
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
|
2001-09-01 21:26:34 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|
2001-09-01 21:26:34 +00:00
|
|
|
|
// Try to go to the next paragarph
|
2003-06-16 14:21:52 +00:00
|
|
|
|
if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|| pimpl_->positions.size() == 1) {
|
|
|
|
|
++p.pit;
|
|
|
|
|
p.index.reset();
|
|
|
|
|
p.it.reset();
|
|
|
|
|
|
2001-09-01 21:26:34 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-21 21:20:50 +00:00
|
|
|
|
// Drop end and move up in the stack.
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.pop_back();
|
2001-09-01 21:26:34 +00:00
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2002-11-08 01:08:27 +00:00
|
|
|
|
|
|
|
|
|
|
2003-10-14 13:01:49 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-10-15 08:49:44 +00:00
|
|
|
|
int ParIterator::index() const
|
|
|
|
|
{
|
|
|
|
|
if (pimpl_->positions.size() <= 1)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return *(pimpl_->positions[pimpl_->positions.size() - 2].index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-10-29 12:18:08 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-06-12 11:09:55 +00:00
|
|
|
|
Paragraph & ParIterator::operator*() const
|
|
|
|
|
{
|
|
|
|
|
return *pimpl_->positions.back().pit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParagraphList::iterator ParIterator::pit() const
|
2003-05-21 21:20:50 +00:00
|
|
|
|
{
|
2003-06-04 12:45:26 +00:00
|
|
|
|
return pimpl_->positions.back().pit;
|
2003-05-21 21:20:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-05-22 08:01:41 +00:00
|
|
|
|
ParagraphList::iterator ParIterator::operator->() const
|
2003-05-21 21:20:50 +00:00
|
|
|
|
{
|
2003-06-04 12:45:26 +00:00
|
|
|
|
return pimpl_->positions.back().pit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParagraphList::iterator ParIterator::outerPar() const
|
|
|
|
|
{
|
|
|
|
|
return pimpl_->positions[0].pit;
|
2003-05-21 21:20:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t ParIterator::size() const
|
|
|
|
|
{
|
|
|
|
|
return pimpl_->positions.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-05-23 10:33:40 +00:00
|
|
|
|
ParagraphList & ParIterator::plist() const
|
|
|
|
|
{
|
2003-06-04 12:45:26 +00:00
|
|
|
|
return *const_cast<ParagraphList*>(pimpl_->positions.back().plist);
|
2003-05-23 10:33:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-05-21 21:20:50 +00:00
|
|
|
|
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 {
|
2003-06-04 12:45:26 +00:00
|
|
|
|
typedef vector<ParPosition> PosHolder;
|
2003-05-21 21:20:50 +00:00
|
|
|
|
PosHolder positions;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParConstIterator::ParConstIterator(ParagraphList::iterator pit,
|
|
|
|
|
ParagraphList const & pl)
|
|
|
|
|
: pimpl_(new Pimpl)
|
|
|
|
|
{
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.push_back(ParPosition(pit, pl));
|
2003-05-21 21:20:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParConstIterator::~ParConstIterator()
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParConstIterator::ParConstIterator(ParConstIterator const & pi)
|
|
|
|
|
: pimpl_(new Pimpl(*pi.pimpl_))
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
2002-11-08 01:08:27 +00:00
|
|
|
|
ParConstIterator & ParConstIterator::operator++()
|
|
|
|
|
{
|
2003-05-21 21:20:50 +00:00
|
|
|
|
while (!pimpl_->positions.empty()) {
|
2003-06-04 12:45:26 +00:00
|
|
|
|
ParPosition & p = pimpl_->positions.back();
|
2002-11-08 01:08:27 +00:00
|
|
|
|
|
|
|
|
|
// Does the current inset contain more "cells" ?
|
2003-05-21 21:20:50 +00:00
|
|
|
|
if (p.index) {
|
|
|
|
|
++(*p.index);
|
2003-05-29 01:13:18 +00:00
|
|
|
|
ParagraphList * plist = (*p.it)->inset->getParagraphs(*p.index);
|
2003-05-05 15:39:48 +00:00
|
|
|
|
if (plist && !plist->empty()) {
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
|
2002-11-08 01:08:27 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
2003-05-21 21:20:50 +00:00
|
|
|
|
++(*p.it);
|
2002-11-08 01:08:27 +00:00
|
|
|
|
} 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
|
2003-05-21 21:20:50 +00:00
|
|
|
|
p.it.reset(p.pit->insetlist.begin());
|
2002-11-08 01:08:27 +00:00
|
|
|
|
|
|
|
|
|
// Try to find the next inset that contains paragraphs
|
2003-05-21 21:20:50 +00:00
|
|
|
|
InsetList::iterator end = p.pit->insetlist.end();
|
|
|
|
|
for (; *p.it != end; ++(*p.it)) {
|
2003-05-29 01:13:18 +00:00
|
|
|
|
ParagraphList * plist = (*p.it)->inset->getParagraphs(0);
|
2003-05-05 15:39:48 +00:00
|
|
|
|
if (plist && !plist->empty()) {
|
2003-05-21 21:20:50 +00:00
|
|
|
|
p.index.reset(0);
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.push_back(ParPosition(plist->begin(), *plist));
|
2002-11-08 01:08:27 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|
2002-11-08 01:08:27 +00:00
|
|
|
|
// Try to go to the next paragarph
|
2003-06-16 14:21:52 +00:00
|
|
|
|
if (next(p.pit) != const_cast<ParagraphList*>(p.plist)->end()
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|| pimpl_->positions.size() == 1) {
|
|
|
|
|
++p.pit;
|
|
|
|
|
p.index.reset();
|
|
|
|
|
p.it.reset();
|
|
|
|
|
|
2002-11-08 01:08:27 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-21 21:20:50 +00:00
|
|
|
|
// Drop end and move up in the stack.
|
2003-06-04 12:45:26 +00:00
|
|
|
|
pimpl_->positions.pop_back();
|
2002-11-08 01:08:27 +00:00
|
|
|
|
}
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|
2002-11-08 01:08:27 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
2003-05-21 21:20:50 +00:00
|
|
|
|
|
|
|
|
|
|
2003-06-12 11:09:55 +00:00
|
|
|
|
Paragraph const & ParConstIterator::operator*() const
|
|
|
|
|
{
|
|
|
|
|
return *pimpl_->positions.back().pit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParagraphList::const_iterator ParConstIterator::pit() const
|
2003-05-21 21:20:50 +00:00
|
|
|
|
{
|
2003-06-04 12:45:26 +00:00
|
|
|
|
return pimpl_->positions.back().pit;
|
2003-05-21 21:20:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-06-12 11:09:55 +00:00
|
|
|
|
ParagraphList::const_iterator ParConstIterator::operator->() const
|
2003-05-21 21:20:50 +00:00
|
|
|
|
{
|
2003-06-04 12:45:26 +00:00
|
|
|
|
return pimpl_->positions.back().pit;
|
2003-05-21 21:20:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-08-27 15:38:23 +00:00
|
|
|
|
ParagraphList const & ParConstIterator::plist() const
|
|
|
|
|
{
|
|
|
|
|
return *pimpl_->positions.back().plist;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-05-21 21:20:50 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
2003-11-02 17:56:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2003-11-03 09:23:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|