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/

Attachment: signature.asc
Description: PGP signature

Reply via email to