URL: <https://savannah.gnu.org/bugs/?68343>
Summary: copy-mode f/F/t/T jumps to column N×4 instead of N
Group: GNU Screen
Submitter: None
Submitted: Mon 11 May 2026 10:45:50 PM UTC
Category: Program Logic
Severity: 3 - Normal
Priority: 5 - Normal
Status: None
Privacy: Public
Assigned to: None
Open/Closed: Open
Discussion Lock: Unlocked
Release: None
Fixed Release: None
Planned Release: None
Work Required: None
_______________________________________________________
Follow-up Comments:
-------------------------------------------------------
Date: Mon 11 May 2026 10:45:50 PM UTC By: Anonymous
Bug
---
In copy mode, the vi-style character-search commands `f`, `F`, `t`, `T`
(and the `;` / `,` repeats) land the cursor at a column that is roughly
4x the column of the target character, not at the target itself.
Affected versions: 5.0.0, 5.0.1 (verified). The commands were added in
4.2.0 (2008, commit 2808ef0) and worked correctly through 4.x.
`/`, `?`, `n`, `N` search are unaffected.
Reproducer
----------
1. screen -c /dev/null (fresh session, no rc)
2. echo abcdefghijklmnopqrstuvwxyz
3. Enter copy mode (Ctrl+A [), position cursor at far left of the
alphabet output line.
4. Type `fb`. Expected: cursor lands on `b`. Actual: cursor lands on `e`.
5. `fc` lands on `i`, `fd` on `m`, `fe` on `q`, `ff` on `u` ... the
landing column is consistently 4x the target's column.
Root cause
----------
mark.c:nextchar() was added in 2008 (commit 2808ef0) when the line
buffer (struct mline.image) was a `char *`. In commit 2b4641c (2012,
first shipped in 5.0.0) the storage was widened to `uint32_t *` so
each cell holds a Unicode codepoint. nextchar() was not updated; it
still casts the buffer to `char *` and indexes byte-by-byte:
displayed_line = (char *)WIN(*yp)->image;
...
if (displayed_line[x] == target) {
On little-endian hosts the low byte of cell N sits at byte offset N*4
and equals the ASCII codepoint, so the loop "finds" the target and
sets the cursor column to that byte offset. revto(cx, cy) then moves
the cursor to that column visually -- 4x the real one.
Fix
---
Index the buffer as uint32_t, matching the storage type. The
(uint32_t)(unsigned char) cast on `target` avoids sign-extension if
the parameter ever carries a high-bit value.
The patch also retabs the four sibling declarations in the same block
so all five comments remain aligned at column 40 (the new wider type
name pushed the modified line one tab stop to the right).
Verification
------------
Patched the 5.0.1 source via Homebrew on macOS 15 (arm64); rebuilt
clean with no new warnings; reproducer above now lands at the correct
column. /, ?, n, N continue to work; word-motion (w, b, e, B, E)
unaffected.
Submission
----------
Patch attached as 0001-mark-fix-fFtT-byte-indexing.patch. The change
is 7 lines (2 functional, 5 cosmetic alignment) and well under the
FSF trivial-contribution threshold; no copyright assignment paperwork
needed.
_______________________________________________________
File Attachments:
Name: screen-fft-fix.patch Size: 1.1KiB
<https://file.savannah.gnu.org/file/screen-fft-fix.patch?file_id=58606>
AGPL NOTICE
These attachments are served by Savane. You can download the corresponding
source code of Savane at
https://savannah.gnu.org/source/savane-c36938be85ff6c1b727bc7dd7fd30e48f9142870.tar.gz
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?68343>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
signature.asc
Description: PGP signature
