Tk Source Code

Changes On Branch tip-446-undodepth
Login

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

Changes In Branch tip-446-undodepth Excluding Merge-Ins

This is equivalent to a diff from 047d31f2 to e1dbced6

2016-05-12
22:22
Unified branched tip-446-undodepth and tip-446-canundo to become branch tip-446 Closed-Leaf check-in: e9c606f4 user: fvogel tags: mistake
22:21
Unified branched tip-446-undodepth and tip-446-canundo to become branch tip-446 check-in: 2bfc04af user: fvogel tags: tip-446
2016-05-02
20:16
Fixed Americano-British English (American English selected) check-in: 192eb2f0 user: fvogel tags: core-8-6-branch
2016-05-01
20:03
Merged core-8-6-branch Closed-Leaf check-in: e1dbced6 user: fvogel tags: tip-446-undodepth
19:58
Fixed [b362182e45] - Generation of virtual events through Tk_HandleEvent is unsafe check-in: 1419e83a user: fvogel tags: trunk
19:51
Fixed [b362182e45] - Generation of virtual events through Tk_HandleEvent is unsafe check-in: 047d31f2 user: fvogel tags: core-8-6-branch
2016-04-29
09:42
Fixed [fd3a4dc111] - <<Modified>> event is not always sent to peers check-in: bf86da71 user: fvogel tags: core-8-6-branch
2016-04-22
20:15
Added test text-11a.51 to check the fix of [b362182e45] Closed-Leaf check-in: cd123af9 user: fvogel tags: bug-b362182e45
2016-04-07
20:18
Tests for [.t edit undodepth/redodepth] check-in: 00090592 user: fvogel tags: tip-446-undodepth

Changes to doc/text.n.
1290
1291
1292
1293
1294
1295
1296






1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312






1313
1314
1315
1316
1317
1318
1319
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331







+
+
+
+
+
+
















+
+
+
+
+
+







of the widget to \fIboolean\fR.
.TP
\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.
.TP
\fIpathName \fBedit redodepth\fR
.
Returns the depth of the redo stack (number of redoable actions). When this is
zero there is nothing to redo. When the \fB\-undo\fR option is false zero is
returned.
.TP
\fIpathName \fBedit reset\fR
.
Clears the undo and redo stacks.
.TP
\fIpathName \fBedit separator\fR
.
Inserts a separator (boundary) on the undo stack. Does nothing when the
\fB\-undo\fR option is false.
.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
stack is empty. Does nothing when the \fB\-undo\fR option is false.
.TP
\fIpathName \fBedit undodepth\fR
.
Returns the depth of the undo stack (number of undoable actions). When this is
zero there is nothing to undo. When the \fB\-undo\fR option is false zero is
returned.
.RE
.TP
\fIpathName \fBget\fR ?\fB\-displaychars\fR? ?\fB\-\-\fR? \fIindex1\fR ?\fIindex2 ...\fR?
.
Return a range of characters from the text. The return value will be all the
characters in the text starting with the one whose index is \fIindex1\fR and
ending just before the one whose index is \fIindex2\fR (the character at
Changes to generic/tkText.c.
2089
2090
2091
2092
2093
2094
2095
2096

2097
2098
2099
2100
2101
2102
2103
2089
2090
2091
2092
2093
2094
2095

2096
2097
2098
2099
2100
2101
2102
2103







-
+







     * Copy down shared flags.
     */

    textPtr->sharedTextPtr->undo = textPtr->undo;
    textPtr->sharedTextPtr->maxUndo = textPtr->maxUndo;
    textPtr->sharedTextPtr->autoSeparators = textPtr->autoSeparators;

    TkUndoSetDepth(textPtr->sharedTextPtr->undoStack,
    TkUndoSetMaxDepth(textPtr->sharedTextPtr->undoStack,
	    textPtr->sharedTextPtr->maxUndo);

    /*
     * A few other options also need special processing, such as parsing the
     * geometry and setting the background from a 3-D border.
     */

5152
5153
5154
5155
5156
5157
5158
5159


5160
5161
5162


5163
5164
5165
5166
5167
5168
5169
5152
5153
5154
5155
5156
5157
5158

5159
5160
5161
5162

5163
5164
5165
5166
5167
5168
5169
5170
5171







-
+
+


-
+
+







    TkText *textPtr,		/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, setModified, oldModified;
    static const char *const editOptionStrings[] = {
	"modified", "redo", "reset", "separator", "undo", NULL
	"modified", "redo", "redodepth", "reset", "separator", "undo",
        "undodepth", NULL
    };
    enum editOptions {
	EDIT_MODIFIED, EDIT_REDO, EDIT_RESET, EDIT_SEPARATOR, EDIT_UNDO
	EDIT_MODIFIED, EDIT_REDO, EDIT_REDODEPTH, EDIT_RESET,
        EDIT_SEPARATOR, EDIT_UNDO, EDIT_UNDODEPTH
    };

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

5219
5220
5221
5222
5223
5224
5225













5226
5227
5228
5229
5230
5231
5232
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247







+
+
+
+
+
+
+
+
+
+
+
+
+







	}
	if (TextEditRedo(textPtr)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1));
	    Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL);
	    return TCL_ERROR;
	}
	break;
    case EDIT_REDODEPTH: {
        int depth = 0;

        if (objc != 3) {
            Tcl_WrongNumArgs(interp, 3, objv, NULL);
            return TCL_ERROR;
        }
        if (textPtr->sharedTextPtr->undo) {
            depth = TkUndoGetDepth(textPtr->sharedTextPtr->undoStack, 1);
        }
        Tcl_SetObjResult(interp, Tcl_NewIntObj(depth));
        break;
    }
    case EDIT_RESET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
	TkUndoClearStacks(textPtr->sharedTextPtr->undoStack);
	break;
5244
5245
5246
5247
5248
5249
5250













5251
5252
5253
5254
5255
5256
5257
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285







+
+
+
+
+
+
+
+
+
+
+
+
+







	}
	if (TextEditUndo(textPtr)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1));
	    Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL);
	    return TCL_ERROR;
	}
	break;
    case EDIT_UNDODEPTH: {
        int depth = 0;

        if (objc != 3) {
            Tcl_WrongNumArgs(interp, 3, objv, NULL);
            return TCL_ERROR;
        }
        if (textPtr->sharedTextPtr->undo) {
            depth = TkUndoGetDepth(textPtr->sharedTextPtr->undoStack, 0);
        }
        Tcl_SetObjResult(interp, Tcl_NewIntObj(depth));
        break;
    }
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
Changes to generic/tkUndo.c.
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
349
350
351
352
353
354
355

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

371
372
373
374
375
376
377
378







-
+














-
+







    stack->depth = 0;
    return stack;
}

/*
 *----------------------------------------------------------------------
 *
 * TkUndoSetDepth --
 * TkUndoSetMaxDepth --
 *
 *	Set the maximum depth of stack.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May delete elements from the stack if the new maximum depth is smaller
 *	than the number of elements previously in the stack.
 *
 *----------------------------------------------------------------------
 */

void
TkUndoSetDepth(
TkUndoSetMaxDepth(
    TkUndoRedoStack *stack,	/* An Undo/Redo stack */
    int maxdepth)		/* The maximum stack depth */
{
    stack->maxdepth = maxdepth;

    if (stack->maxdepth>0 && stack->depth>stack->maxdepth) {
	TkUndoAtom *elem, *prevelem;
420
421
422
423
424
425
426





























































427
428
429
430
431
432
433
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    }
	    elem = elem->next;
	    ckfree(prevelem);
	}
	stack->depth = stack->maxdepth;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkUndoGetDepth
 *
 *	Return the depth of the undo (or redo) stack.
 *
 * Results:
 *	An integer representing the number of undoable (or redoable) actions.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkUndoGetDepth(
    TkUndoRedoStack *stack,	/* An Undo/Redo stack */
    int whichStack)		/* 0 means the undo stack,
                                 * otherwise the redo stack */
{
    int depth = 0;
    TkUndoAtom *elem = NULL;

    if (stack != NULL) {
        if (whichStack) {
            elem = stack->redoStack;
        } else {
            elem = stack->undoStack;
        }

        if (elem != NULL) {
            /*
             * Skip the first (top) separator if there is one.
             */

            if (elem->type == TK_UNDO_SEPARATOR) {
                elem = elem->next;
            }

            /*
             * The number of compound actions in the stack is then
             * the number of separators plus one, except if there is
             * a separator at the bottom of the stack. This latter
             * case cannot however happen (TkUndoInsertSeparator
             * prevents from inserting a separator there).
             */

            while (elem != NULL) {
                if (elem->type == TK_UNDO_SEPARATOR) {
                    depth++;
                }
                elem = elem->next;
            }
            depth++;
        }
    }
    return depth;
}

/*
 *----------------------------------------------------------------------
 *
 * TkUndoClearStacks --
 *
 *	Clear both the undo and redo stack.
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
555
556
557
558
559
560
561

562
563
564
565
566
567
568
569







-
+








void
TkUndoInsertUndoSeparator(
    TkUndoRedoStack *stack)
{
    if (TkUndoInsertSeparator(&stack->undoStack)) {
	stack->depth++;
	TkUndoSetDepth(stack, stack->maxdepth);
	TkUndoSetMaxDepth(stack, stack->maxdepth);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkUndoRevert --
Changes to generic/tkUndo.h.
92
93
94
95
96
97
98
99


100
101
102
103
104
105
106
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106
107







-
+
+







MODULE_SCOPE void	TkUndoClearStack(TkUndoAtom **stack);

/*
 * Functions for working on an undo/redo 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 int	TkUndoGetDepth(TkUndoRedoStack *stack, int whichStack);
MODULE_SCOPE void	TkUndoClearStacks(TkUndoRedoStack *stack);
MODULE_SCOPE void	TkUndoFreeStack(TkUndoRedoStack *stack);
MODULE_SCOPE void	TkUndoInsertUndoSeparator(TkUndoRedoStack *stack);
MODULE_SCOPE TkUndoSubAtom *TkUndoMakeCmdSubAtom(Tcl_Command command,
			    Tcl_Obj *actionScript, TkUndoSubAtom *subAtomList);
MODULE_SCOPE TkUndoSubAtom *TkUndoMakeSubAtom(TkUndoProc *funcPtr,
			    ClientData clientData, Tcl_Obj *actionScript,
Changes to tests/text.test.
6203
6204
6205
6206
6207
6208
6209
6210

6211
6212
6213
6214
6215
6216
6217
6203
6204
6205
6206
6207
6208
6209

6210
6211
6212
6213
6214
6215
6216
6217







-
+







    destroy .t
} -returnCodes {error} -result {wrong # args: should be ".t edit option ?arg ...?"}
test text-27.2 {TextEditCmd procedure, argument parsing} -body {
    pack [text .t]
    .t edit gorp
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad edit option "gorp": must be modified, redo, reset, separator, or undo}
} -returnCodes {error} -result {bad edit option "gorp": must be modified, redo, redodepth, reset, separator, undo, or undodepth}
test text-27.3 {TextEditUndo procedure, undoing changes} -body {
    text .t -undo 1
    pack .t
    .t insert end "line 1\n"
    .t delete 1.4 1.6
    .t insert end "should be gone after undo\n"
    .t edit undo
6490
6491
6492
6493
6494
6495
6496


























6497
6498
6499
6500
6501
6502
6503
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    event generate .top.t <<Cut>>
    event generate .top.t <Delete>
    event generate .top.t <<Undo>>
    .top.t get 1.0 "1.0 lineend"
} -cleanup {
    destroy .top.t .top
} -result "This A an example text"
test text-27.24 {TextEditCmd procedure, undo and redo stack depths} -setup {
    destroy .t
    set res {}
} -body {
    text .t -undo false -autoseparators false
    lappend res [.t edit undodepth] [.t edit redodepth]
    .t configure -undo true
    lappend res [.t edit undodepth] [.t edit redodepth]
    .t insert end "DO\n"
    .t edit separator
    .t insert end "IT\n"
    .t insert end "YOURSELF\n"
    .t edit separator
    lappend res [.t edit undodepth] [.t edit redodepth]
    .t edit undo
    lappend res [.t edit undodepth] [.t edit redodepth]
    .t configure -undo false
    lappend res [.t edit undodepth] [.t edit redodepth]
    .t configure -undo true
    lappend res [.t edit undodepth] [.t edit redodepth]
    .t edit redo
    lappend res [.t edit undodepth] [.t edit redodepth]
} -cleanup {
    destroy .t
} -result {0 0 0 0 2 0 1 1 0 0 1 1 2 0}


test text-28.1 {bug fix - 624372, ControlUtfProc long lines} -body {
    pack [text .t -wrap none]
    .t insert end [string repeat "\1" 500]
} -cleanup {
    destroy .t
} -result {}