[LyX/master] #6401 correct cursor movement for word forward/backward with enabled Mac style (mac_like_cursor_movement)

Stephan Witt switt at lyx.org
Sat Sep 12 12:08:09 UTC 2020


commit 320b6b66566978fb9c75de086b889f0d34c5cf87
Author: Stephan Witt <switt at lyx.org>
Date:   Sat Sep 12 14:34:56 2020 +0200

    #6401 correct cursor movement for word forward/backward with enabled Mac style (mac_like_cursor_movement)
    
    The change includes a rewrite of the cursor movement when „mac style“ is enabled and don’t change anything otherwise.
    The new code for mac uses the document iterator to go forward or backward. The traversal stops at word boundaries.
    If going forward the position increments until a word is reached (if not already inside) and stops at the end of the word.
    If going backward it does the same in opposite direction. The cursor jumps over non-editable insets and math.
    Editable (open) insets are entered and the cursor move detects word boundaries inside them.
---
 src/Text.cpp |  150 +++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 97 insertions(+), 53 deletions(-)

diff --git a/src/Text.cpp b/src/Text.cpp
index 59bfbef..575eea6 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -1146,30 +1146,53 @@ bool Text::cursorForwardOneWord(Cursor & cur)
 {
 	LBUFERR(this == cur.text());
 
-	pos_type const lastpos = cur.lastpos();
-	pit_type pit = cur.pit();
-	pos_type pos = cur.pos();
-	Paragraph const & par = cur.paragraph();
-
-	// Paragraph boundary is a word boundary
-	if (pos == lastpos || (pos + 1 == lastpos && par.isEnvSeparator(pos))) {
-		if (pit != cur.lastpit())
-			return setCursor(cur, pit + 1, 0);
-		else
-			return false;
-	}
-
 	if (lyxrc.mac_like_cursor_movement) {
-		// Skip through trailing punctuation and spaces.
-		while (pos != lastpos && (par.isChar(pos) || par.isSpace(pos)))
-			++pos;
-
-		// Skip over either a non-char inset or a full word
-		if (pos != lastpos && par.isWordSeparator(pos))
-			++pos;
-		else while (pos != lastpos && !par.isWordSeparator(pos))
-			     ++pos;
+		DocIterator dit(cur);
+		DocIterator prv(cur);
+		bool inword = false;
+		bool intext = dit.inTexted();
+		while (!dit.atEnd()) {
+			if (dit.inTexted()) { // no paragraphs in mathed
+				Paragraph const & par = dit.paragraph();
+				pos_type const pos = dit.pos();
+
+				if (!par.isDeleted(pos)) {
+					bool wordsep = par.isWordSeparator(pos);
+					if (inword && wordsep)
+						break; // stop at word end
+					else if (!inword && !wordsep)
+						inword = true;
+				}
+				intext = true;
+			} else if (intext) {
+				// move to end of math
+				while (!dit.inTexted() && !dit.atEnd()) dit.forwardPos();
+				break;
+			}
+			prv = dit;
+			dit.forwardPosIgnoreCollapsed();
+		}
+		if (dit.atEnd()) dit = prv;
+		if (dit == cur) return false; // we didn't move
+		Cursor orig(cur);
+		cur.setCursor(dit);
+		// see comment above
+		cur.bv().checkDepm(cur, orig);
+		return true;
 	} else {
+		pos_type const lastpos = cur.lastpos();
+		pit_type pit = cur.pit();
+		pos_type pos = cur.pos();
+		Paragraph const & par = cur.paragraph();
+
+		// Paragraph boundary is a word boundary
+		if (pos == lastpos || (pos + 1 == lastpos && par.isEnvSeparator(pos))) {
+			if (pit != cur.lastpit())
+				return setCursor(cur, pit + 1, 0);
+			else
+				return false;
+		}
+
 		LASSERT(pos < lastpos, return false); // see above
 		if (!par.isWordSeparator(pos))
 			while (pos != lastpos && !par.isWordSeparator(pos))
@@ -1183,13 +1206,13 @@ bool Text::cursorForwardOneWord(Cursor & cur)
 		// Skip over white space
 		while (pos != lastpos && par.isSpace(pos))
 			     ++pos;
-	}
 
-	// Don't skip a separator inset at the end of a paragraph
-	if (pos == lastpos && pos && par.isEnvSeparator(pos - 1))
-		--pos;
+		// Don't skip a separator inset at the end of a paragraph
+		if (pos == lastpos && pos && par.isEnvSeparator(pos - 1))
+			--pos;
 
-	return setCursor(cur, pit, pos);
+		return setCursor(cur, pit, pos);
+	}
 }
 
 
@@ -1197,34 +1220,55 @@ bool Text::cursorBackwardOneWord(Cursor & cur)
 {
 	LBUFERR(this == cur.text());
 
-	pit_type pit = cur.pit();
-	pos_type pos = cur.pos();
-	Paragraph & par = cur.paragraph();
-
-	// Paragraph boundary is a word boundary
-	if (pos == 0 && pit != 0) {
-		Paragraph & prevpar = getPar(pit - 1);
-		pos = prevpar.size();
-		// Don't stop after an environment separator
-		if (pos && prevpar.isEnvSeparator(pos - 1))
-			--pos;
-		return setCursor(cur, pit - 1, pos);
-	}
-
 	if (lyxrc.mac_like_cursor_movement) {
-		// Skip through punctuation and spaces.
-		while (pos != 0 && (par.isChar(pos - 1) || par.isSpace(pos - 1)))
-			--pos;
-
-		// Skip over either a non-char inset or a full word
-		if (pos != 0 && par.isWordSeparator(pos - 1) && !par.isChar(pos - 1))
-			--pos;
-		else while (pos != 0 && !par.isWordSeparator(pos - 1))
-			     --pos;
+		DocIterator dit(cur);
+		bool inword = false;
+		bool intext = dit.inTexted();
+		while (!dit.atBegin()) {
+			DocIterator prv(dit);
+			dit.backwardPosIgnoreCollapsed();
+			if (dit.inTexted()) { // no paragraphs in mathed
+				Paragraph const & par = dit.paragraph();
+				pos_type pos = dit.pos();
+
+				if (!par.isDeleted(pos)) {
+					bool wordsep = par.isWordSeparator(pos);
+					if (inword && wordsep) {
+						dit = prv;
+						break; // stop at word begin
+					} else if (!inword && !wordsep)
+						inword = true;
+				}
+				intext = true;
+			} else if (intext) {
+				// move to begin of math
+				while (!dit.inTexted() && !dit.atBegin()) dit.backwardPos();
+				break;
+			}
+		}
+		if (dit == cur) return false; // we didn't move
+		Cursor orig(cur);
+		cur.setCursor(dit);
+		// see comment above cursorForwardOneWord
+		cur.bv().checkDepm(cur, orig);
+		return true;
 	} else {
+		Paragraph const & par = cur.paragraph();
+		pit_type const pit = cur.pit();
+		pos_type pos = cur.pos();
+
+		// Paragraph boundary is a word boundary
+		if (pos == 0 && pit != 0) {
+			Paragraph & prevpar = getPar(pit - 1);
+			pos = prevpar.size();
+			// Don't stop after an environment separator
+			if (pos && prevpar.isEnvSeparator(pos - 1))
+				--pos;
+			return setCursor(cur, pit - 1, pos);
+		}
 		// Skip over white space
 		while (pos != 0 && par.isSpace(pos - 1))
-			     --pos;
+			--pos;
 
 		if (pos != 0 && !par.isWordSeparator(pos - 1))
 			while (pos != 0 && !par.isWordSeparator(pos - 1))
@@ -1234,9 +1278,9 @@ bool Text::cursorBackwardOneWord(Cursor & cur)
 				--pos;
 		else if (pos != 0 && !par.isSpace(pos - 1)) // non-char inset
 			--pos;
-	}
 
-	return setCursor(cur, pit, pos);
+		return setCursor(cur, pit, pos);
+	}
 }
 
 


More information about the lyx-cvs mailing list