From f88e67c4c39b7758bad240fdb655bbf5b8d21628 Mon Sep 17 00:00:00 2001 From: hobbs Date: Wed, 5 Apr 2006 19:48:43 +0000 Subject: * generic/tkText.c (DumpLine): stop dumping if we detect that the text widget state has changed while dumping. [Bug 1414171] (InsertChars, DeleteChars): fix undo with space-based path. * tests/text.test (text-25.14): [Bug 1452419] --- generic/tkText.c | 217 ++++++++++++++++++++++++++++++------------------------- tests/text.test | 14 +++- 2 files changed, 130 insertions(+), 101 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index 6bed713..f1fb16d 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -14,7 +14,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkText.c,v 1.33 2003/02/18 21:53:59 hobbs Exp $ + * RCS: @(#) $Id: tkText.c,v 1.33.2.1 2006/04/05 19:48:43 hobbs Exp $ */ #include "default.h" @@ -1367,6 +1367,14 @@ InsertChars(textPtr, indexPtr, string) char indexBuffer[TK_POS_CHARS]; /* + * Don't do anything for an empty string [Bug 1275237] + */ + + if (*string == '\0') { + return; + } + + /* * Don't allow insertions on the last (dummy) line of the text. */ @@ -1398,60 +1406,60 @@ InsertChars(textPtr, indexPtr, string) * Push the insertion on the undo stack */ - if ( textPtr->undo ) { - TkTextIndex toIndex; - - Tcl_DString actionCommand; - Tcl_DString revertCommand; - - if (textPtr->autoSeparators && - textPtr->lastEditMode != TK_TEXT_EDIT_INSERT) { - TkUndoInsertUndoSeparator(textPtr->undoStack); - } - - textPtr->lastEditMode = TK_TEXT_EDIT_INSERT; - - Tcl_DStringInit(&actionCommand); - Tcl_DStringInit(&revertCommand); - - Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&actionCommand," insert ",-1); - TkTextPrintIndex(indexPtr,indexBuffer); - Tcl_DStringAppend(&actionCommand,indexBuffer,-1); - Tcl_DStringAppend(&actionCommand," ",-1); - Tcl_DStringAppendElement(&actionCommand,string); - Tcl_DStringAppend(&actionCommand,";",-1); - Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&actionCommand," mark set insert ",-1); - TkTextIndexForwBytes(indexPtr, (int) strlen(string), - &toIndex); - TkTextPrintIndex(&toIndex, indexBuffer); - Tcl_DStringAppend(&actionCommand,indexBuffer,-1); - Tcl_DStringAppend(&actionCommand,"; ",-1); - Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&actionCommand," see insert",-1); - - Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&revertCommand," delete ",-1); - TkTextPrintIndex(indexPtr,indexBuffer); - Tcl_DStringAppend(&revertCommand,indexBuffer,-1); - Tcl_DStringAppend(&revertCommand," ",-1); - TkTextPrintIndex(&toIndex, indexBuffer); - Tcl_DStringAppend(&revertCommand,indexBuffer,-1); - Tcl_DStringAppend(&revertCommand," ;",-1); - Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&revertCommand," mark set insert ",-1); - TkTextPrintIndex(indexPtr,indexBuffer); - Tcl_DStringAppend(&revertCommand,indexBuffer,-1); - Tcl_DStringAppend(&revertCommand,"; ",-1); - Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&revertCommand," see insert",-1); - - TkUndoPushAction(textPtr->undoStack,&actionCommand, &revertCommand); - - Tcl_DStringFree(&actionCommand); - Tcl_DStringFree(&revertCommand); - + if (textPtr->undo) { + CONST char *cmdName; + TkTextIndex toIndex; + + Tcl_DString actionCommand; + Tcl_DString revertCommand; + + if (textPtr->autoSeparators && + textPtr->lastEditMode != TK_TEXT_EDIT_INSERT) { + TkUndoInsertUndoSeparator(textPtr->undoStack); + } + + textPtr->lastEditMode = TK_TEXT_EDIT_INSERT; + cmdName = Tcl_GetCommandName(textPtr->interp, textPtr->widgetCmd); + + Tcl_DStringInit(&actionCommand); + Tcl_DStringInit(&revertCommand); + + Tcl_DStringAppendElement(&actionCommand, cmdName); + Tcl_DStringAppend(&actionCommand, " insert ", -1); + TkTextPrintIndex(indexPtr,indexBuffer); + Tcl_DStringAppend(&actionCommand, indexBuffer, -1); + Tcl_DStringAppend(&actionCommand, " ", -1); + Tcl_DStringAppendElement(&actionCommand, string); + Tcl_DStringAppend(&actionCommand, ";", -1); + Tcl_DStringAppendElement(&actionCommand, cmdName); + Tcl_DStringAppend(&actionCommand, " mark set insert ", -1); + TkTextIndexForwBytes(indexPtr, (int) strlen(string), &toIndex); + TkTextPrintIndex(&toIndex, indexBuffer); + Tcl_DStringAppend(&actionCommand, indexBuffer,-1); + Tcl_DStringAppend(&actionCommand, "; ", -1); + Tcl_DStringAppendElement(&actionCommand, cmdName); + Tcl_DStringAppend(&actionCommand, " see insert", -1); + + Tcl_DStringAppendElement(&revertCommand, cmdName); + Tcl_DStringAppend(&revertCommand, " delete ", -1); + TkTextPrintIndex(indexPtr, indexBuffer); + Tcl_DStringAppend(&revertCommand, indexBuffer, -1); + Tcl_DStringAppend(&revertCommand, " ", -1); + TkTextPrintIndex(&toIndex, indexBuffer); + Tcl_DStringAppend(&revertCommand, indexBuffer, -1); + Tcl_DStringAppend(&revertCommand, " ;", -1); + Tcl_DStringAppendElement(&revertCommand, cmdName); + Tcl_DStringAppend(&revertCommand, " mark set insert ", -1); + TkTextPrintIndex(indexPtr,indexBuffer); + Tcl_DStringAppend(&revertCommand, indexBuffer, -1); + Tcl_DStringAppend(&revertCommand, "; ", -1); + Tcl_DStringAppendElement(&revertCommand, cmdName); + Tcl_DStringAppend(&revertCommand," see insert", -1); + + TkUndoPushAction(textPtr->undoStack, &actionCommand, &revertCommand); + + Tcl_DStringFree(&actionCommand); + Tcl_DStringFree(&revertCommand); } updateDirtyFlag(textPtr); @@ -1632,59 +1640,60 @@ DeleteChars(textPtr, index1String, index2String, indexPtr1, indexPtr2) */ if (textPtr->undo) { + CONST char *cmdName; Tcl_DString ds; - Tcl_DString actionCommand; - Tcl_DString revertCommand; - + Tcl_DString actionCommand; + Tcl_DString revertCommand; + if (textPtr->autoSeparators && (textPtr->lastEditMode != TK_TEXT_EDIT_DELETE)) { TkUndoInsertUndoSeparator(textPtr->undoStack); } textPtr->lastEditMode = TK_TEXT_EDIT_DELETE; - - Tcl_DStringInit(&actionCommand); - Tcl_DStringInit(&revertCommand); - - Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&actionCommand," delete ",-1); - TkTextPrintIndex(&index1,indexBuffer); - Tcl_DStringAppend(&actionCommand,indexBuffer,-1); - Tcl_DStringAppend(&actionCommand," ",-1); - TkTextPrintIndex(&index2, indexBuffer); - Tcl_DStringAppend(&actionCommand,indexBuffer,-1); - Tcl_DStringAppend(&actionCommand,"; ",-1); - Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&actionCommand," mark set insert ",-1); - TkTextPrintIndex(&index1,indexBuffer); - Tcl_DStringAppend(&actionCommand,indexBuffer,-1); - - Tcl_DStringAppend(&actionCommand,"; ",-1); - Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&actionCommand," see insert",-1); + cmdName = Tcl_GetCommandName(textPtr->interp, textPtr->widgetCmd); + + Tcl_DStringInit(&actionCommand); + Tcl_DStringInit(&revertCommand); + + Tcl_DStringAppendElement(&actionCommand, cmdName); + Tcl_DStringAppend(&actionCommand, " delete ", -1); + TkTextPrintIndex(&index1, indexBuffer); + Tcl_DStringAppend(&actionCommand, indexBuffer, -1); + Tcl_DStringAppend(&actionCommand, " ", -1); + TkTextPrintIndex(&index2, indexBuffer); + Tcl_DStringAppend(&actionCommand, indexBuffer, -1); + Tcl_DStringAppend(&actionCommand, "; ", -1); + Tcl_DStringAppendElement(&actionCommand, cmdName); + Tcl_DStringAppend(&actionCommand, " mark set insert ", -1); + TkTextPrintIndex(&index1, indexBuffer); + Tcl_DStringAppend(&actionCommand,indexBuffer, -1); + + Tcl_DStringAppend(&actionCommand, "; ", -1); + Tcl_DStringAppendElement(&actionCommand, cmdName); + Tcl_DStringAppend(&actionCommand, " see insert", -1); TextGetText(&index1, &index2, &ds); - Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&revertCommand," insert ",-1); - TkTextPrintIndex(&index1,indexBuffer); - Tcl_DStringAppend(&revertCommand,indexBuffer,-1); - Tcl_DStringAppend(&revertCommand," ",-1); - Tcl_DStringAppendElement(&revertCommand,Tcl_DStringValue(&ds)); - Tcl_DStringAppend(&revertCommand,"; ",-1); - Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&revertCommand," mark set insert ",-1); - TkTextPrintIndex(&index2, indexBuffer); - Tcl_DStringAppend(&revertCommand,indexBuffer,-1); - Tcl_DStringAppend(&revertCommand,"; ",-1); - Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1); - Tcl_DStringAppend(&revertCommand," see insert",-1); - - TkUndoPushAction(textPtr->undoStack,&actionCommand, &revertCommand); - - Tcl_DStringFree(&actionCommand); - Tcl_DStringFree(&revertCommand); - + Tcl_DStringAppendElement(&revertCommand, cmdName); + Tcl_DStringAppend(&revertCommand, " insert ", -1); + TkTextPrintIndex(&index1, indexBuffer); + Tcl_DStringAppend(&revertCommand, indexBuffer, -1); + Tcl_DStringAppend(&revertCommand, " ", -1); + Tcl_DStringAppendElement(&revertCommand, Tcl_DStringValue(&ds)); + Tcl_DStringAppend(&revertCommand, "; ", -1); + Tcl_DStringAppendElement(&revertCommand, cmdName); + Tcl_DStringAppend(&revertCommand, " mark set insert ", -1); + TkTextPrintIndex(&index2, indexBuffer); + Tcl_DStringAppend(&revertCommand, indexBuffer, -1); + Tcl_DStringAppend(&revertCommand, "; ", -1); + Tcl_DStringAppendElement(&revertCommand, cmdName); + Tcl_DStringAppend(&revertCommand, " see insert", -1); + + TkUndoPushAction(textPtr->undoStack, &actionCommand, &revertCommand); + + Tcl_DStringFree(&actionCommand); + Tcl_DStringFree(&revertCommand); } updateDirtyFlag(textPtr); @@ -2618,7 +2627,7 @@ DumpLine(interp, textPtr, what, linePtr, startByte, endByte, lineno, command) CONST char *command; /* Script to apply to the segment */ { int offset; - TkTextSegment *segPtr; + TkTextSegment *segPtr, *nextPtr; TkTextIndex index; /* * Must loop through line looking at its segments. @@ -2631,7 +2640,8 @@ DumpLine(interp, textPtr, what, linePtr, startByte, endByte, lineno, command) for (offset = 0, segPtr = linePtr->segPtr ; (offset < endByte) && (segPtr != (TkTextSegment *)NULL) ; - offset += segPtr->size, segPtr = segPtr->nextPtr) { + offset += segPtr->size, segPtr = nextPtr) { + nextPtr = segPtr->nextPtr; if ((what & TK_DUMP_TEXT) && (segPtr->typePtr == &tkTextCharType) && (offset + segPtr->size > startByte)) { char savedChar; /* Last char used in the seg */ @@ -2690,6 +2700,13 @@ DumpLine(interp, textPtr, what, linePtr, startByte, endByte, lineno, command) command, &index, what); } } + if (nextPtr != segPtr->nextPtr) { + /* + * Someone modified the text widget while we were dumping. + * Just stop dumping. [Bug 1414171] + */ + break; + } } } diff --git a/tests/text.test b/tests/text.test index 1c21d21..a5cdfbe 100644 --- a/tests/text.test +++ b/tests/text.test @@ -6,7 +6,7 @@ # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: text.test,v 1.19 2002/10/17 23:38:01 hobbs Exp $ +# RCS: @(#) $Id: text.test,v 1.19.2.1 2006/04/05 19:48:44 hobbs Exp $ package require tcltest 2.1 namespace import -force tcltest::configure @@ -1573,6 +1573,18 @@ test text-25.13 {-maxundo configuration option} { .t get 1.0 end } "line 1\n\n" +test text-25.14 {undo with space-based path} { + set t {.t e x t} + destroy $t + text $t -undo 1 + $t insert end "line 1\n" + $t delete 1.4 1.6 + $t insert end "line 2\n" + $t edit undo + $t edit undo + $t get 1.0 end +} "line 1\n\n" + test text-26.1 {bug fix - 624372, ControlUtfProc long lines} { destroy .t pack [text .t -wrap none] -- cgit v0.12