From 24aa206133a4afbd09b359bada47423e68d7c056 Mon Sep 17 00:00:00 2001
From: fvogel <fvogelnew1@free.fr>
Date: Wed, 10 Dec 2014 21:57:38 +0000
Subject: Fixed TextChanged caller of FindDLine for correct taking into account
 of elided newlines

---
 generic/tkTextDisp.c | 68 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 10 deletions(-)

diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index 6b6d305..946c543 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -4559,6 +4559,8 @@ TextChanged(
     TextDInfo *dInfoPtr = textPtr->dInfoPtr;
     DLine *firstPtr, *lastPtr;
     TkTextIndex rounded;
+    TkTextLine *linePtr;
+    int notBegin;
 
     /*
      * Schedule both a redisplay and a recomputation of display information.
@@ -4584,23 +4586,69 @@ TextChanged(
     /*
      * Find the DLines corresponding to index1Ptr and index2Ptr. There is one
      * tricky thing here, which is that we have to relayout in units of whole
-     * text lines: round index1Ptr back to the beginning of its text line, and
-     * include all the display lines after index2, up to the end of its text
-     * line. This is necessary because the indices stored in the display lines
-     * will no longer be valid. It's also needed because any edit could change
-     * the way lines wrap.
+     * text lines: This is necessary because the indices stored in the display
+     * lines will no longer be valid. It's also needed because any edit could
+     * change the way lines wrap.
+     * To relayout in units of whole text (logical) lines, round index1Ptr
+     * back to the beginning of its text line (or, if this line start is
+     * elided, to the beginning of the text line that starts the display line
+     * it is included in), and include all the display lines after index2Ptr,
+     * up to the end of its text line (or, if this line end is elided, up to
+     * the end of the first non elided text line after this line end).
      */
 
     rounded = *index1Ptr;
-    rounded.byteIndex = 0;
+    do {
+        rounded.byteIndex = 0;
+        notBegin = !TkTextIndexBackBytes(textPtr, &rounded, 1, &rounded);
+    } while (TkTextIsElided(textPtr, &rounded, NULL) && notBegin);
+    if (notBegin) {
+        TkTextIndexForwBytes(textPtr, &rounded, 1, &rounded);
+    }
+
+    /*
+     * 'rounded' now points to the start of a display line as well as the
+     * real (non elided) start of a logical line, and this index is the
+     * closest before index1Ptr.
+     */
+
     firstPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded);
+
     if (firstPtr == NULL) {
+
+        /*
+         * index1Ptr pertains to no display line, i.e this index is after
+         * the last display line. Since index2Ptr is after index1Ptr, there
+         * are no display line to free/redisplay and we can return early.
+         */
+
 	return;
     }
-    lastPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, index2Ptr);
-    while ((lastPtr != NULL)
-	    && (lastPtr->index.linePtr == index2Ptr->linePtr)) {
-	lastPtr = lastPtr->nextPtr;
+
+    rounded = *index2Ptr;
+    linePtr = index2Ptr->linePtr;
+    do {
+        linePtr = TkBTreeNextLine(textPtr, linePtr);
+        if (linePtr == NULL) {
+            break;
+        }
+        rounded.linePtr = linePtr;
+        rounded.byteIndex = 0;
+        TkTextIndexBackBytes(textPtr, &rounded, 1, &rounded);
+    } while (TkTextIsElided(textPtr, &rounded, NULL));
+
+    if (linePtr == NULL) {
+        lastPtr = NULL;
+    } else {
+        TkTextIndexForwBytes(textPtr, &rounded, 1, &rounded);
+
+        /*
+         * 'rounded' now points to the start of a display line as well as the
+         * real (non elided) start of a logical line, and this index is the
+         * closest after index2Ptr.
+         */
+
+        lastPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded);
     }
 
     /*
-- 
cgit v0.12


From 9a6fd67901f76dc489e1231a88e5f2a09c2abce7 Mon Sep 17 00:00:00 2001
From: fvogel <fvogelnew1@free.fr>
Date: Wed, 10 Dec 2014 22:00:20 +0000
Subject: Fixed textDisp-4.1 and -4.2 - The expected test results were not
 relevant without the update between deletion and insertion

---
 tests/textDisp.test | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/tests/textDisp.test b/tests/textDisp.test
index 471a096..678ad4e 100644
--- a/tests/textDisp.test
+++ b/tests/textDisp.test
@@ -537,20 +537,24 @@ test textDisp-4.1 {UpdateDisplayInfo, basic} {textfonts} {
     .t insert end "Line 1\nLine 2\nLine 3\n"
     update
     .t delete 2.0 2.end
+    update
+    set res $tk_textRelayout
     .t insert 2.0 "New Line 2"
     update
-    list [.t bbox 1.0] [.t bbox 2.0] [.t bbox 3.0] $tk_textRelayout
-} [list [list 5 5 7 $fixedHeight] [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 5 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] 2.0]
+    lappend res [.t bbox 1.0] [.t bbox 2.0] [.t bbox 3.0] $tk_textRelayout
+} [list 2.0 [list 5 5 7 $fixedHeight] [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 5 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] 2.0]
 test textDisp-4.2 {UpdateDisplayInfo, re-use tail of text line} {textfonts} {
     .t delete 1.0 end
     .t insert end "Line 1\nLine 2 is so long that it wraps around\nLine 3"
     update
     .t mark set x 2.21
     .t delete 2.2
+    update
+    set res $tk_textRelayout
     .t insert 2.0 X
     update
-    list [.t bbox 2.0] [.t bbox x] [.t bbox 3.0] $tk_textRelayout
-} [list [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 12 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] [list 5 [expr {3*$fixedDiff + 44}] 7 $fixedHeight] {2.0 2.20}]
+    lappend res [.t bbox 2.0] [.t bbox x] [.t bbox 3.0] $tk_textRelayout
+} [list 2.0 2.20 [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 12 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] [list 5 [expr {3*$fixedDiff + 44}] 7 $fixedHeight] {2.0 2.20}]
 test textDisp-4.3 {UpdateDisplayInfo, tail of text line shifts} {textfonts} {
     .t delete 1.0 end
     .t insert end "Line 1\nLine 2 is so long that it wraps around\nLine 3"
-- 
cgit v0.12