#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"
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());
}
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());
// 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;
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()));
}
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
}
-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");
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();
void MathCursor::macroModeClose()
{
- MathUnknownInset * p = inMacroMode();
- if (!p)
+ if (!inMacroMode())
return;
+ MathUnknownInset * p = activeMacro();
p->finalize();
string s = p->name();
--pos();
string MathCursor::macroName() const
{
- return inMacroMode() ? inMacroMode()->name() : string();
+ return inMacroMode() ? activeMacro()->name() : string();
}
}
-
void MathCursor::drawSelection(MathPainterInfo & pi) const
{
if (!selection_)
}
-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_;
}
-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;
}
}
-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();
}
// 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())
}
-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;
}
-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;
// 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
// 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());
// try right
if (hasNextAtom()) {
- MathScriptInset * p = nextAtom()->asScriptInset();
+ MathScriptInset const * p = nextAtom()->asScriptInset();
if (p && p->has(up)) {
push(nextAtom());
idx() = up;
}
-bool MathCursor::idxLineFirst()
-{
- idx() -= idx() % par()->ncols();
- pos() = 0;
- return true;
-}
-
-
bool MathCursor::idxLineLast()
{
idx() -= idx() % par()->ncols();
//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;
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);
// Hack to get \\^ and \\_ working
if (inMacroMode() && macroName() == "\\") {
if (up)
- interpret("\\mathcircumflex");
+ niceInsert(createMathInset("mathcircumflex"));
else
interpret('_');
return true;
idx() = up;
pos() = 0;
} else if (hasPrevAtom() && prevAtom()->asScriptInset()) {
- prevAtom()->asScriptInset()->ensure(up);
+ prevAtom().nucleus()->asScriptInset()->ensure(up);
pushRight(prevAtom());
idx() = up;
pos() = size();
pos() = 0;
} else {
plainInsert(MathAtom(new MathScriptInset(up)));
- prevAtom()->asScriptInset()->ensure(up);
+ prevAtom().nucleus()->asScriptInset()->ensure(up);
pushRight(prevAtom());
idx() = up;
pos() = 0;
--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 {
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;
}
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;
}
return true;
}
if (hasPrevAtom() && prevAtom()->asSpaceInset()) {
- prevAtom()->asSpaceInset()->incSpace();
+ prevAtom().nucleus()->asSpaceInset()->incSpace();
return true;
}
if (popRight())
}
if (c == '%') {
- insert(createMathInset("%"));
+ niceInsert(MathAtom(new MathCommentInset));
return true;
}
{
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();
}
}
}
-
-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;
}