I've implemented a simple, standalone PosIterator, that iterates over
cursor positions in a document (i.e. valid char positions + paragraph
ends). I've made this in principle beacuse it would make trivial to fix
find & replace for instance.
Now, I understand that this is more or less what a "global cursor" would do,
but in my humble understanding (and I mean that "humble"):
- this seems to work now
- it is completely standalone (no Textcursor, no bv, rows, dispatch
or whatever... nothing. And so terribly simple). In other words,
it doesn't have the burden of acting transitionally as a lyx cursor.
- it uses no paroffsets, and thus may be faster. it is
completely non-stable: works on static text only.
Even if some or all of the above are right/wrong, I still cannot make my
mind if this can be useful at all (aside Cursor, or as a transitional
thing). As I changed view a few times in the last hours, I'though I'd
better post it here and ask for comments. And so I'm doing.
struct PosIteratorItem
{
PosIteratorItem(ParagraphList * pl, ParagraphList::iterator pit,
lyx::pos_type pos)
: pl(pl), pit(pit), pos(pos), index(0) {};
ParagraphList * pl;
ParagraphList::iterator pit;
lyx::pos_type pos;
int index;
};
class PosIterator
{
public:
PosIterator(ParIterator & parit, lyx::pos_type p);
PosIterator(ParagraphList * pl, ParagraphList::iterator pit,
lyx::pos_type pos) {
stack_.push_back(PosIteratorItem(pl,pit,pos));
};
PosIterator & operator++();
bool operator!=(PosIterator const &);
ParagraphList::iterator pit() const { return stack_.back().pit; }
lyx::pos_type pos() const { return stack_.back().pos; }
bool at_end() const;
private:
std::vector<PosIteratorItem> stack_;
};
PosIterator & PosIterator::operator++()
{
while (!stack_.empty()) {
PosIteratorItem & p = stack_.back();
if (p.pos < p.pit->size()) {
InsetOld * inset = p.pit->getInset(p.pos);
if (inset) {
ParagraphList * pl = inset->getParagraphs(p.index++);
if (pl) {
stack_.push_back(PosIteratorItem(pl));
return *this;
}
}
p.index = 0;
++p.pos;
} else {
++p.pit;
p.pos = 0;
}
if (p.pit != p.pl->end() || stack_.size() == 1)
return *this;
stack_.pop_back();
}
return *this;
}
bool PosIterator::operator!=(PosIterator const & a)
{
PosIteratorItem const & pa = a.stack_.back();
PosIteratorItem const & p = stack_.back();
return (pa.pl != p.pl || pa.pit != p.pit || pa.pos != p.pos);
}
bool PosIterator::at_end() const
{
return pos() == pit()->size();
}