Tk Source Code

Check-in [86e88288]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:[.text sync -command $cmd] schedules execution of $cmd by the event loop at idle time
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-438
Files: files | file ages | folders
SHA1:86e88288a65c057a65da384739b7c7b9d5362fe6
User & Date: fvogel 2015-12-26 20:52:21
Context
2015-12-26
21:23
Merged core-8-5-branch check-in: 078644f1 user: fvogel tags: tip-438
20:52
[.text sync -command $cmd] schedules execution of $cmd by the event loop at idle time check-in: 86e88288 user: fvogel tags: tip-438
2015-12-21
12:12
Merged core-8-5-branch check-in: a888e911 user: fvogel tags: tip-438
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkText.c.

393
394
395
396
397
398
399

400
401
402
403
404
405
406
....
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
....
6741
6742
6743
6744
6745
6746
6747














































6748
6749
6750
6751
6752
6753
6754
6755
			    const TkTextIndex *index1Ptr,
			    const TkTextIndex *index2Ptr);
static int		TextSearchIndexInLine(const SearchSpec *searchSpecPtr,
			    TkTextLine *linePtr, int byteIndex);
static int		TextPeerCmd(TkText *textPtr, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static TkUndoProc	TextUndoRedoCallback;


/*
 * Declarations of the three search procs required by the multi-line search
 * routines.
 */

static SearchMatchProc		TextSearchFoundMatch;
................................................................................
	    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;
	}
................................................................................
    TkTextSetMark(textPtr, "insert", &index);
    TkTextPrintIndex(textPtr, &index, buf);
    sprintf(buf + strlen(buf), " %d", index.byteIndex);
    Tcl_AppendResult(interp, buf, NULL);

    return TCL_OK;
}














































 
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>







 







|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
....
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
....
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
			    const TkTextIndex *index1Ptr,
			    const TkTextIndex *index2Ptr);
static int		TextSearchIndexInLine(const SearchSpec *searchSpecPtr,
			    TkTextLine *linePtr, int byteIndex);
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
 * routines.
 */

static SearchMatchProc		TextSearchFoundMatch;
................................................................................
	    Tcl_IncrRefCount(cmd);
	    if (TkTextPendingsync(textPtr)) {
		if (textPtr->afterSyncCmd) {
		    Tcl_DecrRefCount(textPtr->afterSyncCmd);
		}
		textPtr->afterSyncCmd = cmd;
	    } else {
		textPtr->afterSyncCmd = cmd;
                Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr);
	    }
	    break;
	} else if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-command command?");
	    result = TCL_ERROR;
	    goto done;
	}
................................................................................
    TkTextSetMark(textPtr, "insert", &index);
    TkTextPrintIndex(textPtr, &index, buf);
    sprintf(buf + strlen(buf), " %d", index.byteIndex);
    Tcl_AppendResult(interp, buf, NULL);

    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * 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
 * fill-column: 78
 * End:
 */

Changes to generic/tkText.h.

778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
    int undo;			/* Non-zero means the undo/redo behaviour is
				 * enabled. */
    int maxUndo;		/* The maximum depth of the undo stack
				 * expressed as the maximum number of compound
				 * 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 */

} TkText;

/*
 * Flag values for TkText records:
 *
 * GOT_SELECTION:		Non-zero means we've already claimed the
 *				selection.







|
>







778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
    int undo;			/* Non-zero means the undo/redo behaviour is
				 * enabled. */
    int maxUndo;		/* The maximum depth of the undo stack
				 * expressed as the maximum number of compound
				 * 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 */
} TkText;

/*
 * Flag values for TkText records:
 *
 * GOT_SELECTION:		Non-zero means we've already claimed the
 *				selection.

Changes to generic/tkTextDisp.c.

2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
	    && 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;
	}

        /*
         * 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).
         */







|
|
|
|
|
|
|
|

|
|
|







2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
	    && 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) {
            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 = NULL;
	}

        /*
         * 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).
         */