patches: fix O(position) lag — use lineForAXIndex: instead of lineRangeForRange:

postAccessibilityNotificationsForFrame: was calling NSString
lineRangeForRange: to detect line-crossing cursor moves.  That
method scans from the start of the string, making it O(cursor_offset).
In large buffers with the cursor near the end, this executes on every
redisplay cycle — causing progressive slowdown proportional to cursor
position.

patch 0002 already builds lineStartOffsets in ensureTextCache (O(N)
once per text change) and exposes lineForAXIndex: (O(log L) binary
search).  Use it instead.

Also remove the now-redundant tlen clamping that existed solely
to prevent lineRangeForRange: from receiving an out-of-range index.
lineForAXIndex: handles out-of-range inputs safely.
This commit is contained in:
2026-03-01 08:27:45 +01:00
parent c4975c3fe4
commit 31ad038360

View File

@@ -27,7 +27,7 @@ diff --git a/src/nsterm.m b/src/nsterm.m
index 8f528bd..7e3d57a 100644 index 8f528bd..7e3d57a 100644
--- a/src/nsterm.m --- a/src/nsterm.m
+++ b/src/nsterm.m +++ b/src/nsterm.m
@@ -8718,6 +8718,551 @@ - (NSRect)accessibilityFrame @@ -8718,6 +8718,552 @@ - (NSRect)accessibilityFrame
@end @end
@@ -432,17 +432,18 @@ index 8f528bd..7e3d57a 100644
+ [self ensureTextCache]; + [self ensureTextCache];
+ if (cachedText && oldPoint > 0) + if (cachedText && oldPoint > 0)
+ { + {
+ NSUInteger tlen = [cachedText length];
+ NSUInteger oldIdx = [self accessibilityIndexForCharpos:oldPoint]; + NSUInteger oldIdx = [self accessibilityIndexForCharpos:oldPoint];
+ NSUInteger newIdx = [self accessibilityIndexForCharpos:point]; + NSUInteger newIdx = [self accessibilityIndexForCharpos:point];
+ if (oldIdx > tlen) oldIdx = tlen;
+ if (newIdx > tlen) newIdx = tlen;
+ +
+ NSRange oldLine = [cachedText lineRangeForRange: + /* Use precomputed lineStartOffsets for O(log L) line lookup.
+ NSMakeRange (oldIdx, 0)]; + NSString lineRangeForRange: is O(offset) — it scans from
+ NSRange newLine = [cachedText lineRangeForRange: + the start of the string, causing progressive slowdown in
+ NSMakeRange (newIdx, 0)]; + large buffers (O(cursor_position) per redisplay cycle).
+ if (oldLine.location != newLine.location) + lineForAXIndex: binary-searches lineStartOffsets, built
+ once per cache rebuild in ensureTextCache. */
+ NSInteger oldLine = [self lineForAXIndex: oldIdx];
+ NSInteger newLine = [self lineForAXIndex: newIdx];
+ if (oldLine != newLine)
+ granularity = ns_ax_text_selection_granularity_line; + granularity = ns_ax_text_selection_granularity_line;
+ else + else
+ { + {