diff --git a/doc/cascadia/SettingsSchema.md b/doc/cascadia/SettingsSchema.md
index 14c83aeb5c..6522b03650 100644
--- a/doc/cascadia/SettingsSchema.md
+++ b/doc/cascadia/SettingsSchema.md
@@ -7,6 +7,7 @@ Properties listed below affect the entire window, regardless of the profile sett
| -------- | --------- | ---- | ------- | ----------- |
| `alwaysShowTabs` | _Required_ | Boolean | `true` | When set to `true`, tabs are always displayed. When set to `false` and `showTabsInTitlebar` is set to `false`, tabs only appear after typing Ctrl + T. |
| `copyOnSelect` | Optional | Boolean | `false` | When set to `true`, a selection is immediately copied to your clipboard upon creation. When set to `false`, the selection persists and awaits further action. |
+| `copyFormatting` | Optional | Boolean | `false` | When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. |
| `defaultProfile` | _Required_ | String | PowerShell guid | Sets the default profile. Opens by typing Ctrl + T or by clicking the '+' icon. The guid of the desired default profile is used as the value. |
| `initialCols` | _Required_ | Integer | `120` | The number of columns displayed in the window upon first load. |
| `initialPosition` | Optional | String | `","` | The position of the top left corner of the window upon first load. On a system with multiple displays, these coordinates are relative to the top left of the primary display. If `launchMode` is set to `"maximized"`, the window will be maximized on the monitor specified by those coordinates. |
diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json
index 356a474ab4..db6a7e894e 100644
--- a/doc/cascadia/profiles.schema.json
+++ b/doc/cascadia/profiles.schema.json
@@ -277,6 +277,11 @@
"description": "When set to true, a selection is immediately copied to your clipboard upon creation. When set to false, the selection persists and awaits further action.",
"type": "boolean"
},
+ "copyFormatting": {
+ "default": false,
+ "description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard.",
+ "type": "boolean"
+ },
"defaultProfile": {
"$ref": "#/definitions/ProfileGuid",
"description": "Sets the default profile. Opens by clicking the '+' icon or typing the key binding assigned to 'newTab'. The guid of the desired default profile is used as the value."
diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp
index 7d6238cb07..62c814779f 100644
--- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp
+++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp
@@ -32,6 +32,7 @@ static constexpr std::wstring_view TitleLengthTabWidthModeValue{ L"titleLength"
static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" };
static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" };
static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" };
+static constexpr std::string_view CopyFormattingKey{ "copyFormatting" };
static constexpr std::string_view LaunchModeKey{ "launchMode" };
static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" };
static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" };
@@ -67,6 +68,7 @@ GlobalAppSettings::GlobalAppSettings() :
_tabWidthMode{ TabViewWidthMode::Equal },
_wordDelimiters{ DEFAULT_WORD_DELIMITERS },
_copyOnSelect{ false },
+ _copyFormatting{ false },
_launchMode{ LaunchMode::DefaultMode },
_debugFeatures{ debugFeaturesDefault }
{
@@ -161,6 +163,11 @@ void GlobalAppSettings::SetCopyOnSelect(const bool copyOnSelect) noexcept
_copyOnSelect = copyOnSelect;
}
+bool GlobalAppSettings::GetCopyFormatting() const noexcept
+{
+ return _copyFormatting;
+}
+
LaunchMode GlobalAppSettings::GetLaunchMode() const noexcept
{
return _launchMode;
@@ -245,6 +252,7 @@ Json::Value GlobalAppSettings::ToJson() const
jsonObject[JsonKey(ShowTabsInTitlebarKey)] = _showTabsInTitlebar;
jsonObject[JsonKey(WordDelimitersKey)] = winrt::to_string(_wordDelimiters);
jsonObject[JsonKey(CopyOnSelectKey)] = _copyOnSelect;
+ jsonObject[JsonKey(CopyFormattingKey)] = _copyFormatting;
jsonObject[JsonKey(LaunchModeKey)] = winrt::to_string(_SerializeLaunchMode(_launchMode));
jsonObject[JsonKey(ThemeKey)] = winrt::to_string(_SerializeTheme(_theme));
jsonObject[JsonKey(TabWidthModeKey)] = winrt::to_string(_SerializeTabWidthMode(_tabWidthMode));
@@ -311,6 +319,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
JsonUtils::GetBool(json, CopyOnSelectKey, _copyOnSelect);
+ JsonUtils::GetBool(json, CopyFormattingKey, _copyFormatting);
+
if (auto launchMode{ json[JsonKey(LaunchModeKey)] })
{
_launchMode = _ParseLaunchMode(GetWstringFromJson(launchMode));
diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h
index 076b912947..44435c3d57 100644
--- a/src/cascadia/TerminalApp/GlobalAppSettings.h
+++ b/src/cascadia/TerminalApp/GlobalAppSettings.h
@@ -68,6 +68,8 @@ public:
bool GetCopyOnSelect() const noexcept;
void SetCopyOnSelect(const bool copyOnSelect) noexcept;
+ bool GetCopyFormatting() const noexcept;
+
std::optional GetInitialX() const noexcept;
std::optional GetInitialY() const noexcept;
@@ -110,6 +112,7 @@ private:
bool _showTabsInTitlebar;
std::wstring _wordDelimiters;
bool _copyOnSelect;
+ bool _copyFormatting;
winrt::Windows::UI::Xaml::ElementTheme _theme;
winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode _tabWidthMode;
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 5df4710db4..a09f0cc846 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -1310,18 +1310,21 @@ namespace winrt::TerminalApp::implementation
// copy text to dataPack
dataPack.SetText(copiedData.Text());
- // copy html to dataPack
- const auto htmlData = copiedData.Html();
- if (!htmlData.empty())
+ if (_settings->GlobalSettings().GetCopyFormatting())
{
- dataPack.SetHtmlFormat(htmlData);
- }
+ // copy html to dataPack
+ const auto htmlData = copiedData.Html();
+ if (!htmlData.empty())
+ {
+ dataPack.SetHtmlFormat(htmlData);
+ }
- // copy rtf data to dataPack
- const auto rtfData = copiedData.Rtf();
- if (!rtfData.empty())
- {
- dataPack.SetRtf(rtfData);
+ // copy rtf data to dataPack
+ const auto rtfData = copiedData.Rtf();
+ if (!rtfData.empty())
+ {
+ dataPack.SetRtf(rtfData);
+ }
}
try