Tk Source Code

Check-in [77834837]
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:Make the sync command generate a <<WidgetViewSync>> event after updating all line metrics. Merge the modified 11a-* tests from the legacy widget.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | revised_text | tip-466
Files: files | file ages | folders
SHA3-256:778348378681463e08810ba4380c37dd0d22e99107d0d98c7737fd36e4a06447
User & Date: jan.nijtmans 2019-01-03 21:46:03
Context
2019-01-03
21:49
Merge trunk check-in: 1444bc30 user: jan.nijtmans tags: revised_text, tip-466
21:46
Make the sync command generate a <<WidgetViewSync>> event after updating all line metrics. Merge the modified 11a-* tests from the legacy widget. check-in: 77834837 user: jan.nijtmans tags: revised_text, tip-466
21:45
Realization of global default value for tag option -undo (bug report [5a670c16ba]). check-in: a263e6c9 user: jan.nijtmans tags: revised_text, tip-466
19:38
Make the sync command generate a <<WidgetViewSync>> event after updating all line metrics. Merge the modified 11a-* tests from the legacy widget. Closed-Leaf check-in: 4aca5dbe user: culler tags: revised_text-aside
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkTextDisp.c.

7214
7215
7216
7217
7218
7219
7220


7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
....
7293
7294
7295
7296
7297
7298
7299



7300
7301
7302
7303
7304
7305
7306
TkTextUpdateLineMetrics(
    TkText *textPtr,		/* Information about widget. */
    unsigned lineNum,		/* Start at this line. */
    unsigned endLine)		/* Go no further than this line. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    const TkRange *range;



    assert(lineNum <= endLine);
    assert((int) endLine <= TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));
    assert(textPtr->sharedTextPtr->allowUpdateLineMetrics);

    dInfoPtr->insideLineMetricUpdate = true;

    if ((range = TkRangeListFindNearest(dInfoPtr->lineMetricUpdateRanges, lineNum))) {
	TkTextLine *linePtr = NULL;
	unsigned count = 0;
	unsigned high = range->high;

	lineNum = range->low;
	endLine = MIN((int) endLine, TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr) - 1);
	assert((int) lineNum < TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));

	while (true) {
	    const TkTextPixelInfo *pixelInfo;
	    int firstLineNum;

	    if (lineNum > high) {
		/*
................................................................................
		TkRangeListRemove(dInfoPtr->lineMetricUpdateRanges, firstLineNum, lineNum - 1);
	    }
	}
    }

    dInfoPtr->insideLineMetricUpdate = false;
    CheckIfLineMetricIsUpToDate(textPtr);



}
 
/*
 *----------------------------------------------------------------------
 *
 * TkTextInvalidateLineMetrics, TextInvalidateLineMetrics --
 *







>
>


|










|
|







 







>
>
>







7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
....
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
TkTextUpdateLineMetrics(
    TkText *textPtr,		/* Information about widget. */
    unsigned lineNum,		/* Start at this line. */
    unsigned endLine)		/* Go no further than this line. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    const TkRange *range;
    int totalLines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
    int fullUpdateRequested = (lineNum == 0 && endLine == totalLines); 

    assert(lineNum <= endLine);
    assert((int) endLine <= totalLines);
    assert(textPtr->sharedTextPtr->allowUpdateLineMetrics);

    dInfoPtr->insideLineMetricUpdate = true;

    if ((range = TkRangeListFindNearest(dInfoPtr->lineMetricUpdateRanges, lineNum))) {
	TkTextLine *linePtr = NULL;
	unsigned count = 0;
	unsigned high = range->high;

	lineNum = range->low;
	endLine = MIN((int) endLine, totalLines - 1);
	assert((int) lineNum < totalLines);

	while (true) {
	    const TkTextPixelInfo *pixelInfo;
	    int firstLineNum;

	    if (lineNum > high) {
		/*
................................................................................
		TkRangeListRemove(dInfoPtr->lineMetricUpdateRanges, firstLineNum, lineNum - 1);
	    }
	}
    }

    dInfoPtr->insideLineMetricUpdate = false;
    CheckIfLineMetricIsUpToDate(textPtr);
    if (fullUpdateRequested) {
	TkTextGenerateWidgetViewSyncEvent(textPtr, true);
    }
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkTextInvalidateLineMetrics, TextInvalidateLineMetrics --
 *

Changes to tests/text.test.

3175
3176
3177
3178
3179
3180
3181

3182
3183
3184
3185
3186

3187
3188
3189
3190
3191
3192
3193
....
3217
3218
3219
3220
3221
3222
3223

3224

3225
3226
3227
3228
3229
3230
3231
3232
3233
....
3357
3358
3359
3360
3361
3362
3363

3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
....
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424



3425


3426
3427
3428
3429
3430


3431
3432
3433
3434

3435
3436



3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
....
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
    destroy .yt
} -body {
    text .yt
    list [catch {.yt pendingsync mytext} msg] $msg
} -cleanup {
    destroy .yt
} -result {1 {wrong # args: should be ".yt pendingsync"}}

test text-11a.2 {TextWidgetCmd procedure, "pendingsync" option} -setup {
    destroy .top.yt .top
} -body {
    toplevel .top
    pack [text .top.yt]

    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
................................................................................
    destroy .yt
} -result {1 {wrong # args: should be ".yt sync ?-command ?command??"}}
test text-11a.12 {TextWidgetCmd procedure, "sync" option} -setup {
    destroy .top.yt .top
} -body {
    toplevel .top
    pack [text .top.yt]

    set content {}

    for {set i 1} {$i < 30} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    .top.yt sync
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
................................................................................
    toplevel .top
    pack [text .top.yt]
    update
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }

    .top.yt insert 1.0 $content
    update
    bind .top.yt <<WidgetViewSync>> { if {%d} {set yud(%W) 1} }
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    if {[.top.yt pendingsync]} {vwait yud(.top.yt)}
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # synchronously wait for completion of line metrics calculation
    # and ensure the test is relevant
    set waited 0
    if {[.top.yt pendingsync]} {set waited 1 ; vwait yud(.top.yt)}
    lappend res $waited
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} -cleanup {
................................................................................
} -cleanup {
    destroy .yt
} -result {}

test text-11a.41 {"sync" "pendingsync" and <<WidgetViewSync>>} -setup {
    destroy .top.yt .top
} -body {
    set res {}
    toplevel .top
    pack [text .top.yt]
    # For this test it is required that the ConfigureNotify event is
    # not messing up the sync state, see comment below (GC).
    while {![winfo ismapped .top.yt]} {
	update
    }
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 50] \n
    }



    bind .top.yt <<WidgetViewSync>> {lappend res Sync:%d}


    .top.yt insert 1.0 $content
    # The original test did contain the lines below, but it makes no sense,
    # because both values (Sync:0 and Sync:1) are ok (GC).
    #    vwait res  ; # event dealt with by the event loop, with %d==0 i.e. we're out of sync
    #    # ensure the test is relevant


    #    lappend res "Pending:[.top.yt pendingsync]"
    # --------------------------------------------------------------------------
    # - <<WidgetViewSync>> fires when sync returns if there was pending syncs
    # - there is no more any pending sync after running 'sync'

    .top.yt sync
    vwait res  ; # event dealt with by the event loop, with %d==1 i.e. we're in sync again



    lappend res "Pending:[.top.yt pendingsync]"
    # Without waiting for Map event the last pending state can be 1, because it can happen
    # that the Configure event will be triggered during vwait (and this is invalidating the
    # line-heights).
    set res
} -cleanup {
    destroy .top.yt .top
} -result {Sync:1 Pending:0}

test text-11a.51 {<<WidgetViewSync>> calls TkSendVirtualEvent(),
                  NOT Tk_HandleEvent().
                  Bug [b362182e45704dd7bbd6aed91e48122035ea3d16]} -setup {
    destroy .top.t .top
} -body {
    set res {}
................................................................................
    .t delete 3.0 18.0
    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]
} -cleanup {
    destroy .pt .t
# NOTE: The peer widget is empty, and in revised version always a last newline
# exists, so the last line index has been increased by 1 (57 -> 58).
} -result {5 11 8 10 5 8 6 8 22 27 38 44 55 60 57 58}


test text-33.1 {TextWidgetCmd procedure, "peer" option} -setup {
    text .t
} -body {
    .t peer foo 1
} -cleanup {
    destroy .t







>





>







 







>

>

|







 







>
|


<
|
<






|







 







<


<
<
<
|
<




>
>
>

>
>

<
<
<
<
>
>
|
<
<
<
>

<
>
>
>

<
<
<



|







 







<







3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
....
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
....
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371

3372

3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
....
3409
3410
3411
3412
3413
3414
3415

3416
3417



3418

3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429




3430
3431
3432



3433
3434

3435
3436
3437
3438



3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
....
7925
7926
7927
7928
7929
7930
7931

7932
7933
7934
7935
7936
7937
7938
    destroy .yt
} -body {
    text .yt
    list [catch {.yt pendingsync mytext} msg] $msg
} -cleanup {
    destroy .yt
} -result {1 {wrong # args: should be ".yt pendingsync"}}

test text-11a.2 {TextWidgetCmd procedure, "pendingsync" option} -setup {
    destroy .top.yt .top
} -body {
    toplevel .top
    pack [text .top.yt]
    update
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
................................................................................
    destroy .yt
} -result {1 {wrong # args: should be ".yt sync ?-command ?command??"}}
test text-11a.12 {TextWidgetCmd procedure, "sync" option} -setup {
    destroy .top.yt .top
} -body {
    toplevel .top
    pack [text .top.yt]
    update
    set content {}
    # Use long lines so the line metrics will need updating.
    for {set i 1} {$i < 30} {incr i} {
        append content [string repeat "$i " 200] \n
    }
    .top.yt insert 1.0 $content
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    .top.yt sync
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
................................................................................
    toplevel .top
    pack [text .top.yt]
    update
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    # Sync the widget and process <<WidgetViewSync>> events before binding.
    .top.yt sync
    update
    bind .top.yt <<WidgetViewSync>> { if {%d} {set yud(%W) 1} }

    .top.yt insert 1.0 $content

    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # synchronously wait for completion of line metrics calculation
    # and verify that the fractions agree.
    set waited 0
    if {[.top.yt pendingsync]} {set waited 1 ; vwait yud(.top.yt)}
    lappend res $waited
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} -cleanup {
................................................................................
} -cleanup {
    destroy .yt
} -result {}

test text-11a.41 {"sync" "pendingsync" and <<WidgetViewSync>>} -setup {
    destroy .top.yt .top
} -body {

    toplevel .top
    pack [text .top.yt]



    update

    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 50] \n
    }
    # Sync the widget and process all <<WidgetViewSync>> events before binding. 
    .top.yt sync
    update
    bind .top.yt <<WidgetViewSync>> {lappend res Sync:%d}
    set res {}
    # The next line triggers <<WidgetViewSync>> with %d==0 i.e. out of sync.
    .top.yt insert 1.0 $content




    vwait res
    # Verify that the line metrics are not up-to-date (pendingsync is 1).
    lappend res "Pending:[.top.yt pendingsync]"



    # Update all line metrics by calling the sync command.
    .top.yt sync

    # <<WidgetViewSync>> should fire with %d==1 i.e. back in sync.
    vwait res
    # At this time the line metrics should be up-to-date (pendingsync is 0).
    lappend res "Pending:[.top.yt pendingsync]"



    set res
} -cleanup {
    destroy .top.yt .top
} -result {Sync:0 Pending:1 Sync:1 Pending:0}

test text-11a.51 {<<WidgetViewSync>> calls TkSendVirtualEvent(),
                  NOT Tk_HandleEvent().
                  Bug [b362182e45704dd7bbd6aed91e48122035ea3d16]} -setup {
    destroy .top.t .top
} -body {
    set res {}
................................................................................
    .t delete 3.0 18.0
    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]
} -cleanup {
    destroy .pt .t
# NOTE: The peer widget is empty, and in revised version always a last newline
# exists, so the last line index has been increased by 1 (57 -> 58).
} -result {5 11 8 10 5 8 6 8 22 27 38 44 55 60 57 58}


test text-33.1 {TextWidgetCmd procedure, "peer" option} -setup {
    text .t
} -body {
    .t peer foo 1
} -cleanup {
    destroy .t