diff options
author | fvogel <fvogelnew1@free.fr> | 2016-02-08 22:01:40 (GMT) |
---|---|---|
committer | fvogel <fvogelnew1@free.fr> | 2016-02-08 22:01:40 (GMT) |
commit | 6a8bbfdc67042715775e07b59ffe497f2c0e7904 (patch) | |
tree | f8129018fdbb361ace97deb6b0fd4a85474927ff | |
parent | 4cf679d27cf1beb50d5806e6173a8071821aff95 (diff) | |
parent | 6ca191e0c126168c21b4c207ee70e0e4a24cef36 (diff) | |
download | tk-6a8bbfdc67042715775e07b59ffe497f2c0e7904.zip tk-6a8bbfdc67042715775e07b59ffe497f2c0e7904.tar.gz tk-6a8bbfdc67042715775e07b59ffe497f2c0e7904.tar.bz2 |
Fixed (with a real fix this time) bug [06c1433906] - Text widget crash during delete
-rw-r--r-- | generic/tkTextDisp.c | 57 | ||||
-rw-r--r-- | tests/textDisp.test | 13 |
2 files changed, 43 insertions, 27 deletions
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 960f11a..7969091 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -4749,9 +4749,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 @@ -4872,16 +4869,9 @@ TextRedrawTag( /* * Round up the starting position if it's before the first line visible on - * the screen (we only care about what's on the screen). Beware that the - * display info structure might need update, for instance if we arrived - * here from an 'after idle' script removing tags in a range whose - * display lines (and dInfo) were partially invalidated by a previous - * delete operation in the text widget. + * the screen (we only care about what's on the screen). */ - if (dInfoPtr->flags & DINFO_OUT_OF_DATE) { - UpdateDisplayInfo(textPtr); - } dlPtr = dInfoPtr->dLinePtr; if (dlPtr == NULL) { return; @@ -6709,6 +6699,7 @@ FindDLine( const TkTextIndex *indexPtr)/* Index of desired character. */ { DLine *dlPtrPrev; + TkTextIndex indexPtr2; if (dlPtr == NULL) { return NULL; @@ -6733,24 +6724,58 @@ 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 - * is on the last display line showing the last logical line. + * is on the last display line. */ indexPtr2 = dlPtrPrev->index; TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount, &indexPtr2); if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) { + /* + * The desired index is on the last display line. + * --> return this display line. + */ dlPtr = dlPtrPrev; - break; } else { - return NULL; + /* + * The desired index is past the visible text. There is no + * 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 5ac2e7a..353999f 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -1181,19 +1181,10 @@ 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 \nLine1\nLine2\n + .t insert 1.0 \nLine2\nLine3\n update .t insert 3.0 "" .t delete 1.0 2.0 |