Filed as Savannah bug #68343: https://savannah.gnu.org/bugs/index.php?68343

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. 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
----------
The change is 7 lines (3 functional, 4 cosmetic alignment) and well
under the FSF trivial-contribution threshold; no copyright assignment
paperwork needed.

Patch attached.

Thanks,
Jon Derryberry

Attachment: 0001-mark-fix-fFtT-byte-indexing.patch
Description: Binary data

Reply via email to