diff options
Diffstat (limited to 'generic/tkTextDisp.c')
-rw-r--r-- | generic/tkTextDisp.c | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 6036222..d8a17a9 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -590,6 +590,7 @@ static int TextGetScrollInfoObj(Tcl_Interp *interp, Tcl_Obj *CONST objv[], double *dblPtr, int *intPtr); static void AsyncUpdateLineMetrics(ClientData clientData); +static void GenerateWidgetViewSyncEvent(TkText *textPtr, Bool InSync); static void AsyncUpdateYScrollbar(ClientData clientData); static int IsStartOfNotMergedLine(TkText *textPtr, CONST TkTextIndex *indexPtr); @@ -2920,6 +2921,8 @@ AsyncUpdateLineMetrics( lineNum = TkTextUpdateLineMetrics(textPtr, lineNum, dInfoPtr->lastMetricUpdateLine, 256); + dInfoPtr->currentMetricUpdateLine = lineNum; + if (tkTextDebug) { char buffer[2 * TCL_INTEGER_SPACE + 1]; @@ -2937,16 +2940,37 @@ 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 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; + } + + /* + * Fire the <<WidgetViewSync>> event since the widget view is in sync + * with its internal data (actually it will be after the next trip + * through the event loop, because the widget redraws at idle-time). + */ + + GenerateWidgetViewSyncEvent(textPtr, 1); + textPtr->refCount--; if (textPtr->refCount == 0) { ckfree((char *) textPtr); } return; } - dInfoPtr->currentMetricUpdateLine = lineNum; /* * Re-arm the timer. We already have a refCount on the text widget so no @@ -2960,6 +2984,45 @@ AsyncUpdateLineMetrics( /* *---------------------------------------------------------------------- * + * GenerateWidgetViewSyncEvent -- + * + * Send the <<WidgetViewSync>> event related to the text widget + * line metrics asynchronous update. + * This is equivalent to: + * event generate $textWidget <<WidgetViewSync>> -detail $s + * where $s is the sync status: true (when the widget view is in + * sync with its internal data) or false (when it is not). + * + * Results: + * None + * + * Side effects: + * If corresponding bindings are present, they will trigger. + * + *---------------------------------------------------------------------- + */ + +static void +GenerateWidgetViewSyncEvent( + TkText *textPtr, /* Information about text widget. */ + Bool InSync) /* True if in sync, false otherwise */ +{ + 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_NewBooleanObj(InSync); + Tk_HandleEvent(&event.general); +} + +/* + *---------------------------------------------------------------------- + * * TkTextUpdateLineMetrics -- * * This function updates the pixel height calculations of a range of @@ -3336,6 +3399,7 @@ TextInvalidateLineMetrics( textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, (ClientData) textPtr); + GenerateWidgetViewSyncEvent(textPtr, 0); } } @@ -5040,6 +5104,7 @@ TkTextRelayoutWindow( textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, (ClientData) textPtr); + GenerateWidgetViewSyncEvent(textPtr, 0); } } } @@ -6034,6 +6099,33 @@ TkTextYviewCmd( /* *-------------------------------------------------------------- * + * 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); +} + +/* + *-------------------------------------------------------------- + * * TkTextScanCmd -- * * This function is invoked to process the "scan" option for the widget |