From 5969910620bf508843c84476d7ccb60a0e9e8506 Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 22 Oct 2009 22:10:08 +0000 Subject: Apply (upgraded) version of [Patch 1469210]. --- ChangeLog | 7 +++++ generic/tkText.c | 78 +++++++++++++++++++++++++++++++++++++++++--------------- generic/tkText.h | 56 ++++++++++++++++++++-------------------- tests/text.test | 15 ++++++++++- 4 files changed, 108 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index 53c6407..a8972c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-10-22 Donal K. Fellows + + * generic/tkText.c (Tk_TextCmd, TextEditUndo, TextEditRedo) + (TextEditCmd, updateDirtyFlag): + * generic/tkText.h: [Patch 1469210]: Corrected handling of marking as + dirty when inserting after an undo from a non-dirty state. + 2009-10-07 Donal K. Fellows * unix/tkUnixScrlbr.c (TkpComputeScrollbarGeometry): [Patch 2088597]: diff --git a/generic/tkText.c b/generic/tkText.c index 6e5cb83..6b24ffa 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.2.7 2007/12/13 00:31:33 hobbs Exp $ + * RCS: @(#) $Id: tkText.c,v 1.33.2.8 2009/10/22 22:10:08 dkf Exp $ */ #include "default.h" @@ -415,7 +415,8 @@ Tk_TextCmd(clientData, interp, argc, argv) textPtr->pickEvent.type = LeaveNotify; textPtr->undoStack = TkUndoInitStack(interp,0); textPtr->undo = 1; - textPtr->isDirtyIncrement = 1; + textPtr->isDirty = 0; + textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; textPtr->autoSeparators = 1; textPtr->lastEditMode = TK_TEXT_EDIT_OTHER; @@ -2794,25 +2795,29 @@ DumpSegment(interp, key, value, command, index, what) static int TextEditUndo(textPtr) - TkText * textPtr; /* Overall information about text widget. */ + TkText *textPtr; /* Overall information about text widget. */ { int status; if (!textPtr->undo) { - return TCL_OK; + return TCL_OK; } /* Turn off the undo feature */ textPtr->undo = 0; - /* The dirty counter should count downwards as we are undoing things */ - textPtr->isDirtyIncrement = -1; + /* Set dirty mode to undo, unless it is fixed */ + if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->dirtyMode = TK_TEXT_DIRTY_UNDO; + } /* revert one compound action */ status = TkUndoRevert(textPtr->undoStack); - /* Restore the isdirty increment */ - textPtr->isDirtyIncrement = 1; + /* Restore dirty mode */ + if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + } /* Turn back on the undo feature */ textPtr->undo = 1; @@ -2833,20 +2838,30 @@ TextEditUndo(textPtr) static int TextEditRedo(textPtr) - TkText * textPtr; /* Overall information about text widget. */ + TkText *textPtr; /* Overall information about text widget. */ { int status; if (!textPtr->undo) { - return TCL_OK; + return TCL_OK; } /* Turn off the undo feature temporarily */ textPtr->undo = 0; + /* Set dirty mode to redo, unless it is fixed */ + if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->dirtyMode = TK_TEXT_DIRTY_REDO; + } + /* reapply one compound action */ status = TkUndoApply(textPtr->undoStack); + /* Restore dirty mode */ + if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + } + /* Turn back on the undo feature */ textPtr->undo = 1; @@ -2891,22 +2906,25 @@ TextEditCmd(textPtr, interp, argc, argv) argv[0], " edit modified ?boolean?\"", (char *) NULL); return TCL_ERROR; } else { - int setModified; + int setModified, wasModified = textPtr->isDirty; if (Tcl_GetBoolean(interp, argv[3], &setModified) != TCL_OK) { return TCL_ERROR; } /* - * Set or reset the dirty info, but trigger a Modified event only - * if it has changed. Ensure a rationalized value for the bit. + * Set or reset the dirty info, and trigger a Modified event (. */ setModified = setModified ? 1 : 0; textPtr->isDirty = setModified; - if (textPtr->modifiedSet != setModified) { - textPtr->modifiedSet = setModified; + if (setModified) { + textPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; + } else { + textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + } + if ((!wasModified) != (!setModified)) { GenerateModifiedEvent(textPtr); } } @@ -3041,7 +3059,7 @@ GenerateModifiedEvent( /* * updateDirtyFlag -- - * increases the dirtyness of the text widget + * updates the dirtyness of the text widget * * Results: * None @@ -3050,16 +3068,36 @@ GenerateModifiedEvent( * None. */ -static void updateDirtyFlag (textPtr) +static void +updateDirtyFlag(textPtr) TkText *textPtr; /* Information about text widget. */ { int oldDirtyFlag; - if (textPtr->modifiedSet) { - return; + if (textPtr->dirtyMode == TK_TEXT_DIRTY_FIXED) { + return; } + + /* + * If dirty flag is negative, only redo operations can make it zero again. + * If we do a normal operation, it can never become zero anymore. + */ + if (textPtr->isDirty < 0 && textPtr->dirtyMode == TK_TEXT_DIRTY_NORMAL) { + textPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; + return; + } + oldDirtyFlag = textPtr->isDirty; - textPtr->isDirty += textPtr->isDirtyIncrement; + + switch (textPtr->dirtyMode) { + case TK_TEXT_DIRTY_UNDO: + textPtr->isDirty--; + break; + default: + textPtr->isDirty++; + break; + } + if (textPtr->isDirty == 0 || oldDirtyFlag == 0) { GenerateModifiedEvent(textPtr); } diff --git a/generic/tkText.h b/generic/tkText.h index 7e1f666..77ff926 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -10,7 +10,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.h,v 1.13.2.1 2006/10/17 05:38:48 dgp Exp $ + * RCS: @(#) $Id: tkText.h,v 1.13.2.2 2009/10/22 22:10:08 dkf Exp $ */ #ifndef _TKTEXT @@ -464,6 +464,19 @@ typedef enum { } TkTextEditMode; /* + * Enumeration defining the ways in which a text widget may be modified (for + * undo/redo handling). + */ + +typedef enum { + TK_TEXT_DIRTY_NORMAL, /* Normal behavior. */ + TK_TEXT_DIRTY_UNDO, /* Reverting a compound action. */ + TK_TEXT_DIRTY_REDO, /* Reapplying a compound action. */ + TK_TEXT_DIRTY_FIXED /* Forced to be dirty; can't be undone/redone + * by normal activity. */ +} TkTextDirtyMode; + +/* * A data structure of the following type is kept for each text widget that * currently exists for this process: */ @@ -639,36 +652,25 @@ typedef struct TkText { * definitions. */ /* - * Information related to the undo/redo functonality + * Information related to the undo/redo funcitonality */ - TkUndoRedoStack * undoStack; /* The undo/redo stack */ - + TkUndoRedoStack *undoStack; /* The undo/redo stack. */ int undo; /* non zero means the undo/redo behaviour is - * enabled */ - - int maxUndo; /* The maximum depth of the undo stack expressed - * as the maximum number of compound statements */ - + * enabled. */ + int maxUndo; /* The maximum depth of the undo stack + * expressed as the maximum number of compound + * statements. */ int autoSeparators; /* non zero means the separatorss will be - * inserted automatically */ - - int modifiedSet; /* Flag indicating that the 'dirtynesss' of - * the text widget has been expplicitly set. - */ - - int isDirty; /* Flag indicating the 'dirtynesss' of the text - * widget. If the flag is not zero, unsaved - * modifications have been applied to the - * text widget */ - - int isDirtyIncrement; /* Amount with which the isDirty flag is - * incremented every edit action - */ - - TkTextEditMode lastEditMode; /* Keeps track of what the last edit mode was - */ - + * inserted automatically. */ + int isDirty; /* Flag indicating the 'dirtynesss' of the + * text widget. If the flag is not zero, + * unsaved modifications have been applied to + * the text widget. */ + TkTextDirtyMode dirtyMode; /* The nature of the dirtyness characterized + * by the isDirty flag. */ + TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode + * was. */ } TkText; /* diff --git a/tests/text.test b/tests/text.test index 0158389..f720721 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.2.2 2007/12/13 00:31:34 hobbs Exp $ +# RCS: @(#) $Id: text.test,v 1.19.2.3 2009/10/22 22:10:08 dkf Exp $ package require tcltest 2.1 namespace import -force tcltest::configure @@ -1620,6 +1620,19 @@ test text-25.14 {undo with space-based path} { $t get 1.0 end } "line 1\n\n" +test text-25.18 {patch 1469210 - inserting after undo} -setup { + destroy .t +} -body { + text .t -undo 1 + .t insert end foo + .t edit modified 0 + .t edit undo + .t insert end bar + .t edit modified +} -cleanup { + destroy .t +} -result 1 + test text-26.1 {bug fix - 624372, ControlUtfProc long lines} { destroy .t pack [text .t -wrap none] -- cgit v0.12