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