Tk Source Code

Timeline
Login

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

50 most recent check-ins

2026-07-15
17:26
Merge nab-reliquats: harden elision, tag and section handling against the remaining corruption classes. Undo/redo of deletions now reconciles the elide topology of the restored range with the current tag information (UpdateElideInfo gets a recompute mode; covers tags excluded from undo and elide states reconfigured between deletion and undo); insertion of non-elided text inside an elided range splits the range (meeting point of two elide tags); switches enrolled in undo tokens survive the annihilation of their counterpart (annihilation marker, stash references, drop at restore); the index arithmetic of joined delete undo tokens handles line-crossing chunks and refuses mark-based joins it cannot compute; the section producers no longer leave short sections at arbitrary cuts (RebuildSections giveback, SplitSection walk-back, BalanceSectionWithLeft, rebalancing after boundary mark removal); [pathName clear] works on peers; tag clearing repairs its range search beyond the boundary line, its undo change list anchoring, its line cache references, partial clears of elided ranges, and re-merges interior chunk boundaries at undo; the branch search examines the first line of a node; TkBTreeTag sets up its undo information before the elision update frees merged segments. With regression tests btree-14.40 - 14.83, text-27.37 - 27.43, text-42.1/42.2. Leaf check-in: 22f077854e user: nab tags: revised_text, tip-466
15:07
Revert the too aggressive part of the previous commit's restore-proc change: dropping a restored switch whenever its stashed counterpart does not point back regressed pure delete/undo/redo round trips (a whole switch pair dying in the same token has the counterpart legitimately paired to another live switch, structurally indistinguishable from the case the change targeted - a mismatch in the number of links and branches followed). The restore procs drop only on the annihilation marker again (NULL fork), as before. The case where an elision update repairs the counterpart pairing between the deletion and the redo (a restored switch stealing its counterpart back, orphaned link) is left as a known bug: it cannot be told apart at the restore proc, its fix belongs in the post-restore reconciliation and is deferred (repro P7). The unused defensive kept-branch reconnection after the walk (never exercised) is dropped as well. Leaf check-in: 6bc537f0bd user: nab tags: nab-reliquats
14:53
Fix six defects found by the tag operation fuzzer, root causes proven by four parallel debugger investigations (all reproducible at the branch point, reached through the layers fixed before): (1) FindBranchSegment never examined the first line of the node before giving up (the bail-out tested the predecessor), so removing the tail of an elided range starting on the first line connected the inserted link to the start marker instead of the enclosing branch (assert; in release builds the fork of a mark segment was overwritten). (2) The first entry of the change list of a tag clearing anchored its skip on the start line of the range instead of the line of the first recorded segment (the token's start index): when the start line carries no recordable segment (tags ending before the range, or tags excluded from undo), the undo walk overshot the end of the document. (3) The tagon/tagoff line cache of the clearing stored the cached result with transfer semantics, stealing two references per cached line (double free of the shared empty tag set). (4) The restore procs re-established the stashed relationship even when the counterpart had been legitimately paired with another switch in the meantime (elision update between the deletion and the undo/redo): the restored switch now drops itself whenever the counterpart does not point back, the recompute after the restore rebuilds the topology. (5) The chunk-wise restore of a tag clearing undo left equal tagged adjacent char segments at boundaries lying inside a chunk; they are merged over the restored lines now. (6) The switch chain is transiently nested while a deletion undo restores switches verbatim inside a newer elided range: the walk of UpdateElideInfo now reconnects a kept branch with a kept link whose pairing was broken (and adopts a dangling link at the end of the pass), the section checker accepts the unmergeable short sections between two switches of the same direction (boundary rules tested independently instead of as pairs, matching the producers), and a delete token whose leading switch is dropped moves the split point protection to the first restored segment so the left boundary of the restored range is merged again. With regression tests btree-14.77 - 14.83. check-in: f3b6944465 user: nab tags: nab-reliquats
13:45
Fix three defects around clearing tags over elided ranges (found by the new tag operation fuzzer, all reproducible at the branch point): (1) TkBTreeFindNextTagged/TkBTreeFindPrevTagged returned tagged segments beyond the end of the search range when the boundary lies within the first searched line - the node walks start past the boundary segment and never encounter it, and the cross-node search only checked the boundary for restricted peers; FindSplitPoints then proceeded on an actually empty range and produced twice the same split segment (assert in TkBTreeClearTags). (2) The undo range setup of TkBTreeClearTags dereferenced a null record when changes were made but nothing was recordable (the cleared range carrying only tags excluded from undo). (3) Clearing a subrange of an elided range stripped the switches inside the range beforehand, orphaning the pair of the enclosing range (its outside part keeps the tags; assert or misplaced link/branch panics later): a partial clearing now recomputes the elide topology from the new tag information after the tags have been cleared, extended to the boundaries of the enclosing elided ranges - the strip beforehand remains only for the whole text case. With regression tests btree-14.74 - 14.76. check-in: a5800d6aa0 user: nab tags: nab-reliquats
13:28
Fix use-after-free in TkBTreeTag when adding an elide tag: the undo information was set up after the elision update, but UpdateElideInfo merges the char segments neighboring a removed switch (zones merging as the elision extends over existing ranges), which can free the segments recorded in data.firstSegPtr/data.lastSegPtr during the tagging walk - converting them to indices afterwards dereferenced freed memory (assert in debug builds, heap corruption in release; dominant crash of tag fuzzing). The undo setup now runs before the elision update, whose zero size switches do not affect the recorded positions. The removal case was already safe (its elision update runs before the tagging walk). With regression test btree-14.73. check-in: e3460ba4e4 user: nab tags: nab-reliquats
13:15
Address the confirmed findings of the adversarial branch review (every mechanism verified by execution): (1) the JoinSections rebalancing after unlinking the boundary marks of a deletion was only applied to the first boundary (the variables for the second one were computed but unused) - a single character deletion on a suitably fragmented line paniced the tree check; and the removed boundary may have separated two equal tagged char segments (deletion of the gap between two elided ranges: the split points are the dead switches, so the split point cleanup could not merge them) - the chars are merged after the unlink now, which also repairs the redo of a reconciled undo. (2) In the walk of UpdateElideInfo, a kept link now immediately closes the elided range opened by a branch inserted in the same pass - the switches of a following elided range reset the link bookkeeping, and the pending branch was connected to the wrong link at the end of the pass (orphaned link, e.g. undoing a deletion over one of two zones whose tag was unelided and re-elided in the meantime). (3) In recompute mode, a fully untagged line is no longer skipped as unaffected when the walk is inside an elided range: it is exactly the transition to process (whole untagged lines restored into a -undo 0 range, or a whole-line insertion at the junction of two elide tags, ended up hidden with wrong logicalLine flags). (4) UndoClearTagsPerform now protects the range ends before calling UpdateElideInfo (its recompute call predates the branch and always hit the entry assert), and extends the range to the boundaries of the enclosing elided ranges. (5) TkBTreeJoinUndoDelete refuses to join delete tokens whose joined end cannot be computed reliably (mark based indices of steady marks do not tell whether the chunks span line boundaries; joining is only an optimization). With regression tests btree-14.65 - 14.72. check-in: 78d3093ab9 user: nab tags: nab-reliquats
12:04
Fix the range ends passed to UpdateElideInfo by the two new recompute call sites (insertion inside an elided range, reconciliation after undo): the closing link of the enclosing range was passed as last segment, but the range extension of UpdateElideInfo walks over trailing zero size segments, so it also walked over the opening branch of a following elided range - encountering that branch resets the pending link bookkeeping, and the post-loop connected an inserted branch to the link of the following range instead (panic 'related branch is not pointing to this link', found by the interleaved fuzzer, seed 615). The last segment of the range is now normalized to the content segment preceding the closing link (ContentBeforeLink); the range extension includes the link again but stops at the following content segment. With regression test btree-14.64. check-in: ce9c20010e user: nab tags: nab-reliquats
11:54
Fix the section producers leaving short sections with an arbitrary (unpinned) boundary next to a switch, which violates the section constraints (panic 'too few segments in section' from CheckSections, reachable without undo): (1) the greedy packing of RebuildSections closed every section at the quota NUM_TEXT_SEGS without looking at the remainder - if the following run is terminated by a switch boundary in less than MIN_TEXT_SEGS segments, some segments are now given back, both parts satisfy the minimum since NUM_TEXT_SEGS is two times MIN_TEXT_SEGS (triggered by ~40 fragmented segments inside an elided range, on any rebuild: delete, tag add of an elide tag, ...); (2) the fixed cut of SplitSection could leave a short right part whose left boundary is a cut, isolating for instance the branch when marks pile up at it - the cut walks back so the right part reaches the minimum (the left part keeps more than that, the section cannot exceed NUM_TEXT_SEGS + MIN_TEXT_SEGS here); also removed the dead left-shift loop (for (i = capacityLHS; i < capacityLHS; ...)) which never executed; (3) JoinSections refused to repair a short section pinned at its right boundary only - it now balances with the left neighbor, reusing the dissolve-or-borrow logic factored out of SplitSectionAtSwitch as BalanceSectionWithLeft; (4) DeleteRange rebalances the section of an unlinked boundary mark (the shrunk section may have lost its permission to be short). With regression tests btree-14.59 - 14.63. check-in: 0f7449e9d2 user: nab tags: nab-reliquats
11:44
Fix the index arithmetic of TkBTreeJoinUndoDelete (join of adjacent delete undo tokens, no elision involved): (1) append case - when the second chunk spans line boundaries, adding its byte size to the byte index of the joined end produced an index beyond the line (assert at redo; with two spanned lines a plain invalid index in release builds); the end now takes the line/byte position of the second chunk's end shifted by the lines of the first chunk, and inherits its surrogate flag (second chunk eating the final newline). (2) prepend case - the start was computed as end2 - byteSize1 (negative byte index, assert at undo; or, matching a later delete by accident, silently corrupted order of the restored chunks), and the line index was taken from the wrong end (line index beyond the tree after multiline deletes, assert in TkBTreeUndoIndexToIndex); the start of the joined range is simply the start of the second chunk, which is valid in every document state since nothing before it changes. With regression tests text-27.37 - 27.43. check-in: 6e8da1b091 user: nab tags: nab-reliquats
11:36
Fix the twin hole of the previous commit: a switch dying inside a deletion stashes its counterpart in the undo token (for the reciprocal reconnection at undo time), but held no reference - if the counterpart (a switch surviving in the tree) was annihilated by an elision update before the token performed, the stash pointed into freed memory and the restore proc wired the restored switch to it (assert in debug builds, heap corruption in release; e.g. delete spanning two elided ranges, then tag configure -elide 0, then undo). The stash now holds a reference (taken in Branch/LinkDeleteProc, released by every consumer: the restore procs, the DELETE_BRANCHES disposal, and the relinking of saved boundary switches in DeleteRange), and the restore procs drop the switch when the stashed counterpart carries the annihilation marker (NULL fork) - a dead-in-token counterpart keeps its fork, so whole enrolled pairs still restore normally. With regression test btree-14.58. check-in: b27c4dd487 user: nab tags: nab-reliquats
11:27
Fix use-after-free when a switch enrolled in an undo/redo token is annihilated by an elision update before the token performs: a deletion bordering an elided range pulls the branch/link into the range, re-inserts it and enrolls it in the token (extra reference); if the pair dies afterwards (undo of the tag add, tag configure -elide 0, tag remove/delete - any path through UpdateElideInfo), the counterpart was freed for real and the enrolled switch kept a fork pointer into freed memory - the restore proc then took the 'stayed alive in the tree' path and dereferenced it (assert in debug builds, heap corruption in release, e.g. redo after undo of an insert adjacent to an elided range start). UpdateElideInfo now marks an enrolled switch as annihilated (NULL fork) instead of parking it for reuse, the restore procs drop an annihilated switch (the elide topology is recomputed from the tags after the restore), and the restore walk of UndoDeletePerform no longer references a dropped segment (lastPtr advances only on success, firstPtr is cleared). With regression tests btree-14.55 - 14.57. check-in: 2d99a48773 user: nab tags: nab-reliquats
11:20
Fix insertion of non-elided text inside an elided range: when the insertion point is the meeting point of two adjacent ranges of distinct elide tags, the new segments receive the intersection of the neighboring tag sets (tagging mode 'within'), which does not elide - the inserted text was invisibly swallowed by the enclosing branch/link pair, and the next UpdateElideInfo run bounded by this non-elided island corrupted the switch chain (mismatch in number of links and branches, misplaced branch/link - fuzz seeds 251/21/398). TkBTreeInsertChars now recomputes the elide topology of the enclosing range when the new segments are not elided but the preceding content segment is, so the range is split around the insertion. With regression tests btree-14.50 - 14.54. check-in: 232de613d4 user: nab tags: nab-reliquats
11:17
Fix undo of deletions in elided ranges whose tags do not restore the old elide state: the switches were saved and restored verbatim, but the restored chars may carry other tags than at the time of the deletion (tags configured with -undo 0 are not restored, and the elide state of a tag may have been reconfigured between the deletion and the undo), so the restored branch/link topology could span non-elided content (misplaced link/branch panics), hide restored text, or resurrect a zone whose tag is gone. UndoDeletePerform now recomputes the elide topology of the restored range from the current tag information, extended to the enclosing elided ranges. For this, UpdateElideInfo gets a recompute mode (tagPtr NULL with ELISION_HAS_BEEN_CHANGED); the call site in UndoClearTagsPerform already used this combination (and hitherto stripped all switches in the range instead of recomputing). With regression tests btree-14.40 - 14.49. check-in: 643b5ea262 user: nab tags: nab-reliquats
10:48
Fix crash of [pathName clear] on a text widget with peers: the peer loop of ClearText called TkTextFreeAllTags once per peer, but the tags are shared (and the freed tags stay in the hash table), so every tag was freed multiple times; only the release of the peer's current tag info belongs into the loop, the tags are now freed once, before the tag table is deleted (mirrors DestroyText). The loop also reset dInfoPtr/dontRepick/lastLineY of the invoking widget instead of the iterated peer, leaving the freed dInfoPtr of the other peers in place (crash in TkTextFreeDInfo on the second iteration). With regression tests text-42.1/42.2. check-in: 266b16dfaf user: nab tags: nab-reliquats
10:19
Merge nab-deleterange-elide: make deletions and undo/redo across elided region boundaries reliable. DeleteRange handles all switch topologies of a deletion range (separate savedLinkPtr/savedBranchPtr, merge of regions becoming adjacent, canonicalization of regions adjacent to the range, counter transfer at line joins, byte-position anchor for the surrogate newline); UndoDeletePerform restores switches with correct sections, counters and mark ordering in multiline tokens, releases the token references (leak), and keeps dead switches out of foreign token chains; delete undo tokens holding switches are not joined anymore; 'edit reset' and ClearText dispose of the retained tag/mark undo tokens; a full undo stack evicts its oldest atom instead of retaining stale ones; TkRangeListDelete/Add/Contains repairs. With regression tests btree-14.12 - btree-14.39, text-27.32/33/35/36, textDisp-38.1 - 38.3. check-in: 182404a7a2 user: nab tags: revised_text, tip-466
10:16
Merge revised_text: trunk merges, nab-tabs-wrap-none, and the five adversarial hardening fixes (nab-integration). The regression tests btree-14.8 - btree-14.35 of this branch move to btree-14.12 - btree-14.39, the merged nab-integration tests own btree-14.8 - btree-14.11. Closed-Leaf check-in: d303deaebf user: nab tags: nab-deleterange-elide
10:02
Merge nab-integration: five fixes from the adversarial hardening campaign - numeric tabs with -wrap none, widget -locale relayout, [checksum -displaytext] eliding, load/ClearText tag rootPtr reset, and UpdateElideInfo branch reuse + protectionFlag clearing. With regression tests. check-in: 45ee0da4df user: nab tags: revised_text, tip-466
10:01
Integrate nab-elide-updateinfo Closed-Leaf check-in: bcf3aadd28 user: nab tags: nab-integration
10:01
Integrate nab-load-tag-reset check-in: 71197c4d79 user: nab tags: nab-integration
10:01
Integrate nab-checksum-displaytext check-in: 76cf95debb user: nab tags: nab-integration
10:01
Integrate nab-locale-relayout check-in: a702702deb user: nab tags: nab-integration
10:01
Integrate nab-tabs-numeric check-in: 9f5ca24c4d user: nab tags: nab-integration
08:27
Add scheduling instructions for Github CI Leaf check-in: 57de653867 user: erikleunissen tags: bug-f093ef6765
2026-07-14
19:56
fix[393f9b0ab8]: Aqua fullscreen bit is not preserved when wm attributes -stylemask is passed an empty list. Patch from Miguel Bagnon. Leaf check-in: f84d2e4ae7 user: culler tags: trunk, main
19:53
fix[393f9b0ab8]: Aqua fullscreen bit is not preserved when wm attributes -stylemask is passed an empty list. Patch from Miguel Bagnon. Leaf check-in: 45a298e054 user: culler tags: core-9-0-branch
15:18
Fix EXEC flag check-in: a9e781cfec user: jan.nijtmans tags: revised_text, tip-466
15:16
Merge trunk check-in: a38aaca69e user: jan.nijtmans tags: revised_text, tip-466
15:12
Add TIP #687 to the changes check-in: f8c3f38d4f user: jan.nijtmans tags: trunk, main
2026-07-12
19:32
Menubar highlighting now working correctly Leaf check-in: 082d4b63ab user: kevin_walzer tags: wayland
17:25
Fix for keypress bug that prevented arrow navigation and copy/paste operations in entry/text widgets; improved clipboard operation; other minor fixes check-in: 588460861c user: kevin_walzer tags: wayland
04:25
Placeholder commit - some keypresses still need work check-in: 0a78dfae70 user: kevin_walzer tags: wayland
04:11
Recent changes have broken non-letter keypresses in entry and text widgets such as right/left, Control-C, etc. - needs further review check-in: 12d7ad97b8 user: kevin_walzer tags: wayland
02:16
Treeview added argc check for set command with multiple values check-in: b594511c0c user: Brian tags: trunk, main
01:06
Refine clipboard check-in: 0f029fccd6 user: kevin_walzer tags: wayland
00:45
Numerous fixes for image color, cursor tracking, and event loop; thanks to Weiwu Zhang for patches check-in: 5a115f8b5c user: kevin_walzer tags: wayland
2026-07-11
20:07
Merge trunk check-in: 53941ee608 user: kevin_walzer tags: wayland
19:00
Systray now works on Wayland; best on KDE, which is the reference SNI/systray implementation; more limited support on Gnome, which only implements a subset of the spec; untested on other compositors; this variation will be documented check-in: 66af4268cd user: kevin_walzer tags: wayland
16:32
Keyboard navigation of menubars now works correctly check-in: 69286b388f user: kevin_walzer tags: wayland
07:17
Merge nab-tabs-wrap-none: fix [5d950fd28a] - default tab stops collapse with -wrap none check-in: 093c990299 user: nab tags: revised_text, tip-466
01:18
Minor cleanup of systray, menus still not working check-in: 62b1edc657 user: kevin_walzer tags: wayland
00:52
Keyboard navigation now working on menus check-in: a4825de19a user: kevin_walzer tags: wayland
2026-07-10
21:38
Evict the oldest undo atom when the stack is full, instead of dropping the new operation while keeping the stale ones. The record gates (TkTextUndoStackIsFull at insert/delete/clearTags/image/window) suppressed the undo token of a new operation once the stack was full, but left the older atoms in place - undoing them then replayed against the shifted content (wrong result, or a B-Tree panic), even without any elision. Removing the gates lets the existing eviction path of InsertCurrentAtom run (it already evicts the oldest atom at the depth limit); the size limit, which has no eviction loop, now clears the stack so that no retained atom is replayed against changed content. With regression test text-27.36. check-in: 7e6d9c795b user: nab tags: nab-deleterange-elide
19:38
DeleteRange: insert the surrogate newline at the end of its anchor segment. TkTextIndexSetSegment addresses the first byte of beforeSurrogate, so the surrogate newline landed up to size bytes too early - re-inserted marks used to hide this by re-anchoring, but after an undo they sit past the range and a redo (or a fresh delete to the end) inserted the surrogate before the branch of an elided region reaching the final newline, pushing content behind the end marker (silent loss; 'end marker of shared resource is not at start of line' with checkers). The insertion now works with the byte position at the end of the anchor, which the segment gravities keep outside of any elided region, fixing also the same corruption without any elision (plain tag on the final newline, and a deletion starting at a line start, where the old fallback anchored at the start of the previous line's last segment). With regression tests btree-14.31 - btree-14.35. check-in: b35db40810 user: nab tags: nab-deleterange-elide
19:15
Scaling-related improvements for the vista and winnative themes. check-in: a189c1e92b user: csaba tags: trunk, main
19:07
Post-review hardening of the elision switch handling. (1) A switch recorded as re-inserted in an undo token could be captured again by a later overlapping delete; recording it as dead then linked both tokens' chains through its single nextPtr (use-after-free at stack teardown): a dead switch now stays a standalone chain tail. (2) The boundary pulls of DeleteRange moved the boundary mark over intermediate marks, sweeping marks outside of the range into it ('delete -marks' destroyed them): the switch is moved over the boundary instead, intermediate marks stay outside; the emptied-section handling of MoveSegmentToLeft/Right no longer frees a section that is still linked in the section chain. (3) JoinSections read sectionPtr->nextPtr after freeing sectionPtr. (4) TkRangeListContainsRange compared in the wrong direction, and TkRangeListContainsAny tested low+1 instead of low-1. With regression tests btree-14.29/14.30. check-in: a3af1a52a0 user: nab tags: nab-deleterange-elide
18:54
Close fork check-in: 6065173fe5 user: oehhar tags: trunk, main
16:32
[4ca13deb] negative comparisen with size_t from nanosvg#291 https://github.com/memononen/nanosvg/pull/291 check-in: 8fb1af3d2f user: oehhar tags: core-9-0-branch
16:29
[4ca13deb] negative comparisen with size_t from nanosvg#291 https://github.com/memononen/nanosvg/pull/291 check-in: b219eac916 user: oehhar tags: trunk, main
14:31
tkRangeList: repair TkRangeListDelete - (a) a range straddling the deletion start kept only its first integer instead of [low, high-1], losing invalidation coverage; (b) deleting inside a gap shifted the successor range onto its neighbor without amalgamating, violating the canonical form (assert in CountIntegers); (c) the right-overlap branch failed to advance past the adjusted range when no amalgamation happened, shifting it twice; (d) the amalgamation memmove copied one element too many. Also TkRangeListAdd: the new-lower-bound branch did not extend the upper bound. Validated by differential fuzzing against a bitset model (700k+ seeds). With regression tests textDisp-38.1 - 38.3. check-in: d818ec4cfa user: nab tags: nab-deleterange-elide
14:31
DeleteRange: canonicalize elided regions adjacent to the deletion range. A link just before the range (region ending exactly at range start) and a branch just after it (region starting exactly at range end) are now pulled into the range, like the overlapping cases already were: deleting all visible text between two elided regions merges them instead of leaving two adjacent switches, and single-sided adjacency re-adds the switch at its place. MoveSegmentToLeft/Right now maintain the backward links of the moved segment (they left stale prev/next pointers, re-pulling the same switch), and the line's segPtr is repaired when the moved boundary mark was heading the line. Restored switches are linked with LinkSwitch (mark ordering rules) instead of LinkSegment. With regression tests btree-14.25 - btree-14.28. check-in: 34e82775b4 user: nab tags: nab-deleterange-elide