Fix bug #8242: undo fails for longest label width

In the existing code for setting layout of pragraph parameters,
Text::undoSpan is used to "guess" which paragraphs should be saved in Undo.
With this patch the approach is more precise: before every explicit change
to a paragraph, a Cursor::recordUndo call is inserted. This is much more robust than trying to guess.

In particular, we do not look at depth changes at all, since they are now
handled in updateBuffer since #8159 has been fixed.
This commit is contained in:
Jean-Marc Lasgouttes 2012-07-16 23:39:24 +02:00
parent 02ce050fb8
commit e2b42b1726
3 changed files with 34 additions and 61 deletions

View File

@ -724,8 +724,7 @@ void Text::breakParagraph(Cursor & cur, bool inverse_logic)
return; return;
} }
// a layout change may affect also the following paragraph cur.recordUndo();
recUndo(cur, cur.pit(), undoSpan(cur.pit()) - 1);
// Always break behind a space // Always break behind a space
// It is better to erase the space (Dekel) // It is better to erase the space (Dekel)

View File

@ -82,8 +82,8 @@ public:
/// set layout over selection /// set layout over selection
void setLayout(pit_type start, pit_type end, void setLayout(pit_type start, pit_type end,
docstring const & layout); docstring const & layout);
/// Set given layout to current cursor position. /// Set given layout to current cursor position or selection.
/// FIXME: replace Cursor with DocIterator. /// Handles undo.
void setLayout(Cursor & cur, docstring const & layout); void setLayout(Cursor & cur, docstring const & layout);
/// what type of depth change to make /// what type of depth change to make
@ -342,10 +342,6 @@ private:
/// The InsetText owner shall have access to everything. /// The InsetText owner shall have access to everything.
friend class InsetText; friend class InsetText;
/// return past-the-last paragraph influenced by a layout
/// change on pit
pit_type undoSpan(pit_type pit);
// fix the cursor `cur' after a characters has been deleted at `where' // fix the cursor `cur' after a characters has been deleted at `where'
// position. Called by deleteEmptyParagraphMechanism // position. Called by deleteEmptyParagraphMechanism
static void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where); static void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where);
@ -374,7 +370,7 @@ private:
void readParagraph(Paragraph & par, Lexer & lex, ErrorList & errorList); void readParagraph(Paragraph & par, Lexer & lex, ErrorList & errorList);
/// Set Label Width string to all paragraphs of the same layout /// Set Label Width string to all paragraphs of the same layout
/// and depth in a sequence. /// and depth in a sequence.
void setLabelWidthStringToSequence(pit_type const par_offset, docstring const & s); void setLabelWidthStringToSequence(Cursor const & cur, docstring const & s);
/// Owner Inset. /// Owner Inset.
InsetText * owner_; InsetText * owner_;

View File

@ -173,25 +173,6 @@ void Text::setInsetFont(BufferView const & bv, pit_type pit,
} }
// return past-the-last paragraph influenced by a layout change on pit
pit_type Text::undoSpan(pit_type pit)
{
pit_type const end = paragraphs().size();
pit_type nextpit = pit + 1;
if (nextpit == end)
return nextpit;
//because of parindents
if (!pars_[pit].getDepth())
return boost::next(nextpit);
//because of depth constrains
for (; nextpit != end; ++pit, ++nextpit) {
if (!pars_[pit].getDepth())
break;
}
return nextpit;
}
void Text::setLayout(pit_type start, pit_type end, void Text::setLayout(pit_type start, pit_type end,
docstring const & layout) docstring const & layout)
{ {
@ -217,8 +198,7 @@ void Text::setLayout(Cursor & cur, docstring const & layout)
pit_type start = cur.selBegin().pit(); pit_type start = cur.selBegin().pit();
pit_type end = cur.selEnd().pit() + 1; pit_type end = cur.selEnd().pit() + 1;
pit_type undopit = undoSpan(end - 1); cur.recordUndoSelection();
recUndo(cur, start, undopit - 1);
setLayout(start, end, layout); setLayout(start, end, layout);
cur.forceBufferUpdate(); cur.forceBufferUpdate();
} }
@ -473,31 +453,31 @@ docstring Text::getStringToIndex(Cursor const & cur)
} }
void Text::setLabelWidthStringToSequence(pit_type const par_offset, void Text::setLabelWidthStringToSequence(Cursor const & cur,
docstring const & s) docstring const & s)
{ {
pit_type offset = par_offset; Cursor c = cur;
// Find first of same layout in sequence // Find first of same layout in sequence
while (!isFirstInSequence(offset)) { while (!isFirstInSequence(c.pit())) {
offset = depthHook(offset, pars_[offset].getDepth()); c.pit() = depthHook(c.pit(), c.paragraph().getDepth());
} }
// now apply label width string to every par // now apply label width string to every par
// in sequence // in sequence
pit_type const end = pars_.size(); depth_type const depth = c.paragraph().getDepth();
depth_type const depth = pars_[offset].getDepth(); Layout const & layout = c.paragraph().layout();
Layout const & layout = pars_[offset].layout(); for ( ; c.pit() <= c.lastpit() ; ++c.pit()) {
for (pit_type pit = offset; pit != end; ++pit) { while (c.paragraph().getDepth() > depth) {
while (pars_[pit].getDepth() > depth) { ++c.pit();
++pit; if (c.pit() > c.lastpit())
if (pit == end)
return; return;
} }
if (pars_[pit].getDepth() < depth) if (c.paragraph().getDepth() < depth)
return; return;
if (pars_[pit].layout() != layout) if (c.paragraph().layout() != layout)
return; return;
pars_[pit].setLabelWidthString(s); c.recordUndo();
c.paragraph().setLabelWidthString(s);
} }
} }
@ -505,26 +485,25 @@ void Text::setLabelWidthStringToSequence(pit_type const par_offset,
void Text::setParagraphs(Cursor & cur, docstring arg, bool merge) void Text::setParagraphs(Cursor & cur, docstring arg, bool merge)
{ {
LASSERT(cur.text(), /**/); LASSERT(cur.text(), /**/);
// make sure that the depth behind the selection are restored, too
pit_type undopit = undoSpan(cur.selEnd().pit());
recUndo(cur, cur.selBegin().pit(), undopit - 1);
//FIXME UNICODE //FIXME UNICODE
string const argument = to_utf8(arg); string const argument = to_utf8(arg);
depth_type priordepth = -1; depth_type priordepth = -1;
Layout priorlayout; Layout priorlayout;
for (pit_type pit = cur.selBegin().pit(), end = cur.selEnd().pit(); Cursor c(cur.bv());
pit <= end; ++pit) { c.setCursor(cur.selectionBegin());
Paragraph & par = pars_[pit]; for ( ; c <= cur.selectionEnd() ; ++c.pit()) {
Paragraph & par = c.paragraph();
ParagraphParameters params = par.params(); ParagraphParameters params = par.params();
params.read(argument, merge); params.read(argument, merge);
// Changes to label width string apply to all paragraphs // Changes to label width string apply to all paragraphs
// with same layout in a sequence. // with same layout in a sequence.
// Do this only once for a selected range of paragraphs // Do this only once for a selected range of paragraphs
// of the same layout and depth. // of the same layout and depth.
if (par.getDepth() != priordepth || par.layout() != priorlayout) cur.recordUndo();
setLabelWidthStringToSequence(pit, params.labelWidthString());
par.params().apply(params, par.layout()); par.params().apply(params, par.layout());
if (par.getDepth() != priordepth || par.layout() != priorlayout)
setLabelWidthStringToSequence(c, params.labelWidthString());
priordepth = par.getDepth(); priordepth = par.getDepth();
priorlayout = par.layout(); priorlayout = par.layout();
} }
@ -537,23 +516,22 @@ void Text::setParagraphs(Cursor & cur, docstring arg, bool merge)
void Text::setParagraphs(Cursor & cur, ParagraphParameters const & p) void Text::setParagraphs(Cursor & cur, ParagraphParameters const & p)
{ {
LASSERT(cur.text(), /**/); LASSERT(cur.text(), /**/);
// make sure that the depth behind the selection are restored, too
pit_type undopit = undoSpan(cur.selEnd().pit());
recUndo(cur, cur.selBegin().pit(), undopit - 1);
depth_type priordepth = -1; depth_type priordepth = -1;
Layout priorlayout; Layout priorlayout;
for (pit_type pit = cur.selBegin().pit(), end = cur.selEnd().pit(); Cursor c(cur.bv());
pit <= end; ++pit) { c.setCursor(cur.selectionBegin());
Paragraph & par = pars_[pit]; for ( ; c < cur.selectionEnd() ; ++c.pit()) {
Paragraph & par = c.paragraph();
// Changes to label width string apply to all paragraphs // Changes to label width string apply to all paragraphs
// with same layout in a sequence. // with same layout in a sequence.
// Do this only once for a selected range of paragraphs // Do this only once for a selected range of paragraphs
// of the same layout and depth. // of the same layout and depth.
if (par.getDepth() != priordepth || par.layout() != priorlayout) cur.recordUndo();
setLabelWidthStringToSequence(pit,
par.params().labelWidthString());
par.params().apply(p, par.layout()); par.params().apply(p, par.layout());
if (par.getDepth() != priordepth || par.layout() != priorlayout)
setLabelWidthStringToSequence(c,
par.params().labelWidthString());
priordepth = par.getDepth(); priordepth = par.getDepth();
priorlayout = par.layout(); priorlayout = par.layout();
} }