From eb3fa653566d6bf130804d7d800f960d72819597 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 7 Jun 2016 21:04:51 +0000 Subject: Possible solution for [1217222] - [.text edit undo/redo] return ranges of modified characters --- generic/tkText.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/generic/tkText.c b/generic/tkText.c index b610844..d101364 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -2781,6 +2781,7 @@ TextPushUndoAction( Tcl_Obj *markSet2InsertObj = NULL; Tcl_Obj *insertCmdObj = Tcl_NewObj(); Tcl_Obj *deleteCmdObj = Tcl_NewObj(); + Tcl_Obj *returnCmdObj = Tcl_NewObj(); /* * Get the index positions. @@ -2830,6 +2831,11 @@ TextPushUndoAction( Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj); Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj); + Tcl_ListObjAppendElement(NULL, returnCmdObj, + Tcl_NewStringObj("list", 4)); + Tcl_ListObjAppendElement(NULL, returnCmdObj, index1Obj); + Tcl_ListObjAppendElement(NULL, returnCmdObj, index2Obj); + /* * Note: we don't wish to use textPtr->widgetCmd in these callbacks * because if we delete the textPtr, but peers still exist, we will then @@ -2847,11 +2853,13 @@ TextPushUndoAction( insertCmdObj, NULL); TkUndoMakeCmdSubAtom(NULL, markSet2InsertObj, iAtom); TkUndoMakeCmdSubAtom(NULL, seeInsertObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, returnCmdObj, iAtom); dAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr, deleteCmdObj, NULL); TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom); TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, returnCmdObj, dAtom); Tcl_DecrRefCount(seeInsertObj); Tcl_DecrRefCount(index1Obj); -- cgit v0.12 From 940954ce6034eac3de51350f4d546ed7279e7ec9 Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 8 Jun 2016 08:34:52 +0000 Subject: Updated documentation regarding return values for [.text edit undo/redo] --- doc/text.n | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/text.n b/doc/text.n index e2bb01f..9633e37 100644 --- a/doc/text.n +++ b/doc/text.n @@ -1305,8 +1305,9 @@ of the widget to \fIboolean\fR. \fIpathName \fBedit redo\fR . When the \fB\-undo\fR option is true, reapplies the last undone edits provided -no other edits were done since then. Generates an error when the redo stack is -empty. Does nothing when the \fB\-undo\fR option is false. +no other edits were done since then, and returns a list of indices indicating +what ranges were changed by the redo operation. Generates an error when the +redo stack is empty. Does nothing when the \fB\-undo\fR option is false. .TP \fIpathName \fBedit reset\fR . @@ -1319,9 +1320,10 @@ Inserts a separator (boundary) on the undo stack. Does nothing when the .TP \fIpathName \fBedit undo\fR . -Undoes the last edit action when the \fB\-undo\fR option is true. An edit -action is defined as all the insert and delete commands that are recorded on -the undo stack in between two separators. Generates an error when the undo +Undoes the last edit action when the \fB\-undo\fR option is true, and returns a +list of indices indicating what ranges were changed by the undo operation. An +edit action is defined as all the insert and delete commands that are recorded +on the undo stack in between two separators. Generates an error when the undo stack is empty. Does nothing when the \fB\-undo\fR option is false. .RE .TP -- cgit v0.12 From abdebd5b836480c1552c478a871c77b4668135ed Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 8 Jun 2016 09:38:29 +0000 Subject: It is not possible to rely only on the interp result. A list of indices has to be built as a return value to undo/redo because there can be several edits between two separators and all such edits have to report which range of text they changed. Note: this commit does not deal with refcounts, it is very likely wrong in that respect. --- generic/tkText.c | 31 +++++++++++++++++++------------ generic/tkUndo.c | 26 ++++++++++++++++++++++---- generic/tkUndo.h | 4 ++-- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index d101364..60e726f 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -395,8 +395,8 @@ static int DumpSegment(TkText *textPtr, Tcl_Interp *interp, const char *key, const char *value, Tcl_Obj *command, const TkTextIndex *index, int what); -static int TextEditUndo(TkText *textPtr); -static int TextEditRedo(TkText *textPtr); +static int TextEditUndo(TkText *textPtr, Tcl_Obj *rangesObj); +static int TextEditRedo(TkText *textPtr, Tcl_Obj *rangesObj); static Tcl_Obj * TextGetText(const TkText *textPtr, const TkTextIndex *index1, const TkTextIndex *index2, int visibleOnly); @@ -5060,7 +5060,7 @@ DumpSegment( * Undo the last change. * * Results: - * None. + * The ranges of text that were changed by the undo operation. * * Side effects: * Apart from manipulating the undo and redo stacks, the state of the @@ -5071,7 +5071,8 @@ DumpSegment( static int TextEditUndo( - TkText *textPtr) /* Overall information about text widget. */ + TkText *textPtr, /* Overall information about text widget. */ + Tcl_Obj *rangesObj) /* Ranges of text that were changed. */ { int status; @@ -5090,7 +5091,7 @@ TextEditUndo( textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_UNDO; } - status = TkUndoRevert(textPtr->sharedTextPtr->undoStack); + status = TkUndoRevert(textPtr->sharedTextPtr->undoStack, rangesObj); if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; @@ -5108,7 +5109,7 @@ TextEditUndo( * Redo the last undone change. * * Results: - * None. + * The ranges of text that were changed by the undo operation. * * Side effects: * Apart from manipulating the undo and redo stacks, the state of the @@ -5119,7 +5120,8 @@ TextEditUndo( static int TextEditRedo( - TkText *textPtr) /* Overall information about text widget. */ + TkText *textPtr, /* Overall information about text widget. */ + Tcl_Obj *rangesObj) /* Ranges of text that were changed. */ { int status; @@ -5138,7 +5140,7 @@ TextEditRedo( textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_REDO; } - status = TkUndoApply(textPtr->sharedTextPtr->undoStack); + status = TkUndoApply(textPtr->sharedTextPtr->undoStack, rangesObj); if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; @@ -5174,6 +5176,7 @@ TextEditCmd( int index, setModified, oldModified; int canRedo = 0; int canUndo = 0; + Tcl_Obj *rangesObj = Tcl_NewObj(); static const char *const editOptionStrings[] = { "canundo", "canredo", "modified", "redo", "reset", "separator", @@ -5257,11 +5260,13 @@ TextEditCmd( return TCL_ERROR; } canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); - if (TextEditRedo(textPtr)) { + if (TextEditRedo(textPtr, rangesObj)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1)); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL); return TCL_ERROR; - } + } else { + Tcl_SetObjResult(interp, rangesObj); + } canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); if (!canUndo || !canRedo) { GenerateUndoStackEvent(textPtr); @@ -5292,11 +5297,13 @@ TextEditCmd( return TCL_ERROR; } canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); - if (TextEditUndo(textPtr)) { + if (TextEditUndo(textPtr, rangesObj)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1)); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL); return TCL_ERROR; - } + } else { + Tcl_SetObjResult(interp, rangesObj); + } canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); if (!canRedo || !canUndo) { GenerateUndoStackEvent(textPtr); diff --git a/generic/tkUndo.c b/generic/tkUndo.c index c66905d..f364326 100644 --- a/generic/tkUndo.c +++ b/generic/tkUndo.c @@ -556,7 +556,8 @@ TkUndoInsertUndoSeparator( * Undo a compound action on the stack. * * Results: - * A Tcl status code + * A Tcl status code. Also, the passed Tcl_(List)Obj is appended by the + * interp results from evaluation of each element of the undo stack. * * Side effects: * None. @@ -566,7 +567,8 @@ TkUndoInsertUndoSeparator( int TkUndoRevert( - TkUndoRedoStack *stack) + TkUndoRedoStack *stack, + Tcl_Obj *retObj) { TkUndoAtom *elem; @@ -598,6 +600,13 @@ TkUndoRevert( EvaluateActionList(stack->interp, elem->revert); + /* + * The interp result is appended to the returned object for each + * element of the undo stack (not for each sub-atom). + */ + + Tcl_ListObjAppendList(NULL, retObj, Tcl_GetObjResult(stack->interp)); + TkUndoPushStack(&stack->redoStack, elem); elem = TkUndoPopStack(&stack->undoStack); } @@ -619,7 +628,8 @@ TkUndoRevert( * Redo a compound action on the stack. * * Results: - * A Tcl status code + * A Tcl status code. Also, the passed Tcl_(List)Obj is appended by the + * interp results from evaluation of each element of the redo stack. * * Side effects: * None. @@ -629,7 +639,8 @@ TkUndoRevert( int TkUndoApply( - TkUndoRedoStack *stack) + TkUndoRedoStack *stack, + Tcl_Obj *retObj) { TkUndoAtom *elem; @@ -660,6 +671,13 @@ TkUndoApply( EvaluateActionList(stack->interp, elem->apply); + /* + * The interp result is appended to the returned object for each + * element of the redo stack (not for each sub-atom). + */ + + Tcl_ListObjAppendList(NULL, retObj, Tcl_GetObjResult(stack->interp)); + TkUndoPushStack(&stack->undoStack, elem); elem = TkUndoPopStack(&stack->redoStack); } diff --git a/generic/tkUndo.h b/generic/tkUndo.h index 490ede9..505e0f0 100644 --- a/generic/tkUndo.h +++ b/generic/tkUndo.h @@ -109,7 +109,7 @@ MODULE_SCOPE TkUndoSubAtom *TkUndoMakeSubAtom(TkUndoProc *funcPtr, TkUndoSubAtom *subAtomList); MODULE_SCOPE void TkUndoPushAction(TkUndoRedoStack *stack, TkUndoSubAtom *apply, TkUndoSubAtom *revert); -MODULE_SCOPE int TkUndoRevert(TkUndoRedoStack *stack); -MODULE_SCOPE int TkUndoApply(TkUndoRedoStack *stack); +MODULE_SCOPE int TkUndoRevert(TkUndoRedoStack *stack, Tcl_Obj *retObj); +MODULE_SCOPE int TkUndoApply(TkUndoRedoStack *stack, Tcl_Obj *retObj); #endif /* _TKUNDO */ -- cgit v0.12 From d60b9e28ecea5421fcb384737837748d9cd677df Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 8 Jun 2016 13:23:22 +0000 Subject: Added test case text-27.26 for [.text edit undo/redo] return values --- tests/text.test | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/text.test b/tests/text.test index 0ec69d0..abbcfe5 100644 --- a/tests/text.test +++ b/tests/text.test @@ -6562,6 +6562,36 @@ test text-27.25 {<> virtual event} -setup { } -cleanup { destroy .t } -result {0 0 1 2 3 4 4 5 6 6 7 8 8 9} +test text-27.26 {edit undo and edit redo return ranges} -setup { + destroy .t + set res {} +} -body { + text .t -undo true -autoseparators false + .t insert end "Hello " + .t edit separator + .t insert end "World!\n" + .t insert 1.6 "GREAT " + .t insert end "Another edit here!!" + lappend res [.t edit undo] + lappend res [.t edit redo] + .t edit separator + .t delete 1.6 + .t delete 1.9 1.10 + .t insert 1.9 L + lappend res [.t edit undo] + lappend res [.t edit redo] + .t replace 1.6 1.10 Tcl/Tk + .t replace 2.8 2.12 "one bites the dust" + lappend res [.t edit undo] + lappend res [.t edit redo] +} -cleanup { + destroy .t +} -result [list {2.0 2.19 1.6 1.12 1.6 2.0} \ + {1.6 2.0 1.6 1.12 2.0 2.19} \ + {1.9 1.10 1.9 1.10 1.6 1.7} \ + {1.6 1.7 1.9 1.10 1.9 1.10} \ + {2.8 2.26 2.8 2.12 1.6 1.12 1.6 1.10} \ + {1.6 1.10 1.6 1.12 2.8 2.12 2.8 2.26} ] test text-28.1 {bug fix - 624372, ControlUtfProc long lines} -body { -- cgit v0.12 From 77f4d07ef5cfb838fee58aeadf50fa3d948d273d Mon Sep 17 00:00:00 2001 From: fvogel Date: Mon, 4 Jul 2016 21:26:53 +0000 Subject: Return indices making sense at undo/redo return time. The returned ranges are optimized (no duplicates, no overlapping ranges). Works but needs polishing. --- generic/tkText.c | 124 +++++++++++++++++++++++++++++++++++++++++++------------ generic/tkUndo.c | 26 ++---------- generic/tkUndo.h | 4 +- library/text.tcl | 67 ++++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+), 50 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index 8698825..f34b221 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -398,8 +398,8 @@ static int DumpSegment(TkText *textPtr, Tcl_Interp *interp, const char *key, const char *value, Tcl_Obj *command, const TkTextIndex *index, int what); -static int TextEditUndo(TkText *textPtr, Tcl_Obj *rangesObj); -static int TextEditRedo(TkText *textPtr, Tcl_Obj *rangesObj); +static int TextEditUndo(TkText *textPtr); +static int TextEditRedo(TkText *textPtr); static Tcl_Obj * TextGetText(const TkText *textPtr, const TkTextIndex *index1, const TkTextIndex *index2, int visibleOnly); @@ -2774,6 +2774,10 @@ TextPushUndoAction( { TkUndoSubAtom *iAtom, *dAtom; int canUndo, canRedo; + static int undoMarkId = -1; + char lMarkName[20] = "tk::undoMarkL"; + char rMarkName[20] = "tk::undoMarkR"; + char stringUndoMarkId[7] = ""; /* * Create the helpers. @@ -2784,7 +2788,10 @@ TextPushUndoAction( Tcl_Obj *markSet2InsertObj = NULL; Tcl_Obj *insertCmdObj = Tcl_NewObj(); Tcl_Obj *deleteCmdObj = Tcl_NewObj(); - Tcl_Obj *returnCmdObj = Tcl_NewObj(); + Tcl_Obj *markSetLUndoMarkCmdObj = Tcl_NewObj(); + Tcl_Obj *markSetRUndoMarkCmdObj = NULL; + Tcl_Obj *markGravityLUndoMarkCmdObj = Tcl_NewObj(); + Tcl_Obj *markGravityRUndoMarkCmdObj = NULL; /* * Get the index positions. @@ -2834,10 +2841,39 @@ TextPushUndoAction( Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj); Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj); - Tcl_ListObjAppendElement(NULL, returnCmdObj, - Tcl_NewStringObj("list", 4)); - Tcl_ListObjAppendElement(NULL, returnCmdObj, index1Obj); - Tcl_ListObjAppendElement(NULL, returnCmdObj, index2Obj); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1)); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj("mark", 4)); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj("set", 3)); + markSetRUndoMarkCmdObj = Tcl_DuplicateObj(markSetLUndoMarkCmdObj); + undoMarkId++; + sprintf(stringUndoMarkId, "%d", undoMarkId); + strcat(lMarkName, stringUndoMarkId); + strcat(rMarkName, stringUndoMarkId); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, + Tcl_NewStringObj(lMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj, + Tcl_NewStringObj(rMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, index1Obj); + Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj, index2Obj); + + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1)); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj("mark", 4)); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj("gravity", 7)); + markGravityRUndoMarkCmdObj = Tcl_DuplicateObj(markGravityLUndoMarkCmdObj); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj(lMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj, + Tcl_NewStringObj(rMarkName, -1)); + Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj, + Tcl_NewStringObj("left", 4)); + Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj, + Tcl_NewStringObj("right", 5)); /* * Note: we don't wish to use textPtr->widgetCmd in these callbacks @@ -2856,13 +2892,19 @@ TextPushUndoAction( insertCmdObj, NULL); TkUndoMakeCmdSubAtom(NULL, markSet2InsertObj, iAtom); TkUndoMakeCmdSubAtom(NULL, seeInsertObj, iAtom); - TkUndoMakeCmdSubAtom(NULL, returnCmdObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, iAtom); dAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr, deleteCmdObj, NULL); TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom); TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom); - TkUndoMakeCmdSubAtom(NULL, returnCmdObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, dAtom); Tcl_DecrRefCount(seeInsertObj); Tcl_DecrRefCount(index1Obj); @@ -5063,7 +5105,7 @@ DumpSegment( * Undo the last change. * * Results: - * The ranges of text that were changed by the undo operation. + * None. * * Side effects: * Apart from manipulating the undo and redo stacks, the state of the @@ -5074,10 +5116,11 @@ DumpSegment( static int TextEditUndo( - TkText *textPtr, /* Overall information about text widget. */ - Tcl_Obj *rangesObj) /* Ranges of text that were changed. */ + TkText *textPtr) /* Overall information about text widget. */ { int status; + Tcl_Obj *cmdObj; + int code; if (!textPtr->sharedTextPtr->undo) { return TCL_OK; @@ -5094,13 +5137,29 @@ TextEditUndo( textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_UNDO; } - status = TkUndoRevert(textPtr->sharedTextPtr->undoStack, rangesObj); + status = TkUndoRevert(textPtr->sharedTextPtr->undoStack); if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } textPtr->sharedTextPtr->undo = 1; + /* + * Convert undo/redo temporary marks set by TkUndoRevert() into + * indices left in the interp result. + */ + + cmdObj = Tcl_ObjPrintf("::tk::TextUndoRedoProcessMarks %s", + Tk_PathName(textPtr->tkwin)); + Tcl_IncrRefCount(cmdObj); + code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL); + if (code != TCL_OK) { + Tcl_AddErrorInfo(textPtr->interp, + "\n (on undoing)"); + Tcl_BackgroundException(textPtr->interp, code); + } + Tcl_DecrRefCount(cmdObj); + return status; } @@ -5112,7 +5171,7 @@ TextEditUndo( * Redo the last undone change. * * Results: - * The ranges of text that were changed by the undo operation. + * None. * * Side effects: * Apart from manipulating the undo and redo stacks, the state of the @@ -5123,10 +5182,11 @@ TextEditUndo( static int TextEditRedo( - TkText *textPtr, /* Overall information about text widget. */ - Tcl_Obj *rangesObj) /* Ranges of text that were changed. */ + TkText *textPtr) /* Overall information about text widget. */ { int status; + Tcl_Obj *cmdObj; + int code; if (!textPtr->sharedTextPtr->undo) { return TCL_OK; @@ -5143,12 +5203,29 @@ TextEditRedo( textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_REDO; } - status = TkUndoApply(textPtr->sharedTextPtr->undoStack, rangesObj); + status = TkUndoApply(textPtr->sharedTextPtr->undoStack); if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } textPtr->sharedTextPtr->undo = 1; + + /* + * Convert undo/redo temporary marks set by TkUndoApply() into + * indices left in the interp result. + */ + + cmdObj = Tcl_ObjPrintf("::tk::TextUndoRedoProcessMarks %s", + Tk_PathName(textPtr->tkwin)); + Tcl_IncrRefCount(cmdObj); + code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL); + if (code != TCL_OK) { + Tcl_AddErrorInfo(textPtr->interp, + "\n (on undoing)"); + Tcl_BackgroundException(textPtr->interp, code); + } + Tcl_DecrRefCount(cmdObj); + return status; } @@ -5179,7 +5256,6 @@ TextEditCmd( int index, setModified, oldModified; int canRedo = 0; int canUndo = 0; - Tcl_Obj *rangesObj = Tcl_NewObj(); static const char *const editOptionStrings[] = { "canundo", "canredo", "modified", "redo", "reset", "separator", @@ -5263,13 +5339,11 @@ TextEditCmd( return TCL_ERROR; } canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); - if (TextEditRedo(textPtr, rangesObj)) { + if (TextEditRedo(textPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1)); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL); return TCL_ERROR; - } else { - Tcl_SetObjResult(interp, rangesObj); - } + } canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); if (!canUndo || !canRedo) { GenerateUndoStackEvent(textPtr); @@ -5300,13 +5374,11 @@ TextEditCmd( return TCL_ERROR; } canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); - if (TextEditUndo(textPtr, rangesObj)) { + if (TextEditUndo(textPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1)); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL); return TCL_ERROR; - } else { - Tcl_SetObjResult(interp, rangesObj); - } + } canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); if (!canRedo || !canUndo) { GenerateUndoStackEvent(textPtr); diff --git a/generic/tkUndo.c b/generic/tkUndo.c index f364326..c66905d 100644 --- a/generic/tkUndo.c +++ b/generic/tkUndo.c @@ -556,8 +556,7 @@ TkUndoInsertUndoSeparator( * Undo a compound action on the stack. * * Results: - * A Tcl status code. Also, the passed Tcl_(List)Obj is appended by the - * interp results from evaluation of each element of the undo stack. + * A Tcl status code * * Side effects: * None. @@ -567,8 +566,7 @@ TkUndoInsertUndoSeparator( int TkUndoRevert( - TkUndoRedoStack *stack, - Tcl_Obj *retObj) + TkUndoRedoStack *stack) { TkUndoAtom *elem; @@ -600,13 +598,6 @@ TkUndoRevert( EvaluateActionList(stack->interp, elem->revert); - /* - * The interp result is appended to the returned object for each - * element of the undo stack (not for each sub-atom). - */ - - Tcl_ListObjAppendList(NULL, retObj, Tcl_GetObjResult(stack->interp)); - TkUndoPushStack(&stack->redoStack, elem); elem = TkUndoPopStack(&stack->undoStack); } @@ -628,8 +619,7 @@ TkUndoRevert( * Redo a compound action on the stack. * * Results: - * A Tcl status code. Also, the passed Tcl_(List)Obj is appended by the - * interp results from evaluation of each element of the redo stack. + * A Tcl status code * * Side effects: * None. @@ -639,8 +629,7 @@ TkUndoRevert( int TkUndoApply( - TkUndoRedoStack *stack, - Tcl_Obj *retObj) + TkUndoRedoStack *stack) { TkUndoAtom *elem; @@ -671,13 +660,6 @@ TkUndoApply( EvaluateActionList(stack->interp, elem->apply); - /* - * The interp result is appended to the returned object for each - * element of the redo stack (not for each sub-atom). - */ - - Tcl_ListObjAppendList(NULL, retObj, Tcl_GetObjResult(stack->interp)); - TkUndoPushStack(&stack->undoStack, elem); elem = TkUndoPopStack(&stack->redoStack); } diff --git a/generic/tkUndo.h b/generic/tkUndo.h index 505e0f0..490ede9 100644 --- a/generic/tkUndo.h +++ b/generic/tkUndo.h @@ -109,7 +109,7 @@ MODULE_SCOPE TkUndoSubAtom *TkUndoMakeSubAtom(TkUndoProc *funcPtr, TkUndoSubAtom *subAtomList); MODULE_SCOPE void TkUndoPushAction(TkUndoRedoStack *stack, TkUndoSubAtom *apply, TkUndoSubAtom *revert); -MODULE_SCOPE int TkUndoRevert(TkUndoRedoStack *stack, Tcl_Obj *retObj); -MODULE_SCOPE int TkUndoApply(TkUndoRedoStack *stack, Tcl_Obj *retObj); +MODULE_SCOPE int TkUndoRevert(TkUndoRedoStack *stack); +MODULE_SCOPE int TkUndoApply(TkUndoRedoStack *stack); #endif /* _TKUNDO */ diff --git a/library/text.tcl b/library/text.tcl index 2bf1b2b..cc78bc2 100644 --- a/library/text.tcl +++ b/library/text.tcl @@ -1202,3 +1202,70 @@ proc ::tk::TextScanDrag {w x y} { $w scan dragto $x $y } } + +# ::tk::TextUndoRedoProcessMarks -- +# +# This proc is executed after an undo or redo action. +# It processes the list of undo/redo marks temporarily set in the +# text widget to positions delimiting where changes happened, and +# returns a flat list of ranges. The temporary marks are removed +# from the text widget. +# +# Arguments: +# w - The text widget + +proc ::tk::TextUndoRedoProcessMarks {w} { + set indices {} + set undoMarks {} + # only consider the temporary marks set by an undo/redo action + foreach mark [$w mark names] { + if {[string range $mark 0 11] eq "tk::undoMark"} { + lappend undoMarks $mark + } + } + # the number of undo/redo marks is always even + set nUndoMarks [llength $undoMarks] + set n [expr {$nUndoMarks / 2}] + set undoMarks [lsort -dictionary $undoMarks] + set Lmarks [lrange $undoMarks 0 [expr {$n - 1}]] + set Rmarks [lrange $undoMarks $n [llength $undoMarks]] + foreach Lmark $Lmarks Rmark $Rmarks { + lappend indices [$w index $Lmark] [$w index $Rmark] + $w mark unset $Lmark $Rmark + } +#puts "Unoptimized indices: $indices" + # process ranges to: + # - remove those already fully included in another range + # - merge overlapping ranges + set ind [lsort -dictionary -stride 2 $indices] + set indices {} + for {set i 0} {$i < $nUndoMarks} {incr i 2} { + set il1 [lindex $ind $i] + set ir1 [lindex $ind [expr {$i + 1}]] + lappend indices $il1 $ir1 +#puts " range1: $il1 $ir1" + for {set j [expr {$i + 2}]} {$j < $nUndoMarks} {incr j 2} { + set il2 [lindex $ind $j] + set ir2 [lindex $ind [expr {$j + 1}]] +#puts " range2: $il2 $ir2" + if {[$w compare $il2 > $ir1]} { + # second range starts after the end of first range + set j $nUndoMarks + } else { + if {[$w compare $ir2 > $ir1]} { + # second range overlaps with first range + set indices [lreplace $indices end-1 end] + lappend indices $il1 $ir2 + } else { + # second range is fully included in first range + } + set ind [lreplace $ind $j [expr {$j + 1}]] + incr j -2 + incr nUndoMarks -2 + } +#puts " indices: $indices" + } + } +#puts "OPTIMIZED indices: $indices" + return $indices +} -- cgit v0.12 From 19daddfc9fecac5b38d749263e8553bc9b44d415 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 5 Jul 2016 20:02:59 +0000 Subject: Better comments explaining the algorithm in ::tk::TextUndoRedoProcessMarks --- library/text.tcl | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/library/text.tcl b/library/text.tcl index cc78bc2..f241abd 100644 --- a/library/text.tcl +++ b/library/text.tcl @@ -1217,13 +1217,17 @@ proc ::tk::TextScanDrag {w x y} { proc ::tk::TextUndoRedoProcessMarks {w} { set indices {} set undoMarks {} + # only consider the temporary marks set by an undo/redo action foreach mark [$w mark names] { if {[string range $mark 0 11] eq "tk::undoMark"} { lappend undoMarks $mark } } - # the number of undo/redo marks is always even + + # transform marks into indices + # the number of undo/redo marks is always even, each right mark + # completes a left mark to give a range set nUndoMarks [llength $undoMarks] set n [expr {$nUndoMarks / 2}] set undoMarks [lsort -dictionary $undoMarks] @@ -1233,39 +1237,51 @@ proc ::tk::TextUndoRedoProcessMarks {w} { lappend indices [$w index $Lmark] [$w index $Rmark] $w mark unset $Lmark $Rmark } -#puts "Unoptimized indices: $indices" + # process ranges to: # - remove those already fully included in another range # - merge overlapping ranges set ind [lsort -dictionary -stride 2 $indices] set indices {} + for {set i 0} {$i < $nUndoMarks} {incr i 2} { set il1 [lindex $ind $i] set ir1 [lindex $ind [expr {$i + 1}]] lappend indices $il1 $ir1 -#puts " range1: $il1 $ir1" + for {set j [expr {$i + 2}]} {$j < $nUndoMarks} {incr j 2} { set il2 [lindex $ind $j] set ir2 [lindex $ind [expr {$j + 1}]] -#puts " range2: $il2 $ir2" + if {[$w compare $il2 > $ir1]} { # second range starts after the end of first range + # -> further second ranges do not need to be considered + # because ranges were sorted by increasing first index set j $nUndoMarks + } else { if {[$w compare $ir2 > $ir1]} { - # second range overlaps with first range + # second range overlaps first range + # -> merge them into a single range set indices [lreplace $indices end-1 end] lappend indices $il1 $ir2 + } else { # second range is fully included in first range + # -> ignore it + } + # in both cases above, the second range shall be + # trimmed out from the list of ranges set ind [lreplace $ind $j [expr {$j + 1}]] incr j -2 incr nUndoMarks -2 + } -#puts " indices: $indices" + } + } -#puts "OPTIMIZED indices: $indices" + return $indices } -- cgit v0.12 From 77f55a8fc19b9564340f53bc04e96c0217bf24a9 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 5 Jul 2016 20:03:53 +0000 Subject: Removed unintended whitespace change --- generic/tkText.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tkText.c b/generic/tkText.c index f34b221..4195238 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -5339,7 +5339,7 @@ TextEditCmd( return TCL_ERROR; } canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); - if (TextEditRedo(textPtr)) { + if (TextEditRedo(textPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1)); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL); return TCL_ERROR; -- cgit v0.12 From 5718d28895a5ea6c26d0dc5e8421b3ff31fe7785 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 5 Jul 2016 20:07:01 +0000 Subject: Added more tests, and fixed test result of text-27.26 since now indices are relative to the text widget state at undo/redo return time, and also because they are optimized (no overlaps) --- tests/text.test | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/tests/text.test b/tests/text.test index a3f9afe..65c3225 100644 --- a/tests/text.test +++ b/tests/text.test @@ -6601,12 +6601,42 @@ test text-27.26 {edit undo and edit redo return ranges} -setup { lappend res [.t edit redo] } -cleanup { destroy .t -} -result [list {2.0 2.19 1.6 1.12 1.6 2.0} \ - {1.6 2.0 1.6 1.12 2.0 2.19} \ - {1.9 1.10 1.9 1.10 1.6 1.7} \ - {1.6 1.7 1.9 1.10 1.9 1.10} \ - {2.8 2.26 2.8 2.12 1.6 1.12 1.6 1.10} \ - {1.6 1.10 1.6 1.12 2.8 2.12 2.8 2.26} ] +} -result [list {1.6 2.0} \ + {1.6 2.19} \ + {1.6 1.7 1.10 1.12} \ + {1.6 1.7 1.9 1.11} \ + {1.6 1.16 2.8 2.19} \ + {1.6 1.16 2.8 2.30} ] +test text-27.27 {edit undo and edit redo return ranges} -setup { + destroy .t + set res {} +} -body { + text .t -undo true -autoseparators false + for {set i 3} {$i >= 1} {incr i -1} { + .t insert 1.0 "Line $i\n" + } + lappend res [.t edit undo] + lappend res [.t edit redo] +} -cleanup { + destroy .t +} -result [list {1.0 2.0} \ + {1.0 4.0} ] +test text-27.28 {edit undo and edit redo do not leave \ + spurious temporary marks behind them} -setup { + destroy .t + set res {} +} -body { + pack [text .t -undo true -autoseparators false] + .t insert end "Hello World.\n" + .t edit separator + .t insert end "Again hello.\n" + .t edit undo + lappend res [lsearch [.t mark names] tk::undoMark*] + .t edit undo + lappend res [lsearch [.t mark names] tk::undoMark*] +} -cleanup { + destroy .t +} -result [list -1 -1] test text-28.1 {bug fix - 624372, ControlUtfProc long lines} -body { -- cgit v0.12 From e28d7bfd6199766d14e5583fcf905289c6737c36 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 5 Jul 2016 20:36:25 +0000 Subject: Fixed copy/paste error in test text-27.28 - one wants to test undo and redo, not twice undo --- tests/text.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/text.test b/tests/text.test index 65c3225..2e4177d 100644 --- a/tests/text.test +++ b/tests/text.test @@ -6632,7 +6632,7 @@ test text-27.28 {edit undo and edit redo do not leave \ .t insert end "Again hello.\n" .t edit undo lappend res [lsearch [.t mark names] tk::undoMark*] - .t edit undo + .t edit redo lappend res [lsearch [.t mark names] tk::undoMark*] } -cleanup { destroy .t -- cgit v0.12 From bf98687ae68fe39f9b67d9cd3c1553bfdd43bf7b Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 6 Jul 2016 17:00:05 +0000 Subject: The undo marks identifier is now a member of textPtr->sharedTextPtr. This makes results of test text-8.22 independant of previous undo/redo actions on other text widgets. --- generic/tkText.c | 5 ++--- generic/tkText.h | 2 ++ tests/text.test | 14 +++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index 4195238..6b90a23 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -2774,7 +2774,6 @@ TextPushUndoAction( { TkUndoSubAtom *iAtom, *dAtom; int canUndo, canRedo; - static int undoMarkId = -1; char lMarkName[20] = "tk::undoMarkL"; char rMarkName[20] = "tk::undoMarkR"; char stringUndoMarkId[7] = ""; @@ -2848,8 +2847,8 @@ TextPushUndoAction( Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, Tcl_NewStringObj("set", 3)); markSetRUndoMarkCmdObj = Tcl_DuplicateObj(markSetLUndoMarkCmdObj); - undoMarkId++; - sprintf(stringUndoMarkId, "%d", undoMarkId); + textPtr->sharedTextPtr->undoMarkId++; + sprintf(stringUndoMarkId, "%d", textPtr->sharedTextPtr->undoMarkId); strcat(lMarkName, stringUndoMarkId); strcat(rMarkName, stringUndoMarkId); Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, diff --git a/generic/tkText.h b/generic/tkText.h index 5d88784..430c96b 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -580,6 +580,8 @@ typedef struct TkSharedText { * statements. */ int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ + int undoMarkId; /* Counts undo marks temporarily used during + undo and redo operations. */ int isDirty; /* Flag indicating the 'dirtyness' of the * text widget. If the flag is not zero, * unsaved modifications have been applied to diff --git a/tests/text.test b/tests/text.test index 2e4177d..1a68239 100644 --- a/tests/text.test +++ b/tests/text.test @@ -1458,7 +1458,19 @@ Line 7" rename .t {} rename test.t .t destroy .t -} -result {{edit undo} {delete 2.1 2.4} {mark set insert 2.1} {see insert} {insert 2.1 ef} {mark set insert 2.3} {see insert}} +} -result [list {edit undo} {delete 2.1 2.4} {mark set insert 2.1} {see insert} \ + {mark set tk::undoMarkL3 2.1} {mark set tk::undoMarkR3 2.4} \ + {mark gravity tk::undoMarkL3 left} {mark gravity tk::undoMarkR3 right} \ + {insert 2.1 ef} {mark set insert 2.3} {see insert} \ + {mark set tk::undoMarkL2 2.1} {mark set tk::undoMarkR2 2.3} \ + {mark gravity tk::undoMarkL2 left} {mark gravity tk::undoMarkR2 right} \ + {mark names} \ + {index tk::undoMarkL2} {index tk::undoMarkR2} \ + {mark unset tk::undoMarkL2 tk::undoMarkR2} \ + {index tk::undoMarkL3} {index tk::undoMarkR3} \ + {mark unset tk::undoMarkL3 tk::undoMarkR3} \ + {compare 2.1 > 2.3} {compare 2.6 > 2.3} ] + test text-8.23 {TextWidgetCmd procedure, "replace" option with undo} -setup { text .t } -body { -- cgit v0.12 From 1052e56fe96f3ece407a6374714af0302c9a5e3c Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 7 Jul 2016 06:39:26 +0000 Subject: Added comments justifying why we can rely on finding all the needed marks still in the text widget at the time they are transformed into indices. --- library/text.tcl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/text.tcl b/library/text.tcl index f241abd..02a8939 100644 --- a/library/text.tcl +++ b/library/text.tcl @@ -1228,6 +1228,19 @@ proc ::tk::TextUndoRedoProcessMarks {w} { # transform marks into indices # the number of undo/redo marks is always even, each right mark # completes a left mark to give a range + # this is true because: + # - undo/redo only deals with insertions and deletions of text + # - insertions may move marks but not delete them + # - when deleting text, marks located inside the deleted range + # are not erased but moved to the start of the deletion range + # . this is done in TkBTreeDeleteIndexRange ("This segment + # refuses to die...") + # . because MarkDeleteProc does nothing else than returning + # a value indicating that marks are not deleted by this + # deleteProc + # . mark deletion rather happen through [.text mark unset xxx] + # which was not used _up to this point of the code_ (it + # is a bit later just before exiting the present proc) set nUndoMarks [llength $undoMarks] set n [expr {$nUndoMarks / 2}] set undoMarks [lsort -dictionary $undoMarks] -- cgit v0.12 From a8a67387bad0e0d7fa2f73dc8e4c97475e1b8e68 Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 3 Aug 2016 10:19:15 +0000 Subject: Fixed [e8a111970a] - Misleading documentation for menu accelerator option --- doc/menu.n | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/menu.n b/doc/menu.n index ed1bb33..9dd7ef4 100644 --- a/doc/menu.n +++ b/doc/menu.n @@ -98,8 +98,10 @@ a bitmap, or an image, controlled by the \fB\-label\fR, \fB\-bitmap\fR, and \fB\-image\fR options for the entry. If the \fB\-accelerator\fR option is specified for an entry then a second textual field is displayed to the right of the label. The accelerator -typically describes a keystroke sequence that may be typed in the +typically describes a keystroke sequence that may be used in the application to cause the same result as invoking the menu entry. +This is a display option, it does not actually set the corresponding +binding (which can be achieved using the \fBbind\fR command). The third field is an \fIindicator\fR. The indicator is present only for checkbutton or radiobutton entries. It indicates whether the entry is selected or not, and is displayed to the left of the entry's @@ -537,8 +539,10 @@ This option is not available for separator or tear-off entries. . Specifies a string to display at the right side of the menu entry. Normally describes an accelerator keystroke sequence that may be -typed to invoke the same function as the menu entry. This option -is not available for separator or tear-off entries. +used to invoke the same function as the menu entry. This is a display +option, it does not actually set the corresponding binding (which can +be achieved using the \fBbind\fR command). This option is not available +for separator or tear-off entries. .TP \fB\-background \fIvalue\fR . -- cgit v0.12 From 87ca801378d1a85bc3c5ae50263cdec51f80cff7 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 11 Aug 2016 12:12:27 +0000 Subject: Consider the Extended flag for both KeyPress and KeyRelease events coming from the extended (keypad) keys. I can't see why implementation of TIP #158 [b8333852a2] considered the extended flag only for KeyPress, and forced clearing it in the state integer for KeyRelease. --- win/tkWinX.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/win/tkWinX.c b/win/tkWinX.c index 6c44059..567b281 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -1321,11 +1321,7 @@ GetState( state &= ~mask; } if (HIWORD(lParam) & KF_EXTENDED) { - if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) { - state |= EXTENDED_MASK; - } else { - state &= ~EXTENDED_MASK; - } + state |= EXTENDED_MASK; } } return state; -- cgit v0.12 From 4fa07b0a11a1de74bd15b1ae9dcec8be210fcd34 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 11 Aug 2016 12:22:13 +0000 Subject: Left and right Control and Alt keys are distinguished using the Extended flag (the previously implemented trick only worked for KeyPress, not for KeyRelease). --- win/tkWinKey.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/win/tkWinKey.c b/win/tkWinKey.c index ed546f7..10cc7b8 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -335,18 +335,24 @@ KeycodeToKeysym( /* * Windows only gives us an undifferentiated VK_CONTROL code (for * example) when either Control key is pressed. To distinguish between - * left and right, we have to query the state of one of the two to - * determine which was actually pressed. So if the keycode indicates - * Control, Shift, or Menu (the key that everybody else calls Alt), do - * this extra test. If the right-side key was pressed, return the - * appropriate keycode. Otherwise, we fall through and rely on the - * keymap table to hold the correct keysym value. + * left and right, we use the Extended flag. Indeed, the right Control + * and Alt (aka Menu) keys are such extended keys (which their left + * counterparts are not). + * Regarding the shift case, Windows does not set the Extended flag for + * the neither the left nor the right shift key. As a consequence another + * way to distinguish between the two keys is to query the state of one + * of the two to determine which was actually pressed. So if the keycode + * indicates Shift, do this extra test. If the right-side key was + * pressed, return the appropriate keycode. Otherwise, we fall through + * and rely on the keymap table to hold the correct keysym value. + * Note: this little trick only works for KeyPress, not for KeyRelease, + * for reasons stated in bug [2945130] */ case VK_CONTROL: - if (GetKeyState(VK_RCONTROL) & 0x80) { - return XK_Control_R; - } + if (state & EXTENDED_MASK) { + return XK_Control_R; + } break; case VK_SHIFT: if (GetKeyState(VK_RSHIFT) & 0x80) { @@ -354,9 +360,9 @@ KeycodeToKeysym( } break; case VK_MENU: - if (GetKeyState(VK_RMENU) & 0x80) { - return XK_Alt_R; - } + if (state & EXTENDED_MASK) { + return XK_Alt_R; + } break; } return keymap[keycode]; -- cgit v0.12 From f494a10c21ef287a1b1546a351f97c3f15f47f99 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 12 Aug 2016 14:44:46 +0000 Subject: Change Tk_FreeXId() into a macro. A few end-of-line spacing eliminations. --- doc/FindPhoto.3 | 18 +++++++++--------- generic/tkDecls.h | 3 +++ generic/tkFrame.c | 1 - generic/tkStubInit.c | 9 +++++++++ generic/tkWindow.c | 2 +- macosx/tkMacOSXSubwindows.c | 2 +- macosx/tkMacOSXXStubs.c | 10 +--------- unix/tkUnixXId.c | 33 --------------------------------- win/tkWinX.c | 24 ------------------------ 9 files changed, 24 insertions(+), 78 deletions(-) diff --git a/doc/FindPhoto.3 b/doc/FindPhoto.3 index 2f15ea6..61a47de 100644 --- a/doc/FindPhoto.3 +++ b/doc/FindPhoto.3 @@ -99,8 +99,8 @@ being written to the photo image. particular photo image to the other procedures. The parameter is the name of the image, that is, the name specified to the \fBimage create photo\fR command, or assigned by that command if no name was specified. -If \fIimageName\fR does not exist or is not a photo image, -\fBTk_FindPhoto\fR returns NULL. +If \fIimageName\fR does not exist or is not a photo image, +\fBTk_FindPhoto\fR returns NULL. .PP \fBTk_PhotoPutBlock\fR is used to supply blocks of image data to be displayed. The call affects an area of the image of size @@ -184,16 +184,16 @@ that describe the address and layout of the image data that the photo image has stored internally. The values are valid until the image is destroyed or its size is changed. .PP -It is possible to modify an image by writing directly to the data +It is possible to modify an image by writing directly to the data the \fIpixelPtr\fR field points to. The size of the image cannot be changed this way, though. -Also, changes made by writing directly to \fIpixelPtr\fR will not be -immediately visible, but only after a call to -\fBTk_ImageChanged\fR or after an event that causes the interested +Also, changes made by writing directly to \fIpixelPtr\fR will not be +immediately visible, but only after a call to +\fBTk_ImageChanged\fR or after an event that causes the interested widgets to redraw themselves. -For these reasons usually it is preferable to make changes to -a copy of the image data and write it back with -\fBTk_PhotoPutBlock\fR or \fBTk_PhotoPutZoomedBlock\fR. +For these reasons usually it is preferable to make changes to +a copy of the image data and write it back with +\fBTk_PhotoPutBlock\fR or \fBTk_PhotoPutZoomedBlock\fR. .PP \fBTk_PhotoGetImage\fR returns 1 for compatibility with the corresponding procedure in the old photo widget. diff --git a/generic/tkDecls.h b/generic/tkDecls.h index 64c32cd..eaaaf6c 100644 --- a/generic/tkDecls.h +++ b/generic/tkDecls.h @@ -1721,6 +1721,9 @@ extern const TkStubs *tkStubsPtr; #undef Tk_SafeInit #undef Tk_CreateConsoleWindow +#undef Tk_FreeXId +#define Tk_FreeXId(display,xid) + #if defined(_WIN32) && defined(UNICODE) # define Tk_MainEx Tk_MainExW EXTERN void Tk_MainExW(int argc, wchar_t **argv, diff --git a/generic/tkFrame.c b/generic/tkFrame.c index f6edfb0..0f1a1b3 100644 --- a/generic/tkFrame.c +++ b/generic/tkFrame.c @@ -458,7 +458,6 @@ TkListCreateFrame( * window associated with the interpreter. * Gives the base name to use for the new * application. */ - { int objc; Tcl_Obj **objv; diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index f08d7f4..21e6a68 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -38,6 +38,15 @@ MODULE_SCOPE const TkStubs tkStubs; */ #undef Tk_MainEx +#undef Tk_FreeXId + +static void +doNothing(void) +{ + /* dummy implementation, no need to do anything */ +} + +#define Tk_FreeXId ((void (*)(Display *, XID)) doNothing) #ifdef _WIN32 diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 0c60321..5855b7c 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -3101,7 +3101,7 @@ Initialize( Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("::safe::TkInit", -1)); Tcl_ListObjAppendElement(NULL, cmd, Tcl_GetObjResult(master)); - + /* * Step 2 : Eval in the master. The argument is the *reversed* interp * path of the slave. diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 9851474..f92d260 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -365,7 +365,7 @@ XMoveResizeWindow( CGFloat Y = (CGFloat)y; CGFloat Width = (CGFloat)width; CGFloat Height = (CGFloat)height; - CGFloat XOff = (CGFloat)macWin->winPtr->wmInfoPtr->xInParent; + CGFloat XOff = (CGFloat)macWin->winPtr->wmInfoPtr->xInParent; CGFloat YOff = (CGFloat)macWin->winPtr->wmInfoPtr->yInParent; NSRect r = NSMakeRect(X + XOff, tkMacOSXZeroScreenHeight - Y - YOff - Height, diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index a2d175b..1313c9f 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -681,14 +681,6 @@ XForceScreenSaver( display->request++; } -void -Tk_FreeXId( - Display *display, - XID xid) -{ - /* no-op function needed for stubs implementation. */ -} - int XSync( Display *display, @@ -897,7 +889,7 @@ XGetImage( * We do not support any other values here. */ int scalefactor = 1; - if (win && [win respondsToSelector:@selector(backingScaleFactor)]) { + if (win && [win respondsToSelector:@selector(backingScaleFactor)]) { scalefactor = ([win backingScaleFactor] == 2.0) ? 2 : 1; } int scaled_height = height * scalefactor; diff --git a/unix/tkUnixXId.c b/unix/tkUnixXId.c index ec2451c..c6873a1 100644 --- a/unix/tkUnixXId.c +++ b/unix/tkUnixXId.c @@ -14,39 +14,6 @@ /* *---------------------------------------------------------------------- * - * Tk_FreeXId -- - * - * This function is called to indicate that an X resource identifier is - * now free. - * - * Results: - * None. - * - * Side effects: - * The identifier is added to the stack of free identifiers for its - * display, so that it can be re-used. - * - *---------------------------------------------------------------------- - */ - -void -Tk_FreeXId( - Display *display, /* Display for which xid was allocated. */ - XID xid) /* Identifier that is no longer in use. */ -{ - /* - * This does nothing, because the XC-MISC extension takes care of - * freeing XIDs for us. It has been a standard X11 extension for - * about 15 years as of 2008. Keith Packard and another X.org - * developer suggested that we remove the previous code that used: - * #define XLIB_ILLEGAL_ACCESS. - */ -} - - -/* - *---------------------------------------------------------------------- - * * Tk_GetPixmap -- * * Same as the XCreatePixmap function except that it manages resource diff --git a/win/tkWinX.c b/win/tkWinX.c index 6c44059..7e25826 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -1610,30 +1610,6 @@ HandleIMEComposition( /* *---------------------------------------------------------------------- * - * Tk_FreeXId -- - * - * This interface is not needed under Windows. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -Tk_FreeXId( - Display *display, - XID xid) -{ - /* Do nothing */ -} - -/* - *---------------------------------------------------------------------- - * * TkWinResendEvent -- * * This function converts an X event into a Windows event and invokes the -- cgit v0.12 From 53641c0fb520f426b05a61602b586bb18b15e01b Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 13 Aug 2016 20:03:33 +0000 Subject: Fixed [a2abc45ee6] - Cursor at wrong position after event generate -warp on secondary screen --- generic/tkBind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tkBind.c b/generic/tkBind.c index 3b05066..d3fdc96 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -3460,7 +3460,7 @@ HandleEventGenerate( Tcl_DoWhenIdle(DoWarp, dispPtr); dispPtr->flags |= TK_DISPLAY_IN_WARP; } - dispPtr->warpWindow = Tk_IdToWindow(Tk_Display(mainWin), + dispPtr->warpWindow = Tk_IdToWindow(dispPtr->display, event.general.xmotion.window); dispPtr->warpMainwin = mainWin; dispPtr->warpX = event.general.xmotion.x; -- cgit v0.12 From 24e47b1d059cf68f776b57faf187e4e022ad2a13 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 19 Aug 2016 20:31:26 +0000 Subject: Fixed [fa32290898] - Can't dismiss ttk::menubutton menu until mouse has hovered over it --- library/menu.tcl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/menu.tcl b/library/menu.tcl index a7aaa3f..b5dd88e 100644 --- a/library/menu.tcl +++ b/library/menu.tcl @@ -607,6 +607,10 @@ proc ::tk::MenuButtonDown menu { if {![winfo viewable $menu]} { return } + if {[$menu index active] eq "none"} { + set Priv(window) {} + return + } $menu postcascade active if {$Priv(postedMb) ne "" && [winfo viewable $Priv(postedMb)]} { grab -global $Priv(postedMb) -- cgit v0.12 From 6fb89b6069a9896acc6a2dc61f6b4f86e1b4e92c Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 19 Aug 2016 21:47:34 +0000 Subject: Fixed [2cf3d6942c] - Test button-5.24 fails. First, use {Helvetica -12} as font for the button text instead of {Helvetica -12 bold} since it's the former and not the latter that is tested against in constraints.tcl regarding the 'font' constraint. Second, don't force -width to a fixed value, otherwise width results can be wrong. Third, adjust the test results in width according to the two previous changes. --- tests/button.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/button.test b/tests/button.test index 708fc30..194e877 100644 --- a/tests/button.test +++ b/tests/button.test @@ -3435,15 +3435,15 @@ test button-5.23 {ConfigureButton - -height option} -constraints { test button-5.24 {ConfigureButton - computing geometry} -constraints { fonts } -body { - button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold} - .b configure -text "Sample text" -width 10 -height 2 + button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} + .b configure -text "Sample text" -height 2 pack .b set result "[winfo reqwidth .b] [winfo reqheight .b]" .b configure -bitmap questhead lappend result [winfo reqwidth .b] [winfo reqheight .b] } -cleanup { destroy .b -} -result {104 46 20 12} +} -result {96 46 30 12} test button-5.25 {ConfigureButton - computing geometry} -setup { button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold} -- cgit v0.12 From d27dd9b903416ca1a90206b913495225ac79133c Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 23 Aug 2016 18:27:14 +0000 Subject: Improved further test button-5.24: the test no longer depends on default values for -padx and -pady and it now computes the expected size of the button --- tests/button.test | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/tests/button.test b/tests/button.test index 194e877..d4db317 100644 --- a/tests/button.test +++ b/tests/button.test @@ -3435,15 +3435,47 @@ test button-5.23 {ConfigureButton - -height option} -constraints { test button-5.24 {ConfigureButton - computing geometry} -constraints { fonts } -body { - button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} - .b configure -text "Sample text" -height 2 + button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \ + -padx 30 -pady 20 + # 1. button with text + .b configure -text "Sample text" pack .b - set result "[winfo reqwidth .b] [winfo reqheight .b]" - .b configure -bitmap questhead - lappend result [winfo reqwidth .b] [winfo reqheight .b] -} -cleanup { - destroy .b -} -result {96 46 30 12} + set textwidth [font measure [.b cget -font] -displayof .b [.b cget -text]] + set expectedwidth [expr {$textwidth + 2*[.b cget -borderwidth] \ + + 2*[.b cget -highlightthickness] + 2*[.b cget -padx]}] + incr expectedwidth 2 ; # added (hardcoded) in tkUnixButton.c + set result [expr $expectedwidth == [winfo reqwidth .b]] + set linespace [lindex [font metrics [.b cget -font] -displayof .b] 5] + set expectedheight [expr {$linespace + 2*[.b cget -borderwidth] \ + + 2*[.b cget -highlightthickness] + 2*[.b cget -pady]}] + incr expectedheight 2 ; # added (hardcoded) in tkUnixButton.c + lappend result [expr $expectedheight == [winfo reqheight .b]] + # 2. button with a bitmap image + # there is no access to characteristics the predefined bitmaps, + # so define one as an image (copied from questhead.xbm) + set myquesthead [image create bitmap -data { + #define myquesthead_width 20 + #define myquesthead_height 22 + static unsigned char myquesthead_bits[] = { + 0xf8, 0x1f, 0x00, 0xac, 0x2a, 0x00, 0x56, 0x55, 0x00, 0xeb, 0xaf, 0x00, + 0xf5, 0x5f, 0x01, 0xfb, 0xbf, 0x00, 0x75, 0x5d, 0x01, 0xfb, 0xbe, 0x02, + 0x75, 0x5d, 0x05, 0xab, 0xbe, 0x0a, 0x55, 0x5f, 0x07, 0xab, 0xaf, 0x00, + 0xd6, 0x57, 0x01, 0xac, 0xab, 0x00, 0xd8, 0x57, 0x00, 0xb0, 0xaa, 0x00, + 0x50, 0x55, 0x00, 0xb0, 0x0b, 0x00, 0xd0, 0x17, 0x00, 0xb0, 0x0b, 0x00, + 0x58, 0x15, 0x00, 0xa8, 0x2a, 0x00}; + }] + .b configure -image $myquesthead + set expectedwidth [expr {[image width $myquesthead] + 2*[.b cget -borderwidth] \ + + 2*[.b cget -highlightthickness]}] + incr expectedwidth 2 ; # added (hardcoded) in tkUnixButton.c + lappend result [expr $expectedwidth == [winfo reqwidth .b]] + set expectedheight [expr {[image height $myquesthead] + 2*[.b cget -borderwidth] \ + + 2*[.b cget -highlightthickness]}] + incr expectedheight 2 ; # added (hardcoded) in tkUnixButton.c + lappend result [expr $expectedheight == [winfo reqheight .b]] +} -cleanup { + destroy .b +} -result {1 1 1 1} test button-5.25 {ConfigureButton - computing geometry} -setup { button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold} -- cgit v0.12 From 1e6f41e17ea6b546ea891d57ed147b09a8c2f7cd Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 23 Aug 2016 19:30:19 +0000 Subject: Added non regression test case menu-38.1 --- tests/menu.test | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/menu.test b/tests/menu.test index aaadc86..a97aa25 100644 --- a/tests/menu.test +++ b/tests/menu.test @@ -3878,6 +3878,35 @@ test menu-37.1 {menubar menues cannot be posted - bug 2160206} -setup { destroy .m } -result {1 {a menubar menu cannot be posted}} +test menu-38.1 {Can't dismiss ttk::menubutton menu until mouse has hovered over it - bug fa32290898} -setup { +} -body { + toplevel .top + ttk::menubutton .top.mb -text "Some menu"; + menu .top.mb.m; + .top.mb.m add command -label "Item 1"; + .top.mb.m add command -label "Item 2"; + .top.mb configure -menu .top.mb.m; + pack .top.mb + update + # simulate mouse click on the menubutton, which posts its menu + event generate .top.mb -warp 1 + update + after 50 + event generate .top.mb + update + # simulate mouse click on the menu again, i.e. without + # entering/leaving the posted menu + event generate .top.mb + update + after 50 + event generate .top.mb + update + # the menu shall have been unposted by the second click + winfo ismapped .top.mb.m +} -cleanup { + destroy .top.mb.m .top.m .top +} -result {0} + # cleanup imageFinish -- cgit v0.12 From 3f31a49af5095bb916f325335fefc3a101c687fe Mon Sep 17 00:00:00 2001 From: fvogel Date: Mon, 29 Aug 2016 17:42:45 +0000 Subject: Constrained test menu-38.1 to Unix or Mac platforms since this test hangs on Windows and the corresponding bug was reported for Linux and Mac only --- tests/menu.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/menu.test b/tests/menu.test index a97aa25..05356e3 100644 --- a/tests/menu.test +++ b/tests/menu.test @@ -3879,7 +3879,7 @@ test menu-37.1 {menubar menues cannot be posted - bug 2160206} -setup { } -result {1 {a menubar menu cannot be posted}} test menu-38.1 {Can't dismiss ttk::menubutton menu until mouse has hovered over it - bug fa32290898} -setup { -} -body { +} -constraints {macOrUnix} -body { toplevel .top ttk::menubutton .top.mb -text "Some menu"; menu .top.mb.m; -- cgit v0.12 From bdab09a0d9b8ae500789e11038ce4a96802388ec Mon Sep 17 00:00:00 2001 From: pspjuth Date: Tue, 30 Aug 2016 19:46:35 +0000 Subject: Made text widget's default undo false again. --- generic/tkText.c | 2 +- tests/text.test | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index 5ad527a..ab77d99 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -547,7 +547,7 @@ CreateWidget( Tcl_InitHashTable(&sharedPtr->windowTable, TCL_STRING_KEYS); Tcl_InitHashTable(&sharedPtr->imageTable, TCL_STRING_KEYS); sharedPtr->undoStack = TkUndoInitStack(interp,0); - sharedPtr->undo = 1; + sharedPtr->undo = 0; sharedPtr->isDirty = 0; sharedPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; sharedPtr->autoSeparators = 1; diff --git a/tests/text.test b/tests/text.test index 720afbe..f640817 100644 --- a/tests/text.test +++ b/tests/text.test @@ -29,6 +29,15 @@ test text-1.1 {configuration option: "autoseparators"} -setup { } -cleanup { destroy .t } -result {1} +test text-1.1b {configuration option: "autoseparators", default} -setup { + text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} + pack .t + update +} -body { + .t cget -autoseparators +} -cleanup { + destroy .t +} -result {1} test text-1.2 {configuration option: "autoseparators"} -setup { text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} pack .t @@ -428,6 +437,15 @@ test text-1.43 {configuration option: "maxundo"} -setup { } -cleanup { destroy .t } -result {5} +test text-1.43b {configuration option: "maxundo", default} -setup { + text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} + pack .t + update +} -body { + .t cget -maxundo +} -cleanup { + destroy .t +} -result {0} test text-1.44 {configuration option: "maxundo"} -setup { text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} pack .t @@ -732,6 +750,15 @@ test text-1.75 {configuration option: "undo"} -setup { } -cleanup { destroy .t } -result {1} +test text-1.75b {configuration option: "undo", default} -setup { + text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} + pack .t + update +} -body { + .t cget -undo +} -cleanup { + destroy .t +} -result {0} test text-1.76 {configuration option: "undo"} -setup { text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} pack .t @@ -6396,8 +6423,23 @@ test text-27.16a {undo configuration options with peers} -body { lappend res [.t edit canundo] lappend res [.tt edit canundo] } -cleanup { - destroy .t + destroy .t .tt } -result {1 1 0 0 100 100 1 1} +test text-27.16b {undo configuration options with peers, defaults} -body { + text .t + .t peer create .tt + set res [.t cget -undo] + lappend res [.tt cget -undo] + lappend res [.t cget -autoseparators] + lappend res [.tt cget -autoseparators] + lappend res [.t cget -maxundo] + lappend res [.tt cget -maxundo] + .t insert end "The undo stack is common between peers" + lappend res [.t edit canundo] + lappend res [.tt edit canundo] +} -cleanup { + destroy .t .tt +} -result {0 0 1 1 0 0 0 0} test text-27.17 {bug fix 1536735 - undo with empty text} -body { text .t -undo 1 set r [.t edit modified] -- cgit v0.12 From 34d8945d9d1dbbb3f599cabcad75ec0305f7615d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 31 Aug 2016 08:50:23 +0000 Subject: Fix use of XMaxTransChars in stead of TCL_UTF_MAX in some places. This should prevent possible buffer overflow when TCL_UTF_MAX=6 Micro-optimizations in tkEntry and ttkEntry --- generic/tkEntry.c | 3 ++- generic/ttk/ttkEntry.c | 3 ++- win/tkWinFont.c | 2 +- win/tkWinKey.c | 4 ++-- win/tkWinX.c | 4 ++-- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/generic/tkEntry.c b/generic/tkEntry.c index ea8d7f1..c0ce47b 100644 --- a/generic/tkEntry.c +++ b/generic/tkEntry.c @@ -1943,7 +1943,8 @@ EntryComputeGeometry( entryPtr->displayString = p; for (i = entryPtr->numChars; --i >= 0; ) { - p += Tcl_UniCharToUtf(ch, p); + memcpy(p, buf, size); + p += size; } *p = '\0'; } diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index f395649..533637d 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -290,7 +290,8 @@ static char *EntryDisplayString(const char *showChar, int numChars) p = displayString = ckalloc(numChars * size + 1); while (numChars--) { - p += Tcl_UniCharToUtf(ch, p); + memcpy(p, buf, size); + p += size; } *p = '\0'; diff --git a/win/tkWinFont.c b/win/tkWinFont.c index 9172b00..940bc10 100644 --- a/win/tkWinFont.c +++ b/win/tkWinFont.c @@ -2188,7 +2188,7 @@ FontMapLoadPage( { FontFamily *familyPtr; Tcl_Encoding encoding; - char src[TCL_UTF_MAX], buf[16]; + char src[XMaxTransChars], buf[16]; USHORT *startCount, *endCount; int i, j, bitOffset, end, segCount; diff --git a/win/tkWinKey.c b/win/tkWinKey.c index ed546f7..5591133 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -102,7 +102,7 @@ TkpGetString( */ int unichar; - char buf[TCL_UTF_MAX]; + char buf[XMaxTransChars]; int len; unichar = keyEv->trans_chars[1] & 0xff; @@ -129,7 +129,7 @@ TkpGetString( if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256)) || (keysym == XK_Return) || (keysym == XK_Tab)) { - char buf[TCL_UTF_MAX]; + char buf[XMaxTransChars]; int len; len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf); diff --git a/win/tkWinX.c b/win/tkWinX.c index 6c44059..99102cb 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -1215,13 +1215,13 @@ GenerateXEvent( break; case WM_UNICHAR: { - char buffer[TCL_UTF_MAX+1]; + char buffer[XMaxTransChars]; int i; event.type = KeyPress; event.xany.send_event = -3; event.xkey.keycode = wParam; event.xkey.nbytes = Tcl_UniCharToUtf((int)wParam, buffer); - for (i=0; i Date: Thu, 1 Sep 2016 20:10:57 +0000 Subject: Cherrypicked [c8256e859a] - Fix from pspjuth to restore the default false value of -undo which was unintentionally changed by [3ff41efa17] --- generic/tkText.c | 2 +- tests/text.test | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index 8be8881..4821993 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -547,7 +547,7 @@ CreateWidget( Tcl_InitHashTable(&sharedPtr->windowTable, TCL_STRING_KEYS); Tcl_InitHashTable(&sharedPtr->imageTable, TCL_STRING_KEYS); sharedPtr->undoStack = TkUndoInitStack(interp,0); - sharedPtr->undo = 1; + sharedPtr->undo = 0; sharedPtr->isDirty = 0; sharedPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; sharedPtr->autoSeparators = 1; diff --git a/tests/text.test b/tests/text.test index 720afbe..f640817 100644 --- a/tests/text.test +++ b/tests/text.test @@ -29,6 +29,15 @@ test text-1.1 {configuration option: "autoseparators"} -setup { } -cleanup { destroy .t } -result {1} +test text-1.1b {configuration option: "autoseparators", default} -setup { + text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} + pack .t + update +} -body { + .t cget -autoseparators +} -cleanup { + destroy .t +} -result {1} test text-1.2 {configuration option: "autoseparators"} -setup { text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} pack .t @@ -428,6 +437,15 @@ test text-1.43 {configuration option: "maxundo"} -setup { } -cleanup { destroy .t } -result {5} +test text-1.43b {configuration option: "maxundo", default} -setup { + text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} + pack .t + update +} -body { + .t cget -maxundo +} -cleanup { + destroy .t +} -result {0} test text-1.44 {configuration option: "maxundo"} -setup { text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} pack .t @@ -732,6 +750,15 @@ test text-1.75 {configuration option: "undo"} -setup { } -cleanup { destroy .t } -result {1} +test text-1.75b {configuration option: "undo", default} -setup { + text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} + pack .t + update +} -body { + .t cget -undo +} -cleanup { + destroy .t +} -result {0} test text-1.76 {configuration option: "undo"} -setup { text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} pack .t @@ -6396,8 +6423,23 @@ test text-27.16a {undo configuration options with peers} -body { lappend res [.t edit canundo] lappend res [.tt edit canundo] } -cleanup { - destroy .t + destroy .t .tt } -result {1 1 0 0 100 100 1 1} +test text-27.16b {undo configuration options with peers, defaults} -body { + text .t + .t peer create .tt + set res [.t cget -undo] + lappend res [.tt cget -undo] + lappend res [.t cget -autoseparators] + lappend res [.tt cget -autoseparators] + lappend res [.t cget -maxundo] + lappend res [.tt cget -maxundo] + .t insert end "The undo stack is common between peers" + lappend res [.t edit canundo] + lappend res [.tt edit canundo] +} -cleanup { + destroy .t .tt +} -result {0 0 1 1 0 0 0 0} test text-27.17 {bug fix 1536735 - undo with empty text} -body { text .t -undo 1 set r [.t edit modified] -- cgit v0.12