diff options
-rw-r--r-- | generic/tkTextDisp.c | 36 | ||||
-rw-r--r-- | tests/textDisp.test | 11 |
2 files changed, 31 insertions, 16 deletions
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index d45ac73..44d451a 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -4683,9 +4683,6 @@ TextChanged( */ lastPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded); - while ((lastPtr != NULL) && (TkTextIndexCmp(&lastPtr->index, &rounded) < 0)) { - lastPtr = lastPtr->nextPtr; - } /* * At least one display line is supposed to change. This makes the @@ -6590,6 +6587,7 @@ FindDLine( CONST TkTextIndex *indexPtr)/* Index of desired character. */ { DLine *dlPtrPrev; + TkTextIndex indexPtr2; if (dlPtr == NULL) { return NULL; @@ -6614,7 +6612,6 @@ FindDLine( dlPtrPrev = dlPtr; dlPtr = dlPtr->nextPtr; if (dlPtr == NULL) { - TkTextIndex indexPtr2; /* * We're past the last display line, either because the desired * index lies past the visible text, or because the desired index @@ -6632,14 +6629,41 @@ FindDLine( } else { /* * The desired index is past the visible text. There is no - * display line displaying something at the desired index + * display line displaying something at the desired index. * --> return NULL. */ } break; } if (TkTextIndexCmp(&dlPtr->index,indexPtr) > 0) { - dlPtr = dlPtrPrev; + /* + * If we're here then we would normally expect that: + * dlPtrPrev->index <= indexPtr < dlPtr->index + * i.e. we have found the searched display line being dlPtr. + * However it is possible that some DLines were unlinked + * previously, leading to a situation where going through + * the list of display lines skips display lines that did + * exist just a moment ago. + */ + indexPtr2 = dlPtrPrev->index; + TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount, + &indexPtr2); + if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) { + /* + * Confirmed: + * dlPtrPrev->index <= indexPtr < dlPtr->index + * --> return dlPtrPrev. + */ + dlPtr = dlPtrPrev; + } else { + /* + * The last (rightmost) index shown by dlPtrPrev is still + * before the desired index. This may be because there was + * previously a display line between dlPtrPrev and dlPtr + * and this display line has been unlinked. + * --> return dlPtr. + */ + } break; } } diff --git a/tests/textDisp.test b/tests/textDisp.test index 6aa3721..885c940 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -1181,16 +1181,7 @@ test textDisp-8.12 {TkTextChanged, moving the insert cursor redraws only past an .t mark set insert 3.8 ; # within the same line update lappend res $tk_textRedraw - # This last one is tricky: correct result really is {2.0 3.0} when - # calling .t mark set insert, two calls to TkTextChanged are done: - # (a) to redraw the line of the past position of the cursor - # (b) to redraw the line of the new position of the cursor - # During (a) the display line showing the cursor gets unlinked, - # which leads TkTextChanged in (b) to schedule a redraw starting - # one line _before_ the line containing the insert cursor. This is - # because during (b) findDLine cannot return the display line the - # cursor is in since this display line was just unlinked in (a). -} {{8.0 9.0} {8.0 12.0} {8.0 12.0} {3.0 8.0} {2.0 3.0}} +} {{8.0 9.0} {8.0 12.0} {8.0 12.0} {3.0 8.0} {3.0 4.0}} test textDisp-8.13 {TkTextChanged, used to crash, see [06c1433906]} { .t delete 1.0 end .t insert 1.0 \nLine2\nLine3\n |