[PR #16270] Use full TextAttribute when copying data into Clipboard #30886

Closed
opened 2026-01-31 09:43:34 +00:00 by claunia · 0 comments
Owner

Original Pull Request: https://github.com/microsoft/terminal/pull/16270

State: closed
Merged: No


This PR replaces TextBuffer::TextAndColor with TextBuffer::TextAndAttribute which gives us the opportunity to use all of the text attribute we save within buffer while copying data into the clipboard.

We'll use til::small_rle for storing the attributes for each row in the selection rect. This helps in minimizing the memory required for storing all the attribute of a row.

This PR also fixes two bugs in the formatted copy:

  • We were applying line breaks after every selected TextBuffer row, even though the row could have been a wrapped row. This caused wrapped rows to break when they shouldn't. Fix: we now add a newline (<BR> in HTML, \line in RTF) only when we see \r or \n in the text.
  • We were mishandling Unicode text (\uN) within RTF copy. Every next character that uses a surrogate pair or high codepoint was missing in the copied text when pasted to Word. Fix: command \uc4 should have been \uc1, which is used to tell how many characters will be used as a fallback for a unicode character. We always use 1 ? character as the fallback (and not 4, as was the case).

Validation Steps Performed

  • All copying scenarios work as before.
  • Used this echo string from #12586 to validate we are copying all characters of the string.
echo "This is some Ascii \ {}`nLow code units: á é í ó ú `u{2b81} `u{2b82}`nHigh code units: `u{a7b5} `u{a7b7}`nSurrogates: `u{1f366} `u{1f47e} `u{1f440}"

PR Checklist

**Original Pull Request:** https://github.com/microsoft/terminal/pull/16270 **State:** closed **Merged:** No --- This PR replaces `TextBuffer::TextAndColor` with `TextBuffer::TextAndAttribute` which gives us the opportunity to use all of the text attribute we save within buffer while copying data into the clipboard. We'll use `til::small_rle` for storing the attributes for each row in the selection rect. This helps in minimizing the memory required for storing all the attribute of a row. This PR also fixes two bugs in the formatted copy: - We were applying line breaks after every _selected_ `TextBuffer` row, even though the row could have been a wrapped row. This caused wrapped rows to break when they shouldn't. **Fix: we now add a newline (`<BR>` in HTML, `\line` in RTF) only when we see `\r` or `\n` in the text.** - We were mishandling Unicode text (`\uN`) within RTF copy. Every next character that uses a surrogate pair or high codepoint was missing in the copied text when pasted to **Word**. **Fix: command `\uc4` should have been `\uc1`**, which is used to tell how many characters will be used as a fallback for a unicode character. We always use 1 `?` character as the fallback (and not 4, as was the case). ## Validation Steps Performed - All copying scenarios work as before. - Used this echo string from #12586 to validate we are copying *all* characters of the string. ```pwsh echo "This is some Ascii \ {}`nLow code units: á é í ó ú `u{2b81} `u{2b82}`nHigh code units: `u{a7b5} `u{a7b7}`nSurrogates: `u{1f366} `u{1f47e} `u{1f440}" ``` ## PR Checklist - [x] Closes #16191 - [x] Add other attributes to formatted-copy - [x] Refactor `GenRTF` and `GenHTML` to loop using `TextAttrbute` RLE runs. - [ ] Refactor most of our Copy codepaths to get rid of `GetText` and the stuff we do with `TextAndColor`/`TextAndAttribute`. `GenHTML` and `GenRTF` read from the buffer directly.
claunia added the pull-request label 2026-01-31 09:43:34 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#30886