]> git.lyx.org Git - features.git/commitdiff
deep iterators for math insets;
authorAndré Pönitz <poenitz@gmx.net>
Wed, 5 Dec 2001 17:50:18 +0000 (17:50 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Wed, 5 Dec 2001 17:50:18 +0000 (17:50 +0000)
use brute force for to determine "best" position when doing cursor up/down
(will be sped up a bit again soonish...)

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@3153 a592a061-630c-0410-9148-cb99ea01b6c8

src/mathed/Makefile.am
src/mathed/README
src/mathed/math_cursor.C
src/mathed/math_cursor.h
src/mathed/math_gridinset.C
src/mathed/math_inset.h
src/mathed/math_iterator.C [new file with mode: 0644]
src/mathed/math_iterator.h [new file with mode: 0644]
src/mathed/math_xdata.C
src/mathed/math_xdata.h

index 4a624d3188018ab7f3807e75082af4cc9846b01a..a3963baff5c4b8d5f4086075eb31a6cfe29047d8 100644 (file)
@@ -68,6 +68,8 @@ libmathed_la_SOURCES = \
        math_hullinset.h \
        math_inset.C \
        math_inset.h \
+       math_iterator.C \
+       math_iterator.h \
        math_kerninset.C \
        math_kerninset.h \
        math_lefteqninset.C \
index caf9498e1ec8e5919301fe3a2d41e74fd233b017..d23b8610d5c68585b46b588055f6bcf965d67cb0 100644 (file)
@@ -26,12 +26,12 @@ Inset hierarchy:
 
       /   \
 
- Array     "Matrix"
+ Array    Hull
          (base for eqnarray/align/...)
 
 
 
 There are only two "real LyXInsets" in here:
 
-Formula       - containing a pointer to a  MathMatrixInset (a misnomer...)
+Formula       - containing a pointer to a  MathHullInset 
 FormulaMacro  - containing a pointer to a  MathMacroTemplate
index 0d70e911ce2bda37b4a767c58d42839765221439..6c11fca0bcdd20058dd395d029db9272a9def1a9 100644 (file)
 #include "debug.h"
 #include "LColor.h"
 #include "Painter.h"
-#include "math_support.h"
 #include "formulabase.h"
-#include "math_cursor.h"
-#include "math_casesinset.h"
-#include "math_factory.h"
 #include "math_arrayinset.h"
 #include "math_braceinset.h"
+#include "math_casesinset.h"
 #include "math_charinset.h"
+#include "math_cursor.h"
 #include "math_deliminset.h"
+#include "math_factory.h"
 #include "math_hullinset.h"
+#include "math_iterator.h"
+#include "math_mathmlstream.h"
+#include "math_parser.h"
+#include "math_replace.h"
 #include "math_scriptinset.h"
 #include "math_spaceinset.h"
 #include "math_specialcharinset.h"
-#include "math_mathmlstream.h"
-#include "math_replace.h"
-#include "math_parser.h"
+#include "math_support.h"
 
 #define FILEDEBUG 0
 
@@ -67,7 +68,7 @@ struct Selection
                        data_.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
                else {
                        std::vector<MathInset::idx_type> indices =
-                               (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
+                               i1.par_->idxBetween(i1.idx_, i2.idx_);
                        for (MathInset::idx_type i = 0; i < indices.size(); ++i)
                                data_.push_back(i1.cell(indices[i]));
                }
@@ -82,7 +83,7 @@ struct Selection
                        i1.cell().erase(i1.pos_, i2.pos_);
                else {
                        std::vector<MathInset::idx_type> indices =
-                               (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
+                               i1.par_->idxBetween(i1.idx_, i2.idx_);
                        for (unsigned i = 0; i < indices.size(); ++i)
                                i1.cell(indices[i]).erase();
                }
@@ -116,13 +117,6 @@ struct Selection
 Selection theSelection;
 
 
-#if FILEDEBUG
-std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
-{
-       os << "(par: " << p.par_ << " idx: " << p.idx_ << " pos: " << p.pos_ << ")";
-       return os;
-}
-#endif
 
 }
 
@@ -136,11 +130,7 @@ MathCursor::MathCursor(InsetFormulaBase * formula, bool left)
 
 void MathCursor::push(MathAtom & t)
 {
-       MathCursorPos p;
-       p.par_ = &t;
-       p.idx_ = 0;
-       p.pos_ = 0;
-       Cursor_.push_back(p);
+       Cursor_.push_back(MathCursorPos(t.nucleus()));
 }
 
 
@@ -192,48 +182,19 @@ bool MathCursor::popRight()
 
 
 #if FILEDEBUG
-void MathCursor::dump(char const * what) const
-{
-       lyxerr << "MC: " << what << "\n";
-       for (unsigned i = 0; i < Cursor_.size(); ++i)
-               lyxerr << "  i: " << i 
-                       << " Cursor: pos: " << Cursor_[i].pos_
-                       << " idx: " << Cursor_[i].idx_
-                       << " par: " << Cursor_[i].par_ << "\n";
-
-       for (unsigned i = 0; i < Anchor_.size(); ++i)
-               lyxerr << "  i: " << i 
-                       << " Anchor: pos: " << Anchor_[i].pos_
-                       << " idx: " << Anchor_[i].idx_
-                       << " par: " << Anchor_[i].par_ << "\n";
-
-       lyxerr  << " sel: " << selection_ << "\n";
-}
-
-
-void MathCursor::seldump(char const * str) const
-{
-       //lyxerr << "SEL: " << str << ": '" << theSelection << "'\n";
-       //dump("   Pos");
-
-       lyxerr << "\n\n\n=================vvvvvvvvvvvvv=======================   "
-               <<  str << "\ntheSelection: " << selection_
-               << " '" /*<< theSelection.glue()*/ << "'\nCursor:";
-       for (unsigned int i = 0; i < Cursor_.size(); ++i) 
-               lyxerr << Cursor_[i].par_ << "\n'" /*<< Cursor_[i].cell()*/ << "'\n";
-       lyxerr << "\nAnchor: ";
-       for (unsigned int i = 0; i < Anchor_.size(); ++i) 
-               lyxerr << Anchor_[i].par_ << "\n'" /*<< Anchor_[i].cell()*/ << "'\n";
-       //lyxerr << "\ncursor.pos_: " << pos();
-       //lyxerr << "\nanchor.pos_: " << anchor().pos_;
-       lyxerr << "\n===================^^^^^^^^^^^^=====================\n\n\n";
-}
-
+       void MathCursor::dump(char const * what) const
+       {
+               lyxerr << "MC: " << what << "\n";
+               lyxerr << " Cursor: " << Cursor_.size() << "\n";
+               for (unsigned i = 0; i < Cursor_.size(); ++i)
+                       lyxerr << "    i: " << i << " " << Cursor_[i] << "\n";
+               lyxerr << " Anchor: " << Anchor_.size() << "\n";
+               for (unsigned i = 0; i < Anchor_.size(); ++i)
+                       lyxerr << "    i: " << i << " " << Anchor_[i] << "\n";
+               lyxerr  << " sel: " << selection_ << "\n";
+       }
 #else
-
-void MathCursor::seldump(char const *) const {}
-void MathCursor::dump(char const *) const {}
-
+       void MathCursor::dump(char const *) const {}
 #endif
 
 
@@ -246,7 +207,7 @@ UpdatableInset * MathCursor::asHyperActiveInset() const
 bool MathCursor::isInside(MathInset const * p) const
 {
        for (unsigned i = 0; i < Cursor_.size(); ++i) 
-               if (Cursor_[i].par_->nucleus() == p) 
+               if (Cursor_[i].par_ == p) 
                        return true;
        return false;
 }
@@ -267,7 +228,7 @@ bool MathCursor::openable(MathAtom const & t, bool sel) const
                // we can't move into anything new during selection
                if (Cursor_.size() == Anchor_.size())
                        return false;
-               if (&t != Anchor_[Cursor_.size()].par_)
+               if (t.nucleus() != Anchor_[Cursor_.size()].par_)
                        return false;
        }
        return true;
@@ -280,7 +241,7 @@ bool MathCursor::positionable(MathAtom const & t, int x, int y) const
                // we can't move into anything new during selection
                if (Cursor_.size() >= Anchor_.size())
                        return false;
-               if (&t != Anchor_[Cursor_.size()].par_)
+               if (t.nucleus() != Anchor_[Cursor_.size()].par_)
                        return false;
        }
 
@@ -371,6 +332,7 @@ void MathCursor::last()
 }
 
 
+#if 0
 void MathCursor::setPos(int x, int y)
 {
        //dump("setPos 1");
@@ -407,6 +369,47 @@ void MathCursor::setPos(int x, int y)
        //dump("setPos 2");
 }
 
+#else
+
+void MathCursor::setPos(int x, int y)
+{
+       dump("setPos 1");
+       cursor_type best_cursor;
+       double best_dist = 1e10;
+
+       MathIterator it(formula()->par().nucleus());
+       MathIterator et;
+       for ( ; it != et; ++it) {
+               if (selection_) {
+                       // avoid deeper nested insets when selecting
+                       if (it.cursor().size() > Anchor_.size())
+                               continue;
+                       // anchor might be deeper!
+                       if (it.cursor().size() == Anchor_.size())
+                               if (it.par() != Anchor_.back().par_)
+                                       continue;
+                       //if (it.par() != Anchor_[it.cursor().size()].par_)
+                       //      continue;
+               }
+               //lyxerr << it.position() << endl;
+               int xo = it.position().xpos();
+               int yo = it.position().ypos();
+               double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
+               if (d < best_dist) {
+                       best_dist   = d;
+                       best_cursor = it.cursor();
+               }
+       }
+       if (best_dist < 1e10)
+               Cursor_ = best_cursor;
+       //lyxerr << "x: " << x << " y: " << y << " dist: " << best_dist << "\n";
+       dump("setPos 2");
+}
+
+#endif
+
+
+
 
 void MathCursor::home(bool sel)
 {
@@ -687,7 +690,7 @@ string MathCursor::macroName() const
 
 void MathCursor::selCopy()
 {
-       seldump("selCopy");
+       dump("selCopy");
        if (selection_) {
                theSelection.grab(*this);
                selClear();
@@ -697,7 +700,7 @@ void MathCursor::selCopy()
 
 void MathCursor::selCut()
 {
-       seldump("selCut");
+       dump("selCut");
        if (selection_) {
                theSelection.grab(*this);
                theSelection.erase(*this);
@@ -710,7 +713,7 @@ void MathCursor::selCut()
 
 void MathCursor::selDel()
 {
-       seldump("selDel");
+       dump("selDel");
        if (selection_) {
                theSelection.erase(*this);
                if (pos() > size())
@@ -722,7 +725,7 @@ void MathCursor::selDel()
 
 void MathCursor::selPaste()
 {
-       seldump("selPaste");
+       dump("selPaste");
        theSelection.paste(*this);
        //theSelection.grab(*this);
        //selClear();
@@ -741,23 +744,25 @@ void MathCursor::selHandle(bool sel)
 
 void MathCursor::selStart()
 {
-       seldump("selStart");
+       dump("selStart 1");
        //theSelection.clear();
        Anchor_ = Cursor_;
        selection_ = true;
+       dump("selStart 2");
 }
 
 
 void MathCursor::selClear()
 {
-       seldump("selClear");
+       dump("selClear 1");
        selection_ = false;
+       dump("selClear 2");
 }
 
 
 void MathCursor::selGet(MathArray & ar)
 {
-       seldump("selGet");
+       dump("selGet");
        if (!selection_)
                return;
 
@@ -786,7 +791,7 @@ void MathCursor::drawSelection(Painter & pain) const
                pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
        } else {
                std::vector<MathInset::idx_type> indices
-                       = (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
+                       = i1.par_->idxBetween(i1.idx_, i2.idx_);
                for (unsigned i = 0; i < indices.size(); ++i) {
                        MathXArray & c = i1.xcell(indices[i]);
                        int x1 = c.xo();
@@ -850,14 +855,16 @@ void MathCursor::getPos(int & x, int & y)
 #ifdef WITH_WARNINGS
 #warning This should probably take cellXOffset and cellYOffset into account
 #endif
+       dump("getPos 1");
        x = xarray().xo() + xarray().pos2x(pos());
        y = xarray().yo();
+       dump("getPos 2");
 }
 
 
-MathAtom & MathCursor::par() const
+MathInset * MathCursor::par() const
 {
-       return *cursor().par_;
+       return cursor().par_;
 }
 
 
@@ -906,7 +913,7 @@ bool MathCursor::selection() const
 MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
 {
        for (int i = Cursor_.size() - 1; i >= 0; --i) {
-               MathGridInset * p = (*Cursor_[i].par_)->asGridInset();
+               MathGridInset * p = Cursor_[i].par_->asGridInset();
                if (p) {
                        idx = Cursor_[i].idx_;
                        return p;
@@ -1153,8 +1160,12 @@ MathCursorPos const & MathCursor::cursor() const
 bool MathCursor::goUp()
 {
        // first ask the inset if it knows better then we
-       if (par()->idxUp(idx(), pos()))
+       if (par()->idxUp(idx(), pos())) {
+               int xlow, xhigh, ylow, yhigh;
+               xarray().boundingBox(xlow, xhigh, ylow, yhigh);
+               bruteFind(xlow, xhigh, ylow, yhigh);
                return true;
+       }
 
        // leave subscript to the nearest side  
        MathScriptInset * p = par()->asScriptInset();
@@ -1175,8 +1186,12 @@ bool MathCursor::goUp()
 bool MathCursor::goDown()
 {
        // first ask the inset if it knows better then we
-       if (par()->idxDown(idx(), pos()))
+       if (par()->idxDown(idx(), pos())) {
+               int xlow, xhigh, ylow, yhigh;
+               xarray().boundingBox(xlow, xhigh, ylow, yhigh);
+               bruteFind(xlow, xhigh, ylow, yhigh);
                return true;
+       }
 
        // leave superscript to the nearest side        
        MathScriptInset * p = par()->asScriptInset();
@@ -1200,8 +1215,8 @@ bool MathCursor::bruteUpDown(int ylow, int yhigh)
        int x0;
        int y0;
        getPos(x0, y0);
-       std::vector<MathCursorPos> save = Cursor_;
-       std::vector<MathCursorPos> best;
+       cursor_type save = Cursor_;
+       cursor_type best;
        double best_dist = 1e10; // large enough
        bool found  = false;
        for (int y = ylow; y < yhigh; y += 4) {
@@ -1229,6 +1244,35 @@ bool MathCursor::bruteUpDown(int ylow, int yhigh)
 }
 
 
+bool MathCursor::bruteFind(int xlow, int xhigh, int ylow, int yhigh)
+{
+       //lyxerr << "looking at range: " << ylow << " " << yhigh << "\n";
+       int x;
+       int y;
+       getPos(x, y);
+
+       cursor_type best_cursor;
+       double best_dist = 1e10;
+
+       MathIterator it(formula()->par().nucleus());
+       MathIterator et;
+       for ( ; it != et; ++it) {
+               int xo = it.position().xpos();
+               int yo = it.position().ypos();
+               if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
+                       double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
+                       if (d < best_dist) {
+                               best_dist   = d;
+                               best_cursor = it.cursor();
+                       }
+               }
+       }
+       if (best_dist < 1e10)
+               Cursor_ = best_cursor;
+       return true;
+}
+
+
 bool MathCursor::idxLeft()
 {
        return par()->idxLeft(idx(), pos());
@@ -1443,75 +1487,109 @@ bool MathCursor::interpret(char c)
 
 
 
-////////////////////////////////////////////////////////////////////////
-
-
-bool operator==(MathCursorPos const & ti, MathCursorPos const & it)
+MathCursorPos MathCursor::normalAnchor() const
 {
-       return ti.par_ == it.par_ && ti.idx_ == it.idx_ && ti.pos_ == it.pos_;
+       // use Anchor on the same level as Cursor
+       MathCursorPos normal = Anchor_[Cursor_.size() - 1];
+       if (Cursor_.size() < Anchor_.size() && !(normal < cursor())) {
+               // anchor is behind cursor -> move anchor behind the inset
+               ++normal.pos_;
+       }
+       return normal;
 }
 
 
-bool operator<(MathCursorPos const & ti, MathCursorPos const & it)
+void MathCursor::stripFromLastEqualSign()
 {
-       if (ti.par_ != it.par_) {
-               lyxerr << "can't compare cursor and anchor in different insets\n";
-               return true;
-       }
-       if (ti.idx_ != it.idx_)
-               return ti.idx_ < it.idx_;
-       return ti.pos_ < it.pos_;
+       // find position of last '=' in the array
+       MathArray & ar = cursor().cell();
+       MathArray::const_iterator et = ar.end();
+       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+               if ((*it)->getChar() == '=')
+                       et = it;
+
+       // delete everything behind this position
+       ar.erase(et - ar.begin(), ar.size());
+       pos() = ar.size(); 
 }
 
 
+////////////////////////////////////////////////////////////////////////
+
+
+MathCursorPos::MathCursorPos()
+       : par_(0), idx_(0), pos_(0)
+{}
+
+
+MathCursorPos::MathCursorPos(MathInset * p)
+       : par_(p), idx_(0), pos_(0)
+{}
+
+
 MathArray & MathCursorPos::cell(MathCursor::idx_type idx) const
 {
-       return (*par_)->cell(idx);
+       return par_->cell(idx);
 }
 
 
 MathArray & MathCursorPos::cell() const
 {
-       return (*par_)->cell(idx_);
+       return par_->cell(idx_);
 }
 
 
 MathXArray & MathCursorPos::xcell(MathCursor::idx_type idx) const
 {
-       return (*par_)->xcell(idx);
+       return par_->xcell(idx);
 }
 
 
 MathXArray & MathCursorPos::xcell() const
 {
-       return (*par_)->xcell(idx_);
+       return par_->xcell(idx_);
 }
 
 
-MathCursorPos MathCursor::normalAnchor() const
+int MathCursorPos::xpos() const
 {
-       // use Anchor on the same level as Cursor
-       MathCursorPos normal = Anchor_[Cursor_.size() - 1];
-       if (Cursor_.size() < Anchor_.size() && !(normal < cursor())) {
-               // anchor is behind cursor -> move anchor behind the inset
-               ++normal.pos_;
-       }
-       return normal;
+       return xcell().xo() + xcell().pos2x(pos_);
 }
 
 
-void MathCursor::stripFromLastEqualSign()
+int MathCursorPos::ypos() const
 {
-       // find position of last '=' in the array
-       MathArray & ar = cursor().cell();
-       MathArray::const_iterator et = ar.end();
-       for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
-               if ((*it)->getChar() == '=')
-                       et = it;
+       return xcell().yo();
+}
 
-       // delete everything behind this position
-       ar.erase(et - ar.begin(), ar.size());
-       pos() = ar.size(); 
+std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
+{
+       os << "(par: " << p.par_ << " idx: " << p.idx_ << " pos: " << p.pos_ << ")";
+       return os;
+}
+
+
+bool operator==(MathCursorPos const & ti, MathCursorPos const & it)
+{
+       return ti.par_ == it.par_ && ti.idx_ == it.idx_ && ti.pos_ == it.pos_;
+}
+
+
+bool operator!=(MathCursorPos const & ti, MathCursorPos const & it)
+{
+       return ti.par_ != it.par_ || ti.idx_ != it.idx_ || ti.pos_ != it.pos_;
+}
+
+
+bool operator<(MathCursorPos const & ti, MathCursorPos const & it)
+{
+       if (ti.par_ != it.par_) {
+               lyxerr << "can't compare cursor and anchor in different insets\n";
+               return true;
+       }
+       if (ti.idx_ != it.idx_)
+               return ti.idx_ < it.idx_;
+       return ti.pos_ < it.pos_;
 }
 
 
index f38125aa459c82c4873e85dde7e7cea28523ee9c..50533563090120ef1cf90bf0fccd0ae0da7aa0e8 100644 (file)
@@ -42,13 +42,12 @@ this formula's mathHullInset to the current position.
 
 
 /// Description of a position 
-struct MathCursorPos {
-       /// pointer to an inset
-       MathAtom * par_;
-       /// cell index of a position in this inset
-       MathInset::idx_type idx_;
-       /// position in this cell
-       MathInset::pos_type pos_;
+class MathCursorPos {
+public:
+       /// 
+       MathCursorPos();
+       /// 
+       explicit MathCursorPos(MathInset * p);
 
        /// returns cell corresponding to this position
        MathArray & cell() const;
@@ -58,12 +57,28 @@ struct MathCursorPos {
        MathXArray & xcell() const;
        /// returns xcell corresponding to this position
        MathXArray & xcell(MathInset::idx_type idx) const;
+       ///
+       int xpos() const;
+       ///
+       int ypos() const;
+
+public:
+       /// pointer to an inset
+       MathInset * par_;
+       /// cell index of a position in this inset
+       MathInset::idx_type idx_;
+       /// position in this cell
+       MathInset::pos_type pos_;
 };
 
 /// test for equality
 bool operator==(MathCursorPos const &, MathCursorPos const &);
-/// test for unequality
+/// test for inequality
+bool operator!=(MathCursorPos const &, MathCursorPos const &);
+/// test for order
 bool operator<(MathCursorPos const &, MathCursorPos const &);
+/// output
+std::ostream & operator<<(std::ostream &, MathCursorPos const &);
 
 
 /// see above
@@ -128,7 +143,7 @@ public:
        /// in pixels from top of screen
        void getPos(int & x, int & y);
        /// 
-       MathAtom & par() const;
+       MathInset * par() const;
        /// return the next enclosing grid inset and the cursor's index in it
        MathGridInset * enclosingGrid(idx_type &) const;
        ///
@@ -275,6 +290,8 @@ private:
        bool goDown();
        /// moves position somehow down
        bool bruteUpDown(int ylow, int yhigh);
+       /// moves position into box
+       bool bruteFind(int xlow, int xhigh, int ylow, int yhigh);
 
        ///
        string macroName() const;
index 56bfaeae558e2195b722fa62e2e78a2c180d78a1..ce2d94bee5782cdb510ee4fdd849ff2c74322062 100644 (file)
@@ -487,31 +487,27 @@ int MathGridInset::cellYOffset(idx_type idx) const
 }
 
 
-bool MathGridInset::idxUp(idx_type & /*idx*/, pos_type & /*pos*/) const
+bool MathGridInset::idxUp(idx_type & idx, pos_type & pos) const
 {
-       return false;
-/*
+       //return false;
        if (idx < ncols())
                return false;
        int x = cellXOffset(idx) + xcell(idx).pos2x(pos);
        idx -= ncols();
        pos = xcell(idx).x2pos(x - cellXOffset(idx));
        return true;
-*/
 }
 
        
-bool MathGridInset::idxDown(idx_type & /*idx*/, pos_type & /*pos*/) const
+bool MathGridInset::idxDown(idx_type & idx, pos_type & pos) const
 {
-       return false;
-/*
+       //return false;
        if (idx >= ncols() * (nrows() - 1))
                return false;
        int x = cellXOffset(idx) + xcell(idx).pos2x(pos);
        idx += ncols();
        pos = xcell(idx).x2pos(x - cellXOffset(idx));
        return true;
-*/
 }
        
        
index ca568a3ed8d245f31aed0eace26d5a266a7fca5d..3acdd53a3bbd3c97ee60a67e745e537e237c6b32 100644 (file)
@@ -72,6 +72,7 @@ class LaTeXFeatures;
 class BufferView;
 class UpdatableInset;
 class MathMacroTemplate;
+class MathPosFinder;
 
 
 class MathInset {
diff --git a/src/mathed/math_iterator.C b/src/mathed/math_iterator.C
new file mode 100644 (file)
index 0000000..0ea88d5
--- /dev/null
@@ -0,0 +1,137 @@
+
+#include <config.h>
+
+#include "debug.h"
+#include "math_iterator.h"
+
+
+MathIterator::MathIterator()
+{}
+
+
+MathIterator::MathIterator(MathInset * p)
+{
+       push(p);
+}
+
+
+MathIterator::MathIterator(MathCursor::cursor_type const & c)
+       : cursor_(c)
+{}
+
+
+MathCursorPos const & MathIterator::position() const
+{
+       return cursor_.back();
+}
+
+
+MathCursorPos & MathIterator::position()
+{
+       return cursor_.back();
+}
+
+
+MathCursor::cursor_type const & MathIterator::cursor() const
+{
+       return cursor_;
+}
+
+
+MathInset * MathIterator::par() const
+{
+       return cursor_.size() ? cursor_.back().par_ : 0;
+}
+
+
+MathXArray const & MathIterator::xcell() const
+{
+       if (!par())
+               lyxerr << "MathIterator::xcell: no cell\n";
+       return par()->xcell(position().idx_);
+}
+
+
+MathInset * MathIterator::nextInset() const
+{
+       if (position().pos_ == xcell().data_.size())
+               return 0;
+       return (xcell().begin() + position().pos_)->nucleus();
+}
+
+
+void MathIterator::push(MathInset * p)
+{
+       //lyxerr << "push: " << p << endl;
+       cursor_.push_back(MathCursorPos(p));
+}
+
+
+void MathIterator::pop()
+{
+       //lyxerr << "pop: " << endl;
+       cursor_.pop_back();
+}
+
+
+MathCursorPos const & MathIterator::operator*() const
+{
+       return position();
+}
+
+
+MathCursorPos const & MathIterator::operator->() const
+{
+       return position();
+}
+
+
+void MathIterator::operator++()
+{
+       // move into the current inset if possible
+       // it is impossible for pos() == size()!
+       if (nextInset() && nextInset()->isActive()) {
+               push(nextInset());
+               return;
+       }
+
+       // otherwise move on one cell position if possible
+       if (position().pos_ < xcell().data_.size()) {
+               // pos() == size() is valid!
+               ++position().pos_;
+               return;
+       }
+
+       // otherwise move on one cell if possible
+       if (position().idx_ + 1 < par()->nargs()) {
+               // idx() == nargs() is _not_ valid!
+               ++position().idx_;
+               position().pos_ = 0;
+               return;
+       }
+
+       // otherwise leave array, move on one cell
+       // this might yield pos() == size(), but that's a ok.
+       pop();
+       ++position().pos_;
+}
+
+
+
+bool operator==(MathIterator const & it, MathIterator const & jt)
+{
+       //lyxerr << "==: " << it.cursor().size() << " " << jt.cursor().size() << endl;
+       if (it.cursor().size() != jt.cursor().size())
+               return false;
+       return it.cursor() == jt.cursor();      
+}
+
+
+bool operator!=(MathIterator const & it, MathIterator const & jt)
+{
+       //lyxerr << "!=: " << it.cursor().size() << " " << jt.cursor().size() << endl;
+       if (it.cursor().size() != jt.cursor().size())
+               return true;
+       return it.cursor() != jt.cursor();      
+}
+
diff --git a/src/mathed/math_iterator.h b/src/mathed/math_iterator.h
new file mode 100644 (file)
index 0000000..f56911c
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef MATH_ITERATOR_H
+#define MATH_ITERATOR_H
+
+#include "math_cursor.h"
+
+// this helper struct is used for traversing math insets
+
+class MathIterator {
+public:
+       /// default constructor, used for end of range
+       MathIterator();
+       /// start with given formula
+       explicit MathIterator(MathInset * p);
+       /// start with given position
+       explicit MathIterator(MathCursor::cursor_type const & cursor);
+       ///
+       MathCursorPos const & operator*() const;
+       ///
+       MathCursorPos const & operator->() const;
+       ///
+       void operator++();
+       /// read access to top most item
+       MathCursorPos const & position() const;
+       /// write access to top most item
+       MathCursorPos & position();
+       /// read access to full path
+       MathCursor::cursor_type const & cursor() const;
+       /// read access to top most inset
+       MathInset * par() const;
+       
+private:
+       /// write access to top most item
+       MathXArray const & xcell() const;
+       /// write access to top most item
+       MathInset * nextInset() const;
+       /// own level down
+       void push(MathInset *);
+       /// own level up
+       void pop();
+
+       /// current position
+       MathCursor::cursor_type cursor_;
+};
+
+///
+bool operator==(MathIterator const &, MathIterator const &);
+///
+bool operator!=(MathIterator const &, MathIterator const &);
+
+
+#endif
index 8663e7f115e75dff2566e9a9e9271330eed172f4..37786bbc74f0585d87edf841977e486adaf9f090 100644 (file)
@@ -151,3 +151,39 @@ bool MathXArray::covers(int x, int y) const
        int const y1 = yo_ + descent_;
        return x >= x0 && x <= x1 && y >= y0 && y <= y1;
 }
+
+
+void MathXArray::boundingBox(int & x1, int & x2, int & y1, int & y2)
+{
+       x1 = xo_;
+       x2 = xo_ + width_;
+       y1 = yo_ - ascent_;
+       y2 = yo_ + descent_;
+}
+
+/*
+void MathXArray::findPos(MathPosFinder & f) const
+{
+       double x = xo_;
+       double y = yo_; 
+       for (const_iterator it = begin(); it < end(); ++it) {
+               // check this position in the cell first
+               f.visit(x, y);
+               f.nextPos();
+
+               // check inset
+               MathInset const * p = it->nucleus();
+               p->findPos(f);
+
+               // move on
+               MathScriptInset const * q = (it + 1 == end()) ? 0 : asScript(it);
+               if (q) {
+                       x += q->width(p);
+                       f.nextPos();
+                       ++it;
+               } else {
+                       x += p->width();
+               }
+       }
+}
+*/
index 0fb7842d66c014307706bfffc544b71c6007f810..dd059aaefb9066f8739b7a2f49f4f303abfb83bf 100644 (file)
 
 class Painter;
 
+
+/** This class extends a MathArray by drawing routines and caches for
+ * metric information.
+ */
 class MathXArray
 {
 public:
-       ///
+       /// type for positions and sizes
        typedef MathArray::size_type       size_type;
-       ///
+       /// const iterator into the underlying MathArray
        typedef MathArray::const_iterator  const_iterator;
 
-       ///
+       /// constructor
        MathXArray();
-       ///
+       /// rebuild cached metrics information
        void metrics(MathMetricsInfo const & st) const;
-       ///
+       /// redraw cell using cache metrics information
        void draw(Painter & pain, int x, int y) const;
 
-       ///
+       /// access to cached x coordinate of last drawing
        int xo() const { return xo_; }
-       ///
+       /// access to cached y coordinate of last drawing
        int yo() const { return yo_; }
-       ///
+       /// returns x coordinate of given position in the array
        int pos2x(size_type pos) const;
-       ///
+       /// returns position of given x coordinate
        size_type x2pos(int pos) const;
        /// returns distance of this cell to the point given by x and y
        // assumes valid position and size cache
        int dist(int x, int y) const;
 
-       ///
+       /// ascent of this cell above the baseline
        int ascent() const { return ascent_; }
-       ///
+       /// descent of this cell below the baseline
        int descent() const { return descent_; }
-       ///
+       /// height of the cell
        int height() const { return ascent_ + descent_; }
-       ///
+       /// width of this cell
        int width() const { return width_; }
        /// do we cover point(x, y)?
        bool covers(int x, int y) const;
+       /// bounding box of this cell
+       void boundingBox(int & xlow, int & xhigh, int & ylow, int & yhigh);
+       /// find best position to do things
+       //void findPos(PosFinder &) const;
 
-       ///
+       /// begin iterator of the underlying MathArray
        const_iterator begin() const { return data_.begin(); }
-       ///
+       /// end iterator of the underlying MathArray
        const_iterator end() const { return data_.end(); }
        
 public:
-       ///
+       /// the underlying MathArray
        MathArray data_;
-       ///
+       /// cached width of cell
        mutable int width_;
-       ///
+       /// cached ascent of cell
        mutable int ascent_;
-       ///
+       /// cached descent of cell
        mutable int descent_;
-       ///
+       /// cached x coordinate of last drawing
        mutable int xo_;
-       ///
+       /// cached y coordinate of last drawing
        mutable int yo_;
-       ///
+       /// cache size information of last drawing
        mutable MathMetricsInfo size_;
 };
 
+/// output cell on a stream
 std::ostream & operator<<(std::ostream & os, MathXArray const & ar);
 
 #endif