Tk Source Code

Check-in [6dfcc8fc]
Login

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

Overview
Comment:[Bug-1630262], [Bug-1615425]: segfault when deleting lines or tagging outside of the -startline/-endline range with peer text widgets. [Bug-3487407]: Weird text indices.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-5-branch
Files: files | file ages | folders
SHA1: 6dfcc8fcfa744972be7ebe6720289b49f2c67736
User & Date: fvogel 2012-02-28 20:14:21
Context
2012-03-04
16:55
Patch from the cygwin folks check-in: b6c4a954 user: jan.nijtmans tags: core-8-5-branch
2012-02-28
20:44
[Bug-1630262], [Bug-1615425]: segfault when deleting lines or tagging outside of the -startline/-endline range with peer text widgets. [Bug-3487407]: Weird text indices. check-in: 5528cb09 user: fvogel tags: trunk
20:14
[Bug-1630262], [Bug-1615425]: segfault when deleting lines or tagging outside of the -startline/-endline range with peer text widgets. [Bug-3487407]: Weird text indices. check-in: 6dfcc8fc user: fvogel tags: core-8-5-branch
13:46
[Bug 3495198]: Corrected types of canvas bitmap options. check-in: 1b7382b2 user: dkf tags: core-8-5-branch
2012-02-18
21:55
Bug-3487407: Weird text indices Closed-Leaf check-in: f39a8001 user: fvogel tags: bug-1630262
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.










1
2
3
4
5
6
7









2012-02-28  Donal K. Fellows  <[email protected]>

	* doc/canvas.n: [Bug 3495198]: Corrected types of bitmap options.

2012-02-26  Jan Nijtmans  <[email protected]>

	* xlib/xcolors.c: Provide fallback for _strtoi64
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2012-02-28  Francois Vogel  <[email protected]>

	* generic/tkText.c:      [Bug-1630262], [Bug-1615425]: segfault
	* generic/tkTextBTree.c  when deleting lines or tagging outside of
	* generic/tkTextDisp.c   the -startline/-endline range with peer
	* generic/tkTextMark.c   text widgets.
	* tests/text.test        [Bug-3487407]: Weird text indices.
	* tests/textMark.test

2012-02-28  Donal K. Fellows  <[email protected]>

	* doc/canvas.n: [Bug 3495198]: Corrected types of bitmap options.

2012-02-26  Jan Nijtmans  <[email protected]>

	* xlib/xcolors.c: Provide fallback for _strtoi64

Changes to generic/tkText.c.

2103
2104
2105
2106
2107
2108
2109




2110
2111
2112
2113
2114
2115
2116
	}

	/* Indices are potentially obsolete after changing -startline and/or
	 * -endline, therefore increase the epoch.
	 * Also, clamp the insert and current (unshared) marks to the new
	 * -startline/-endline range limits of the widget. All other (shared)
	 * marks are unchanged.




	 */

	textPtr->sharedTextPtr->stateEpoch++;
	TkTextMarkNameToIndex(textPtr, "insert", &index3);
	if (TkTextIndexCmp(&index3, &index1) < 0) {
	    textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &index1);
	}







>
>
>
>







2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
	}

	/* Indices are potentially obsolete after changing -startline and/or
	 * -endline, therefore increase the epoch.
	 * Also, clamp the insert and current (unshared) marks to the new
	 * -startline/-endline range limits of the widget. All other (shared)
	 * marks are unchanged.
         * The return value of TkTextMarkNameToIndex does not need to be
         * checked: "insert" and "current" marks always exist, and the
         * purpose of the code below precisely is to move them inside the
         * -startline/-endline range.
	 */

	textPtr->sharedTextPtr->stateEpoch++;
	TkTextMarkNameToIndex(textPtr, "insert", &index3);
	if (TkTextIndexCmp(&index3, &index1) < 0) {
	    textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &index1);
	}
3093
3094
3095
3096
3097
3098
3099





3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115





3116
3117
3118
3119
3120
3121
3122
		 * Deletion range starts on top line but after topIndex. Use
		 * the current topIndex as the new one.
		 */

		resetView = 1;
		line = line1;
		byteIndex = tPtr->topIndex.byteIndex;





	    }
	} else if (index2.linePtr == tPtr->topIndex.linePtr) {
	    /*
	     * Deletion range ends on top line but before topIndex. Figure out
	     * what will be the new character index for the character
	     * currently pointed to by topIndex.
	     */

	    resetView = 1;
	    line = line2;
	    byteIndex = tPtr->topIndex.byteIndex;
	    if (index1.linePtr != index2.linePtr) {
		byteIndex -= index2.byteIndex;
	    } else {
		byteIndex -= (index2.byteIndex - index1.byteIndex);
	    }





	}
	if (resetView) {
	    lineAndByteIndex[resetViewCount] = line;
	    lineAndByteIndex[resetViewCount+1] = byteIndex;
	} else {
	    lineAndByteIndex[resetViewCount] = -1;
	}







>
>
>
>
>
















>
>
>
>
>







3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
		 * Deletion range starts on top line but after topIndex. Use
		 * the current topIndex as the new one.
		 */

		resetView = 1;
		line = line1;
		byteIndex = tPtr->topIndex.byteIndex;
            } else {
                /*
                 * Deletion range starts after the top line. This peers's view
                 * will not need to be reset. Nothing to do.
                 */
	    }
	} else if (index2.linePtr == tPtr->topIndex.linePtr) {
	    /*
	     * Deletion range ends on top line but before topIndex. Figure out
	     * what will be the new character index for the character
	     * currently pointed to by topIndex.
	     */

	    resetView = 1;
	    line = line2;
	    byteIndex = tPtr->topIndex.byteIndex;
	    if (index1.linePtr != index2.linePtr) {
		byteIndex -= index2.byteIndex;
	    } else {
		byteIndex -= (index2.byteIndex - index1.byteIndex);
	    }
        } else {
            /*
             * Deletion range ends before the top line. This peers's view
             * will not need to be reset. Nothing to do.
             */
	}
	if (resetView) {
	    lineAndByteIndex[resetViewCount] = line;
	    lineAndByteIndex[resetViewCount+1] = byteIndex;
	} else {
	    lineAndByteIndex[resetViewCount] = -1;
	}
3153
3154
3155
3156
3157
3158
3159
3160








3161
3162
3163
3164
3165
3166
3167





















3168
3169
3170
3171
3172
3173
3174
	int line = lineAndByteIndex[resetViewCount];

	if (line != -1) {
	    int byteIndex = lineAndByteIndex[resetViewCount+1];
	    TkTextIndex indexTmp;

	    if (tPtr == textPtr) {
		if (viewUpdate) {








		    TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line,
			    byteIndex, &indexTmp);
		    TkTextSetYView(tPtr, &indexTmp, 0);
		}
	    } else {
		TkTextMakeByteIndex(sharedTextPtr->tree, NULL, line,
			byteIndex, &indexTmp);





















		TkTextSetYView(tPtr, &indexTmp, 0);
	    }
	}
	resetViewCount += 2;
    }
    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
	ckfree((char *) lineAndByteIndex);







|
>
>
>
>
>
>
>
>





|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
	int line = lineAndByteIndex[resetViewCount];

	if (line != -1) {
	    int byteIndex = lineAndByteIndex[resetViewCount+1];
	    TkTextIndex indexTmp;

	    if (tPtr == textPtr) {
                if (viewUpdate) {
                    /*
                     * line cannot be before -startline of textPtr because
                     * this line corresponds to an index which is necessarily
                     * between "1.0" and "end" relative to textPtr.
                     * Therefore no need to clamp line to the -start/-end
                     * range.
                     */

		    TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line,
			    byteIndex, &indexTmp);
		    TkTextSetYView(tPtr, &indexTmp, 0);
		}
	    } else {
                TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, line,
			byteIndex, &indexTmp);
                /*
                 * line may be before -startline of tPtr and must be
                 * clamped to -startline before providing it to
                 * TkTextSetYView otherwise lines before -startline
                 * would be displayed.
                 * There is no need to worry about -endline however,
                 * because the view will only be reset if the deletion
                 * involves the TOP line of the screen
                 */

                if (tPtr->start != NULL) {
                    int start;
                    TkTextIndex indexStart;

                    start = TkBTreeLinesTo(NULL, tPtr->start);
                    TkTextMakeByteIndex(sharedTextPtr->tree, NULL, start,
			    0, &indexStart);
                    if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) {
                        indexTmp = indexStart;
                    }
                }
		TkTextSetYView(tPtr, &indexTmp, 0);
	    }
	}
	resetViewCount += 2;
    }
    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
	ckfree((char *) lineAndByteIndex);

Changes to generic/tkTextBTree.c.

658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
	treePtr->startEndRef = (TkText **)
		ckrealloc((char *) treePtr->startEndRef,
		sizeof(TkText *) * count);

	if (textPtr->start != NULL) {
	    count--;
	    treePtr->startEnd[count] = textPtr->start;
	    treePtr->startEndRef[count] = treePtr->sharedTextPtr->peers;
	}
	if (textPtr->end != NULL) {
	    count--;
	    treePtr->startEnd[count] = textPtr->end;
	    treePtr->startEndRef[count] = treePtr->sharedTextPtr->peers;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *







|




|







658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
	treePtr->startEndRef = (TkText **)
		ckrealloc((char *) treePtr->startEndRef,
		sizeof(TkText *) * count);

	if (textPtr->start != NULL) {
	    count--;
	    treePtr->startEnd[count] = textPtr->start;
	    treePtr->startEndRef[count] = textPtr;
	}
	if (textPtr->end != NULL) {
	    count--;
	    treePtr->startEnd[count] = textPtr->end;
	    treePtr->startEndRef[count] = textPtr;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619

    nodePtr = treePtr->rootPtr;
    if ((line < 0) || (line >= nodePtr->numLines)) {
	return NULL;
    }

    /*
     * Check for the any start/end offset for this text widget.
     */

    if (textPtr != NULL) {
	if (textPtr->start != NULL) {
	    line += TkBTreeLinesTo(NULL, textPtr->start);
	    if (line >= nodePtr->numLines) {
		return NULL;







|







1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619

    nodePtr = treePtr->rootPtr;
    if ((line < 0) || (line >= nodePtr->numLines)) {
	return NULL;
    }

    /*
     * Check for any start/end offset for this text widget.
     */

    if (textPtr != NULL) {
	if (textPtr->start != NULL) {
	    line += TkBTreeLinesTo(NULL, textPtr->start);
	    if (line >= nodePtr->numLines) {
		return NULL;
1987
1988
1989
1990
1991
1992
1993
1994










1995


1996













1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
		nodePtr2 = nodePtr2->nextPtr) {
	    if (nodePtr2 == NULL) {
		Tcl_Panic("TkBTreeLinesTo couldn't find node");
	    }
	    index += nodePtr2->numLines;
	}
    }
    if (textPtr != NULL && textPtr->start != NULL) {










	index -= TkBTreeLinesTo(NULL, textPtr->start);


    }













    return index;
}

/*
 *----------------------------------------------------------------------
 *
 * TkBTreeLinkSegment --
 *
 *	This function adds a new segment to a B-tree at a given location.
 *







|
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>


|







1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
		nodePtr2 = nodePtr2->nextPtr) {
	    if (nodePtr2 == NULL) {
		Tcl_Panic("TkBTreeLinesTo couldn't find node");
	    }
	    index += nodePtr2->numLines;
	}
    }
    if (textPtr != NULL) {
        /* 
         * The index to return must be relative to textPtr, not to the entire
         * tree. Take care to never return a negative index when linePtr
         * denotes a line before -startline, or an index larger than the
         * number of lines in textPtr when linePtr is a line past -endline.
         */

        int indexStart, indexEnd;

        if (textPtr->start != NULL) {
            indexStart = TkBTreeLinesTo(NULL, textPtr->start);
        } else {
            indexStart = 0;
        }
        if (textPtr->end != NULL) {
            indexEnd = TkBTreeLinesTo(NULL, textPtr->end);
        } else {
            indexEnd = TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL);
        }
        if (index < indexStart) {
            index = 0;
        } else if (index > indexEnd) {
            index = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
        } else {
            index -= indexStart;
        }
    }
    return index;
}

/*
 *----------------------------------------------------------------------
 *
 * TkBTreeLinkSegment --
 *
 *	This function adds a new segment to a B-tree at a given location.
 *

Changes to generic/tkTextDisp.c.

1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
	 * displayed, or the lines above it.
	 */

	int spaceLeft = maxY - y;

	if (spaceLeft <= dInfoPtr->newTopPixelOffset) {
	    /*
	     * We can full up all the needed space just by showing more of the
	     * current top line.
	     */

	    dInfoPtr->newTopPixelOffset -= spaceLeft;
	    y += spaceLeft;
	    spaceLeft = 0;
	} else {







|







1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
	 * displayed, or the lines above it.
	 */

	int spaceLeft = maxY - y;

	if (spaceLeft <= dInfoPtr->newTopPixelOffset) {
	    /*
	     * We can fill up all the needed space just by showing more of the
	     * current top line.
	     */

	    dInfoPtr->newTopPixelOffset -= spaceLeft;
	    y += spaceLeft;
	    spaceLeft = 0;
	} else {
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
	fromLine = TkBTreeLinesTo(textPtr, linePtr);

	/*
	 * Invalidate the height calculations of each line in the given range.
	 */

	TkBTreeLinePixelEpoch(textPtr, linePtr) = 0;
	while (counter > 0 && linePtr != 0) {
	    linePtr = TkBTreeNextLine(textPtr, linePtr);
	    if (linePtr != NULL) {
		TkBTreeLinePixelEpoch(textPtr, linePtr) = 0;
	    }
	    counter--;
	}

	/*
	 * Now schedule an examination of each line in the union of the old
	 * and new update ranges, including the (possibly empty) range in
	 * between. If that between range is not-empty, then we are examining
	 * more lines than is strictly necessary (but the examination of the
	 * extra lines should be quick, since their pixelCalculationEpoch will
	 * be up to date). However, to keep track of that would require more
	 * complex record-keeping that what we have.
	 */

	if (dInfoPtr->lineUpdateTimer == NULL) {
	    dInfoPtr->currentMetricUpdateLine = fromLine;
	    if (action == TK_TEXT_INVALIDATE_DELETE) {
		lineCount = 0;
	    }







|














|







3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
	fromLine = TkBTreeLinesTo(textPtr, linePtr);

	/*
	 * Invalidate the height calculations of each line in the given range.
	 */

	TkBTreeLinePixelEpoch(textPtr, linePtr) = 0;
	while (counter > 0 && linePtr != NULL) {
	    linePtr = TkBTreeNextLine(textPtr, linePtr);
	    if (linePtr != NULL) {
		TkBTreeLinePixelEpoch(textPtr, linePtr) = 0;
	    }
	    counter--;
	}

	/*
	 * Now schedule an examination of each line in the union of the old
	 * and new update ranges, including the (possibly empty) range in
	 * between. If that between range is not-empty, then we are examining
	 * more lines than is strictly necessary (but the examination of the
	 * extra lines should be quick, since their pixelCalculationEpoch will
	 * be up to date). However, to keep track of that would require more
	 * complex record-keeping than what we have.
	 */

	if (dInfoPtr->lineUpdateTimer == NULL) {
	    dInfoPtr->currentMetricUpdateLine = fromLine;
	    if (action == TK_TEXT_INVALIDATE_DELETE) {
		lineCount = 0;
	    }

Changes to generic/tkTextMark.c.

281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296
297
298







299


300
301
302
303
304
305
306
	 * If this is the insertion point that's being moved, be sure to force
	 * a display update at the old position. Also, don't let the insertion
	 * cursor be after the final newline of the file.
	 */

	if (markPtr == textPtr->insertMarkPtr) {
	    TkTextIndex index, index2;


	    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
	    TkTextIndexForwChars(NULL,&index, 1, &index2, COUNT_INDICES);

	    /*
	     * While we wish to redisplay, no heights have changed, so no need
	     * to call TkTextInvalidateLineMetrics.
	     */

	    TkTextChanged(NULL, textPtr, &index, &index2);
	    if (TkBTreeLinesTo(textPtr, indexPtr->linePtr) ==







		    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr))  {


		TkTextIndexBackChars(NULL,indexPtr, 1, &insertIndex,
			COUNT_INDICES);
		indexPtr = &insertIndex;
	    }
	}
	TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);
    } else {







>










|
>
>
>
>
>
>
>
|
>
>







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
	 * If this is the insertion point that's being moved, be sure to force
	 * a display update at the old position. Also, don't let the insertion
	 * cursor be after the final newline of the file.
	 */

	if (markPtr == textPtr->insertMarkPtr) {
	    TkTextIndex index, index2;
            int nblines;

	    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);
	    TkTextIndexForwChars(NULL,&index, 1, &index2, COUNT_INDICES);

	    /*
	     * While we wish to redisplay, no heights have changed, so no need
	     * to call TkTextInvalidateLineMetrics.
	     */

	    TkTextChanged(NULL, textPtr, &index, &index2);

            /*
             * The number of lines in the widget is zero if and only if it is
             * a partial peer with -startline == -endline, i.e. an empty
             * peer. In this case the mark shall be set exactly at the given
             * index, and not one character backwards (bug 3487407).
             */

	    nblines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
	    if ((TkBTreeLinesTo(textPtr, indexPtr->linePtr) == nblines)
		    && (nblines > 0))  {
		TkTextIndexBackChars(NULL,indexPtr, 1, &insertIndex,
			COUNT_INDICES);
		indexPtr = &insertIndex;
	    }
	}
	TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);
    } else {
381
382
383
384
385
386
387

388
389
390





391
392
393
394
395
396
397
 * TkTextMarkNameToIndex --
 *
 *	Given the name of a mark, return an index corresponding to the mark
 *	name.
 *
 * Results:
 *	The return value is TCL_OK if "name" exists as a mark in the text

 *	widget. In this case *indexPtr is filled in with the next segment
 *	whose after the mark whose size is non-zero. TCL_ERROR is returned if
 *	the mark doesn't exist in the text widget.





 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */








>
|
|
|
>
>
>
>
>







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
 * TkTextMarkNameToIndex --
 *
 *	Given the name of a mark, return an index corresponding to the mark
 *	name.
 *
 * Results:
 *	The return value is TCL_OK if "name" exists as a mark in the text
 *	widget and is located within its -starline/-endline range. In this
 *	case *indexPtr is filled in with the next segment who is after the
 *	mark whose size is non-zero. TCL_ERROR is returned if the mark
 *	doesn't exist in the text widget, or if it is out of its -starline/
 *	-endline range. In this latter case *indexPtr still contains valid
 *	information, in particular TkTextMarkNameToIndex called with the
 *	"insert" or "current" mark name may return TCL_ERROR, but *indexPtr
 *	contains the correct index of this mark before -startline or after
 *	-endline.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

Changes to tests/text.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# This file is a Tcl script to test the code in the file tkText.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

# Create entries in the option database to be sure that geometry options
# like border width have predictable values.

option add *Text.borderWidth 2
option add *Text.highlightThickness 2
option add *Text.font {Courier -12}

text .t -width 20 -height 10













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# This file is a Tcl script to test the code in the file tkText.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

# Create entries in the odeption database to be sure that geometry options
# like border width have predictable values.

option add *Text.borderWidth 2
option add *Text.highlightThickness 2
option add *Text.font {Courier -12}

text .t -width 20 -height 10
3617
3618
3619
3620
3621
3622
3623






























































































3624
3625
3626
3627
3628
3629
3630
    lappend res [.t tag ranges sel]
    .t configure -start 25 -end 30
    lappend res [.t tag ranges sel]
    .t configure -start {} -end {}
    lappend res [.t tag ranges sel]
    set res
} {{10.0 20.0} {6.0 16.0} {6.0 11.0} {1.0 6.0} {1.0 2.0} {} {10.0 20.0}}































































































test text-33.1 {widget dump -command alters tags} {
    .t delete 1.0 end
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    proc Dumpy {key value index} {
      #puts "KK: $key, $value"







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
    lappend res [.t tag ranges sel]
    .t configure -start 25 -end 30
    lappend res [.t tag ranges sel]
    .t configure -start {} -end {}
    lappend res [.t tag ranges sel]
    set res
} {{10.0 20.0} {6.0 16.0} {6.0 11.0} {1.0 6.0} {1.0 2.0} {} {10.0 20.0}}

test text-32.2 {peer widget -start, -end and deletion (bug 1630262)} -setup {
    destroy .t .pt
    set res {}
} -body {
    text .t
    .t peer create .pt
    for {set i 1} {$i < 100} {incr i} {
      .t insert end "Line $i\n"
    }
    .t configure -startline 5
    # none of the following delete shall crash
    # (all did before fixing bug 1630262)
    # 1. delete on the same line: line1 == line2 in DeleteIndexRange,
    #    and resetView is true neither for .t not for .pt
    .pt delete 2.0 2.2
    # 2. delete just one line: line1 < line2 in DeleteIndexRange,
    #    and resetView is true only for .t, not for .pt
    .pt delete 2.0 3.0
    # 3. delete several lines: line1 < line2 in DeleteIndexRange,
    #    and resetView is true only for .t, not for .pt
    .pt delete 2.0 5.0
    # 4. delete to the end line: line1 < line2 in DeleteIndexRange,
    #    and resetView is true only for .t, not for .pt
    .pt delete 2.0 end
    # this test succeeds provided there is no crash
    set res 1
} -cleanup {
    destroy .pt
} -result {1}

test text-32.3 {peer widget -start, -end and deletion (bug 1630262)} -setup {
    destroy .t .pt
    set res {}
} -body {
    text .t
    .t peer create .pt
    for {set i 1} {$i < 100} {incr i} {
      .t insert end "Line $i\n"
    }
    .t configure -startline 5
    .pt configure -startline 3
    # the following delete shall not crash
    # (it did before fixing bug 1630262)
    .pt delete 2.0 3.0
    # moreover -startline shall be correct
    # (was wrong before fixing bug 1630262)
    lappend res [.t cget -start] [.pt cget -start]
} -cleanup {
    destroy .pt
} -result {4 3}

test text-32.4 {peer widget -start, -end and deletion (bug 1630262)} -setup {
    destroy .t .pt
    set res {}
} -body {
    text .t
    .t peer create .pt
    for {set i 1} {$i < 100} {incr i} {
      .t insert end "Line $i\n"
    }
    .t configure -startline 5 -endline 15
    .pt configure -startline 8 -endline 12
    # .pt now shows a range entirely inside the range of .pt
    # from .t, delete lines located after [.pt cget -end]
    .t delete 9.0 10.0
    # from .t, delete lines straddling [.pt cget -end]
    .t delete 6.0 9.0
    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]
    .t configure -startline 5 -endline 12
    .pt configure -startline 8 -endline 12
    # .pt now shows again a range entirely inside the range of .pt
    # from .t, delete lines located before [.pt cget -start]
    .t delete 2.0 3.0
    # from .t, delete lines straddling [.pt cget -start]
    .t delete 2.0 5.0
    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]
    .t configure -startline 22 -endline 31
    .pt configure -startline 42 -endline 51
    # .t now shows a range entirely before the range of .pt
    # from .t, delete some lines, then do it from .pt
    .t delete 2.0 3.0
    .t delete 2.0 5.0
    .pt delete 2.0 5.0
    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]
    .t configure -startline 55 -endline 75
    .pt configure -startline 60 -endline 70
    # .pt now shows a range entirely inside the range of .t
    # from .t, delete a range straddling the entire range of .pt
    .t delete 3.0 18.0
    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]
} -cleanup {
    destroy .pt
} -result {5 11 8 10 5 8 6 8 22 27 38 44 55 60 57 57}

test text-33.1 {widget dump -command alters tags} {
    .t delete 1.0 end
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    proc Dumpy {key value index} {
      #puts "KK: $key, $value"

Changes to tests/textMark.test.

166
167
168
169
170
171
172







173
174
175
176
177
178
179
  lappend res [.t get mymark]
  lappend res [catch {.pt get mymark} msg] $msg
} -cleanup {
  .t configure -startline {} -endline {}
  .pt configure -startline {} -endline {}
  .t mark unset mymark
} -result {1 {bad text index "mymark"} 1.0 1.0 1 {bad text index "mymark"} L 1 {bad text index "mymark"}}








catch {eval {.t mark unset} [.t mark names]}
test textMark-7.1 {MarkFindNext - invalid mark name} haveCourier12 {
    catch {.t mark next bogus} x
    set x
} {bad text index "bogus"}
test textMark-7.2 {MarkFindNext - marks at same location} haveCourier12 {







>
>
>
>
>
>
>







166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  lappend res [.t get mymark]
  lappend res [catch {.pt get mymark} msg] $msg
} -cleanup {
  .t configure -startline {} -endline {}
  .pt configure -startline {} -endline {}
  .t mark unset mymark
} -result {1 {bad text index "mymark"} 1.0 1.0 1 {bad text index "mymark"} L 1 {bad text index "mymark"}}
test textMark-6.5 {insert and current marks in an empty peer - bug 3487407} -body {
  .t mark set insert 1.0
  .t configure -start 5 -end 5
  set res [.t index insert]
} -cleanup {
  .t configure -startline {} -endline {}
} -result {1.0}

catch {eval {.t mark unset} [.t mark names]}
test textMark-7.1 {MarkFindNext - invalid mark name} haveCourier12 {
    catch {.t mark next bogus} x
    set x
} {bad text index "bogus"}
test textMark-7.2 {MarkFindNext - marks at same location} haveCourier12 {

Changes to tests/textTag.test.

143
144
145
146
147
148
149













150
151
152
153
154
155
156
    .t tag ranges sel
} {1.1 1.5 2.4 3.1 4.2 4.4}
test textTag-2.13 {TkTextTagCmd - "add" option} haveCourier12 {
    .t tag remove sel 1.0 end
    .t tag add sel 1.1 1.5 2.4
    .t tag ranges sel
} {1.1 1.5 2.4 2.5}














catch {.t tag delete x}
test textTag-3.1 {TkTextTagCmd - "bind" option} haveCourier12 {
    list [catch {.t tag bind} msg] $msg
} {1 {wrong # args: should be ".t tag bind tagName ?sequence? ?command?"}}
test textTag-3.2 {TkTextTagCmd - "bind" option} haveCourier12 {
    list [catch {.t tag bind 1 2 3 4} msg] $msg







>
>
>
>
>
>
>
>
>
>
>
>
>







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
    .t tag ranges sel
} {1.1 1.5 2.4 3.1 4.2 4.4}
test textTag-2.13 {TkTextTagCmd - "add" option} haveCourier12 {
    .t tag remove sel 1.0 end
    .t tag add sel 1.1 1.5 2.4
    .t tag ranges sel
} {1.1 1.5 2.4 2.5}
test textTag-2.14 {tag add before -startline - Bug 1615425} haveCourier12 {
    text .tt
    for {set i 1} {$i <10} {incr i} {
        .tt insert end "Line $i\n"
    }
    .tt tag configure mytag -font {Courier 12 bold}
    .tt peer create .ptt
    .ptt configure -startline 3 -endline 7
    # the test succeeds if next line does not crash
    .tt tag add mytag 1.0 1.end
    destroy .ptt .tt
    set res 1
} {1}

catch {.t tag delete x}
test textTag-3.1 {TkTextTagCmd - "bind" option} haveCourier12 {
    list [catch {.t tag bind} msg] $msg
} {1 {wrong # args: should be ".t tag bind tagName ?sequence? ?command?"}}
test textTag-3.2 {TkTextTagCmd - "bind" option} haveCourier12 {
    list [catch {.t tag bind 1 2 3 4} msg] $msg