]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/math_cursor.C
updates to latexfeatures stuff; allow empty \document_path
[lyx.git] / src / mathed / math_cursor.C
index 309ed06d167035ecaeee66a5623077978907acda..e54922cae0898837ea7d06d86854bba7785278ca 100644 (file)
  *   the GNU General Public Licence version 2 or later.
  */
 
+#include <config.h>
+
 #ifdef __GNUG__
 #pragma implementation
 #endif
 
-#include <config.h>
-#include <algorithm>
-#include <cctype>
-
 #include "support/lstrings.h"
 #include "support/LAssert.h"
 #include "debug.h"
 #include "LColor.h"
 #include "Painter.h"
+#include "math_cursor.h"
 #include "formulabase.h"
 #include "math_arrayinset.h"
 #include "math_braceinset.h"
+#include "math_boxinset.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"
@@ -46,6 +45,9 @@
 #include "math_specialcharinset.h"
 #include "math_support.h"
 
+#include <algorithm>
+#include <cctype>
+
 #define FILEDEBUG 0
 
 using std::endl;
@@ -58,19 +60,47 @@ namespace {
 
 struct Selection
 {
+       typedef MathInset::col_type col_type;
+       typedef MathInset::row_type row_type;
+       typedef MathInset::idx_type idx_type;
+
+       Selection()
+               : data_(1, 1)
+       {}
+
+       void region(MathCursorPos const & i1, MathCursorPos const & i2,
+               row_type & r1, row_type & r2, col_type & c1, col_type & c2)
+       {
+               MathInset * p = i1.par_;
+               c1 = p->col(i1.idx_);
+               c2 = p->col(i2.idx_);
+               if (c1 > c2)
+                       std::swap(c1, c2);
+               r1 = p->row(i1.idx_);
+               r2 = p->row(i2.idx_);
+               if (r1 > r2)
+                       std::swap(r1, r2);
+       }
+
        void grab(MathCursor const & cursor)
        {
-               data_.clear();
                MathCursorPos i1;
                MathCursorPos i2;
                cursor.getSelection(i1, i2); 
-               if (i1.idx_ == i2.idx_)
-                       data_.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
-               else {
-                       std::vector<MathInset::idx_type> indices =
-                               i1.par_->nucleus()->idxBetween(i1.idx_, i2.idx_);
-                       for (MathInset::idx_type i = 0; i < indices.size(); ++i)
-                               data_.push_back(i1.cell(indices[i]));
+               // shouldn'tt we assert on i1.par_ == i2.par_?
+               if (i1.idx_ == i2.idx_) {
+                       data_ = MathGridInset(1, 1);
+                       data_.cell(0) = MathArray(i1.cell(), i1.pos_, i2.pos_);
+               } else {
+                       row_type r1, r2;
+                       col_type c1, c2;
+                       region(i1, i2, r1, r2, c1, c2); 
+                       data_ = MathGridInset(c2 - c1 + 1, r2 - r1 + 1);
+                       for (row_type row = 0; row < data_.nrows(); ++row) 
+                               for (col_type col = 0; col < data_.ncols(); ++col) {
+                                       idx_type i = i1.par_->index(row + r1, col + c1);
+                                       data_.cell(data_.index(row, col)) = i1.par_->cell(i);
+                               }
                }
        }
 
@@ -82,35 +112,51 @@ struct Selection
                if (i1.idx_ == i2.idx_)
                        i1.cell().erase(i1.pos_, i2.pos_);
                else {
-                       std::vector<MathInset::idx_type> indices =
-                               i1.par_->nucleus()->idxBetween(i1.idx_, i2.idx_);
-                       for (unsigned i = 0; i < indices.size(); ++i)
-                               i1.cell(indices[i]).erase();
+                       MathInset * p = i1.par_;
+                       row_type r1, r2;
+                       col_type c1, c2;
+                       region(i1, i2, r1, r2, c1, c2); 
+                       for (row_type row = r1; row <= r2; ++row) 
+                               for (col_type col = c1; col <= c2; ++col)
+                                       p->cell(p->index(row, col)).erase();
                }
                cursor.cursor() = i1;
        }
 
        void paste(MathCursor & cursor) const
        {
-               MathArray ar = glue();
-               cursor.paste(ar);
+               if (data_.nargs() == 1) {
+                       // single cell/part of cell
+                       cursor.insert(data_.cell(0));
+               } else {
+                       // mulitple cells
+                       idx_type idx;
+                       MathGridInset * p = cursor.enclosingGrid(idx);
+                       col_type const numcols = min(data_.ncols(), p->ncols() - p->col(idx));
+                       row_type const numrows = min(data_.nrows(), p->nrows() - p->row(idx));
+                       for (row_type row = 0; row < numrows; ++row) 
+                               for (col_type col = 0; col < numcols; ++col) {
+                                       idx_type i = p->index(row + p->row(idx), col + p->col(idx));
+                                       p->cell(i).push_back(data_.cell(data_.index(row, col)));
+                               }
+               }
        }
 
        // glues selection to one cell
        MathArray glue() const
        {
                MathArray ar;
-               for (unsigned i = 0; i < data_.size(); ++i)
-                       ar.push_back(data_[i]);
+               for (unsigned i = 0; i < data_.nargs(); ++i)
+                       ar.push_back(data_.cell(i));
                return ar;
        }
 
        void clear()
        {
-               data_.clear();
+               data_ = MathGridInset(1, 1);
        }
 
-       std::vector<MathArray> data_;
+       MathGridInset data_;
 };
 
 
@@ -122,7 +168,7 @@ Selection theSelection;
 
 
 MathCursor::MathCursor(InsetFormulaBase * formula, bool left)
-       : formula_(formula), lastcode_(LM_TC_VAR), selection_(false)
+       : formula_(formula), lastcode_(LM_TC_MIN), selection_(false)
 {
        left ? first() : last();
 }
@@ -130,11 +176,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()));
 }
 
 
@@ -160,11 +202,9 @@ bool MathCursor::popLeft()
        //cerr << "Leaving atom "; par()->write(cerr, false); cerr << " left\n";
        if (Cursor_.size() <= 1)
                return false;
-       //if (nextInset())
-       //      nextInset()->removeEmptyScripts();
+       if (par()->asScriptInset())
+               par()->asScriptInset()->removeEmptyScripts();
        Cursor_.pop_back();
-       //if (nextAtom())
-       //      nextAtom()->removeEmptyScripts();
        return true;
 }
 
@@ -174,11 +214,9 @@ bool MathCursor::popRight()
        //cerr << "Leaving atom "; par()->write(cerr, false); cerr << " right\n";
        if (Cursor_.size() <= 1)
                return false;
-       //if (nextInset())
-       //      nextInset()->removeEmptyScripts();
+       if (par()->asScriptInset())
+               par()->asScriptInset()->removeEmptyScripts();
        Cursor_.pop_back();
-       //if (nextInset())
-       //      nextInset()->removeEmptyScripts();
        posRight();
        return true;
 }
@@ -211,7 +249,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;
 }
@@ -232,7 +270,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;
@@ -262,11 +300,11 @@ bool MathCursor::left(bool sel)
        dump("Left 1");
        if (inMacroMode()) {
                macroModeClose();
-               lastcode_ = LM_TC_VAR;
+               lastcode_ = LM_TC_MIN;
                return true;
        }
        selHandle(sel);
-       lastcode_ = LM_TC_VAR;
+       lastcode_ = LM_TC_MIN;
 
        if (hasPrevAtom() && openable(prevAtom(), sel)) {
                if (prevAtom()->isHyperActive()) {
@@ -285,11 +323,11 @@ bool MathCursor::right(bool sel)
        dump("Right 1");
        if (inMacroMode()) {
                macroModeClose();
-               lastcode_ = LM_TC_VAR;
+               lastcode_ = LM_TC_MIN;
                return true;
        }
        selHandle(sel);
-       lastcode_ = LM_TC_VAR;
+       lastcode_ = LM_TC_MIN;
 
        if (hasNextAtom() && openable(nextAtom(), sel)) {
                if (nextAtom()->isHyperActive()) {
@@ -320,41 +358,34 @@ void MathCursor::last()
 }
 
 
+bool positionable(MathCursor::cursor_type const & cursor,
+                  MathCursor::cursor_type const & anchor)
+{
+       // avoid deeper nested insets when selecting
+       if (cursor.size() > anchor.size())
+               return false;
+
+       // anchor might be deeper, should have same path then
+       for (MathCursor::cursor_type::size_type i = 0; i < cursor.size(); ++i)
+               if (cursor[i].par_ != anchor[i].par_)
+                       return false;
+
+       // position should be ok.
+       return true;
+}
+
 
 void MathCursor::setPos(int x, int y)
 {
        dump("setPos 1");
-       cursor_type best_cursor;
-       double best_dist = 1e10;
-
-       MathIterator it = ibegin(formula()->par());
-       MathIterator et = iend(formula()->par());
-       for ( ; it != et; ++it) {
-               //lyxerr << "*it: " << *it << "  *et: " << *et << "\n";
-               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().nucleus() != Anchor_.back().par_->nucleus())
-                                       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();
-               }
+       bool res = bruteFind(x, y,
+               formula()->xlow(), formula()->xhigh(),
+               formula()->ylow(), formula()->yhigh());
+       if (!res) {
+               // this ccan happen on creation of "math-display"
+               dump("setPos 1.5");
+               first();
        }
-       if (best_dist < 1e10)
-               Cursor_ = best_cursor;
-       //lyxerr << "x: " << x << " y: " << y << " dist: " << best_dist << "\n";
-       lyx::Assert(Cursor_.size());
        dump("setPos 2");
 }
 
@@ -365,7 +396,7 @@ void MathCursor::home(bool sel)
        dump("home 1");
        selHandle(sel);
        macroModeClose();
-       lastcode_ = LM_TC_VAR;
+       lastcode_ = LM_TC_MIN;
        if (!par()->idxHome(idx(), pos())) 
                popLeft();
        dump("home 2");
@@ -377,7 +408,7 @@ void MathCursor::end(bool sel)
        dump("end 1");
        selHandle(sel);
        macroModeClose();
-       lastcode_ = LM_TC_VAR;
+       lastcode_ = LM_TC_MIN;
        if (!par()->idxEnd(idx(), pos()))
                popRight();
        dump("end 2");
@@ -540,28 +571,11 @@ bool MathCursor::up(bool sel)
        dump("up 1");
        macroModeClose();
        selHandle(sel);
-
-       if (!selection_) {
-               MathInset::idx_type i = 0;
-               MathInset::pos_type p = 0;
-
-               // check whether we could move into the inset
-               if (hasPrevAtom() && prevAtom()->idxLastUp(i, p)) {
-                       pushRight(prevAtom());
-                       idx() = i;
-                       pos() = p;
-                       return true;
-               }
-
-               if (hasNextAtom() && nextAtom()->idxFirstUp(i, p)) {
-                       pushLeft(nextAtom());
-                       idx() = i;
-                       pos() = p;
-                       return true;
-               }
-       }
-
-       return goUp() || selection_;
+       cursor_type save = Cursor_;
+       if (goUpDown(true))
+               return true;
+       Cursor_ = save;
+       return selection_;
 }
 
 
@@ -570,28 +584,11 @@ bool MathCursor::down(bool sel)
        dump("down 1");
        macroModeClose();
        selHandle(sel);
-
-       if (!selection_) {
-               MathInset::idx_type i = 0;
-               MathInset::pos_type p = 0;
-
-               // check whether we could move into the inset
-               if (hasPrevAtom() && prevAtom()->idxLastDown(i, p)) {
-                       pushRight(prevAtom());
-                       idx() = i;
-                       pos() = p;
-                       return true;
-               }
-
-               if (hasNextAtom() && nextAtom()->idxFirstDown(i, p)) {
-                       pushLeft(nextAtom());
-                       idx() = i;
-                       pos() = p;
-                       return true;
-               }
-       }
-
-       return goDown() || selection_;
+       cursor_type save = Cursor_;
+       if (goUpDown(false))
+               return true;
+       Cursor_ = save;
+       return selection_;
 }
 
 
@@ -620,9 +617,9 @@ void MathCursor::macroModeClose()
 }
 
 
-int MathCursor::macroNamePos() const
+MathInset::difference_type MathCursor::macroNamePos() const
 {
-       for (int i = pos() - 1; i >= 0; --i) { 
+       for (MathInset::difference_type i = pos() - 1; i >= 0; --i) { 
                MathAtom & p = array().at(i);
                if (p->code() == LM_TC_TEX && p->getChar() == '\\')
                        return i;
@@ -634,7 +631,8 @@ int MathCursor::macroNamePos() const
 string MathCursor::macroName() const
 {
        string s;
-       for (int i = macroNamePos(); i >= 0 && i < int(pos()); ++i) 
+       MathInset::difference_type i = macroNamePos(); 
+       for ( ; i >= 0 && i < int(pos()); ++i) 
                s += array().at(i)->getChar();
        return s;
 }
@@ -742,7 +740,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();
@@ -811,9 +809,9 @@ void MathCursor::getPos(int & x, int & y)
 }
 
 
-MathAtom & MathCursor::par() const
+MathInset * MathCursor::par() const
 {
-       return *cursor().par_;
+       return cursor().par_;
 }
 
 
@@ -861,8 +859,8 @@ 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();
+       for (MathInset::difference_type i = Cursor_.size() - 1; i >= 0; --i) {
+               MathGridInset * p = Cursor_[i].par_->asGridInset();
                if (p) {
                        idx = Cursor_[i].idx_;
                        return p;
@@ -899,30 +897,34 @@ void MathCursor::pullArg(bool goright)
 }
 
 
-void MathCursor::normalize() const
+void MathCursor::normalize()
 {
-#ifdef WITH_WARNINGS
-#warning This is evil!
-#endif
-       MathCursor * it = const_cast<MathCursor *>(this);
+       // rebreak
+       {
+               MathIterator it = ibegin(formula()->par().nucleus());
+               MathIterator et = iend(formula()->par().nucleus());
+               for ( ; it != et; ++it) 
+                       if (it.par()->asBoxInset())
+                               it.par()->asBoxInset()->rebreak();
+       }
 
        if (idx() >= par()->nargs()) {
                lyxerr << "this should not really happen - 1: "
                       << idx() << " " << par()->nargs() << "\n";
                dump("error 2");
        }
-       it->idx() = min(idx(), par()->nargs() - 1);
+       idx() = min(idx(), par()->nargs() - 1);
 
        if (pos() > size()) {
                lyxerr << "this should not really happen - 2: "
-                       << pos() << " " << size() <<  " in idx: " << it->idx()
+                       << pos() << " " << size() <<  " in idx: " << idx()
                        << " in atom: '";
                WriteStream wi(lyxerr, false);
-               it->par()->write(wi);
+               par()->write(wi);
                lyxerr << "\n";
                dump("error 4");
        }
-       it->pos() = min(pos(), size());
+       pos() = min(pos(), size());
 }
 
 
@@ -934,13 +936,13 @@ MathCursor::size_type MathCursor::size() const
 
 MathCursor::col_type MathCursor::hullCol() const
 {
-       return Cursor_[0].par_->nucleus()->asGridInset()->col(Cursor_[0].idx_);
+       return Cursor_[0].par_->asGridInset()->col(Cursor_[0].idx_);
 }
 
 
 MathCursor::row_type MathCursor::hullRow() const
 {
-       return Cursor_[0].par_->nucleus()->asGridInset()->row(Cursor_[0].idx_);
+       return Cursor_[0].par_->asGridInset()->row(Cursor_[0].idx_);
 }
 
 
@@ -1120,71 +1122,66 @@ MathCursorPos const & MathCursor::cursor() const
 }
 
 
-bool MathCursor::goUp()
+bool MathCursor::goUpDown(bool up)
 {
-       // first ask the inset if it knows better then we
-       if (par()->idxUp(idx(), pos())) {
-               //lyxerr << "ask cell\n";
-               int xlow, xhigh, ylow, yhigh;
-               xarray().boundingBox(xlow, xhigh, ylow, yhigh);
-               bruteFind(xlow, xhigh, ylow, yhigh);
-               return true;
-       }
-
-       // if not, apply brute force.
-       //lyxerr << "brute force\n";
-       return
-               bruteFind(
-                       formula()->xlow(),
-                       formula()->xhigh(),
-                       formula()->ylow(),
-                       xarray().yo() - 4 - xarray().ascent()
-               );
-}
+       int xlow, xhigh, ylow, yhigh;
 
+  int xo, yo;
+       getPos(xo, yo);
 
-bool MathCursor::goDown()
-{
-       // first ask the inset if it knows better then we
-       if (par()->idxDown(idx(), pos())) {
-               //lyxerr << "ask cell\n";
-               int xlow, xhigh, ylow, yhigh;
-               xarray().boundingBox(xlow, xhigh, ylow, yhigh);
-               bruteFind(xlow, xhigh, ylow, yhigh);
+       // try current cell first
+       xarray().boundingBox(xlow, xhigh, ylow, yhigh);
+       if (up)
+               yhigh = yo - 4;
+       else
+               ylow = yo + 4;
+       if (bruteFind(xo, yo, xlow, xhigh, ylow, yhigh))
                return true;
-       }
 
-       // if not, apply brute force.
-       //lyxerr << "brute force\n";
-       return
-               bruteFind(
-                       formula()->xlow(),
-                       formula()->xhigh(),
-                       xarray().yo() + 4 + xarray().descent(),
-                       formula()->yhigh()
-               );
+       // try to find an inset that knows better then we
+       while (1) {
+               // we found a cell that think something "below" us.
+               if (up) {
+                       if (par()->idxUp(idx()))
+                               break;
+               } else {
+                       if (par()->idxDown(idx()))
+                               break;
+               }
+
+               if (!popLeft()) {
+                       // no such inset found, just take something "above"
+                       return
+                               bruteFind(xo, yo,
+                                       formula()->xlow(),
+                                       formula()->xhigh(),
+                                       up ? formula()->ylow() : yo + 4,
+                                       up ? yo - 4 : formula()->yhigh()
+                               );
+               }
+       }
+       xarray().boundingBox(xlow, xhigh, ylow, yhigh);
+       bruteFind(xo, yo, xlow, xhigh, ylow, yhigh);
+       return true;
 }
 
 
-bool MathCursor::bruteFind(int xlow, int xhigh, int ylow, int yhigh)
+bool MathCursor::bruteFind(int x, int y, int xlow, int xhigh, int ylow, int yhigh)
 {
-       int x;
-       int y;
-       getPos(x, y);
-       //lyxerr << "looking at range: "
-       //      << "[" << xlow << "..." << xhigh << "]" 
-       //      << " x [" << ylow << "..." << yhigh << "]"
-       //      << "   xo: " << x << "  yo: " << y << "\n";
-
        cursor_type best_cursor;
        double best_dist = 1e10;
 
-       MathIterator it = ibegin(formula()->par());
-       MathIterator et = iend(formula()->par());
+       MathIterator it = ibegin(formula()->par().nucleus());
+       MathIterator et = iend(formula()->par().nucleus());
        for ( ; it != et; ++it) {
+               // avoid invalid nesting hen selecting
+               if (selection_ && !positionable(it.cursor(), Anchor_))
+                       continue;
                int xo = it.position().xpos();
                int yo = it.position().ypos();
-               if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
+               if (xlow - 2 <= xo && xo <= xhigh + 2 &&
+                   ylow - 2 <= yo && yo <= yhigh + 2)
+               {
                        double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
                        if (d < best_dist) {
                                best_dist   = d;
@@ -1260,7 +1257,7 @@ bool MathCursor::interpret(string const & s)
 
        if (s == "\\over" || s == "\\choose" || s == "\\atop") {
                MathArray ar = array();
-               MathAtom t = createMathInset(s.substr(1));
+               MathAtom t(createMathInset(s.substr(1)));
                t->asNestInset()->cell(0).swap(array());
                pos() = 0;
                niceInsert(t);
@@ -1280,35 +1277,37 @@ bool MathCursor::interpret(string const & s)
 }
 
 
-bool MathCursor::interpret(char c)
+bool MathCursor::script(bool up)
 {
-       //lyxerr << "interpret 2: '" << c << "'\n";
-       if (c == '^' || c == '_') {
-               macroModeClose();
-               const bool up = (c == '^');
-               selCut();
-               if (hasPrevAtom() && prevAtom()->asScriptInset()) {
-                       prevAtom()->asScriptInset()->ensure(up);
-                       pushRight(prevAtom());
-                       idx() = up;
-                       pos() = size();
-               } else if (hasNextAtom() && nextAtom()->asScriptInset()) {
-                       nextAtom()->asScriptInset()->ensure(up);
-                       pushLeft(nextAtom());
-                       idx() = up;
-                       pos() = 0;
-               } else {
-                       plainInsert(MathAtom(new MathScriptInset(up)));
-                       prevAtom()->asScriptInset()->ensure(up);
-                       pushRight(prevAtom());
-                       idx() = up;
-                       pos() = 0;
-               }
-               selPaste();
-               dump("1");
-               return true;
+       macroModeClose();
+       selCut();
+       if (hasPrevAtom() && prevAtom()->asScriptInset()) {
+               prevAtom()->asScriptInset()->ensure(up);
+               pushRight(prevAtom());
+               idx() = up;
+               pos() = size();
+       } else if (hasNextAtom() && nextAtom()->asScriptInset()) {
+               nextAtom()->asScriptInset()->ensure(up);
+               pushLeft(nextAtom());
+               idx() = up;
+               pos() = 0;
+       } else {
+               plainInsert(MathAtom(new MathScriptInset(up)));
+               prevAtom()->asScriptInset()->ensure(up);
+               pushRight(prevAtom());
+               idx() = up;
+               pos() = 0;
        }
+       selPaste();
+       dump("1");
+       return true;
+}
+
+
+bool MathCursor::interpret(char c)
+{
 
+       // Removed super/subscript handling from here  to ::script -MV
 
        // handle macroMode
        if (inMacroMode()) {
@@ -1346,13 +1345,17 @@ bool MathCursor::interpret(char c)
                return true;
        }
 
-       if (selection_)
+       if (selection_) {
                selClear();
+               if (c == ' ')
+                       return true;
+               // fall through in the other cases
+       }
 
-       if (lastcode_ == LM_TC_TEXTRM) {
-               // suppress direct insertion of to spaces in a row
+       if (lastcode_ == LM_TC_TEXTRM || par()->asBoxInset()) {
+               // suppress direct insertion of two spaces in a row
                // the still allows typing  '<space>a<space>' and deleting the 'a', but
-               // it is better than nothing
+               // it is better than nothing...
                if (c == ' ' && hasPrevAtom() && prevAtom()->getChar() == ' ')
                        return true;
                insert(c, LM_TC_TEXTRM);
@@ -1364,10 +1367,8 @@ bool MathCursor::interpret(char c)
                        prevAtom()->asSpaceInset()->incSpace();
                        return true;
                }
-       
-               if (mathcursor->popRight())
+               if (popRight())
                        return true;
-
                // if are at the very end, leave the formula
                return pos() != size();
        }
@@ -1412,7 +1413,7 @@ bool MathCursor::interpret(char c)
        }
 
        // no special circumstances, so insert the character without any fuss
-       insert(c, lastcode_);
+       insert(c, lastcode_ == LM_TC_MIN ? MathCharInset::nativeCode(c) : lastcode_);
        lastcode_ = LM_TC_MIN;
        return true;
 }
@@ -1421,7 +1422,12 @@ bool MathCursor::interpret(char c)
 
 MathCursorPos MathCursor::normalAnchor() const
 {
-       lyx::Assert(Anchor_.size() >= Cursor_.size());
+       if (Anchor_.size() < Cursor_.size()) {
+               Anchor_ = Cursor_;
+               lyxerr << "unusual Anchor size\n";
+               dump("1");
+       }
+       //lyx::Assert(Anchor_.size() >= Cursor_.size());
        // use Anchor on the same level as Cursor
        MathCursorPos normal = Anchor_[Cursor_.size() - 1];
        if (Cursor_.size() < Anchor_.size() && !(normal < cursor())) {
@@ -1447,3 +1453,10 @@ void MathCursor::stripFromLastEqualSign()
 }
 
 
+void MathCursor::setSelection(cursor_type const & where, size_type n)
+{
+       selection_ = true;
+       Anchor_ = where;
+       Cursor_ = where;
+       cursor().pos_ += n;
+}