Tk Source Code

Check-in [625b52ac]
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:Rename "yupdate" to "sync" and fix various test-cases
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-438
Files: files | file ages | folders
SHA1: 625b52ac1965c60eea39fe6fc6f1637e188e701a
User & Date: jan.nijtmans 2015-11-19 22:02:27
Context
2015-11-21
08:43
Adjusted when <<WidgetViewSync>> fires. Also %d now only has boolean value. Implementation in sync with TIP #438 rev. 1.10 check-in: 615bbce0 user: fvogel tags: tip-438
2015-11-19
22:02
Rename "yupdate" to "sync" and fix various test-cases check-in: 625b52ac user: jan.nijtmans tags: tip-438
21:59
Tcl_Preserve should be first I guess check-in: ab37b4ef user: fvogel tags: tip-438
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkText.c.

685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
....
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
....
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
    register TkText *textPtr = (TkText *) clientData;
    int result = TCL_OK;
    int index;

    static const char *optionStrings[] = {
	"bbox", "cget", "compare", "configure", "count", "debug", "delete",
	"dlineinfo", "dump", "edit", "get", "image", "index", "insert",
	"mark", "peer", "pendingyupdate", "replace", "scan", "search",
	"see", "tag", "window", "xview", "yupdate", "yview", NULL
    };
    enum options {
	TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT,
	TEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT,
	TEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK,
	TEXT_PEER, TEXT_PENDINGYUPDATE, TEXT_REPLACE, TEXT_SCAN,
	TEXT_SEARCH, TEXT_SEE, TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW,
	TEXT_YUPDATE, TEXT_YVIEW
    };

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

................................................................................
    }
    case TEXT_MARK:
	result = TkTextMarkCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_PEER:
	result = TextPeerCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_PENDINGYUPDATE: {
        int number;

        if (objc != 2) {
            Tcl_WrongNumArgs(interp, 2, objv, NULL);
            result = TCL_ERROR;
            goto done;
        }
        number = TkTextPendingyupdate(textPtr);
        Tcl_SetObjResult(interp, Tcl_NewIntObj(number));
        break;
    }
    case TEXT_REPLACE: {
	const TkTextIndex *indexFromPtr, *indexToPtr;

	if (objc < 5) {
................................................................................
	break;
    case TEXT_WINDOW:
	result = TkTextWindowCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_XVIEW:
	result = TkTextXviewCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_YUPDATE: {
	if (objc == 4) {
		Tcl_Obj *cmd = objv[3];
		const char *option = Tcl_GetString(objv[2]);
		if (strncmp(option, "-command", objv[2]->length)) {
		    Tcl_AppendResult(interp, "wrong option \"", option, "\": should be \"-command\"", NULL);
		    result = TCL_ERROR;
		    goto done;
		}
		Tcl_IncrRefCount(cmd);
		if (TkTextPendingyupdate(textPtr)) {
		    if (textPtr->afterSyncCmd) {
			Tcl_DecrRefCount(textPtr->afterSyncCmd);
		    }
			textPtr->afterSyncCmd = cmd;
		} else {
			result = Tcl_EvalObjEx(interp, cmd, TCL_EVAL_GLOBAL);
			Tcl_DecrRefCount(cmd);
		}
		break;
	} else if (objc != 2) {
		Tcl_WrongNumArgs(interp, 2, objv, "?-command command?");
		result = TCL_ERROR;
		goto done;
	}
	if (textPtr->afterSyncCmd) {
		Tcl_DecrRefCount(textPtr->afterSyncCmd);






|
|





|
|
|







 







|







|







 







|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
....
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
....
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
    register TkText *textPtr = (TkText *) clientData;
    int result = TCL_OK;
    int index;

    static const char *optionStrings[] = {
	"bbox", "cget", "compare", "configure", "count", "debug", "delete",
	"dlineinfo", "dump", "edit", "get", "image", "index", "insert",
	"mark", "peer", "pendingsync", "replace", "scan", "search",
	"see", "sync", "tag", "window", "xview", "yview", NULL
    };
    enum options {
	TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT,
	TEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT,
	TEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK,
	TEXT_PEER, TEXT_PENDINGSYNC, TEXT_REPLACE, TEXT_SCAN,
	TEXT_SEARCH, TEXT_SEE, TEXT_SYNC, TEXT_TAG, TEXT_WINDOW,
	TEXT_XVIEW, TEXT_YVIEW
    };

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

................................................................................
    }
    case TEXT_MARK:
	result = TkTextMarkCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_PEER:
	result = TextPeerCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_PENDINGSYNC: {
        int number;

        if (objc != 2) {
            Tcl_WrongNumArgs(interp, 2, objv, NULL);
            result = TCL_ERROR;
            goto done;
        }
        number = TkTextPendingsync(textPtr);
        Tcl_SetObjResult(interp, Tcl_NewIntObj(number));
        break;
    }
    case TEXT_REPLACE: {
	const TkTextIndex *indexFromPtr, *indexToPtr;

	if (objc < 5) {
................................................................................
	break;
    case TEXT_WINDOW:
	result = TkTextWindowCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_XVIEW:
	result = TkTextXviewCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_SYNC: {
	if (objc == 4) {
	    Tcl_Obj *cmd = objv[3];
	    const char *option = Tcl_GetString(objv[2]);
	    if (strncmp(option, "-command", objv[2]->length)) {
		Tcl_AppendResult(interp, "wrong option \"", option, "\": should be \"-command\"", NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    Tcl_IncrRefCount(cmd);
	    if (TkTextPendingsync(textPtr)) {
		if (textPtr->afterSyncCmd) {
		    Tcl_DecrRefCount(textPtr->afterSyncCmd);
		}
		    textPtr->afterSyncCmd = cmd;
	    } else {
		    result = Tcl_EvalObjEx(interp, cmd, TCL_EVAL_GLOBAL);
		    Tcl_DecrRefCount(cmd);
	    }
	break;
	} else if (objc != 2) {
		Tcl_WrongNumArgs(interp, 2, objv, "?-command command?");
		result = TCL_ERROR;
		goto done;
	}
	if (textPtr->afterSyncCmd) {
		Tcl_DecrRefCount(textPtr->afterSyncCmd);

Changes to generic/tkText.h.

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
MODULE_SCOPE int	TkTextMarkCmd(TkText *textPtr, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TkTextMarkNameToIndex(TkText *textPtr,
			    const char *name, TkTextIndex *indexPtr);
MODULE_SCOPE void	TkTextMarkSegToIndex(TkText *textPtr,
			    TkTextSegment *markPtr, TkTextIndex *indexPtr);
MODULE_SCOPE void	TkTextEventuallyRepick(TkText *textPtr);
MODULE_SCOPE int	TkTextPendingyupdate(TkText *textPtr);
MODULE_SCOPE void	TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr);
MODULE_SCOPE void	TkTextPixelIndex(TkText *textPtr, int x, int y,
			    TkTextIndex *indexPtr, int *nearest);
MODULE_SCOPE int	TkTextPrintIndex(const TkText *textPtr,
			    const TkTextIndex *indexPtr, char *string);
MODULE_SCOPE Tcl_Obj *	TkTextNewIndexObj(TkText *textPtr,
			    const TkTextIndex *indexPtr);






|







1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
MODULE_SCOPE int	TkTextMarkCmd(TkText *textPtr, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TkTextMarkNameToIndex(TkText *textPtr,
			    const char *name, TkTextIndex *indexPtr);
MODULE_SCOPE void	TkTextMarkSegToIndex(TkText *textPtr,
			    TkTextSegment *markPtr, TkTextIndex *indexPtr);
MODULE_SCOPE void	TkTextEventuallyRepick(TkText *textPtr);
MODULE_SCOPE int	TkTextPendingsync(TkText *textPtr);
MODULE_SCOPE void	TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr);
MODULE_SCOPE void	TkTextPixelIndex(TkText *textPtr, int x, int y,
			    TkTextIndex *indexPtr, int *nearest);
MODULE_SCOPE int	TkTextPrintIndex(const TkText *textPtr,
			    const TkTextIndex *indexPtr, char *string);
MODULE_SCOPE Tcl_Obj *	TkTextNewIndexObj(TkText *textPtr,
			    const TkTextIndex *indexPtr);

Changes to generic/tkTextDisp.c.

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
....
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
....
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
....
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
....
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
static int		DlineXOfIndex(TkText *textPtr,
			    DLine *dlPtr, int byteIndex);
static int		TextGetScrollInfoObj(Tcl_Interp *interp,
			    TkText *textPtr, int objc,
			    Tcl_Obj *CONST objv[], double *dblPtr,
			    int *intPtr);
static void		AsyncUpdateLineMetrics(ClientData clientData);
static void		GenerateTextLineHeightsInvalidEvent(TkText *textPtr);
static void		AsyncUpdateYScrollbar(ClientData clientData);
static int              IsStartOfNotMergedLine(TkText *textPtr,
                            CONST TkTextIndex *indexPtr);

/*
 * Result values returned by TextGetScrollInfoObj:
 */
................................................................................
    if (tkTextDebug) {
	char buffer[2 * TCL_INTEGER_SPACE + 1];

	sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine);
	LOG("tk_textInvalidateLine", buffer);
    }

    GenerateTextLineHeightsInvalidEvent(textPtr);

    /*
     * If we're not in the middle of a long-line calculation (metricEpoch==-1)
     * and we've reached the last line, then we're done.
     */

    if (dInfoPtr->metricEpoch == -1
	    && lineNum == dInfoPtr->lastMetricUpdateLine) {
	/*
	 * We have looped over all lines, so we're done. We must release our
	 * refCount on the widget (the timer token was already set to NULL
	 * above). If there is a registered command, run that first.
	 */

	if (textPtr->afterSyncCmd != NULL) {
	    int code;
	    Tcl_Preserve((ClientData)textPtr->interp);
	    code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL);
	    if (code != TCL_OK && code != TCL_CONTINUE
			&& code != TCL_BREAK) {
		    Tcl_AddErrorInfo(textPtr->interp, "\n    (text yupdate)");
		    Tcl_BackgroundError(textPtr->interp);
	    }
	    Tcl_Release((ClientData)textPtr->interp);
	    Tcl_DecrRefCount(textPtr->afterSyncCmd);
	    textPtr->afterSyncCmd = 0;
	}

................................................................................
    dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
	    AsyncUpdateLineMetrics, (ClientData) textPtr);
}
 
/*
 *----------------------------------------------------------------------
 *
 * GenerateTextLineHeightsInvalidEvent --
 *
 *      Send the <<TextLineHeightsInvalid>> event related to the text widget
 *      line metrics asynchronous update.
 *      This is equivalent to:
 *         event generate $textWidget <<TextLineHeightsInvalid>> -detail $N
 *      where $N is the number of lines for which the height is outdated.
 *
 * Results:
 *      None
 *
 * Side effects:
 *      If corresponding bindings are present, they will trigger.
 *
 *----------------------------------------------------------------------
 */

static void
GenerateTextLineHeightsInvalidEvent(
    TkText *textPtr)		/* Information about text widget. */
{
    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(textPtr->tkwin);
    event.general.xany.display = Tk_Display(textPtr->tkwin);
    event.virtual.name = Tk_GetUid("TextLineHeightsInvalid");
    event.virtual.user_data = Tcl_NewIntObj(TkTextPendingyupdate(textPtr));
    Tk_HandleEvent(&event.general);
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkTextUpdateLineMetrics --
................................................................................
    }
    return TCL_OK;
}
 
/*
 *--------------------------------------------------------------
 *
 * TkTextPendingyupdate --
 *
 *	This function computes how many lines are not up-to-date regarding
 *	asynchronous height calculations.
 *
 * Results:
 *	Returns a positive integer corresponding to the number of lines for
 *	which the height is outdated.
................................................................................
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkTextPendingyupdate(
    TkText *textPtr)		/* Information about text widget. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;

    return (dInfoPtr->lastMetricUpdateLine - dInfoPtr->currentMetricUpdateLine);
}
 






|







 







|











|








|







 







|

|


|












|










|
|







 







|







 







|







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
....
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
....
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
....
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
....
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
static int		DlineXOfIndex(TkText *textPtr,
			    DLine *dlPtr, int byteIndex);
static int		TextGetScrollInfoObj(Tcl_Interp *interp,
			    TkText *textPtr, int objc,
			    Tcl_Obj *CONST objv[], double *dblPtr,
			    int *intPtr);
static void		AsyncUpdateLineMetrics(ClientData clientData);
static void		GenerateWidgetViewSyncEvent(TkText *textPtr);
static void		AsyncUpdateYScrollbar(ClientData clientData);
static int              IsStartOfNotMergedLine(TkText *textPtr,
                            CONST TkTextIndex *indexPtr);

/*
 * Result values returned by TextGetScrollInfoObj:
 */
................................................................................
    if (tkTextDebug) {
	char buffer[2 * TCL_INTEGER_SPACE + 1];

	sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine);
	LOG("tk_textInvalidateLine", buffer);
    }

    GenerateWidgetViewSyncEvent(textPtr);

    /*
     * If we're not in the middle of a long-line calculation (metricEpoch==-1)
     * and we've reached the last line, then we're done.
     */

    if (dInfoPtr->metricEpoch == -1
	    && lineNum == dInfoPtr->lastMetricUpdateLine) {
	/*
	 * We have looped over all lines, so we're done. We must release our
	 * refCount on the widget (the timer token was already set to NULL
	 * above). If there is a registered aftersync command, run that first.
	 */

	if (textPtr->afterSyncCmd != NULL) {
	    int code;
	    Tcl_Preserve((ClientData)textPtr->interp);
	    code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL);
	    if (code != TCL_OK && code != TCL_CONTINUE
			&& code != TCL_BREAK) {
		    Tcl_AddErrorInfo(textPtr->interp, "\n    (text sync)");
		    Tcl_BackgroundError(textPtr->interp);
	    }
	    Tcl_Release((ClientData)textPtr->interp);
	    Tcl_DecrRefCount(textPtr->afterSyncCmd);
	    textPtr->afterSyncCmd = 0;
	}

................................................................................
    dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
	    AsyncUpdateLineMetrics, (ClientData) textPtr);
}
 
/*
 *----------------------------------------------------------------------
 *
 * GenerateWidgetViewSyncEvent --
 *
 *      Send the <<WidgetViewSync>> event related to the text widget
 *      line metrics asynchronous update.
 *      This is equivalent to:
 *         event generate $textWidget <<WidgetViewSync>> -detail $N
 *      where $N is the number of lines for which the height is outdated.
 *
 * Results:
 *      None
 *
 * Side effects:
 *      If corresponding bindings are present, they will trigger.
 *
 *----------------------------------------------------------------------
 */

static void
GenerateWidgetViewSyncEvent(
    TkText *textPtr)		/* Information about text widget. */
{
    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(textPtr->tkwin);
    event.general.xany.display = Tk_Display(textPtr->tkwin);
    event.virtual.name = Tk_GetUid("WidgetViewSync");
    event.virtual.user_data = Tcl_NewIntObj(TkTextPendingsync(textPtr));
    Tk_HandleEvent(&event.general);
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkTextUpdateLineMetrics --
................................................................................
    }
    return TCL_OK;
}
 
/*
 *--------------------------------------------------------------
 *
 * TkTextPendingsync --
 *
 *	This function computes how many lines are not up-to-date regarding
 *	asynchronous height calculations.
 *
 * Results:
 *	Returns a positive integer corresponding to the number of lines for
 *	which the height is outdated.
................................................................................
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkTextPendingsync(
    TkText *textPtr)		/* Information about text widget. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;

    return (dInfoPtr->lastMetricUpdateLine - dInfoPtr->currentMetricUpdateLine);
}
 

Changes to tests/text.test.

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
...
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
} {.t2 Text}

test text-3.1 {TextWidgetCmd procedure, basics} {
    list [catch {.t} msg] $msg
} {1 {wrong # args: should be ".t option ?arg arg ...?"}}
test text-3.2 {TextWidgetCmd procedure} {
    list [catch {.t gorp 1.0 z 1.2} msg] $msg
} {1 {bad option "gorp": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}

test text-4.1 {TextWidgetCmd procedure, "bbox" option} {
    list [catch {.t bbox} msg] $msg
} {1 {wrong # args: should be ".t bbox index"}}
test text-4.2 {TextWidgetCmd procedure, "bbox" option} {
    list [catch {.t bbox a b} msg] $msg
} {1 {wrong # args: should be ".t bbox index"}}
................................................................................
    list [catch {.t compare 1.0 >> 1.2} msg] $msg
} {1 {bad comparison operator ">>": must be <, <=, ==, >=, >, or !=}}
test text-6.13 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare 1.0 z 1.2} msg] $msg
} {1 {bad comparison operator "z": must be <, <=, ==, >=, >, or !=}}
test text-6.14 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t co 1.0 z 1.2} msg] $msg
} {1 {ambiguous option "co": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}

# "configure" option is already covered above

test text-7.1 {TextWidgetCmd procedure, "debug" option} {
    list [catch {.t debug 0 1} msg] $msg
} {1 {wrong # args: should be ".t debug boolean"}}
test text-7.2 {TextWidgetCmd procedure, "debug" option} {
    list [catch {.t de 0 1} msg] $msg
} {1 {ambiguous option "de": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}
test text-7.3 {TextWidgetCmd procedure, "debug" option} {
    .t debug true
    .t deb
} 1
test text-7.4 {TextWidgetCmd procedure, "debug" option} {
    .t debug false
    .t debug
................................................................................
    list [catch {.t index} msg] $msg
} {1 {wrong # args: should be ".t index index"}}
test text-10.2 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t ind a b} msg] $msg
} {1 {wrong # args: should be ".t index index"}}
test text-10.3 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t in a b} msg] $msg
} {1 {ambiguous option "in": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}
test text-10.4 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t index @xyz} msg] $msg
} {1 {bad text index "@xyz"}}
test text-10.5 {TextWidgetCmd procedure, "index" option} {
    .t index 1.2
} 1.2

................................................................................
} {{First second third} {1.0 1.5} {1.6 1.12} {1.6 1.12} {1.6 1.12}}
test text-11.10 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "First" bold " second" silly
    list [.t get 1.0 1.end] [.t tag ranges bold] [.t tag ranges silly]
} {{First second} {1.0 1.5} {1.5 1.12}}

test text-11a.1 {TextWidgetCmd procedure, "yupdate" option} {
    destroy .yt
    text .yt
    list [catch {.yt yupdate mytext} msg] $msg
} {1 {wrong # args: should be ".yt yupdate"}}
test text-11a.2 {TextWidgetCmd procedure, "yupdate" option} {
    destroy .top.yt .top
    toplevel .top
    pack [text .top.yt]
    set content {}
    for {set i 1} {$i < 30} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    .top.yt yupdate
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    # first case: do not wait for completion of line metrics calculation
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
    # second case: wait for completion of line metrics calculation
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    .top.yt yupdate
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 0 1}
test text-11a.11 {TextWidgetCmd procedure, "pendingyupdate" option} {
    destroy .yt
    text .yt
    list [catch {.yt pendingyupdate mytext} msg] $msg
} {1 {wrong # args: should be ".yt pendingyupdate"}}
test text-11a.12 {TextWidgetCmd procedure, "pendingyupdate" option} {
    destroy .top.yt .top
    toplevel .top
    pack [text .top.yt]
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    update
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    while {[.top.yt pendingyupdate]} {update}
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # ensure the test is relevant
    lappend res [expr {[.top.yt pendingyupdate] > 0}]
    # asynchronously wait for completion of line metrics calculation
    while {[.top.yt pendingyupdate]} {update}
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 1 1}
test text-11a.21 {"<<TextLineHeightsInvalid>>" event} {
    destroy .top.yt .top
    toplevel .top
    pack [text .top.yt]
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    update
    bind .top.yt <<TextLineHeightsInvalid>> { if {%d == 0} {set yud(%W) 1} }
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    if {[.top.yt pendingyupdate]} {vwait yud(.top.yt)}
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # synchronously wait for completion of line metrics calculation
    # and ensure the test is relevant
    set waited 0
    if {[.top.yt pendingyupdate]} {set waited 1 ; vwait yud(.top.yt)}
    lappend res $waited
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 1 1}

# edit, mark, scan, search, see, tag, window, xview and yview actions are tested elsewhere.






|







 







|








|







 







|







 







|


|
|
|










|












|




|


|
|
|











|






|

|




|









|


|








|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
...
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
} {.t2 Text}

test text-3.1 {TextWidgetCmd procedure, basics} {
    list [catch {.t} msg] $msg
} {1 {wrong # args: should be ".t option ?arg arg ...?"}}
test text-3.2 {TextWidgetCmd procedure} {
    list [catch {.t gorp 1.0 z 1.2} msg] $msg
} {1 {bad option "gorp": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}}

test text-4.1 {TextWidgetCmd procedure, "bbox" option} {
    list [catch {.t bbox} msg] $msg
} {1 {wrong # args: should be ".t bbox index"}}
test text-4.2 {TextWidgetCmd procedure, "bbox" option} {
    list [catch {.t bbox a b} msg] $msg
} {1 {wrong # args: should be ".t bbox index"}}
................................................................................
    list [catch {.t compare 1.0 >> 1.2} msg] $msg
} {1 {bad comparison operator ">>": must be <, <=, ==, >=, >, or !=}}
test text-6.13 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare 1.0 z 1.2} msg] $msg
} {1 {bad comparison operator "z": must be <, <=, ==, >=, >, or !=}}
test text-6.14 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t co 1.0 z 1.2} msg] $msg
} {1 {ambiguous option "co": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}}

# "configure" option is already covered above

test text-7.1 {TextWidgetCmd procedure, "debug" option} {
    list [catch {.t debug 0 1} msg] $msg
} {1 {wrong # args: should be ".t debug boolean"}}
test text-7.2 {TextWidgetCmd procedure, "debug" option} {
    list [catch {.t de 0 1} msg] $msg
} {1 {ambiguous option "de": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}}
test text-7.3 {TextWidgetCmd procedure, "debug" option} {
    .t debug true
    .t deb
} 1
test text-7.4 {TextWidgetCmd procedure, "debug" option} {
    .t debug false
    .t debug
................................................................................
    list [catch {.t index} msg] $msg
} {1 {wrong # args: should be ".t index index"}}
test text-10.2 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t ind a b} msg] $msg
} {1 {wrong # args: should be ".t index index"}}
test text-10.3 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t in a b} msg] $msg
} {1 {ambiguous option "in": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}}
test text-10.4 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t index @xyz} msg] $msg
} {1 {bad text index "@xyz"}}
test text-10.5 {TextWidgetCmd procedure, "index" option} {
    .t index 1.2
} 1.2

................................................................................
} {{First second third} {1.0 1.5} {1.6 1.12} {1.6 1.12} {1.6 1.12}}
test text-11.10 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "First" bold " second" silly
    list [.t get 1.0 1.end] [.t tag ranges bold] [.t tag ranges silly]
} {{First second} {1.0 1.5} {1.5 1.12}}

test text-11a.1 {TextWidgetCmd procedure, "sync" option} {
    destroy .yt
    text .yt
    list [catch {.yt sync mytext} msg] $msg
} {1 {wrong # args: should be ".yt sync ?-command command?"}}
test text-11a.2 {TextWidgetCmd procedure, "sync" option} {
    destroy .top.yt .top
    toplevel .top
    pack [text .top.yt]
    set content {}
    for {set i 1} {$i < 30} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    .top.yt sync
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    # first case: do not wait for completion of line metrics calculation
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
    # second case: wait for completion of line metrics calculation
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    .top.yt sync
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 0 1}
test text-11a.11 {TextWidgetCmd procedure, "pendingsync" option} {
    destroy .yt
    text .yt
    list [catch {.yt pendingsync mytext} msg] $msg
} {1 {wrong # args: should be ".yt pendingsync"}}
test text-11a.12 {TextWidgetCmd procedure, "pendingsync" option} {
    destroy .top.yt .top
    toplevel .top
    pack [text .top.yt]
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    update
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    while {[.top.yt pendingsync]} {update}
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # ensure the test is relevant
    lappend res [expr {[.top.yt pendingsync] > 0}]
    # asynchronously wait for completion of line metrics calculation
    while {[.top.yt pendingsync]} {update}
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 1 1}
test text-11a.21 {"<<WidgetViewSync>>" event} {
    destroy .top.yt .top
    toplevel .top
    pack [text .top.yt]
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    update
    bind .top.yt <<WidgetViewSync>> { if {%d == 0} {set yud(%W) 1} }
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    if {[.top.yt pendingsync]} {vwait yud(.top.yt)}
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # synchronously wait for completion of line metrics calculation
    # and ensure the test is relevant
    set waited 0
    if {[.top.yt pendingsync]} {set waited 1 ; vwait yud(.top.yt)}
    lappend res $waited
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 1 1}

# edit, mark, scan, search, see, tag, window, xview and yview actions are tested elsewhere.

Changes to tests/textDisp.test.

4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
    set result {}
} -body {
    .t1 insert end $txt
    .t1 debug 1
    set ge [winfo geometry .]
    scan $ge "%dx%d+%d+%d" width height left top
    update
    .t1 yupdate
    set negative 0
    bind .t1 <<TextLineHeightsInvalid>> { if {%d < 0} {set negative 1} }
    # Without the fix for bug 2677890, changing the width of the toplevel
    # will launch recomputation of the line heights, but will produce negative
    # number of still remaining outdated lines, which is obviously wrong.
    # Thus we use this way to check for regression regarding bug 2677890,
    # i.e. to check that the fix for this bug really is still in.
    wm geometry . "[expr {$width * 2}]x$height+$left+$top"
    update
    .t1 yupdate
    set negative
} -cleanup {
    destroy .t1
} -result {0}

test textDisp-34.2 {text yupdate syntax} -body {
} -body {
    pack [text .t1] -expand 1 -fill both
    .t1 yupdate foo
} -cleanup {
    destroy .t1
} -returnCodes 1 -result {wrong # args: should be ".t1 yupdate ?-command command?"}

test textDisp-34.3 {text yupdate syntax} -body {
} -body {
    pack [text .t1] -expand 1 -fill both
    .t1 yupdate -comx foo
} -cleanup {
    destroy .t1
} -returnCodes 1 -result {wrong option "-comx": should be "-command"}

test textDisp-34.4 {text yupdate syntax} -body {
} -body {
    set ::x 0
    pack [text .t1] -expand 1 -fill both
    .t1 yupdate -comm [list set ::x 1]
    set ::x
} -cleanup {
    destroy .t1
} -result {1}

deleteWindows
option clear

# cleanup
cleanupTests
return






|

|







|





|


|


|

|


|




|



|











4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
    set result {}
} -body {
    .t1 insert end $txt
    .t1 debug 1
    set ge [winfo geometry .]
    scan $ge "%dx%d+%d+%d" width height left top
    update
    .t1 sync
    set negative 0
    bind .t1 <<WidgetViewSync>> { if {%d < 0} {set negative 1} }
    # Without the fix for bug 2677890, changing the width of the toplevel
    # will launch recomputation of the line heights, but will produce negative
    # number of still remaining outdated lines, which is obviously wrong.
    # Thus we use this way to check for regression regarding bug 2677890,
    # i.e. to check that the fix for this bug really is still in.
    wm geometry . "[expr {$width * 2}]x$height+$left+$top"
    update
    .t1 sync
    set negative
} -cleanup {
    destroy .t1
} -result {0}

test textDisp-34.2 {text sync syntax} -body {
} -body {
    pack [text .t1] -expand 1 -fill both
    .t1 sync foo
} -cleanup {
    destroy .t1
} -returnCodes 1 -result {wrong # args: should be ".t1 sync ?-command command?"}

test textDisp-34.3 {text sync syntax} -body {
} -body {
    pack [text .t1] -expand 1 -fill both
    .t1 sync -comx foo
} -cleanup {
    destroy .t1
} -returnCodes 1 -result {wrong option "-comx": should be "-command"}

test textDisp-34.4 {text sync syntax} -body {
} -body {
    set ::x 0
    pack [text .t1] -expand 1 -fill both
    .t1 sync -comm [list set ::x 1]
    set ::x
} -cleanup {
    destroy .t1
} -result {1}

deleteWindows
option clear

# cleanup
cleanupTests
return