From 7fba872bef36903476be033836a8394fd742a1c0 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 26 Dec 2015 20:52:21 +0000 Subject: [.text sync -command $cmd] schedules execution of $cmd by the event loop at idle time --- generic/tkText.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- generic/tkText.h | 3 ++- generic/tkTextDisp.c | 22 +++++++++++----------- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index a2b7dde..0cb8431 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -397,6 +397,7 @@ static int TextSearchIndexInLine(const SearchSpec *searchSpecPtr, static int TextPeerCmd(TkText *textPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static TkUndoProc TextUndoRedoCallback; +static void RunAfterSyncCmd(ClientData clientData); /* * Declarations of the three search procs required by the multi-line search @@ -1512,8 +1513,8 @@ TextWidgetObjCmd( } textPtr->afterSyncCmd = cmd; } else { - result = Tcl_EvalObjEx(interp, cmd, TCL_EVAL_GLOBAL); - Tcl_DecrRefCount(cmd); + textPtr->afterSyncCmd = cmd; + Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr); } break; } else if (objc != 2) { @@ -6747,6 +6748,52 @@ TkpTesttextCmd( } /* + *---------------------------------------------------------------------- + * + * RunAfterSyncCmd -- + * + * This function is called by the event loop and excutes the command + * scheduled by [.text sync -command $cmd]. + * + * Results: + * None. + * + * Side effects: + * Anything may happen, depending on $cmd contents. + * + *---------------------------------------------------------------------- + */ + +static void +RunAfterSyncCmd( + ClientData clientData) /* Information about text widget. */ +{ + register TkText *textPtr = (TkText *) clientData; + int code; + + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { + /* + * The widget has been deleted. Don't do anything. + */ + + if (--textPtr->refCount == 0) { + ckfree((char *) textPtr); + } + return; + } + + Tcl_Preserve((ClientData) textPtr->interp); + code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL); + if (code == TCL_ERROR) { + Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); + Tcl_BackgroundError(textPtr->interp); + } + Tcl_Release((ClientData) textPtr->interp); + Tcl_DecrRefCount(textPtr->afterSyncCmd); + textPtr->afterSyncCmd = NULL; +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/generic/tkText.h b/generic/tkText.h index 49ee479..ea8ce07 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -782,7 +782,8 @@ typedef struct TkText { * statements. */ int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ - Tcl_Obj *afterSyncCmd; /* Command to be executed when lines are up to date */ + Tcl_Obj *afterSyncCmd; /* Command to be executed when lines are up to + * date */ } TkText; /* diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index ba584ac..39311a6 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -2958,18 +2958,18 @@ AsyncUpdateLineMetrics( * 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); + if (textPtr->afterSyncCmd) { + int code; + Tcl_Preserve((ClientData) textPtr->interp); + code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, + TCL_EVAL_GLOBAL); + if (code == TCL_ERROR) { + Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); + Tcl_BackgroundError(textPtr->interp); } - Tcl_Release((ClientData)textPtr->interp); - Tcl_DecrRefCount(textPtr->afterSyncCmd); - textPtr->afterSyncCmd = 0; + Tcl_Release((ClientData) textPtr->interp); + Tcl_DecrRefCount(textPtr->afterSyncCmd); + textPtr->afterSyncCmd = NULL; } /* -- cgit v0.12