* fixed bug #4357 when pasting a macro with script index

* fixed some other unreported bug when the cursor is not inside or near the macro during fold/unfold
 * fixed the bug that the cursor jumped into the first parameter when pasting a macro. This should only happen when the macro was entered interactively


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@21611 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Stefan Schimanski 2007-11-14 17:33:49 +00:00
parent 3ab1031f97
commit 240e59ae0d
5 changed files with 41 additions and 23 deletions

View File

@ -950,7 +950,7 @@ bool Cursor::macroModeClose()
MathMacro * atomAsMacro = atom.nucleus()->asMacro(); MathMacro * atomAsMacro = atom.nucleus()->asMacro();
if (atomAsMacro) { if (atomAsMacro) {
// make non-greedy, i.e. don't eat parameters from the right // make non-greedy, i.e. don't eat parameters from the right
atomAsMacro->setDisplayMode(MathMacro::DISPLAY_NONGREEDY_INIT); atomAsMacro->setDisplayMode(MathMacro::DISPLAY_INTERACTIVE_INIT);
} }
plainInsert(atom); plainInsert(atom);
return true; return true;

View File

@ -383,20 +383,26 @@ void MathData::updateMacros(MetricsInfo & mi)
// is it a virgin macro which was never attached to parameters? // is it a virgin macro which was never attached to parameters?
bool fromInitToNormalMode bool fromInitToNormalMode
= (oldDisplayMode == MathMacro::DISPLAY_INIT = (oldDisplayMode == MathMacro::DISPLAY_INIT
|| oldDisplayMode == MathMacro::DISPLAY_NONGREEDY_INIT) || oldDisplayMode == MathMacro::DISPLAY_INTERACTIVE_INIT)
&& newDisplayMode == MathMacro::DISPLAY_NORMAL; && newDisplayMode == MathMacro::DISPLAY_NORMAL;
bool greedy = (oldDisplayMode != MathMacro::DISPLAY_NONGREEDY_INIT);
// if the macro was entered interactively (i.e. not by paste or during
// loading), it should not be greedy, but the cursor should
// automatically jump into the macro when behind
bool interactive = (oldDisplayMode == MathMacro::DISPLAY_INTERACTIVE_INIT);
// attach parameters // attach parameters
attachMacroParameters(cur, i, macroNumArgs, macroOptionals, attachMacroParameters(cur, i, macroNumArgs, macroOptionals,
fromInitToNormalMode, greedy); fromInitToNormalMode, interactive);
// FIXME: proper anchor handling, this removes the selection // FIXME: proper anchor handling, this removes the selection
cur.updateInsets(&cur.bottom().inset()); cur.updateInsets(&cur.bottom().inset());
cur.clearSelection(); cur.clearSelection();
} }
// give macro the chance to adapt to new situation // Give macro the chance to adapt to new situation.
// The macroInset could be invalid now because it was put into a script
// inset and therefore "deep" copied. So get it again from the MathData.
InsetMath * inset = operator[](i).nucleus(); InsetMath * inset = operator[](i).nucleus();
if (inset->asScriptInset()) if (inset->asScriptInset())
inset = inset->asScriptInset()->nuc()[0].nucleus(); inset = inset->asScriptInset()->nuc()[0].nucleus();
@ -477,6 +483,10 @@ void MathData::detachMacroParameters(Cursor & cur, const size_type macroPos)
insert(p, optarg); insert(p, optarg);
p += optarg.size(); p += optarg.size();
// cursor in macro?
if (curMacroSlice == -1)
continue;
// cursor in optional argument of macro? // cursor in optional argument of macro?
if (curMacroIdx == j) { if (curMacroIdx == j) {
if (brace) { if (brace) {
@ -491,13 +501,17 @@ void MathData::detachMacroParameters(Cursor & cur, const size_type macroPos)
} }
// put them back into the MathData // put them back into the MathData
for (; j < detachedArgs.size(); ++j) { for (; j < detachedArgs.size(); ++j, ++p) {
MathData const & arg = detachedArgs[j]; MathData const & arg = detachedArgs[j];
if (arg.size() == 1 && !arg[0]->asScriptInset()) // && arg[0]->asCharInset()) if (arg.size() == 1 && !arg[0]->asScriptInset()) // && arg[0]->asCharInset())
insert(p, arg[0]); insert(p, arg[0]);
else else
insert(p, MathAtom(new InsetMathBrace(arg))); insert(p, MathAtom(new InsetMathBrace(arg)));
// cursor in macro?
if (curMacroSlice == -1)
continue;
// cursor in j-th argument of macro? // cursor in j-th argument of macro?
if (curMacroIdx == j) { if (curMacroIdx == j) {
if (operator[](p).nucleus()->asBraceInset()) { if (operator[](p).nucleus()->asBraceInset()) {
@ -510,8 +524,6 @@ void MathData::detachMacroParameters(Cursor & cur, const size_type macroPos)
} }
} else if (cur[curMacroSlice - 1].pos() >= int(p)) } else if (cur[curMacroSlice - 1].pos() >= int(p))
++cur[curMacroSlice - 1].pos(); ++cur[curMacroSlice - 1].pos();
++p;
} }
// FIXME: proper anchor handling, this removes the selection // FIXME: proper anchor handling, this removes the selection
@ -523,29 +535,28 @@ void MathData::detachMacroParameters(Cursor & cur, const size_type macroPos)
void MathData::attachMacroParameters(Cursor & cur, void MathData::attachMacroParameters(Cursor & cur,
const size_type macroPos, const size_type macroNumArgs, const size_type macroPos, const size_type macroNumArgs,
const int macroOptionals, const bool fromInitToNormalMode, const int macroOptionals, const bool fromInitToNormalMode,
const bool greedy) const bool interactiveInit)
{ {
MathMacro * macroInset = operator[](macroPos).nucleus()->asMacro(); MathMacro * macroInset = operator[](macroPos).nucleus()->asMacro();
// start at atom behind the macro again, maybe with some new arguments from above // start at atom behind the macro again, maybe with some new arguments
// to add them back into the macro inset // from the detach phase above, to add them back into the macro inset
size_t p = macroPos + 1; size_t p = macroPos + 1;
std::vector<MathData> detachedArgs; std::vector<MathData> detachedArgs;
MathAtom scriptToPutAround; MathAtom scriptToPutAround;
// find cursor slice again // find cursor slice again of this MathData
int thisSlice = cur.find(*this); int thisSlice = cur.find(*this);
int thisPos = -1; int thisPos = -1;
if (thisSlice != -1) if (thisSlice != -1)
thisPos = cur[thisSlice].pos(); thisPos = cur[thisSlice].pos();
// find arguments behind the macro // find arguments behind the macro
if (greedy) { if (!interactiveInit) {
collectOptionalParameters(cur, macroOptionals, detachedArgs, p, collectOptionalParameters(cur, macroOptionals, detachedArgs, p,
macroPos, thisPos, thisSlice); macroPos, thisPos, thisSlice);
collectParameters(cur, macroNumArgs, detachedArgs, p, collectParameters(cur, macroNumArgs, detachedArgs, p,
scriptToPutAround, scriptToPutAround, macroPos, thisPos, thisSlice);
macroPos, thisPos, thisSlice);
} }
// attach arguments back to macro inset // attach arguments back to macro inset
@ -558,15 +569,20 @@ void MathData::attachMacroParameters(Cursor & cur,
= operator[](macroPos); = operator[](macroPos);
operator[](macroPos) = scriptToPutAround; operator[](macroPos) = scriptToPutAround;
// go into the script inset nucleus
if (thisPos == int(macroPos)) if (thisPos == int(macroPos))
cur.append(0, 0); cur.append(0, 0);
// get pointer to "deep" copied macro inset
InsetMathScript * scriptInset
= operator[](macroPos).nucleus()->asScriptInset();
macroInset = scriptInset->nuc()[0].nucleus()->asMacro();
} }
// remove them from the MathData // remove them from the MathData
erase(begin() + macroPos + 1, begin() + p); erase(begin() + macroPos + 1, begin() + p);
// cursor outside this MathData?
// no need to update the cursor?
if (thisSlice == -1) if (thisSlice == -1)
return; return;
@ -574,8 +590,10 @@ void MathData::attachMacroParameters(Cursor & cur,
if (thisPos >= int(p)) if (thisPos >= int(p))
cur[thisSlice].pos() -= p - (macroPos + 1); cur[thisSlice].pos() -= p - (macroPos + 1);
// was the macro inset just inserted and was now folded? // was the macro inset just inserted interactively and was now folded
// and the cursor is just behind?
if (cur[thisSlice].pos() == int(macroPos + 1) if (cur[thisSlice].pos() == int(macroPos + 1)
&& interactiveInit
&& fromInitToNormalMode && fromInitToNormalMode
&& macroInset->arity() > 0 && macroInset->arity() > 0
&& thisSlice + 1 == int(cur.depth())) { && thisSlice + 1 == int(cur.depth())) {

View File

@ -173,7 +173,7 @@ private:
/// ///
void attachMacroParameters(Cursor & cur, const size_type macroPos, void attachMacroParameters(Cursor & cur, const size_type macroPos,
const size_type macroNumArgs, const int macroOptionals, const size_type macroNumArgs, const int macroOptionals,
const bool fromInitToNormalMode, const bool greedy); const bool fromInitToNormalMode, const bool interactiveInit);
/// ///
void collectOptionalParameters(Cursor & cur, void collectOptionalParameters(Cursor & cur,
const size_type numOptionalParams, std::vector<MathData> & params, const size_type numOptionalParams, std::vector<MathData> & params,

View File

@ -165,7 +165,7 @@ bool MathMacro::editMode(Cursor const & cur) const {
void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
{ {
// calculate new metrics according to display mode // calculate new metrics according to display mode
if (displayMode_ == DISPLAY_INIT || displayMode_ == DISPLAY_NONGREEDY_INIT) { if (displayMode_ == DISPLAY_INIT || displayMode_ == DISPLAY_INTERACTIVE_INIT) {
mathed_string_dim(mi.base.font, from_ascii("\\") + name(), dim); mathed_string_dim(mi.base.font, from_ascii("\\") + name(), dim);
} else if (displayMode_ == DISPLAY_UNFOLDED) { } else if (displayMode_ == DISPLAY_UNFOLDED) {
cell(0).metrics(mi, dim); cell(0).metrics(mi, dim);
@ -280,7 +280,7 @@ void MathMacro::draw(PainterInfo & pi, int x, int y) const
int expx = x; int expx = x;
int expy = y; int expy = y;
if (displayMode_ == DISPLAY_INIT || displayMode_ == DISPLAY_NONGREEDY_INIT) { if (displayMode_ == DISPLAY_INIT || displayMode_ == DISPLAY_INTERACTIVE_INIT) {
PainterInfo pi2(pi.base.bv, pi.pain); PainterInfo pi2(pi.base.bv, pi.pain);
pi2.base.font.setColor(macro_ ? Color_latex : Color_error); pi2.base.font.setColor(macro_ ? Color_latex : Color_error);
//pi2.base.style = LM_ST_TEXT; //pi2.base.style = LM_ST_TEXT;

View File

@ -87,7 +87,7 @@ public:
enum DisplayMode { enum DisplayMode {
DISPLAY_INIT, DISPLAY_INIT,
DISPLAY_NONGREEDY_INIT, DISPLAY_INTERACTIVE_INIT,
DISPLAY_UNFOLDED, DISPLAY_UNFOLDED,
DISPLAY_NORMAL, DISPLAY_NORMAL,
}; };