As the bug report notes, you do NOT get this crash if you move up or
down in the table a bit before you do the rest. The reason is that
moving up and down sets the cursor's x_target_, and it is because that
is not set that we enter the other code at all and eventually crash.
That is, in InsetTabular's dispatch, we have:

(*) cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX());

You can see the potential for trouble here already. cur.pit() is in the
NEW cell, i.e., the one to which we are moving; it was changed a few
lines previously, and cur.idx() points to the new cell, too. But we are
trying to calculate cur.pos(), which means that cur.pos() is currently
the one from the OLD cell. So the cursor is in an inconsistent state.
Calling cur.targetX() leads us to call Cursor::getPos(), and that is
what causes the crash.

We fix the problem by making sure we call targetX() on the original
cursor. The same problem clearly exists in the DOWN stuff, so we fix
that, too.

By the way, should we be setting x_target_ here once we have calculated
it?


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@38530 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Richard Heck 2011-04-26 22:41:48 +00:00
parent 637d43a32b
commit 2bf904ca34

View File

@ -4036,11 +4036,15 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
// setting also the right targetX.
cur.selHandle(act == LFUN_DOWN_SELECT);
if (tabular.cellRow(cur.idx()) != tabular.nrows() - 1) {
int const xtarget = cur.targetX();
// WARNING: Once cur.idx() has been reset, the cursor is in
// an inconsistent state until pos() has been set. Be careful
// what you do with it!
cur.idx() = tabular.cellBelow(cur.idx());
cur.pit() = 0;
TextMetrics const & tm =
cur.bv().textMetrics(cell(cur.idx())->getText(0));
cur.pos() = tm.x2pos(cur.pit(), 0, cur.targetX());
cur.pos() = tm.x2pos(cur.pit(), 0, xtarget);
cur.setCurrentFont();
}
}
@ -4070,13 +4074,17 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
// setting also the right targetX.
cur.selHandle(act == LFUN_UP_SELECT);
if (tabular.cellRow(cur.idx()) != 0) {
int const xtarget = cur.targetX();
// WARNING: Once cur.idx() has been reset, the cursor is in
// an inconsistent state until pos() has been set. Be careful
// what you do with it!
cur.idx() = tabular.cellAbove(cur.idx());
cur.pit() = cur.lastpit();
Text const * text = cell(cur.idx())->getText(0);
TextMetrics const & tm = cur.bv().textMetrics(text);
ParagraphMetrics const & pm =
tm.parMetrics(cur.lastpit());
cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX());
cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, xtarget);
cur.setCurrentFont();
}
}