When inserting math inset over selection, place cursor better

This is a follow up to 503c7c16.

The new argument for placing cursor after insertion of inset is:
* if inset has no cell, do nothing
* otherwise, place inset in entry cell.
  + if entry cell is not empty (we pasted a selection), go to next cell
  + if this next cell does not exit, stay after the inset.
This commit is contained in:
Jean-Marc Lasgouttes 2018-11-05 21:29:22 -10:00
parent 097da3a943
commit b0937fb93e
3 changed files with 42 additions and 32 deletions

View File

@ -901,6 +901,31 @@ void Cursor::pushBackward(Inset & p)
}
void Cursor::editInsertedInset()
{
LASSERT(!empty(), return);
if (pos() == 0)
return;
InsetMath &p = prevMath();
if (!p.isActive())
return;
posBackward();
push(p);
p.idxFirst(*this);
// this could be a while() loop, but only one cell is not empty in
// cases we are interested in. The cell is not empty because we
// have inserted the selection in there.
if (!cell().empty()) {
// if it is not empty, move to the next one.
if (!inset().idxNext(*this))
// If there is no next one, exit the inset.
popForward();
}
}
bool Cursor::popBackward()
{
LASSERT(!empty(), return false);
@ -1521,14 +1546,9 @@ void Cursor::niceInsert(MathAtom const & t)
plainInsert(t);
// If possible, enter the new inset and move the contents of the selection
if (t->isActive()) {
posBackward();
// be careful here: don't use 'pushBackward(t)' as this we need to
// push the clone, not the original
pushBackward(*nextInset());
// We may not use niceInsert here (recursion)
MathData ar(buffer());
asArray(safe, ar);
insert(ar);
idx_type const idx = prevMath().asNestInset()->firstIdx();
asArray(safe, prevMath().cell(idx));
editInsertedInset();
} else if (t->asMacro() && !safe.empty()) {
MathData ar(buffer());
asArray(safe, ar);
@ -1665,20 +1685,14 @@ bool Cursor::down()
}
void Cursor::handleNest(MathAtom const & a, int c)
{
//lyxerr << "Cursor::handleNest: " << c << endl;
MathAtom t = a;
asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(c));
insert(t);
posBackward();
pushBackward(*nextInset());
}
void Cursor::handleNest(MathAtom const & a)
{
handleNest(a, a.nucleus()->asNestInset()->firstIdx());
idx_type const idx = a.nucleus()->asNestInset()->firstIdx();
//lyxerr << "Cursor::handleNest: " << idx << endl;
MathAtom t = a;
asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(idx));
insert(t);
editInsertedInset();
}

View File

@ -259,6 +259,10 @@ public:
void push(Inset & inset);
/// add a new cursor slice, place cursor at front (move backwards)
void pushBackward(Inset & inset);
/// try to put cursor in inset before it in entry cell, or next one
/// if it is not empty, or exit the slice if there is no next one.
void editInsertedInset();
/// pop one level off the cursor
void pop();
/// pop one slice off the cursor stack and go backwards
@ -517,13 +521,9 @@ public:
/// the name of the macro we are currently inputting
docstring macroName();
/// replace selected stuff with at, placing the former
// selection in entry cell of atom
void handleNest(MathAtom const & at);
/// replace selected stuff with at, placing the former
// selection in given cell of atom
void handleNest(MathAtom const & at, int cell);
/// make sure cursor position is valid
/// FIXME: It does a subset of fixIfBroken. Maybe merge them?

View File

@ -873,14 +873,10 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
// via macro mode, we want to put the cursor inside it
// if relevant. Think typing "\frac<space>".
if (c == ' '
&& cur.inMacroMode() && cur.macroName() != "\\"
&& cur.macroModeClose() && cur.pos() > 0) {
MathAtom const atom = cur.prevAtom();
if (atom->asNestInset() && atom->isActive()) {
cur.posBackward();
cur.pushBackward(*cur.nextInset());
}
} else if (!interpretChar(cur, c)) {
&& cur.inMacroMode() && cur.macroName() != "\\"
&& cur.macroModeClose() && cur.pos() > 0)
cur.editInsertedInset();
else if (!interpretChar(cur, c)) {
cmd = FuncRequest(LFUN_FINISHED_FORWARD);
cur.undispatched();
// FIXME: can we avoid skipping the end of the string?