From f0e7b98adcaa0890c60fdf84c8e9753f8f903a53 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 19 Nov 2015 20:46:40 +0000 Subject: First test-implementation of "$t yupdate -command ". TODO: more testcases and documentation --- generic/tkText.c | 37 +++++++++++++++++++++++++++++-------- generic/tkText.h | 1 + generic/tkTextDisp.c | 13 ++++++++++++- tests/textDisp.test | 18 ++++++++++++++++++ 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 -- cgit v0.12