summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhobbs <hobbs>2007-12-13 00:29:53 (GMT)
committerhobbs <hobbs>2007-12-13 00:29:53 (GMT)
commit3d75268cfe0948ae13452dc01b24cdba45c80201 (patch)
tree33056fe3801033c058441541f2c75af12cf992b2
parent8f401244434ca3ab876d8efa799317d9e41c59f1 (diff)
downloadtk-3d75268cfe0948ae13452dc01b24cdba45c80201.zip
tk-3d75268cfe0948ae13452dc01b24cdba45c80201.tar.gz
tk-3d75268cfe0948ae13452dc01b24cdba45c80201.tar.bz2
* 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 <<Modified>> [Bug 1737288]
-rw-r--r--ChangeLog8
-rw-r--r--generic/tkText.c88
-rw-r--r--tests/text.test37
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 <jeffh@ActiveState.com>
+
+ * 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 <<Modified>> [Bug 1737288]
+
2007-12-12 Daniel Steffen <das@users.sourceforge.net>
* 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 <<Modified>>"
- */
+ 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 <<Modified>>
+ *
+ * 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 <<Modified>>
- */
-
- 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 <<Modified>> "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 {<<Modified>> virtual event} {
set ::retval unmodified
catch {destroy .t}
@@ -3051,6 +3066,26 @@ test text-25.11 {<<Modified>> virtual event} {
.t insert end "nothing special\n"
set ::retval
} {modified}
+test text-25.11.1 {<<Modified>> virtual event - insert before Modified} {
+ set ::retval {}
+ destroy .t
+ pack [text .t -undo 1]
+ bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }
+ update idletasks
+ .t insert end "nothing special"
+ set ::retval
+} {nothing special}
+test text-25.11.2 {<<Modified>> virtual event - delete before Modified} {
+ # Bug 1737288, make sure we delete chars before triggering <<Modified>>
+ set ::retval {}
+ destroy .t
+ pack [text .t -undo 1]
+ bind .t <<Modified>> { 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 {<<Selection>> virtual event} {
set ::retval no_selection
catch {destroy .t}