Tk Source Code

Check-in [b699eb0e]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Took comments from Koen Danckaert into account (with my thanks) to simplify the implementation of TkUndoCanUndo() and TkUndoCanRedo() in tkUndo.c, and in tkText.c to remove direct calls to internals of the undo or redo stack
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-446
Files: files | file ages | folders
SHA1: b699eb0e2cb0acd16c39095dcf9f632b931614ee
User & Date: fvogel 2016-05-17 20:00:20
Context
2016-05-30
18:05
Merged TIP #446 accepted by TCT vote. This fixes [1273358] - Ask a text widget for the depth of its undo and redo stacks. check-in: 85fe3473 user: fvogel tags: core-8-6-branch
2016-05-17
20:00
Took comments from Koen Danckaert into account (with my thanks) to simplify the implementation of TkUndoCanUndo() and TkUndoCanRedo() in tkUndo.c, and in tkText.c to remove direct calls to internals of the undo or redo stack Closed-Leaf check-in: b699eb0e user: fvogel tags: tip-446
2016-05-12
22:21
Unified branched tip-446-undodepth and tip-446-canundo to become branch tip-446 check-in: 2bfc04af user: fvogel tags: tip-446
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkText.c.

2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
....
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
....
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
....
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
....
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
    int insert,			/* 1 if insert, else delete. */
    const TkTextIndex *index1Ptr,
				/* Index describing first location. */
    const TkTextIndex *index2Ptr)
				/* Index describing second location. */
{
    TkUndoSubAtom *iAtom, *dAtom;
    TkUndoAtom *redoElem, *undoElem;

    /*
     * Create the helpers.
     */

    Tcl_Obj *seeInsertObj = Tcl_NewObj();
    Tcl_Obj *markSet1InsertObj = Tcl_NewObj();
................................................................................
    TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom);
    TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom);

    Tcl_DecrRefCount(seeInsertObj);
    Tcl_DecrRefCount(index1Obj);
    Tcl_DecrRefCount(index2Obj);

    undoElem = textPtr->sharedTextPtr->undoStack->undoStack;
    redoElem = textPtr->sharedTextPtr->undoStack->redoStack;

    /*
     * Depending whether the action is to insert or delete, we provide the
     * appropriate second and third arguments to TkUndoPushAction. (The first
     * is the 'actionCommand', and the second the 'revertCommand').
     */

    if (insert) {
	TkUndoPushAction(textPtr->sharedTextPtr->undoStack, iAtom, dAtom);
    } else {
	TkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom);
    }

    if (undoElem == NULL || redoElem != NULL) {
        GenerateUndoStackEvent(textPtr);
    }
}
 
/*
 *----------------------------------------------------------------------
 *
................................................................................
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, setModified, oldModified;
    int canRedo = 0;
    int canUndo = 0;
    TkUndoAtom *redoElem, *undoElem;

    static const char *const editOptionStrings[] = {
	"canundo", "canredo", "modified", "redo", "reset", "separator",
        "undo", NULL
    };
    enum editOptions {
	EDIT_CANUNDO, EDIT_CANREDO, EDIT_MODIFIED, EDIT_REDO, EDIT_RESET,
................................................................................
	}
	break;
    case EDIT_REDO:
        if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
	undoElem = textPtr->sharedTextPtr->undoStack->undoStack;
        if (TextEditRedo(textPtr)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1));
	    Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL);
	    return TCL_ERROR;
	}
        redoElem = textPtr->sharedTextPtr->undoStack->redoStack;
        if (undoElem == NULL || redoElem == NULL) {
            GenerateUndoStackEvent(textPtr);
        }
	break;
    case EDIT_RESET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
        undoElem = textPtr->sharedTextPtr->undoStack->undoStack;
        redoElem = textPtr->sharedTextPtr->undoStack->redoStack;
	TkUndoClearStacks(textPtr->sharedTextPtr->undoStack);
        if (undoElem != NULL || redoElem != NULL) {
            GenerateUndoStackEvent(textPtr);
        }
	break;
    case EDIT_SEPARATOR:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
................................................................................
	TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);
	break;
    case EDIT_UNDO:
        if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
        redoElem = textPtr->sharedTextPtr->undoStack->redoStack;
	if (TextEditUndo(textPtr)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1));
	    Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL);
	    return TCL_ERROR;
	}
        undoElem = textPtr->sharedTextPtr->undoStack->undoStack;
        if (redoElem == NULL || undoElem == NULL) {
            GenerateUndoStackEvent(textPtr);
        }
	break;
    }
    return TCL_OK;
}
 






|







 







|
|













|







 







<







 







|





|
|








|
|

|







 







|





|
|







2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
....
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
....
5162
5163
5164
5165
5166
5167
5168

5169
5170
5171
5172
5173
5174
5175
....
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
....
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
    int insert,			/* 1 if insert, else delete. */
    const TkTextIndex *index1Ptr,
				/* Index describing first location. */
    const TkTextIndex *index2Ptr)
				/* Index describing second location. */
{
    TkUndoSubAtom *iAtom, *dAtom;
    int canUndo, canRedo;

    /*
     * Create the helpers.
     */

    Tcl_Obj *seeInsertObj = Tcl_NewObj();
    Tcl_Obj *markSet1InsertObj = Tcl_NewObj();
................................................................................
    TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom);
    TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom);

    Tcl_DecrRefCount(seeInsertObj);
    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
     * is the 'actionCommand', and the second the 'revertCommand').
     */

    if (insert) {
	TkUndoPushAction(textPtr->sharedTextPtr->undoStack, iAtom, dAtom);
    } else {
	TkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom);
    }

    if (!canUndo || canRedo) {
        GenerateUndoStackEvent(textPtr);
    }
}
 
/*
 *----------------------------------------------------------------------
 *
................................................................................
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, setModified, oldModified;
    int canRedo = 0;
    int canUndo = 0;


    static const char *const editOptionStrings[] = {
	"canundo", "canredo", "modified", "redo", "reset", "separator",
        "undo", NULL
    };
    enum editOptions {
	EDIT_CANUNDO, EDIT_CANREDO, EDIT_MODIFIED, EDIT_REDO, EDIT_RESET,
................................................................................
	}
	break;
    case EDIT_REDO:
        if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
	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) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
................................................................................
	TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);
	break;
    case EDIT_UNDO:
        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;
}
 

Changes to generic/tkUndo.c.

491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
...
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
 *----------------------------------------------------------------------
 */

int
TkUndoCanRedo(
    TkUndoRedoStack *stack)	/* An Undo/Redo stack */
{
    int canRedo = 0;
    TkUndoAtom *elem = stack->redoStack;

    while (elem != NULL) {
        if (elem->type != TK_UNDO_SEPARATOR) {
            canRedo = 1;
            break;
        }
        elem = elem->next;
    }
    return canRedo;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkUndoCanUndo --
 *
................................................................................
 *----------------------------------------------------------------------
 */

int
TkUndoCanUndo(
    TkUndoRedoStack *stack)	/* An Undo/Redo stack */
{
    int canUndo = 0;
    TkUndoAtom *elem = stack->undoStack;

    while (elem != NULL) {
        if (elem->type != TK_UNDO_SEPARATOR) {
            canUndo = 1;
            break;
        }
        elem = elem->next;
    }
    return canUndo;
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkUndoInsertUndoSeparator --
 *






<
|
<
<
<
<
<
<
<
<
<







 







<
|
<
<
<
<
<
<
<
<
<







491
492
493
494
495
496
497

498









499
500
501
502
503
504
505
...
514
515
516
517
518
519
520

521









522
523
524
525
526
527
528
 *----------------------------------------------------------------------
 */

int
TkUndoCanRedo(
    TkUndoRedoStack *stack)	/* An Undo/Redo stack */
{

    return stack->redoStack != NULL;









}
 
/*
 *----------------------------------------------------------------------
 *
 * TkUndoCanUndo --
 *
................................................................................
 *----------------------------------------------------------------------
 */

int
TkUndoCanUndo(
    TkUndoRedoStack *stack)	/* An Undo/Redo stack */
{

    return stack->undoStack != NULL;









}
 
/*
 *----------------------------------------------------------------------
 *
 * TkUndoInsertUndoSeparator --
 *