From 1c3b7359656edd8a158c3056d26d732e01c34994 Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 22 Oct 2009 21:36:24 +0000 Subject: Apply (slight cleaner, tested) version of [Patch 1469210]. --- ChangeLog | 5 ++++ generic/tkText.c | 69 +++++++++++++++++++++++++++++++++++++++++++------------- generic/tkText.h | 33 +++++++++++++++++++++------ tests/text.test | 15 ++++++++++-- 4 files changed, 97 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 542b85b..4fa8ca5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2009-10-22 Donal K. Fellows + * generic/tkText.c (CreateWidget, 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. + * win/tkWinDialog.c (GetFileNameA): Make the handling of the filter index the same as in GetFileNameW. diff --git a/generic/tkText.c b/generic/tkText.c index 46c2e19..c1cc433 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -13,7 +13,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.91 2009/09/07 07:29:04 das Exp $ + * RCS: @(#) $Id: tkText.c,v 1.92 2009/10/22 21:36:24 dkf Exp $ */ #include "default.h" @@ -543,7 +543,8 @@ CreateWidget( Tcl_InitHashTable(&sharedPtr->imageTable, TCL_STRING_KEYS); sharedPtr->undoStack = TkUndoInitStack(interp,0); sharedPtr->undo = 1; - sharedPtr->isDirtyIncrement = 1; + sharedPtr->isDirty = 0; + sharedPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; sharedPtr->autoSeparators = 1; sharedPtr->lastEditMode = TK_TEXT_EDIT_OTHER; sharedPtr->stateEpoch = 0; @@ -4899,16 +4900,21 @@ TextEditUndo( } /* - * Turn off the undo feature while we revert a compound action. Note that - * the dirty counter counts backwards while we are undoing... + * Turn off the undo feature while we revert a compound action, setting + * the dirty handling mode to undo for the duration (unless it is + * 'fixed'). */ textPtr->sharedTextPtr->undo = 0; - textPtr->sharedTextPtr->isDirtyIncrement = -1; + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_UNDO; + } status = TkUndoRevert(textPtr->sharedTextPtr->undoStack); - textPtr->sharedTextPtr->isDirtyIncrement = 1; + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + } textPtr->sharedTextPtr->undo = 1; return status; @@ -4943,13 +4949,20 @@ TextEditRedo( /* * Turn off the undo feature temporarily while we revert a previously - * undone compound action. + * undone compound action, setting the dirty handling mode to redo for the + * duration (unless it is 'fixed'). */ textPtr->sharedTextPtr->undo = 0; + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_REDO; + } status = TkUndoApply(textPtr->sharedTextPtr->undoStack); + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + } textPtr->sharedTextPtr->undo = 1; return status; } @@ -5014,17 +5027,18 @@ TextEditCmd( } /* - * 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->sharedTextPtr->isDirty = setModified; - if (textPtr->sharedTextPtr->modifiedSet != setModified) { - textPtr->sharedTextPtr->modifiedSet = setModified; - GenerateModifiedEvent(textPtr); + if (setModified) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; + } else { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } + GenerateModifiedEvent(textPtr); } break; case EDIT_REDO: @@ -5192,7 +5206,7 @@ GenerateModifiedEvent( * * UpdateDirtyFlag -- * - * Increases the dirtyness of the text widget + * Updates the dirtyness of the text widget * * Results: * None @@ -5208,14 +5222,37 @@ UpdateDirtyFlag( TkSharedText *sharedTextPtr)/* Information about text widget. */ { int oldDirtyFlag; + TkText *textPtr; + + /* + * If we've been forced to be dirty, we stay dirty (until explicitly + * reset, of course). + */ - if (sharedTextPtr->modifiedSet) { + if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_FIXED) { return; } + + if (sharedTextPtr->isDirty < 0 + && sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_NORMAL) { + /* + * If dirty flag is negative, only redo operations can make it zero + * again. If we do a normal operation, it can never become zero any + * more (other than by explicit reset). + */ + + sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; + return; + } + oldDirtyFlag = sharedTextPtr->isDirty; - sharedTextPtr->isDirty += sharedTextPtr->isDirtyIncrement; + if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_UNDO) { + sharedTextPtr->isDirty--; + } else { + sharedTextPtr->isDirty++; + } + if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) { - TkText *textPtr; for (textPtr = sharedTextPtr->peers; textPtr != NULL; textPtr = textPtr->next) { GenerateModifiedEvent(textPtr); diff --git a/generic/tkText.h b/generic/tkText.h index 0a97630..6957120 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -9,7 +9,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.36 2008/12/06 10:48:29 dkf Exp $ + * RCS: @(#) $Id: tkText.h,v 1.37 2009/10/22 21:36:24 dkf Exp $ */ #ifndef _TKTEXT @@ -500,6 +500,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; + +/* * The following enum is used to define a type for the -state option of the * Text widget. */ @@ -549,10 +562,10 @@ typedef struct TkSharedText { * longer valid. */ /* - * Information related to the undo/redo functonality + * Information related to the undo/redo functionality. */ - 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 @@ -560,14 +573,12 @@ typedef struct TkSharedText { * statements. */ int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ - int modifiedSet; /* Flag indicating that the 'dirtyness' of - * the text widget has been explicitly set. */ int isDirty; /* Flag indicating the 'dirtyness' 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. */ + TkTextDirtyMode dirtyMode; /* The nature of the dirtyness characterized + * by the isDirty flag. */ TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode * was. */ @@ -1138,3 +1149,11 @@ MODULE_SCOPE void TkTextWinFreeClient(Tcl_HashEntry *hPtr, # define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TKTEXT */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tests/text.test b/tests/text.test index 8fd077d..5d3060a 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.54 2008/12/19 15:33:40 dgp Exp $ +# RCS: @(#) $Id: text.test,v 1.55 2009/10/22 21:36:24 dkf Exp $ package require tcltest 2.2 eval tcltest::configure $argv @@ -6079,7 +6079,18 @@ test text-27.17 {bug fix 1536735 - undo with empty text} -body { } -cleanup { destroy .t } -result {0 0 1 0} - +test text-27.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-28.1 {bug fix - 624372, ControlUtfProc long lines} -body { pack [text .t -wrap none] -- cgit v0.12