summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorfvogel <fvogelnew1@free.fr>2016-05-30 18:07:48 (GMT)
committerfvogel <fvogelnew1@free.fr>2016-05-30 18:07:48 (GMT)
commit61f4d4b1a44a82f6d6082cc1aee657e9891d954c (patch)
tree13255d2cd63dc0c7da5e6be2d5e7e39a47dd391d /generic
parentb03ce9960743ca1b27876129d6eb5ae3e8c978c2 (diff)
parent46068f3d4b5d7f6f6099a8558c0a5ba58ab72927 (diff)
downloadtk-61f4d4b1a44a82f6d6082cc1aee657e9891d954c.zip
tk-61f4d4b1a44a82f6d6082cc1aee657e9891d954c.tar.gz
tk-61f4d4b1a44a82f6d6082cc1aee657e9891d954c.tar.bz2
Merged TIP #446 accepted by TCT vote. This fixes [1273358] - Ask a text widget for the depth of its undo and redo stacks.
Diffstat (limited to 'generic')
-rw-r--r--generic/tkText.c112
-rw-r--r--generic/tkUndo.c52
-rw-r--r--generic/tkUndo.h4
3 files changed, 146 insertions, 22 deletions
diff --git a/generic/tkText.c b/generic/tkText.c
index 82fc6b0..ea2aed3 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -401,6 +401,7 @@ static Tcl_Obj * TextGetText(const TkText *textPtr,
const TkTextIndex *index1,
const TkTextIndex *index2, int visibleOnly);
static void GenerateModifiedEvent(TkText *textPtr);
+static void GenerateUndoStackEvent(TkText *textPtr);
static void UpdateDirtyFlag(TkSharedText *sharedPtr);
static void RunAfterSyncCmd(ClientData clientData);
static void TextPushUndoAction(TkText *textPtr,
@@ -2093,7 +2094,7 @@ ConfigureText(
textPtr->sharedTextPtr->maxUndo = textPtr->maxUndo;
textPtr->sharedTextPtr->autoSeparators = textPtr->autoSeparators;
- TkUndoSetDepth(textPtr->sharedTextPtr->undoStack,
+ TkUndoSetMaxDepth(textPtr->sharedTextPtr->undoStack,
textPtr->sharedTextPtr->maxUndo);
/*
@@ -2769,6 +2770,7 @@ TextPushUndoAction(
/* Index describing second location. */
{
TkUndoSubAtom *iAtom, *dAtom;
+ int canUndo, canRedo;
/*
* Create the helpers.
@@ -2855,6 +2857,9 @@ TextPushUndoAction(
Tcl_DecrRefCount(index1Obj);
Tcl_DecrRefCount(index2Obj);
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+
/*
* Depending whether the action is to insert or delete, we provide the
* appropriate second and third arguments to TkUndoPushAction. (The first
@@ -2866,6 +2871,10 @@ TextPushUndoAction(
} else {
TkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom);
}
+
+ if (!canUndo || canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
}
/*
@@ -5155,11 +5164,16 @@ TextEditCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
int index, setModified, oldModified;
+ int canRedo = 0;
+ int canUndo = 0;
+
static const char *const editOptionStrings[] = {
- "modified", "redo", "reset", "separator", "undo", NULL
+ "canundo", "canredo", "modified", "redo", "reset", "separator",
+ "undo", NULL
};
enum editOptions {
- EDIT_MODIFIED, EDIT_REDO, EDIT_RESET, EDIT_SEPARATOR, EDIT_UNDO
+ EDIT_CANUNDO, EDIT_CANREDO, EDIT_MODIFIED, EDIT_REDO, EDIT_RESET,
+ EDIT_SEPARATOR, EDIT_UNDO
};
if (objc < 3) {
@@ -5173,6 +5187,26 @@ TextEditCmd(
}
switch ((enum editOptions) index) {
+ case EDIT_CANREDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (textPtr->sharedTextPtr->undo) {
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canRedo));
+ break;
+ case EDIT_CANUNDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (textPtr->sharedTextPtr->undo) {
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canUndo));
+ break;
case EDIT_MODIFIED:
if (objc == 3) {
Tcl_SetObjResult(interp,
@@ -5206,29 +5240,36 @@ TextEditCmd(
*/
if ((!oldModified) != (!setModified)) {
- for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
- textPtr = textPtr->next) {
- GenerateModifiedEvent(textPtr);
- }
+ GenerateModifiedEvent(textPtr);
}
break;
case EDIT_REDO:
- if (objc != 3) {
+ if (objc != 3) {
Tcl_WrongNumArgs(interp, 3, objv, NULL);
return TCL_ERROR;
}
- if (TextEditRedo(textPtr)) {
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ if (TextEditRedo(textPtr)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1));
Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL);
return TCL_ERROR;
}
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ if (!canUndo || !canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
break;
case EDIT_RESET:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 3, objv, NULL);
return TCL_ERROR;
}
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
TkUndoClearStacks(textPtr->sharedTextPtr->undoStack);
+ if (canUndo || canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
break;
case EDIT_SEPARATOR:
if (objc != 3) {
@@ -5238,15 +5279,20 @@ TextEditCmd(
TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);
break;
case EDIT_UNDO:
- if (objc != 3) {
+ if (objc != 3) {
Tcl_WrongNumArgs(interp, 3, objv, NULL);
return TCL_ERROR;
}
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
if (TextEditUndo(textPtr)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1));
Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL);
return TCL_ERROR;
}
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ if (!canRedo || !canUndo) {
+ GenerateUndoStackEvent(textPtr);
+ }
break;
}
return TCL_OK;
@@ -5341,7 +5387,8 @@ TextGetText(
*
* Send an event that the text was modified. This is equivalent to:
* event generate $textWidget <<Modified>>
- *
+ * for all peers of $textWidget.
+*
* Results:
* None
*
@@ -5355,8 +5402,41 @@ static void
GenerateModifiedEvent(
TkText *textPtr) /* Information about text widget. */
{
- Tk_MakeWindowExist(textPtr->tkwin);
- TkSendVirtualEvent(textPtr->tkwin, "Modified", NULL);
+ for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
+ textPtr = textPtr->next) {
+ Tk_MakeWindowExist(textPtr->tkwin);
+ TkSendVirtualEvent(textPtr->tkwin, "Modified", NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateUndoStackEvent --
+ *
+ * Send an event that the undo or redo stack became empty or unempty.
+ * This is equivalent to:
+ * event generate $textWidget <<UndoStack>>
+ * for all peers of $textWidget.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * May force the text window (and all peers) into existence.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateUndoStackEvent(
+ TkText *textPtr) /* Information about text widget. */
+{
+ for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
+ textPtr = textPtr->next) {
+ Tk_MakeWindowExist(textPtr->tkwin);
+ TkSendVirtualEvent(textPtr->tkwin, "UndoStack", NULL);
+ }
}
/*
@@ -5380,7 +5460,6 @@ UpdateDirtyFlag(
TkSharedText *sharedTextPtr)/* Information about text widget. */
{
int oldDirtyFlag;
- TkText *textPtr;
/*
* If we've been forced to be dirty, we stay dirty (until explicitly
@@ -5411,10 +5490,7 @@ UpdateDirtyFlag(
}
if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) {
- for (textPtr = sharedTextPtr->peers; textPtr != NULL;
- textPtr = textPtr->next) {
- GenerateModifiedEvent(textPtr);
- }
+ GenerateModifiedEvent(sharedTextPtr->peers);
}
}
diff --git a/generic/tkUndo.c b/generic/tkUndo.c
index 8359e0a..c66905d 100644
--- a/generic/tkUndo.c
+++ b/generic/tkUndo.c
@@ -353,7 +353,7 @@ TkUndoInitStack(
/*
*----------------------------------------------------------------------
*
- * TkUndoSetDepth --
+ * TkUndoSetMaxDepth --
*
* Set the maximum depth of stack.
*
@@ -368,7 +368,7 @@ TkUndoInitStack(
*/
void
-TkUndoSetDepth(
+TkUndoSetMaxDepth(
TkUndoRedoStack *stack, /* An Undo/Redo stack */
int maxdepth) /* The maximum stack depth */
{
@@ -478,6 +478,52 @@ TkUndoFreeStack(
/*
*----------------------------------------------------------------------
*
+ * TkUndoCanRedo --
+ *
+ * Returns true if redo is possible, i.e. if the redo stack is not empty.
+ *
+ * Results:
+ * A boolean.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoCanRedo(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ return stack->redoStack != NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoCanUndo --
+ *
+ * Returns true if undo is possible, i.e. if the undo stack is not empty.
+ *
+ * Results:
+ * A boolean.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoCanUndo(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ return stack->undoStack != NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkUndoInsertUndoSeparator --
*
* Insert a separator on the undo stack, indicating a border for an
@@ -498,7 +544,7 @@ TkUndoInsertUndoSeparator(
{
if (TkUndoInsertSeparator(&stack->undoStack)) {
stack->depth++;
- TkUndoSetDepth(stack, stack->maxdepth);
+ TkUndoSetMaxDepth(stack, stack->maxdepth);
}
}
diff --git a/generic/tkUndo.h b/generic/tkUndo.h
index e63aac4..490ede9 100644
--- a/generic/tkUndo.h
+++ b/generic/tkUndo.h
@@ -96,9 +96,11 @@ MODULE_SCOPE void TkUndoClearStack(TkUndoAtom **stack);
*/
MODULE_SCOPE TkUndoRedoStack *TkUndoInitStack(Tcl_Interp *interp, int maxdepth);
-MODULE_SCOPE void TkUndoSetDepth(TkUndoRedoStack *stack, int maxdepth);
+MODULE_SCOPE void TkUndoSetMaxDepth(TkUndoRedoStack *stack, int maxdepth);
MODULE_SCOPE void TkUndoClearStacks(TkUndoRedoStack *stack);
MODULE_SCOPE void TkUndoFreeStack(TkUndoRedoStack *stack);
+MODULE_SCOPE int TkUndoCanRedo(TkUndoRedoStack *stack);
+MODULE_SCOPE int TkUndoCanUndo(TkUndoRedoStack *stack);
MODULE_SCOPE void TkUndoInsertUndoSeparator(TkUndoRedoStack *stack);
MODULE_SCOPE TkUndoSubAtom *TkUndoMakeCmdSubAtom(Tcl_Command command,
Tcl_Obj *actionScript, TkUndoSubAtom *subAtomList);