]> git.lyx.org Git - lyx.git/blobdiff - src/Text2.cpp
ctests: fix/update CJK tests.
[lyx.git] / src / Text2.cpp
index 869684ed86ecf19e9c7456f051ffc9a0b5011ba6..356e4e8dd18bd29742c6458dfce32305a9b176c0 100644 (file)
@@ -779,24 +779,30 @@ bool Text::cursorDownParagraph(Cursor & cur)
        return updated;
 }
 
+namespace {
 
-// fix the cursor `cur' after a characters has been deleted at `where'
-// position. Called by deleteEmptyParagraphMechanism
-void Text::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where)
+void deleteSpaces(Paragraph & par, pos_type const from, pos_type to,
+                                 int num_spaces, bool const trackChanges)
 {
-       // Do nothing if cursor is not in the paragraph where the
-       // deletion occurred,
-       if (cur.pit() != where.pit())
+       if (!num_spaces)
                return;
 
-       // If cursor position is after the deletion place update it
-       if (cur.pos() > where.pos())
-               --cur.pos();
+       // First, delete spaces marked as inserted
+       int pos = from;
+       while (pos < to && num_spaces > 0) {
+               Change const & change = par.lookupChange(pos);
+               if (change.inserted() && change.currentAuthor()) {
+                       par.eraseChar(pos, trackChanges);
+                       --num_spaces;
+                       --to;
+               } else
+                       ++pos;
+       }
+
+       // Then remove remaining spaces
+       par.eraseChars(from, from + num_spaces, trackChanges);
+}
 
-       // Check also if we don't want to set the cursor on a spot behind the
-       // pagragraph because we erased the last character.
-       if (cur.pos() > cur.lastpos())
-               cur.pos() = cur.lastpos();
 }
 
 
@@ -815,8 +821,8 @@ bool Text::deleteEmptyParagraphMechanism(Cursor & cur,
           There are still some small problems that can lead to
           double spaces stored in the document file or space at
           the beginning of paragraphs(). This happens if you have
-          the cursor between to spaces and then save. Or if you
-          cut and paste and the selection have a space at the
+          the cursor between two spaces and then save. Or if you
+          cut and paste and the selection has a space at the
           beginning and then save right after the paste. (Lgb)
        */
 
@@ -836,34 +842,55 @@ bool Text::deleteEmptyParagraphMechanism(Cursor & cur,
 
        // Whether a common inset is found and whether the cursor is still in
        // the same paragraph (possibly nested).
-       bool const same_par = depth < cur.depth() && old.pit() == cur[depth].pit();
+       bool const same_par = depth < cur.depth() && old.idx() == cur[depth].idx()
+               && old.pit() == cur[depth].pit();
        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);
-// 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
+               // find range of spaces around cursors
+               pos_type from = old.pos();
+               while (from > 0
+                      && oldpar.isLineSeparator(from - 1)
+                      && !oldpar.isDeleted(from - 1))
+                       --from;
+               pos_type to = old.pos();
+               while (to < oldpar.size() - 1
+                      && oldpar.isLineSeparator(to)
+                      && !oldpar.isDeleted(to))
+                       ++to;
+
+               int num_spaces = to - from;
+
+               // If we are not at the extremity of the paragraph, keep one space
+               if (from != to && from > 0 && to < oldpar.size())
+                       --num_spaces;
+
+               // If cursor is inside range, keep one additional space
+               if (same_par && cur.pos() > from && cur.pos() < to)
+                       --num_spaces;
+
+               // Remove spaces and adapt cursor.
+               if (num_spaces > 0) {
+                       pos_type const oldsize = oldpar.size();
+                       deleteSpaces(oldpar, from, to, num_spaces,
+                               cur.buffer()->params().track_changes);
+                       // correct cur position
+                       // FIXME: there can be other cursors pointing there, we should update them
                        if (same_par) {
-                               fixCursorAfterDelete(cur[depth], old.top());
+                               if (cur[depth].pos() >= to)
+                                       cur[depth].pos() -= oldsize - oldpar.size();
+                               else if (cur[depth].pos() > from)
+                                       cur[depth].pos() = min(from + 1, old.lastpos());
                                need_anchor_change = true;
                        }
                        return true;
                }
        }
 
-       // only do our magic if we changed paragraph
+       // only do our other magic if we changed paragraph
        if (same_par)
                return false;
 
@@ -925,13 +952,29 @@ 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;
+
+                       int num_spaces = to - from;
+
+                       // If we are not at the extremity of the paragraph, keep one space
+                       if (from != to && from > 0 && to < par.size())
+                               --num_spaces;
+
+                       // Remove spaces if needed
+                       deleteSpaces(par, from , to, num_spaces, trackChanges);
                }
 
                // don't delete anything if this is the only remaining paragraph