]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/math_cursor.C
try to correct x position where curosr drops of inset.
[lyx.git] / src / mathed / math_cursor.C
index cc011e635963b12a55cbe2c6416ffaa111463e6f..6a371a2a9b121baa0c54a7a1e87c38fa037328db 100644 (file)
 #include "frontends/Painter.h"
 #include "math_cursor.h"
 #include "formulabase.h"
+#include "funcrequest.h"
 #include "math_autocorrect.h"
 #include "math_arrayinset.h"
 #include "math_braceinset.h"
-#include "math_casesinset.h"
+#include "math_commentinset.h"
 #include "math_charinset.h"
 #include "math_extern.h"
 #include "math_factory.h"
@@ -91,7 +92,7 @@ void MathCursor::push(MathAtom & t)
 
 void MathCursor::pushLeft(MathAtom & t)
 {
-       //cerr << "Entering atom "; t->write(cerr, false); cerr << " left\n";
+       //lyxerr << "Entering atom " << t << " left\n";
        push(t);
        t->idxFirst(idx(), pos());
 }
@@ -99,7 +100,7 @@ void MathCursor::pushLeft(MathAtom & t)
 
 void MathCursor::pushRight(MathAtom & t)
 {
-       //cerr << "Entering atom "; t->write(cerr, false); cerr << " right\n";
+       //lyxerr << "Entering atom " << t << " right\n";
        posLeft();
        push(t);
        t->idxLast(idx(), pos());
@@ -174,7 +175,7 @@ bool MathCursor::openable(MathAtom const & t, bool sel) const
                // we can't move into anything new during selection
                if (depth() == Anchor_.size())
                        return false;
-               if (t.nucleus() != Anchor_[depth()].par_)
+               if (t.operator->() != Anchor_[depth()].par_)
                        return false;
        }
        return true;
@@ -411,31 +412,10 @@ void MathCursor::paste(MathArray const & ar)
 
 void MathCursor::paste(MathGridInset const & data)
 {
-       if (data.nargs() == 1) {
-               // single cell/part of cell
-               paste(data.cell(0));
-       } else {
-               // multiple cells
-               idx_type idx; // index of upper left cell
-               MathGridInset * p = 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).append(data.cell(data.index(row, col)));
-                       }
-                       // append the left over horizontal cells to the last column
-                       idx_type i = p->index(row + p->row(idx), p->ncols() - 1);
-                       for (MathInset::col_type col = numcols; col < data.ncols(); ++col)
-                               p->cell(i).append(data.cell(data.index(row, col)));
-               }
-               // append the left over vertical cells to the last _cell_
-               idx_type i = p->nargs() - 1;
-               for (row_type row = numrows; row < data.nrows(); ++row)
-                       for (col_type col = 0; col < data.ncols(); ++col)
-                               p->cell(i).append(data.cell(data.index(row, col)));
-       }
+       ostringstream os;
+  WriteStream wi(os, false, false);
+  data.write(wi);
+       dispatch(FuncRequest(LFUN_PASTE, os.str()));
 }
 
 
@@ -452,6 +432,14 @@ void MathCursor::backspace()
                return;
        }
 
+       if (inMacroMode()) {
+               MathUnknownInset * p = activeMacro();
+               if (p->name().size() > 1) {
+                       p->setName(p->name().substr(0, p->name().size() - 1));
+                       return;
+               }
+       }
+
 /*
        if (prevAtom()->asScriptInset()) {
                // simply enter nucleus
@@ -520,30 +508,6 @@ void MathCursor::erase()
 }
 
 
-void MathCursor::delLine()
-{
-       autocorrect_ = false;
-       macroModeClose();
-
-       if (selection_) {
-               selDel();
-               return;
-       }
-
-       if (par()->nrows() > 1) {
-               // grid are the only things with more than one row...
-               lyx::Assert(par()->asGridInset());
-               par()->asGridInset()->delRow(hullRow());
-       }
-
-       if (idx() >= par()->nargs())
-               idx() = par()->nargs() - 1;
-
-       if (pos() > size())
-               pos() = size();
-}
-
-
 bool MathCursor::up(bool sel)
 {
        dump("up 1");
@@ -574,11 +538,9 @@ bool MathCursor::down(bool sel)
 
 bool MathCursor::toggleLimits()
 {
-       if (!hasNextAtom())
-               return false;
-       MathScriptInset * t = nextAtom()->asScriptInset();
-       if (!t)
+       if (!hasNextAtom() || !nextAtom()->asScriptInset())
                return false;
+       MathScriptInset * t = nextAtom().nucleus()->asScriptInset();
        int old = t->limits();
        t->limits(old < 0 ? 1 : -1);
        return old != t->limits();
@@ -587,9 +549,9 @@ bool MathCursor::toggleLimits()
 
 void MathCursor::macroModeClose()
 {
-       MathUnknownInset * p = inMacroMode();
-       if (!p)
+       if (!inMacroMode())
                return;
+       MathUnknownInset * p = activeMacro();
        p->finalize();
        string s = p->name();
        --pos();
@@ -601,7 +563,7 @@ void MathCursor::macroModeClose()
 
 string MathCursor::macroName() const
 {
-       return inMacroMode() ? inMacroMode()->name() : string();
+       return inMacroMode() ? activeMacro()->name() : string();
 }
 
 
@@ -688,7 +650,6 @@ void MathCursor::selGet(MathArray & ar)
 }
 
 
-
 void MathCursor::drawSelection(MathPainterInfo & pi) const
 {
        if (!selection_)
@@ -700,20 +661,31 @@ void MathCursor::drawSelection(MathPainterInfo & pi) const
 }
 
 
-void MathCursor::handleNest(MathAtom const & at)
+void MathCursor::handleNest(MathAtom const & a)
 {
-       at->cell(0) = grabAndEraseSelection().glue();
+       MathAtom at = a;
+       at.nucleus()->cell(0) = grabAndEraseSelection().glue();
        insert(at);
        pushRight(prevAtom());
 }
 
 
-void MathCursor::getPos(int & x, int & y)
+void MathCursor::getPos(int & x, int & y) const
 {
        par()->getPos(idx(), pos(), x, y);
 }
 
 
+int MathCursor::targetX() const
+{
+       if (targetx_ != -1)
+               return targetx_;
+       int x = 0, y = 0;
+       getPos(x, y);
+       return x;
+}
+
+
 MathInset * MathCursor::par() const
 {
        return cursor().par_;
@@ -750,12 +722,24 @@ MathCursor::pos_type & MathCursor::pos()
 }
 
 
-MathUnknownInset * MathCursor::inMacroMode() const
+bool MathCursor::inMacroMode() const
 {
        if (!hasPrevAtom())
-               return 0;
-       MathUnknownInset * p = prevAtom()->asUnknownInset();
-       return (p && !p->final()) ? p : 0;
+               return false;
+       MathUnknownInset const * p = prevAtom()->asUnknownInset();
+       return p && !p->final();
+}
+
+
+MathUnknownInset * MathCursor::activeMacro()
+{
+       return inMacroMode() ? prevAtom().nucleus()->asUnknownInset() : 0;
+}
+
+
+MathUnknownInset const * MathCursor::activeMacro() const
+{
+       return inMacroMode() ? prevAtom()->asUnknownInset() : 0;
 }
 
 
@@ -784,16 +768,10 @@ MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
 }
 
 
-MathHullInset * MathCursor::enclosingHull(MathCursor::idx_type & idx) const
+void MathCursor::popToHere(MathInset const * p)
 {
-       for (MathInset::difference_type i = depth() - 1; i >= 0; --i) {
-               MathHullInset * p = Cursor_[i].par_->asHullInset();
-               if (p) {
-                       idx = Cursor_[i].idx_;
-                       return p;
-               }
-       }
-       return 0;
+       while (depth() && Cursor_.back().par_ != p)
+               Cursor_.pop_back();
 }
 
 
@@ -857,7 +835,7 @@ void MathCursor::normalize()
        // remove empty scripts if possible
        if (1) {
                for (pos_type i = 0; i < size(); ++i) {
-                       MathScriptInset * p = array()[i]->asScriptInset();
+                       MathScriptInset * p = array()[i].nucleus()->asScriptInset();
                        if (p) {
                                p->removeEmptyScripts();
                                //if (p->empty())
@@ -877,22 +855,6 @@ MathCursor::size_type MathCursor::size() const
 }
 
 
-MathCursor::col_type MathCursor::hullCol() const
-{
-       idx_type idx = 0;
-       MathHullInset * p = enclosingHull(idx);
-       return p->col(idx);
-}
-
-
-MathCursor::row_type MathCursor::hullRow() const
-{
-       idx_type idx = 0;
-       MathHullInset * p = enclosingHull(idx);
-       return p->row(idx);
-}
-
-
 bool MathCursor::hasPrevAtom() const
 {
        return pos() > 0;
@@ -963,57 +925,6 @@ void MathCursor::idxPrev()
 }
 
 
-void MathCursor::splitCell()
-{
-       if (idx() + 1 == par()->nargs())
-               return;
-       MathArray ar = array();
-       ar.erase(0, pos());
-       array().erase(pos(), size());
-       ++idx();
-       pos() = 0;
-       array().insert(0, ar);
-}
-
-
-void MathCursor::breakLine()
-{
-       // leave inner cells
-       while (popRight())
-               ;
-
-       idx_type dummy;
-       MathHullInset * p = enclosingHull(dummy);
-       if (!p)
-               return;
-
-       if (p->getType() == "simple" || p->getType() == "equation") {
-               p->mutate("eqnarray");
-               idx() = 1;
-               pos() = 0;
-       } else {
-               p->addRow(hullRow());
-
-               // split line
-               const row_type r = hullRow();
-               for (col_type c = hullCol() + 1; c < p->ncols(); ++c)
-                       std::swap(p->cell(p->index(r, c)), p->cell(p->index(r + 1, c)));
-
-               // split cell
-               splitCell();
-               std::swap(p->cell(idx()), p->cell(idx() + p->ncols() - 1));
-       }
-}
-
-
-//void MathCursor::readLine(MathArray & ar) const
-//{
-//     idx_type base = row() * par()->ncols();
-//     for (idx_type off = 0; off < par()->ncols(); ++off)
-//             ar.push_back(par()->cell(base + off));
-//}
-
-
 char MathCursor::valign() const
 {
        idx_type idx;
@@ -1062,7 +973,8 @@ bool MathCursor::goUpDown(bool up)
        // Be warned: The 'logic' implemented in this function is highly fragile.
        // A distance of one pixel or a '<' vs '<=' _really_ matters.
        // So fiddle around with it only if you know what you are doing!
-  int xo, yo;
+  int xo = 0;
+       int yo = 0;
        getPos(xo, yo);
 
        // check if we had something else in mind, if not, this is the future goal
@@ -1074,7 +986,7 @@ bool MathCursor::goUpDown(bool up)
        // try neigbouring script insets
        // try left
        if (hasPrevAtom()) {
-               MathScriptInset * p = prevAtom()->asScriptInset();
+               MathScriptInset const * p = prevAtom()->asScriptInset();
                if (p && p->has(up)) {
                        --pos();
                        push(nextAtom());
@@ -1087,7 +999,7 @@ bool MathCursor::goUpDown(bool up)
 
        // try right
        if (hasNextAtom()) {
-               MathScriptInset * p = nextAtom()->asScriptInset();
+               MathScriptInset const * p = nextAtom()->asScriptInset();
                if (p && p->has(up)) {
                        push(nextAtom());
                        idx() = up;
@@ -1170,14 +1082,6 @@ bool MathCursor::bruteFind
 }
 
 
-bool MathCursor::idxLineFirst()
-{
-       idx() -= idx() % par()->ncols();
-       pos() = 0;
-       return true;
-}
-
-
 bool MathCursor::idxLineLast()
 {
        idx() -= idx() % par()->ncols();
@@ -1208,15 +1112,6 @@ bool MathCursor::interpret(string const & s)
        //owner_->getIntl()->getTransManager().TranslateAndInsert(s[0], lt);
        //lyxerr << "trans: '" << s[0] << "'  int: " << int(s[0]) << endl;
 
-       if (s.size() >= 5 && s.substr(0, 5) == "cases") {
-               unsigned int n = 1;
-               istringstream is(s.substr(5).c_str());
-               is >> n;
-               n = max(1u, n);
-               niceInsert(MathAtom(new MathCasesInset(n)));
-               return true;
-       }
-
        if (s.size() >= 6 && s.substr(0, 6) == "matrix") {
                unsigned int m = 1;
                unsigned int n = 1;
@@ -1247,7 +1142,7 @@ bool MathCursor::interpret(string const & s)
 
        if (name == "over" || name == "choose" || name == "atop") {
                MathAtom t(createMathInset(name));
-               t->asNestInset()->cell(0) = array();
+               t.nucleus()->asNestInset()->cell(0) = array();
                array().clear();
                pos() = 0;
                niceInsert(t);
@@ -1274,7 +1169,7 @@ bool MathCursor::script(bool up)
        // Hack to get \\^ and \\_ working
        if (inMacroMode() && macroName() == "\\") {
                if (up)
-                       interpret("\\mathcircumflex");
+                       niceInsert(createMathInset("mathcircumflex"));
                else
                        interpret('_');
                return true;
@@ -1288,7 +1183,7 @@ bool MathCursor::script(bool up)
                idx() = up;
                pos() = 0;
        } else if (hasPrevAtom() && prevAtom()->asScriptInset()) {
-               prevAtom()->asScriptInset()->ensure(up);
+               prevAtom().nucleus()->asScriptInset()->ensure(up);
                pushRight(prevAtom());
                idx() = up;
                pos() = size();
@@ -1300,7 +1195,7 @@ bool MathCursor::script(bool up)
                pos() = 0;
        } else {
                plainInsert(MathAtom(new MathScriptInset(up)));
-               prevAtom()->asScriptInset()->ensure(up);
+               prevAtom().nucleus()->asScriptInset()->ensure(up);
                pushRight(prevAtom());
                idx() = up;
                pos() = 0;
@@ -1319,7 +1214,7 @@ bool MathCursor::interpret(char c)
                --pos();
                plainErase();
                int n = c - '0';
-               MathMacroTemplate * p = formula()->par()->asMacroTemplate();
+               MathMacroTemplate const * p = formula()->par()->asMacroTemplate();
                if (p && 1 <= n && n <= p->numargs())
                        insert(MathAtom(new MathMacroArgument(c - '0')));
                else {
@@ -1334,14 +1229,8 @@ bool MathCursor::interpret(char c)
                string name = macroName();
                //lyxerr << "interpret name: '" << name << "'\n";
 
-               if (name.empty() && c == '\\') {
-                       backspace();
-                       interpret("\\backslash");
-                       return true;
-               }
-
                if (isalpha(c)) {
-                       inMacroMode()->setName(inMacroMode()->name() + c);
+                       activeMacro()->setName(activeMacro()->name() + c);
                        return true;
                }
 
@@ -1349,10 +1238,13 @@ bool MathCursor::interpret(char c)
                if (name == "\\") {
                        // remove the '\\'
                        backspace();
-                       if (c == '\\')
-                               interpret("\\backslash");
-                       else
-                               interpret(string("\\") + c);
+                       if (c == '\\') {
+                               if (currentMode() == MathInset::TEXT_MODE)
+                                       niceInsert(createMathInset("textbackslash"));
+                               else
+                                       niceInsert(createMathInset("backslash"));
+                       } else
+                               niceInsert(createMathInset(string(1, c)));
                        return true;
                }
 
@@ -1405,7 +1297,7 @@ bool MathCursor::interpret(char c)
                        return true;
                }
                if (hasPrevAtom() && prevAtom()->asSpaceInset()) {
-                       prevAtom()->asSpaceInset()->incSpace();
+                       prevAtom().nucleus()->asSpaceInset()->incSpace();
                        return true;
                }
                if (popRight())
@@ -1441,7 +1333,7 @@ bool MathCursor::interpret(char c)
        }
 
        if (c == '%') {
-               insert(createMathInset("%"));
+               niceInsert(MathAtom(new MathCommentInset));
                return true;
        }
 
@@ -1488,10 +1380,10 @@ void MathCursor::insetToggle()
 {
        if (hasNextAtom()) {
                // toggle previous inset ...
-               nextAtom()->lock(!nextAtom()->lock());
+               nextAtom().nucleus()->lock(!nextAtom()->lock());
        } else if (popLeft() && hasNextAtom()) {
                // ... or enclosing inset if we are in the last inset position
-               nextAtom()->lock(!nextAtom()->lock());
+               nextAtom().nucleus()->lock(!nextAtom()->lock());
                posRight();
        }
 }
@@ -1616,97 +1508,36 @@ MathCursorPos MathCursor::normalAnchor() const
 }
 
 
-
-void MathCursor::handleExtern(const string & arg)
-{
-       string lang;
-       string extra;
-       istringstream iss(arg.c_str());
-       iss >> lang >> extra;
-       if (extra.empty())
-               extra = "noextra";
-
-
-       if (selection()) {
-               MathArray ar;
-               selGet(ar);
-               lyxerr << "use selection: " << ar << "\n";
-               insert(pipeThroughExtern(lang, extra, ar));
-               return;
-       }
-
-       MathArray eq;
-       eq.push_back(MathAtom(new MathCharInset('=')));
-
-       popToEnclosingHull();
-
-       idx_type idx = 0;
-       MathHullInset * hull = enclosingHull(idx);
-       lyx::Assert(hull);
-       idxLineFirst();
-
-       if (hull->getType() == "simple") {
-               MathArray::size_type pos = cursor().cell().find_last(eq);
-               MathArray ar;
-               if (pos == size()) {
-                       ar = array();
-                       lyxerr << "use whole cell: " << ar << "\n";
-               } else {
-                       ar = MathArray(array().begin() + pos + 1, array().end());
-                       lyxerr << "use partial cell form pos: " << pos << "\n";
-               }
-               end();
-               insert(eq);
-               insert(pipeThroughExtern(lang, extra, ar));
-               return;
-       }
-
-       if (hull->getType() == "equation") {
-               lyxerr << "use equation inset\n";
-               hull->mutate("eqnarray");
-               MathArray & ar = cursor().cell();
-               lyxerr << "use cell: " << ar << "\n";
-               idxRight();
-               cursor().cell() = eq;
-               idxRight();
-               cursor().cell() = pipeThroughExtern(lang, extra, ar);
-               idxLineLast();
-               return;
-       }
-
-       {
-               lyxerr << "use eqnarray\n";
-               idxLineLast();
-               MathArray ar = cursor().cell();
-               lyxerr << "use cell: " << ar << "\n";
-               breakLine();
-               idxRight();
-               cursor().cell() = eq;
-               idxRight();
-               cursor().cell() = pipeThroughExtern(lang, extra, ar);
-               idxLineLast();
-       }
-
-}
-
-
-int MathCursor::dispatch(string const & cmd)
+MathInset::result_type MathCursor::dispatch(FuncRequest const & cmd)
 {
        // try to dispatch to adajcent items if they are not editable
        // actually, this should only happen for mouse clicks...
-       if (hasNextAtom() && !openable(nextAtom(), false))
-               if (int res = nextAtom()->dispatch(cmd, 0, 0))
+       idx_type d1;
+       pos_type d2;
+       if (hasNextAtom() && !openable(nextAtom(), false)) {
+               MathInset::result_type res = nextAtom().nucleus()->dispatch(cmd, d1, d2);
+               if (res != MathInset::UNDISPATCHED)
                        return res;
-       if (hasPrevAtom() && !openable(prevAtom(), false))
-               if (int res = prevAtom()->dispatch(cmd, 0, 0))
+       }
+       if (hasPrevAtom() && !openable(prevAtom(), false)) {
+               MathInset::result_type res = prevAtom().nucleus()->dispatch(cmd, d1, d2);
+               if (res != MathInset::UNDISPATCHED)
                        return res;
+       }
 
        for (int i = Cursor_.size() - 1; i >= 0; --i) {
                MathCursorPos & pos = Cursor_[i];
-               if (int res = pos.par_->dispatch(cmd, pos.idx_, pos.pos_))
+               MathInset::result_type const res
+                       = pos.par_->dispatch(cmd, pos.idx_, pos.pos_);
+               if (res != MathInset::UNDISPATCHED) {
+                       if (res == MathInset::DISPATCHED_POP) {
+                               Cursor_.shrink(i + 1);
+                               selClear();
+                       }
                        return res;
+               }
        }
-       return 0;
+       return MathInset::UNDISPATCHED;
 }