On Sun, Feb 02, 2020 at 08:36:53PM -0500, Scott Kostyshak wrote:

> The logic in RandomAccessList is overly
> complicated (and inefficient) and I'm working on simplifying it by using
> a splice instead of all of those swaps.

The attached patch implements the splice approach. I've tested the patch
in a few situations and it works well. With the splice approach it is
now efficient and the logic is cleaner. However, the patch uses a
special case that is not elegant for when the next sibling is at the end
of the document. I cannot seem to use iterCont_ for the last paragraph
in this case. The cases could probably be combined but I don't have a
good understanding of RandomAccessList.

I don't expect anyone to take a look but I post it just in case.

Scott
From 7750175d366f23f23778a9a0e53ef05320723b22 Mon Sep 17 00:00:00 2001
From: Scott Kostyshak <skost...@lyx.org>
Date: Sun, 2 Feb 2020 16:19:29 -0500
Subject: [PATCH] Paragraph-move-down now moves sub-items as well

---
 src/Text3.cpp                  | 49 +++++++++++++++++++++++++++++++---
 src/support/RandomAccessList.h | 17 ++++++++++++
 2 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/src/Text3.cpp b/src/Text3.cpp
index f5444e7baa..b84b2a87bf 100644
--- a/src/Text3.cpp
+++ b/src/Text3.cpp
@@ -671,12 +671,53 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 	switch (act) {
 
 	case LFUN_PARAGRAPH_MOVE_DOWN: {
-		pit_type const pit = cur.pit();
-		cur.recordUndo(pit, pit + 1);
-		pars_.swap(pit, pit + 1);
+		depth_type const cur_depth = pars_[cur.pit()].params().depth();
+		pit_type pit = cur.pit() + 1;
+		Paragraph cpar;
+		while (pit != pit_type(pars_.size())) {
+			cpar = pars_[pit];
+			// <= because it's possible to go e.g. from depth 2 to 0
+			if (cpar.params().depth() <= cur_depth)
+				break;
+			++pit;
+		}
+		if (cpar.params().depth() < cur_depth) {
+			// we did not encounter an equal depth before a smaller
+			// depth, so there is no sibling. e.g.:
+			// 1. hello
+			//    a. blah <cur>
+			// 2. goodbye
+			break;
+		}
+		if (cpar.params().depth() > cur_depth) {
+			// all paragraphs below cur have larger depth
+			// so there is no next sibling. e.g.:
+			// 1. hello <cur>
+			//    a. blah
+			// <end of document>
+			break;
+		}
+		pit_type const next_sib = pit;
+
+		// this is the depth of the paragraph below whose "family" we
+		// want to move.
+		depth_type next_sib_depth = cpar.params().depth();
+		pit_type pit2 = next_sib + 1;
+		while (pit2 != pit_type(pars_.size())) {
+			cpar = pars_[pit2];
+			// <= because it's possible to go e.g. from depth 2 to 0
+			if (cpar.params().depth() <= next_sib_depth)
+				break;
+			++pit2;
+		}
+		pit_type const next_sib_end = pit2 - 1;
+
+		cur.recordUndo(cur.pit(), next_sib_end);
+		pars_.swap(cur.pit(), next_sib - 1, next_sib_end);
 		needsUpdate = true;
 		cur.forceBufferUpdate();
-		++cur.pit();
+		// move the cursor with the paragraph contents where it was.
+		cur.pit() = next_sib_end - (next_sib - cur.pit()) + 1;
 		break;
 	}
 
diff --git a/src/support/RandomAccessList.h b/src/support/RandomAccessList.h
index 2565d62513..2ce5d5d228 100644
--- a/src/support/RandomAccessList.h
+++ b/src/support/RandomAccessList.h
@@ -246,6 +246,23 @@ public:
 		return it;
 	}
 
+	void swap(size_t from_beg, size_t from_end, size_t to_end)
+	{
+		// swap of contiguous ranges of elements:
+		//
+		// swap elements from_beg through from_end with
+		// elements from_end + 1 through to_end.
+		// The ranges do not need to be the same length.
+
+		if (to_end + 1 == iterCont_.size()) {
+			// using iterCont_[to_end + 1] does not work for this case.
+			container_.splice(container_.end(), container_, iterCont_[from_beg], iterCont_[from_end + 1]);
+		} else {
+			container_.splice(iterCont_[to_end + 1], container_, iterCont_[from_beg], iterCont_[from_end + 1]);
+		}
+		recreateVector();
+	}
+
 	void swap(size_t i, size_t j)
 	{
 		size_t const p = std::max(i, j);
-- 
2.20.1

Attachment: signature.asc
Description: PGP signature

-- 
lyx-devel mailing list
lyx-devel@lists.lyx.org
http://lists.lyx.org/mailman/listinfo/lyx-devel

Reply via email to