Improve DEPM

Now any sequence of spaces around old cursor will be removed, even at
start or end of paragraph. Sequences of more than 2 characters are
also taken into account.

The version of DEPM which acts on a sequence of paragraphs is also
rewritten to match the local one.
This commit is contained in:
Jean-Marc Lasgouttes 2018-07-22 22:13:44 +02:00
parent 16ca5290c0
commit 20976e81fb
2 changed files with 52 additions and 25 deletions

View File

@ -348,10 +348,6 @@ private:
/// The InsetText owner shall have access to everything. /// The InsetText owner shall have access to everything.
friend class InsetText; friend class InsetText;
// fix the cursor `cur' after a characters has been deleted at `where'
// position. Called by deleteEmptyParagraphMechanism
static void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where);
// At cursor position 0, try to merge the paragraph with the one before it. // At cursor position 0, try to merge the paragraph with the one before it.
// Ignore change tracking, i.e., physically remove the end-of-par character // Ignore change tracking, i.e., physically remove the end-of-par character
bool backspacePos0(Cursor & cur); bool backspacePos0(Cursor & cur);

View File

@ -780,9 +780,11 @@ bool Text::cursorDownParagraph(Cursor & cur)
} }
// fix the cursor `cur' after a characters has been deleted at `where' namespace {
// fix the cursor `cur' after characters has been deleted at `where'
// position. Called by deleteEmptyParagraphMechanism // position. Called by deleteEmptyParagraphMechanism
void Text::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where) void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where,
pos_type from, pos_type to)
{ {
// Do nothing if cursor is not in the paragraph where the // Do nothing if cursor is not in the paragraph where the
// deletion occurred, // deletion occurred,
@ -790,8 +792,8 @@ void Text::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where)
return; return;
// If cursor position is after the deletion place update it // If cursor position is after the deletion place update it
if (cur.pos() > where.pos()) if (cur.pos() > from)
--cur.pos(); cur.pos() = max(from, cur.pos() - (to - from));
// Check also if we don't want to set the cursor on a spot behind the // Check also if we don't want to set the cursor on a spot behind the
// pagragraph because we erased the last character. // pagragraph because we erased the last character.
@ -799,6 +801,8 @@ void Text::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where)
cur.pos() = cur.lastpos(); cur.pos() = cur.lastpos();
} }
}
bool Text::deleteEmptyParagraphMechanism(Cursor & cur, bool Text::deleteEmptyParagraphMechanism(Cursor & cur,
Cursor & old, bool & need_anchor_change) Cursor & old, bool & need_anchor_change)
@ -840,23 +844,35 @@ bool Text::deleteEmptyParagraphMechanism(Cursor & cur,
bool const same_par_pos = depth == cur.depth() - 1 && same_par bool const same_par_pos = depth == cur.depth() - 1 && same_par
&& old.pos() == cur[depth].pos(); && old.pos() == cur[depth].pos();
// If the chars around the old cursor were spaces, delete one of them. // If the chars around the old cursor were spaces, delete some of
// them , but only if the cursor has really moved.
if (!same_par_pos) { if (!same_par_pos) {
// Only if the cursor has really moved. // find range of spaces around cursors
if (old.pos() > 0 int from = old.pos();
&& old.pos() < oldpar.size() while (from > 0
&& oldpar.isLineSeparator(old.pos()) && oldpar.isLineSeparator(from - 1)
&& oldpar.isLineSeparator(old.pos() - 1) && !oldpar.isDeleted(from - 1))
&& !oldpar.isDeleted(old.pos() - 1) --from;
&& !oldpar.isDeleted(old.pos())) { int to = old.pos();
oldpar.eraseChar(old.pos() - 1, cur.buffer()->params().track_changes); while (to < oldpar.size() - 1
&& oldpar.isLineSeparator(to)
&& !oldpar.isDeleted(to))
++to;
// If we are not at the extremity of the paragraph, keep one space
if (from != to && from > 0 && to < oldpar.size())
++from;
// Remove spaces and adapt cursor.
if (from < to) {
oldpar.eraseChars(from, to, cur.buffer()->params().track_changes);
// FIXME: This will not work anymore when we have multiple views of the same buffer // FIXME: This will not work anymore when we have multiple views of the same buffer
// In this case, we will have to correct also the cursors held by // In this case, we will have to correct also the cursors held by
// other bufferviews. It will probably be easier to do that in a more // other bufferviews. It will probably be easier to do that in a more
// automated way in CursorSlice code. (JMarc 26/09/2001) // automated way in CursorSlice code. (JMarc 26/09/2001)
// correct all cursor parts // correct all cursor parts
if (same_par) { if (same_par) {
fixCursorAfterDelete(cur[depth], old.top()); fixCursorAfterDelete(cur[depth], old.top(), from, to);
need_anchor_change = true; need_anchor_change = true;
} }
return true; return true;
@ -925,13 +941,28 @@ void Text::deleteEmptyParagraphMechanism(pit_type first, pit_type last, bool tra
if (par.isFreeSpacing()) if (par.isFreeSpacing())
continue; continue;
for (pos_type pos = 1; pos < par.size(); ++pos) { pos_type from = 0;
if (par.isLineSeparator(pos) && par.isLineSeparator(pos - 1) while (from < par.size()) {
&& !par.isDeleted(pos - 1)) { // skip non-spaces
if (par.eraseChar(pos - 1, trackChanges)) { while (from < par.size()
--pos; && (!par.isLineSeparator(from) || par.isDeleted(from)))
} ++from;
} LYXERR0("from=" << from);
// find string of spaces
pos_type to = from;
while (to < par.size()
&& par.isLineSeparator(to) && !par.isDeleted(to))
++to;
LYXERR0("to=" << to);
// empty? We are done
if (from == to)
break;
// if inside the line, keep one space
if (from > 0 && to < par.size())
++from;
// remove the extra spaces
if (from < to)
par.eraseChars(from, to, trackChanges);
} }
// don't delete anything if this is the only remaining paragraph // don't delete anything if this is the only remaining paragraph