commit 286be197e0c8cbbc1ca0aa8dda33d42cb9c7985b
Author: Jean-Marc Lasgouttes <[email protected]>
Date:   Sun Jul 22 22:13:44 2018 +0200

    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.
    
    (cherry picked from commit 20976e81fb25899ee8d3ec5ed941fda6b453f59f)
    (cherry picked from commit c54fe6c5840afdbbac5e242db724fb0bf6bc084f)
---
 src/Text.h    |    4 ---
 src/Text2.cpp |   71 ++++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/src/Text.h b/src/Text.h
index 046ca9d..61af5ff 100644
--- a/src/Text.h
+++ b/src/Text.h
@@ -347,10 +347,6 @@ private:
        /// The InsetText owner shall have access to everything.
        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.
        // Ignore change tracking, i.e., physically remove the end-of-par 
character
        bool backspacePos0(Cursor & cur);
diff --git a/src/Text2.cpp b/src/Text2.cpp
index 8eb70f8..e0f5963 100644
--- a/src/Text2.cpp
+++ b/src/Text2.cpp
@@ -785,9 +785,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
-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
        // deletion occurred,
@@ -795,8 +797,8 @@ void Text::fixCursorAfterDelete(CursorSlice & cur, 
CursorSlice const & where)
                return;
 
        // If cursor position is after the deletion place update it
-       if (cur.pos() > where.pos())
-               --cur.pos();
+       if (cur.pos() > from)
+               cur.pos() = max(from, cur.pos() - (to - from));
 
        // Check also if we don't want to set the cursor on a spot behind the
        // pagragraph because we erased the last character.
@@ -804,6 +806,8 @@ void Text::fixCursorAfterDelete(CursorSlice & cur, 
CursorSlice const & where)
                cur.pos() = cur.lastpos();
 }
 
+}
+
 
 bool Text::deleteEmptyParagraphMechanism(Cursor & cur,
                Cursor & old, bool & need_anchor_change)
@@ -845,23 +849,35 @@ bool Text::deleteEmptyParagraphMechanism(Cursor & cur,
        bool const same_par_pos = depth == cur.depth() - 1 && same_par
                && 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) {
-               // Only if the cursor has really moved.
-               if (old.pos() > 0
-                   && old.pos() < oldpar.size()
-                   && oldpar.isLineSeparator(old.pos())
-                   && oldpar.isLineSeparator(old.pos() - 1)
-                   && !oldpar.isDeleted(old.pos() - 1)
-                   && !oldpar.isDeleted(old.pos())) {
-                       oldpar.eraseChar(old.pos() - 1, 
cur.buffer()->params().track_changes);
+               // find range of spaces around cursors
+               int from = old.pos();
+               while (from > 0
+                      && oldpar.isLineSeparator(from - 1)
+                      && !oldpar.isDeleted(from - 1))
+                       --from;
+               int to = old.pos();
+               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
 // 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
 // automated way in CursorSlice code. (JMarc 26/09/2001)
                        // correct all cursor parts
                        if (same_par) {
-                               fixCursorAfterDelete(cur[depth], old.top());
+                               fixCursorAfterDelete(cur[depth], old.top(), 
from, to);
                                need_anchor_change = true;
                        }
                        return true;
@@ -930,13 +946,26 @@ void Text::deleteEmptyParagraphMechanism(pit_type first, 
pit_type last, bool tra
                if (par.isFreeSpacing())
                        continue;
 
-               for (pos_type pos = 1; pos < par.size(); ++pos) {
-                       if (par.isLineSeparator(pos) && par.isLineSeparator(pos 
- 1)
-                           && !par.isDeleted(pos - 1)) {
-                               if (par.eraseChar(pos - 1, trackChanges)) {
-                                       --pos;
-                               }
-                       }
+               pos_type from = 0;
+               while (from < par.size()) {
+                       // skip non-spaces
+                       while (from < par.size()
+                              && (!par.isLineSeparator(from) || 
par.isDeleted(from)))
+                               ++from;
+                       // find string of spaces
+                       pos_type to = from;
+                       while (to < par.size()
+                              && par.isLineSeparator(to) && !par.isDeleted(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

Reply via email to