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();
}



Reply via email to