summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkText.c37
-rw-r--r--generic/tkText.h1
-rw-r--r--generic/tkTextDisp.c13
-rw-r--r--tests/textDisp.test18
4 files changed, 60 insertions, 9 deletions
diff --git a/generic/tkText.c b/generic/tkText.c
index 5c7f187..2c4d54c 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -1508,14 +1508,31 @@ TextWidgetObjCmd(
result = TkTextXviewCmd(textPtr, interp, objc, objv);
break;
case TEXT_YUPDATE: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- result = TCL_ERROR;
- goto done;
- }
- TkTextUpdateLineMetrics(textPtr, 1,
- TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1);
- break;
+ if ((objc == 4) && !strncmp(Tcl_GetString(objv[2]), "-command", objv[3]->length)) {
+ Tcl_Obj *cmd = objv[3];
+ Tcl_IncrRefCount(cmd);
+ if (TkTextPendingyupdate(textPtr)) {
+ if (textPtr->linesUpdatedCmd) {
+ Tcl_DecrRefCount(textPtr->linesUpdatedCmd);
+ }
+ textPtr->linesUpdatedCmd = 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->linesUpdatedCmd) {
+ Tcl_DecrRefCount(textPtr->linesUpdatedCmd);
+ }
+ textPtr->linesUpdatedCmd = NULL;
+ TkTextUpdateLineMetrics(textPtr, 1,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1);
+ break;
}
case TEXT_YVIEW:
result = TkTextYviewCmd(textPtr, interp, objc, objv);
@@ -1993,6 +2010,10 @@ DestroyText(
textPtr->tkwin = NULL;
textPtr->refCount--;
Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd);
+ if (textPtr->linesUpdatedCmd != 0){
+ Tcl_DecrRefCount(textPtr->linesUpdatedCmd);
+ textPtr->linesUpdatedCmd = 0;
+ }
if (textPtr->refCount == 0) {
ckfree((char *) textPtr);
}
diff --git a/generic/tkText.h b/generic/tkText.h
index 2d1bcaa..192ab12 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -782,6 +782,7 @@ typedef struct TkText {
* statements. */
int autoSeparators; /* Non-zero means the separators will be
* inserted automatically. */
+ Tcl_Obj *linesUpdatedCmd; /* Command to be executed when lines are up to date */
} TkText;
/*
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index ff90520..d31d2f3 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -2942,9 +2942,20 @@ AsyncUpdateLineMetrics(
/*
* 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).
+ * above). If there is a registered command, run that first.
*/
+ if (textPtr->linesUpdatedCmd != NULL) {
+ Tcl_Preserve((ClientData)textPtr->interp);
+ int code = Tcl_EvalObjEx(textPtr->interp, textPtr->linesUpdatedCmd, 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);
+ }
+
textPtr->refCount--;
if (textPtr->refCount == 0) {
ckfree((char *) textPtr);
diff --git a/tests/textDisp.test b/tests/textDisp.test
index 4c88b38..f2b176c 100644
--- a/tests/textDisp.test
+++ b/tests/textDisp.test
@@ -4191,6 +4191,24 @@ test textDisp-34.1 {Line heights recalculation problem: bug 2677890} -setup {
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 {
+ set ::x 0
+ pack [text .t1] -expand 1 -fill both
+ .t1 yupdate -command [list set ::x 1]
+ set ::x
+} -cleanup {
+ destroy .t1
+} -result {1}
+
deleteWindows
option clear