From 67481e97e63a0719feb2dadf4ce7de6eb0abb459 Mon Sep 17 00:00:00 2001 From: hobbs Date: Thu, 13 Dec 2007 00:29:53 +0000 Subject: * generic/tkText.c (DeleteIndexRange, TextEditCmd, UpdateDirtyFlag): * tests/text.test (text-25.10.1,25.11.[12]): Don't require [update idle] to trigger Modified event [Bug 1809538] Modified virtual event should only fire on state change [Bug 1799782] Make sure we delete chars before triggering <> [Bug 1737288] --- ChangeLog | 8 ++++++ generic/tkText.c | 88 ++++++++++++++++++++++++++++++-------------------------- tests/text.test | 37 +++++++++++++++++++++++- 3 files changed, 92 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b5b1a2..296ecdf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-12-12 Jeff Hobbs + + * generic/tkText.c (DeleteIndexRange, TextEditCmd, UpdateDirtyFlag): + * tests/text.test (text-25.10.1,25.11.[12]): + Don't require [update idle] to trigger Modified event [Bug 1809538] + Modified virtual event should only fire on state change [Bug 1799782] + Make sure we delete chars before triggering <> [Bug 1737288] + 2007-12-12 Daniel Steffen * macosx/tkMacOSXWm.c (ApplyMasterOverrideChanges): Revert 2007-10-26 diff --git a/generic/tkText.c b/generic/tkText.c index ac40ac5..ca6b424 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.77 2007/12/11 22:14:58 dkf Exp $ + * RCS: @(#) $Id: tkText.c,v 1.78 2007/12/13 00:29:53 hobbs Exp $ */ #include "default.h" @@ -388,6 +388,7 @@ static int TextEditRedo(TkText *textPtr); static Tcl_Obj * TextGetText(CONST TkText *textPtr, CONST TkTextIndex *index1, CONST TkTextIndex *index2, int visibleOnly); +static void GenerateModifiedEvent(TkText *textPtr); static void UpdateDirtyFlag(TkSharedText *sharedPtr); static void TextPushUndoAction(TkText *textPtr, Tcl_Obj *undoString, int insert, @@ -3120,11 +3121,11 @@ DeleteIndexRange( get = TextGetText(textPtr, &index1, &index2, 0); TextPushUndoAction(textPtr, get, 0, &index1, &index2); } - UpdateDirtyFlag(sharedTextPtr); - sharedTextPtr->stateEpoch++; TkBTreeDeleteIndexRange(sharedTextPtr->tree, &index1, &index2); + + UpdateDirtyFlag(sharedTextPtr); } resetViewCount = 0; @@ -4986,7 +4987,6 @@ TextEditCmd( return TCL_ERROR; } else { int setModified; - XEvent event; if (Tcl_GetBooleanFromObj(interp, objv[3], &setModified) != TCL_OK) { @@ -4994,30 +4994,17 @@ TextEditCmd( } /* - * Set or reset the dirty info and trigger a Modified event. + * Set or reset the dirty info, but trigger a Modified event only + * if it has changed. Ensure a rationalized value for the bit. */ - if (setModified) { - textPtr->sharedTextPtr->isDirty = 1; - textPtr->sharedTextPtr->modifiedSet = 1; - } else { - textPtr->sharedTextPtr->isDirty = 0; - textPtr->sharedTextPtr->modifiedSet = 0; - } - - /* - * Send an event that the text was modified. This is equivalent to - * "event generate $textWidget <>" - */ + setModified = setModified ? 1 : 0; - memset(&event, 0, sizeof(event)); - event.xany.type = VirtualEvent; - event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.xany.send_event = False; - event.xany.window = Tk_WindowId(textPtr->tkwin); - event.xany.display = Tk_Display(textPtr->tkwin); - ((XVirtualEvent *) &event)->name = Tk_GetUid("Modified"); - Tk_HandleEvent(&event); + textPtr->sharedTextPtr->isDirty = setModified; + if (textPtr->sharedTextPtr->modifiedSet != setModified) { + textPtr->sharedTextPtr->modifiedSet = setModified; + GenerateModifiedEvent(textPtr); + } } break; case EDIT_REDO: @@ -5148,6 +5135,41 @@ TextGetText( /* *---------------------------------------------------------------------- * + * GenerateModifiedEvent -- + * + * Send an event that the text was modified. This is equivalent to + * event generate $textWidget <> + * + * Results: + * None + * + * Side effects: + * May force the text window into existence. + * + *---------------------------------------------------------------------- + */ + +static void +GenerateModifiedEvent( + TkText *textPtr) /* Information about text widget. */ +{ + XEvent event; + + Tk_MakeWindowExist(textPtr->tkwin); + + memset(&event, 0, sizeof(event)); + event.xany.type = VirtualEvent; + event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); + event.xany.send_event = False; + event.xany.window = Tk_WindowId(textPtr->tkwin); + event.xany.display = Tk_Display(textPtr->tkwin); + ((XVirtualEvent *) &event)->name = Tk_GetUid("Modified"); + Tk_HandleEvent(&event); +} + +/* + *---------------------------------------------------------------------- + * * UpdateDirtyFlag -- * * Increases the dirtyness of the text widget @@ -5176,21 +5198,7 @@ UpdateDirtyFlag( TkText *textPtr; for (textPtr = sharedTextPtr->peers; textPtr != NULL; textPtr = textPtr->next) { - /* - * Send an event that the text was modified. This is equivalent to - * event generate $textWidget <> - */ - - XEvent event; - - memset(&event, 0, sizeof(event)); - event.xany.type = VirtualEvent; - event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.xany.send_event = False; - event.xany.window = Tk_WindowId(textPtr->tkwin); - event.xany.display = Tk_Display(textPtr->tkwin); - ((XVirtualEvent *) &event)->name = Tk_GetUid("Modified"); - Tk_HandleEvent(&event); + GenerateModifiedEvent(textPtr); } } } diff --git a/tests/text.test b/tests/text.test index 6306373..de6f460 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.47 2007/12/11 22:14:58 dkf Exp $ +# RCS: @(#) $Id: text.test,v 1.48 2007/12/13 00:29:53 hobbs Exp $ package require tcltest 2.1 eval tcltest::configure $argv @@ -3041,6 +3041,21 @@ test text-25.10 {TextEditCmd procedure, set modified flag} { .t edit modified 1 .t edit modified } {1} +test text-25.10.1 {TextEditCmd procedure, set modified flag repeat} { + catch {destroy .t} + text .t + pack .t + set ::retval {} + bind .t <> "lappend ::retval modified" + # Shouldn't require [update idle] to trigger event [Bug 1809538] + lappend ::retval [.t edit modified] + .t edit modified 1 + update idletasks + lappend ::retval [.t edit modified] + .t edit modified 1 ; # binding should only fire once [Bug 1799782] + update idletasks + lappend ::retval [.t edit modified] +} {0 modified 1 1} test text-25.11 {<> virtual event} { set ::retval unmodified catch {destroy .t} @@ -3051,6 +3066,26 @@ test text-25.11 {<> virtual event} { .t insert end "nothing special\n" set ::retval } {modified} +test text-25.11.1 {<> virtual event - insert before Modified} { + set ::retval {} + destroy .t + pack [text .t -undo 1] + bind .t <> { set ::retval [.t get 1.0 end-1c] } + update idletasks + .t insert end "nothing special" + set ::retval +} {nothing special} +test text-25.11.2 {<> virtual event - delete before Modified} { + # Bug 1737288, make sure we delete chars before triggering <> + set ::retval {} + destroy .t + pack [text .t -undo 1] + bind .t <> { set ::retval [.t get 1.0 end-1c] } + .t insert end "nothing special" + .t edit modified 0 + .t delete 1.0 1.2 + set ::retval +} {thing special} test text-25.12 {<> virtual event} { set ::retval no_selection catch {destroy .t} -- cgit v0.12