Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use full TextAttribute when copying data into Clipboard #16270

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ CLIPCHILDREN
CLIPSIBLINGS
closetest
cloudconsole
clrf
cls
CLSCTX
clsids
Expand Down Expand Up @@ -1162,8 +1163,8 @@ msrc
MSVCRTD
msys
MTSM
munged
munges
Munged
murmurhash
muxes
myapplet
Expand Down Expand Up @@ -1967,7 +1968,13 @@ uiautomationcore
uielem
UIELEMENTENABLEDONLY
UINTs
ul
ulc
ulcch
uld
uldb
uldash
ulwave
umul
umulh
Unadvise
Expand Down
435 changes: 227 additions & 208 deletions src/buffer/out/textBuffer.cpp

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions src/buffer/out/textBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,33 +229,33 @@ class TextBuffer final
std::wstring GetCustomIdFromId(uint16_t id) const;
void CopyHyperlinkMaps(const TextBuffer& OtherBuffer);

class TextAndColor
struct TextAndAttribute
{
public:
std::vector<std::wstring> text;
std::vector<std::vector<COLORREF>> FgAttr;
std::vector<std::vector<COLORREF>> BkAttr;
std::vector<til::small_rle<TextAttribute, uint16_t, 1>> attrs;
};

size_t SpanLength(const til::point coordStart, const til::point coordEnd) const;

const TextAndColor GetText(const bool includeCRLF,
const bool trimTrailingWhitespace,
const std::vector<til::inclusive_rect>& textRects,
std::function<std::pair<COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors = nullptr,
const bool formatWrappedRows = false) const;
const TextAndAttribute GetText(const bool includeCRLF,
const bool trimTrailingWhitespace,
const std::vector<til::inclusive_rect>& textRects,
std::function<std::tuple<COLORREF, COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors = nullptr,
const bool formatWrappedRows = false) const;

std::wstring GetPlainText(const til::point& start, const til::point& end) const;

static std::string GenHTML(const TextAndColor& rows,
static std::string GenHTML(const TextAndAttribute& rows,
const int fontHeightPoints,
const std::wstring_view fontFaceName,
const COLORREF backgroundColor);
const COLORREF backgroundColor,
const bool isIntenseBold);

static std::string GenRTF(const TextAndColor& rows,
static std::string GenRTF(const TextAndAttribute& rows,
const int fontHeightPoints,
const std::wstring_view fontFaceName,
const COLORREF backgroundColor);
const COLORREF backgroundColor,
const bool isIntenseBold);

struct PositionInformation
{
Expand Down
7 changes: 5 additions & 2 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}

const auto bgColor = _terminal->GetAttributeColors({}).second;
const auto isIntenseBold = _terminal->GetRenderSettings().GetRenderMode(::Microsoft::Console::Render::RenderSettings::Mode::IntenseIsBold);

// convert text to HTML format
// GH#5347 - Don't provide a title for the generated HTML, as many
Expand All @@ -1271,15 +1272,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TextBuffer::GenHTML(bufferData,
_actualFont.GetUnscaledSize().height,
_actualFont.GetFaceName(),
bgColor) :
bgColor,
isIntenseBold) :
"";

// convert to RTF format
const auto rtfData = formats == nullptr || WI_IsFlagSet(formats.Value(), CopyFormat::RTF) ?
TextBuffer::GenRTF(bufferData,
_actualFont.GetUnscaledSize().height,
_actualFont.GetFaceName(),
bgColor) :
bgColor,
isIntenseBold) :
"";

// send data up for clipboard
Expand Down
12 changes: 7 additions & 5 deletions src/cascadia/TerminalControl/HwndTerminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ try
return nullptr;
}

TextBuffer::TextAndColor bufferData;
TextBuffer::TextAndAttribute bufferData;
{
const auto lock = publicTerminal->_terminal->LockForWriting();
bufferData = publicTerminal->_terminal->RetrieveSelectedTextFromBuffer(false);
Expand Down Expand Up @@ -963,9 +963,9 @@ void __stdcall TerminalKillFocus(void* terminal)
// Routine Description:
// - Copies the text given onto the global system clipboard.
// Arguments:
// - rows - Rows of text data to copy
// - rows - Rows of text and attribute data to copy
// - fAlsoCopyFormatting - true if the color and formatting should also be copied, false otherwise
HRESULT HwndTerminal::_CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, const bool fAlsoCopyFormatting)
HRESULT HwndTerminal::_CopyTextToSystemClipboard(const TextBuffer::TextAndAttribute& rows, const bool fAlsoCopyFormatting)
try
{
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
Expand Down Expand Up @@ -1007,16 +1007,18 @@ try
{
const auto& fontData = _actualFont;
const int iFontHeightPoints = fontData.GetUnscaledSize().height; // this renderer uses points already
const auto isIntenseBold = _terminal->GetRenderSettings().GetRenderMode(::Microsoft::Console::Render::RenderSettings::Mode::IntenseIsBold);

COLORREF bgColor;
{
const auto lock = _terminal->LockForReading();
bgColor = _terminal->GetAttributeColors({}).second;
}

auto HTMLToPlaceOnClip = TextBuffer::GenHTML(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor);
auto HTMLToPlaceOnClip = TextBuffer::GenHTML(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor, isIntenseBold);
_CopyToSystemClipboard(HTMLToPlaceOnClip, L"HTML Format");

auto RTFToPlaceOnClip = TextBuffer::GenRTF(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor);
auto RTFToPlaceOnClip = TextBuffer::GenRTF(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor, isIntenseBold);
_CopyToSystemClipboard(RTFToPlaceOnClip, L"Rich Text Format");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalControl/HwndTerminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct HwndTerminal : ::Microsoft::Console::Types::IControlAccessibilityInfo

void _UpdateFont(int newDpi);
void _WriteTextToConnection(const std::wstring_view text) noexcept;
HRESULT _CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, const bool fAlsoCopyFormatting);
HRESULT _CopyTextToSystemClipboard(const TextBuffer::TextAndAttribute& rows, const bool fAlsoCopyFormatting);
HRESULT _CopyToSystemClipboard(std::string stringToCopy, LPCWSTR lpszFormat);
void _PasteTextFromClipboard() noexcept;

Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ class Microsoft::Terminal::Core::Terminal final :
til::point SelectionEndForRendering() const;
const SelectionEndpoint SelectionEndpointTarget() const noexcept;

const TextBuffer::TextAndColor RetrieveSelectedTextFromBuffer(bool trimTrailingWhitespace);
const TextBuffer::TextAndAttribute RetrieveSelectedTextFromBuffer(bool trimTrailingWhitespace);
#pragma endregion

#ifndef NDEBUG
Expand Down
10 changes: 7 additions & 3 deletions src/cascadia/TerminalCore/TerminalSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,13 +836,17 @@ void Terminal::ClearSelection()
// Arguments:
// - singleLine: collapse all of the text to one line
// Return Value:
// - wstring text from buffer. If extended to multiple lines, each line is separated by \r\n
const TextBuffer::TextAndColor Terminal::RetrieveSelectedTextFromBuffer(bool singleLine)
// - wstring text and attribute from buffer. If extended to multiple lines, each line is separated by \r\n
const TextBuffer::TextAndAttribute Terminal::RetrieveSelectedTextFromBuffer(bool singleLine)
{
const auto selectionRects = _GetSelectionRects();

const auto GetAttributeColors = [&](const auto& attr) {
return _renderSettings.GetAttributeColors(attr);
const auto [fg, bg] = _renderSettings.GetAttributeColors(attr);
// TODO: GetAttributeUnderlineColor calls GetAttributeColors
// internally, which is redundant.
const auto ul = _renderSettings.GetAttributeUnderlineColor(attr);
return std::tuple{ fg, bg, ul };
};

// GH#6740: Block selection should preserve the visual structure:
Expand Down
18 changes: 12 additions & 6 deletions src/interactivity/win32/Clipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,11 @@ void Clipboard::StoreSelectionToClipboard(const bool copyFormatting)
const auto& renderSettings = gci.GetRenderSettings();

const auto GetAttributeColors = [&](const auto& attr) {
return renderSettings.GetAttributeColors(attr);
const auto [fg, bg] = renderSettings.GetAttributeColors(attr);
// TODO: GetAttributeUnderlineColor calls GetAttributeColors
// internally, which is redundant.
const auto ul = renderSettings.GetAttributeUnderlineColor(attr);
return std::tuple{ fg, bg, ul };
};

bool includeCRLF, trimTrailingWhitespace;
Expand All @@ -256,9 +260,9 @@ void Clipboard::StoreSelectionToClipboard(const bool copyFormatting)
// Routine Description:
// - Copies the text given onto the global system clipboard.
// Arguments:
// - rows - Rows of text data to copy
// - rows - Rows of text and attribute data to copy
// - fAlsoCopyFormatting - true if the color and formatting should also be copied, false otherwise
void Clipboard::CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, const bool fAlsoCopyFormatting)
void Clipboard::CopyTextToSystemClipboard(const TextBuffer::TextAndAttribute& rows, const bool fAlsoCopyFormatting)
{
std::wstring finalString;

Expand Down Expand Up @@ -299,12 +303,14 @@ void Clipboard::CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows,
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& fontData = gci.GetActiveOutputBuffer().GetCurrentFont();
const auto iFontHeightPoints = fontData.GetUnscaledSize().height * 72 / ServiceLocator::LocateGlobals().dpi;
const auto bgColor = gci.GetRenderSettings().GetAttributeColors({}).second;
const auto& renderSettings = gci.GetRenderSettings();
const auto bgColor = renderSettings.GetAttributeColors({}).second;
const auto isIntenseBold = renderSettings.GetRenderMode(::Microsoft::Console::Render::RenderSettings::Mode::IntenseIsBold);

auto HTMLToPlaceOnClip = TextBuffer::GenHTML(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor);
auto HTMLToPlaceOnClip = TextBuffer::GenHTML(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor, isIntenseBold);
CopyToSystemClipboard(HTMLToPlaceOnClip, L"HTML Format");

auto RTFToPlaceOnClip = TextBuffer::GenRTF(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor);
auto RTFToPlaceOnClip = TextBuffer::GenRTF(rows, iFontHeightPoints, fontData.GetFaceName(), bgColor, isIntenseBold);
CopyToSystemClipboard(RTFToPlaceOnClip, L"Rich Text Format");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/interactivity/win32/clipboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace Microsoft::Console::Interactivity::Win32

void StoreSelectionToClipboard(_In_ const bool fAlsoCopyFormatting);

void CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, _In_ const bool copyFormatting);
void CopyTextToSystemClipboard(const TextBuffer::TextAndAttribute& rows, _In_ const bool copyFormatting);
void CopyToSystemClipboard(std::string stringToPlaceOnClip, LPCWSTR lpszFormat);

bool FilterCharacterOnPaste(_Inout_ WCHAR* const pwch);
Expand Down
Loading