mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-17 11:41:04 +00:00
Compare commits
10 Commits
dev/cazamo
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a83c0f167 | ||
|
|
b2666fb346 | ||
|
|
8f4fdf9751 | ||
|
|
33a80191c1 | ||
|
|
84ae7adec6 | ||
|
|
a6ebdd3d4a | ||
|
|
031998bfc3 | ||
|
|
41e08a68bd | ||
|
|
81170aff78 | ||
|
|
c90ace8326 |
@@ -350,7 +350,7 @@ void ROW::_init() noexcept
|
||||
std::iota(_charOffsets.begin(), _charOffsets.end(), uint16_t{ 0 });
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
void ROW::CopyFrom(const ROW& source)
|
||||
@@ -1143,6 +1143,13 @@ til::CoordType ROW::GetTrailingColumnAtCharOffset(const ptrdiff_t offset) const
|
||||
return _createCharToColumnMapper(offset).GetTrailingColumnAt(offset);
|
||||
}
|
||||
|
||||
uint16_t ROW::GetCharOffset(til::CoordType col) const noexcept
|
||||
{
|
||||
const auto columns = GetReadableColumnCount();
|
||||
const auto colBeg = clamp(col, 0, columns);
|
||||
return _uncheckedCharOffset(gsl::narrow_cast<size_t>(colBeg));
|
||||
}
|
||||
|
||||
DelimiterClass ROW::DelimiterClassAt(til::CoordType column, const std::wstring_view& wordDelimiters) const noexcept
|
||||
{
|
||||
const auto col = _clampedColumn(column);
|
||||
|
||||
@@ -172,6 +172,7 @@ public:
|
||||
std::wstring_view GetText(til::CoordType columnBegin, til::CoordType columnEnd) const noexcept;
|
||||
til::CoordType GetLeadingColumnAtCharOffset(ptrdiff_t offset) const noexcept;
|
||||
til::CoordType GetTrailingColumnAtCharOffset(ptrdiff_t offset) const noexcept;
|
||||
uint16_t GetCharOffset(til::CoordType col) const noexcept;
|
||||
DelimiterClass DelimiterClassAt(til::CoordType column, const std::wstring_view& wordDelimiters) const noexcept;
|
||||
|
||||
auto AttrBegin() const noexcept { return _attr.begin(); }
|
||||
|
||||
@@ -308,6 +308,11 @@ namespace TerminalAppLocalTests
|
||||
// TerminalPage and not only create them successfully, but also create a
|
||||
// tab using those settings successfully.
|
||||
|
||||
// - - - IMPORTANT - - -
|
||||
// GH#14623: "closeOnExit": "never" is important for all test profiles. Without
|
||||
// it, the spawned process exits immediately in the UAP test environment,
|
||||
// and the default "automatic" close-on-exit behavior removes the
|
||||
// tab/pane asynchronously, racing against test assertions.
|
||||
static constexpr std::wstring_view settingsJson0{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
@@ -315,12 +320,14 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
"name" : "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1
|
||||
"historySize": 1,
|
||||
"closeOnExit": "never"
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2
|
||||
"historySize": 2,
|
||||
"closeOnExit": "never"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
@@ -347,10 +354,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::TryDuplicateBadTab()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
// * Create a tab with a profile with GUID 1
|
||||
// * Reload the settings so that GUID 1 is no longer in the list of profiles
|
||||
// * Try calling _DuplicateFocusedTab on tab 1
|
||||
@@ -365,12 +368,14 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
"name" : "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1
|
||||
"historySize": 1,
|
||||
"closeOnExit": "never"
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2
|
||||
"historySize": 2,
|
||||
"closeOnExit": "never"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
@@ -382,7 +387,8 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2
|
||||
"historySize": 2,
|
||||
"closeOnExit": "never"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
@@ -438,10 +444,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::TryDuplicateBadPane()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
// * Create a tab with a profile with GUID 1
|
||||
// * Reload the settings so that GUID 1 is no longer in the list of profiles
|
||||
// * Try calling _SplitPane(Duplicate) on tab 1
|
||||
@@ -456,12 +458,14 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
"name" : "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1
|
||||
"historySize": 1,
|
||||
"closeOnExit": "never"
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2
|
||||
"historySize": 2,
|
||||
"closeOnExit": "never"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
@@ -473,7 +477,8 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2
|
||||
"historySize": 2,
|
||||
"closeOnExit": "never"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
@@ -572,25 +577,29 @@ namespace TerminalAppLocalTests
|
||||
"name" : "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"tabTitle" : "Profile 0",
|
||||
"historySize": 1
|
||||
"historySize": 1,
|
||||
"closeOnExit": "never"
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"tabTitle" : "Profile 1",
|
||||
"historySize": 2
|
||||
"historySize": 2,
|
||||
"closeOnExit": "never"
|
||||
},
|
||||
{
|
||||
"name" : "profile2",
|
||||
"guid": "{6239a42c-3333-49a3-80bd-e8fdd045185c}",
|
||||
"tabTitle" : "Profile 2",
|
||||
"historySize": 3
|
||||
"historySize": 3,
|
||||
"closeOnExit": "never"
|
||||
},
|
||||
{
|
||||
"name" : "profile3",
|
||||
"guid": "{6239a42c-4444-49a3-80bd-e8fdd045185c}",
|
||||
"tabTitle" : "Profile 3",
|
||||
"historySize": 4
|
||||
"historySize": 4,
|
||||
"closeOnExit": "never"
|
||||
}
|
||||
],
|
||||
"schemes":
|
||||
@@ -693,7 +702,6 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
@@ -733,10 +741,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::MoveFocusFromZoomedPane()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
|
||||
Log::Comment(L"Create a second pane");
|
||||
@@ -782,10 +786,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::CloseZoomedPane()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
|
||||
Log::Comment(L"Create a second pane");
|
||||
@@ -841,10 +841,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::SwapPanes()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
|
||||
Log::Comment(L"Setup 4 panes.");
|
||||
@@ -1051,31 +1047,31 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::NextMRUTab()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
// This is a test for GH#8025 - we want to make sure that we can do both
|
||||
// in-order and MRU tab traversal, using the tab switcher and with the
|
||||
// tab switcher disabled.
|
||||
// This is a test for GH#8025 - we want to make sure that MRU tab
|
||||
// ordering works correctly and that in-order/disabled switching works.
|
||||
//
|
||||
// Note: We test MRU ordering directly rather than going through the
|
||||
// command palette tab switcher, because the palette's anchor key
|
||||
// handling auto-dismisses when no modifier keys are held (which we
|
||||
// can't simulate in the test environment).
|
||||
|
||||
auto page = _commonSetup();
|
||||
|
||||
Log::Comment(L"Create a second tab");
|
||||
Log::Comment(L"Create Tab[1]");
|
||||
TestOnUIThread([&page]() {
|
||||
NewTerminalArgs newTerminalArgs{ 1 };
|
||||
page->_OpenNewTab(newTerminalArgs);
|
||||
});
|
||||
VERIFY_ARE_EQUAL(2u, page->_tabs.Size());
|
||||
|
||||
Log::Comment(L"Create a third tab");
|
||||
Log::Comment(L"Create Tab[2]");
|
||||
TestOnUIThread([&page]() {
|
||||
NewTerminalArgs newTerminalArgs{ 2 };
|
||||
page->_OpenNewTab(newTerminalArgs);
|
||||
});
|
||||
VERIFY_ARE_EQUAL(3u, page->_tabs.Size());
|
||||
|
||||
Log::Comment(L"Create a fourth tab");
|
||||
Log::Comment(L"Create Tab[3]");
|
||||
TestOnUIThread([&page]() {
|
||||
NewTerminalArgs newTerminalArgs{ 3 };
|
||||
page->_OpenNewTab(newTerminalArgs);
|
||||
@@ -1084,99 +1080,89 @@ namespace TerminalAppLocalTests
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
|
||||
VERIFY_ARE_EQUAL(3u, focusedIndex, L"Verify the fourth tab is the focused one");
|
||||
VERIFY_ARE_EQUAL(3u, focusedIndex, L"Verify Tab[3] is focused");
|
||||
});
|
||||
|
||||
Log::Comment(L"Select the second tab");
|
||||
Log::Comment(L"Select Tab[1]");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_SelectTab(1);
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
|
||||
VERIFY_ARE_EQUAL(1u, focusedIndex, L"Verify the second tab is the focused one");
|
||||
VERIFY_ARE_EQUAL(1u, focusedIndex, L"Verify Tab[1] is focused");
|
||||
});
|
||||
|
||||
Log::Comment(L"Change the tab switch order to MRU switching");
|
||||
// MRU order should now be: Tab[1], Tab[3], Tab[2], Tab[0]
|
||||
// Verify the MRU list directly.
|
||||
Log::Comment(L"Verify MRU order: MRU[0]=Tab[1], MRU[1]=Tab[3]");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_settings.GlobalSettings().TabSwitcherMode(TabSwitcherMode::MostRecentlyUsed);
|
||||
VERIFY_ARE_EQUAL(4u, page->_mruTabs.Size());
|
||||
uint32_t mruIdx;
|
||||
page->_tabs.IndexOf(page->_mruTabs.GetAt(0), mruIdx);
|
||||
VERIFY_ARE_EQUAL(1u, mruIdx, L"MRU[0] should be Tab[1] (most recent)");
|
||||
page->_tabs.IndexOf(page->_mruTabs.GetAt(1), mruIdx);
|
||||
VERIFY_ARE_EQUAL(3u, mruIdx, L"MRU[1] should be Tab[3] (last tab added)");
|
||||
});
|
||||
|
||||
Log::Comment(L"Switch to the next MRU tab, which is the fourth tab");
|
||||
Log::Comment(L"Select MRU[1]=Tab[3] directly");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_SelectNextTab(true, nullptr);
|
||||
});
|
||||
|
||||
Log::Comment(L"Sleep to let events propagate");
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
Log::Comment(L"Hide the command palette, to confirm the selection");
|
||||
// If you don't do this, the palette will just stay open, and the
|
||||
// next time we call _HandleNextTab, we'll continue traversing the
|
||||
// MRU list, instead of just hoping one entry.
|
||||
page->LoadCommandPalette().Visibility(Visibility::Collapsed);
|
||||
// The next MRU tab after Tab[1] is Tab[3]
|
||||
uint32_t nextMruIdx;
|
||||
page->_tabs.IndexOf(page->_mruTabs.GetAt(1), nextMruIdx);
|
||||
page->_SelectTab(nextMruIdx);
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
|
||||
VERIFY_ARE_EQUAL(3u, focusedIndex, L"Verify the fourth tab is the focused one");
|
||||
VERIFY_ARE_EQUAL(3u, focusedIndex, L"Verify Tab[3] is focused");
|
||||
});
|
||||
|
||||
Log::Comment(L"Switch to the next MRU tab, which is the second tab");
|
||||
Log::Comment(L"Select MRU[1]=Tab[1] directly");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_SelectNextTab(true, nullptr);
|
||||
});
|
||||
|
||||
Log::Comment(L"Sleep to let events propagate");
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
Log::Comment(L"Hide the command palette, to confirm the selection");
|
||||
// If you don't do this, the palette will just stay open, and the
|
||||
// next time we call _HandleNextTab, we'll continue traversing the
|
||||
// MRU list, instead of just hoping one entry.
|
||||
page->LoadCommandPalette().Visibility(Visibility::Collapsed);
|
||||
uint32_t nextMruIdx;
|
||||
page->_tabs.IndexOf(page->_mruTabs.GetAt(1), nextMruIdx);
|
||||
page->_SelectTab(nextMruIdx);
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
|
||||
VERIFY_ARE_EQUAL(1u, focusedIndex, L"Verify the second tab is the focused one");
|
||||
});
|
||||
|
||||
Log::Comment(L"Change the tab switch order to in-order switching");
|
||||
page->_settings.GlobalSettings().TabSwitcherMode(TabSwitcherMode::InOrder);
|
||||
|
||||
Log::Comment(L"Switch to the next in-order tab, which is the third tab");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_SelectNextTab(true, nullptr);
|
||||
});
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
|
||||
VERIFY_ARE_EQUAL(2u, focusedIndex, L"Verify the third tab is the focused one");
|
||||
VERIFY_ARE_EQUAL(1u, focusedIndex, L"Verify Tab[1] is focused");
|
||||
});
|
||||
|
||||
// The Disabled tab switcher mode uses direct index-based switching
|
||||
// without the command palette, so it works in the test environment.
|
||||
Log::Comment(L"Change the tab switch order to not use the tab switcher (which is in-order always)");
|
||||
page->_settings.GlobalSettings().TabSwitcherMode(TabSwitcherMode::Disabled);
|
||||
|
||||
Log::Comment(L"Switch to the next in-order tab, which is the fourth tab");
|
||||
Log::Comment(L"Switch to the next in-order tab: Tab[2]");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_SelectNextTab(true, nullptr);
|
||||
});
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
|
||||
VERIFY_ARE_EQUAL(3u, focusedIndex, L"Verify the fourth tab is the focused one");
|
||||
VERIFY_ARE_EQUAL(2u, focusedIndex, L"Verify Tab[2] is focused");
|
||||
});
|
||||
|
||||
Log::Comment(L"Switch to the next in-order tab: Tab[3]");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_SelectNextTab(true, nullptr);
|
||||
});
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
|
||||
VERIFY_ARE_EQUAL(3u, focusedIndex, L"Verify Tab[3] is focused");
|
||||
});
|
||||
}
|
||||
|
||||
void TabTests::VerifyCommandPaletteTabSwitcherOrder()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
// This is a test for GH#8188 - we want to make sure that the order of tabs
|
||||
// is preserved in the CommandPalette's TabSwitcher
|
||||
// This is a test for GH#8188 - we want to make sure that the MRU
|
||||
// ordering is correctly maintained as tabs are selected.
|
||||
//
|
||||
// Note: We verify MRU ordering directly rather than going through
|
||||
// the command palette tab switcher, because the palette's anchor key
|
||||
// handling auto-dismisses when no modifier keys are held (which we
|
||||
// can't simulate in the test environment).
|
||||
|
||||
auto page = _commonSetup();
|
||||
|
||||
@@ -1189,7 +1175,7 @@ namespace TerminalAppLocalTests
|
||||
});
|
||||
VERIFY_ARE_EQUAL(4u, page->_mruTabs.Size());
|
||||
|
||||
Log::Comment(L"give alphabetical names to all switch tab actions");
|
||||
Log::Comment(L"give alphabetical names to all tabs");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_GetTabImpl(page->_tabs.GetAt(0))->Title(L"a");
|
||||
});
|
||||
@@ -1211,18 +1197,14 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(L"c", page->_tabs.GetAt(2).Title());
|
||||
VERIFY_ARE_EQUAL(L"d", page->_tabs.GetAt(3).Title());
|
||||
|
||||
// MRU order after creating Tab[0]-Tab[3]: MRU[0]=Tab[3], MRU[3]=Tab[0]
|
||||
VERIFY_ARE_EQUAL(L"d", page->_mruTabs.GetAt(0).Title());
|
||||
VERIFY_ARE_EQUAL(L"c", page->_mruTabs.GetAt(1).Title());
|
||||
VERIFY_ARE_EQUAL(L"b", page->_mruTabs.GetAt(2).Title());
|
||||
VERIFY_ARE_EQUAL(L"a", page->_mruTabs.GetAt(3).Title());
|
||||
});
|
||||
|
||||
Log::Comment(L"Change the tab switch order to MRU switching");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_settings.GlobalSettings().TabSwitcherMode(TabSwitcherMode::MostRecentlyUsed);
|
||||
});
|
||||
|
||||
Log::Comment(L"Select the tabs from 0 to 3");
|
||||
Log::Comment(L"Select Tab[0] through Tab[3] to establish MRU order");
|
||||
RunOnUIThread([&page]() {
|
||||
page->_UpdatedSelectedTab(page->_tabs.GetAt(0));
|
||||
page->_UpdatedSelectedTab(page->_tabs.GetAt(1));
|
||||
@@ -1230,47 +1212,31 @@ namespace TerminalAppLocalTests
|
||||
page->_UpdatedSelectedTab(page->_tabs.GetAt(3));
|
||||
});
|
||||
|
||||
Log::Comment(L"Verify MRU order: MRU[0]='d', MRU[1]='c', MRU[2]='b', MRU[3]='a'");
|
||||
VERIFY_ARE_EQUAL(4u, page->_mruTabs.Size());
|
||||
VERIFY_ARE_EQUAL(L"d", page->_mruTabs.GetAt(0).Title());
|
||||
VERIFY_ARE_EQUAL(L"c", page->_mruTabs.GetAt(1).Title());
|
||||
VERIFY_ARE_EQUAL(L"b", page->_mruTabs.GetAt(2).Title());
|
||||
VERIFY_ARE_EQUAL(L"a", page->_mruTabs.GetAt(3).Title());
|
||||
|
||||
Log::Comment(L"Switch to the next MRU tab, which is the third tab");
|
||||
RunOnUIThread([&page]() {
|
||||
page->_SelectNextTab(true, nullptr);
|
||||
// In the course of a single tick, the Command Palette will:
|
||||
// * open
|
||||
// * select the proper tab from the mru's list
|
||||
// * raise an event for _filteredActionsView().SelectionChanged to
|
||||
// immediately preview the new tab
|
||||
// * raise a _SwitchToTabRequestedHandlers event
|
||||
// * then dismiss itself, because we can't fake holing down an
|
||||
// anchor key in the tests
|
||||
Log::Comment(L"Select Tab[2]='c' (MRU[1] after 'd')");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_SelectTab(2);
|
||||
});
|
||||
|
||||
Log::Comment(L"Verify MRU order updated: MRU[0]='c', MRU[1]='d', MRU[2]='b', MRU[3]='a'");
|
||||
TestOnUIThread([&page]() {
|
||||
VERIFY_ARE_EQUAL(L"c", page->_mruTabs.GetAt(0).Title());
|
||||
VERIFY_ARE_EQUAL(L"d", page->_mruTabs.GetAt(1).Title());
|
||||
VERIFY_ARE_EQUAL(L"b", page->_mruTabs.GetAt(2).Title());
|
||||
VERIFY_ARE_EQUAL(L"a", page->_mruTabs.GetAt(3).Title());
|
||||
});
|
||||
|
||||
const auto palette = winrt::get_self<winrt::TerminalApp::implementation::CommandPalette>(page->LoadCommandPalette());
|
||||
|
||||
VERIFY_ARE_EQUAL(winrt::TerminalApp::implementation::CommandPaletteMode::TabSwitchMode, palette->_currentMode, L"Verify we are in the tab switcher mode");
|
||||
// At this point, the contents of the command palette's _mruTabs list is
|
||||
// still the _old_ ordering (d, c, b, a). The ordering is only updated
|
||||
// in TerminalPage::_SelectNextTab, but as we saw before, the palette
|
||||
// will also dismiss itself immediately when that's called. So we can't
|
||||
// really inspect the contents of the list in this test, unfortunately.
|
||||
}
|
||||
|
||||
void TabTests::TestWindowRenameSuccessful()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
@@ -1303,7 +1269,6 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
@@ -1336,10 +1301,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::TestPreviewCommitScheme()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
Log::Comment(L"Preview a color scheme. Make sure it's applied, then committed accordingly");
|
||||
|
||||
auto page = _commonSetup();
|
||||
@@ -1402,10 +1363,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::TestPreviewDismissScheme()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
Log::Comment(L"Preview a color scheme. Make sure it's applied, then dismissed accordingly");
|
||||
|
||||
auto page = _commonSetup();
|
||||
@@ -1454,10 +1411,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::TestPreviewSchemeWhilePreviewing()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
Log::Comment(L"Preview a color scheme, then preview another scheme. ");
|
||||
|
||||
Log::Comment(L"Preview a color scheme. Make sure it's applied, then committed accordingly");
|
||||
@@ -1525,10 +1478,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
void TabTests::TestClampSwitchToTab()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Ignore", L"True") // GH#19610 tracks re-enabling this test
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
Log::Comment(L"Test that switching to a tab index higher than the number of tabs just clamps to the last tab.");
|
||||
|
||||
auto page = _commonSetup();
|
||||
|
||||
@@ -672,9 +672,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Dieser Linktyp wird derzeit nicht unterstützt:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Abbrechen</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Dieser Link kann zu einem unsicheren Speicherort führen. Links können ihren Computer und Ihre Daten beschädigen. Klicken Sie zum Schutz Des Computers nur auf Links aus vertrauenswürdigen Quellen.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Trotzdem öffnen</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Einstellungen</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>This link type is currently not supported:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>This link may lead to an unsafe location. Hyperlinks can be harmful to your computer and data. To protect your computer, only click links from trusted sources.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Open anyway</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Este tipo de vínculo no se admite actualmente:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancelar</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Este vínculo puede dar lugar a una ubicación no segura. Los hipervínculos pueden ser perjudiciales para el equipo y los datos. Para proteger el equipo, haga clic solo en vínculos de orígenes de confianza.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Abrir de todas formas</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Configuración</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Ce type de lien n’est actuellement pas pris en charge :</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Annuler</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Ce lien peut entraîner un emplacement non sécurisé. Les liens hypertexte peuvent endommager votre ordinateur et vos données. Pour protéger votre ordinateur, cliquez uniquement sur des liens provenant de sources fiables.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Ouvrir quand même</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Paramètres</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Questo tipo di collegamento non è al momento supportato:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Annulla</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Questo collegamento potrebbe causare un percorso non sicuro. I collegamenti ipertestuali possono essere dannosi per il computer e i dati. Per proteggere il computer, fare clic solo su collegamenti da origini attendibili.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Apri comunque</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Impostazioni</value>
|
||||
</data>
|
||||
|
||||
@@ -670,9 +670,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>このリンクの種類は現在サポートされていません:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>キャンセル</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>このリンクは安全でない可能性があります。ハイパーリンクは、コンピューターやデータに問題を起こす可能性があります。コンピューターを保護するには、信頼できるソースからのリンクのみをクリックしてください。</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>開く</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>設定</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>이 링크 형식은 현재 지원되지 않습니다.</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>취소</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>이 링크로 인해 안전하지 않은 위치가 발생할 수 있습니다. 하이퍼링크는 컴퓨터와 데이터를 손상시킬 수 있습니다. 컴퓨터를 보호하려면 신뢰할 수 있는 원본의 링크만 클릭하세요.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>열기</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>설정</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Não há suporte para este tipo de link no momento:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancelar</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Este link pode levar a um local não seguro. Hiperlinks podem ser prejudiciais ao computador e aos dados. Para proteger o computador, clique somente em links de fontes confiáveis.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Abrir mesmo assim</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Configurações</value>
|
||||
</data>
|
||||
|
||||
@@ -669,8 +669,14 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Ťђïś łϊηќ ŧурē ιş çũґѓзⁿτľÿ ñστ şΰρρоŕŧĕđ: !!! !!! !!! !!! </value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Сąñс℮ł !</value>
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Çдπсёľ !</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Ŧђīś ℓîŋќ мαў ľêãδ τб áń úʼnšàƒé ℓоćάŧίоñ. Ĥўрзŗℓĭŋķѕ çâⁿ ъέ ђąřмƒúļ τό ўôця ċómφύŧèґ аňδ ðáťǻ. Ţб ρгøťėçŧ ўòύг ςömφùţĕŕ, ŏŋľỳ čℓΐςķ łίŋκѕ ƒřöм ťŗμѕŧєđ śόυяčêś. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Őρέй ǻпŷŵãγ !!!</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Śëţťĩпğś !!</value>
|
||||
|
||||
@@ -669,8 +669,14 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Ťђïś łϊηќ ŧурē ιş çũґѓзⁿτľÿ ñστ şΰρρоŕŧĕđ: !!! !!! !!! !!! </value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Сąñс℮ł !</value>
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Çдπсёľ !</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Ŧђīś ℓîŋќ мαў ľêãδ τб áń úʼnšàƒé ℓоćάŧίоñ. Ĥўрзŗℓĭŋķѕ çâⁿ ъέ ђąřмƒúļ τό ўôця ċómφύŧèґ аňδ ðáťǻ. Ţб ρгøťėçŧ ўòύг ςömφùţĕŕ, ŏŋľỳ čℓΐςķ łίŋκѕ ƒřöм ťŗμѕŧєđ śόυяčêś. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Őρέй ǻпŷŵãγ !!!</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Śëţťĩпğś !!</value>
|
||||
|
||||
@@ -669,8 +669,14 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Ťђïś łϊηќ ŧурē ιş çũґѓзⁿτľÿ ñστ şΰρρоŕŧĕđ: !!! !!! !!! !!! </value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Сąñс℮ł !</value>
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Çдπсёľ !</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Ŧђīś ℓîŋќ мαў ľêãδ τб áń úʼnšàƒé ℓоćάŧίоñ. Ĥўрзŗℓĭŋķѕ çâⁿ ъέ ђąřмƒúļ τό ўôця ċómφύŧèґ аňδ ðáťǻ. Ţб ρгøťėçŧ ўòύг ςömφùţĕŕ, ŏŋľỳ čℓΐςķ łίŋκѕ ƒřöм ťŗμѕŧєđ śόυяčêś. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Őρέй ǻпŷŵãγ !!!</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Śëţťĩпğś !!</value>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>Этот тип связи в настоящее время не поддерживается:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Отмена</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>Эта ссылка может привести к небезопасному расположению. Гиперссылки могут нанести вред компьютеру и данным. Чтобы защитить компьютер, щелкните ссылки только из надежных источников.</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>Все равно открыть</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>Параметры</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>当前不支持此链接类型:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>取消</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>此链接可能会导致不安全的位置。超链接可能对你的计算机和数据有害。若要保护你的计算机,请仅单击来自受信任源的链接。</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>仍然打开</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>设置</value>
|
||||
</data>
|
||||
|
||||
@@ -669,9 +669,15 @@
|
||||
<data name="UnsupportedSchemeText" xml:space="preserve">
|
||||
<value>目前不支援此連結類型:</value>
|
||||
</data>
|
||||
<data name="CouldNotOpenUriDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<data name="UriErrorDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>取消</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmText" xml:space="preserve">
|
||||
<value>此連結可能通往不安全地點。超連結可能對你的電腦和資料造成傷害。為了保護你的電腦,只點擊來自可信來源的連結。</value>
|
||||
</data>
|
||||
<data name="UnsafeUrlConfirmAllowAction" xml:space="preserve">
|
||||
<value>一律開啟</value>
|
||||
</data>
|
||||
<data name="SettingsTab" xml:space="preserve">
|
||||
<value>設定</value>
|
||||
</data>
|
||||
|
||||
@@ -3085,18 +3085,42 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
void TerminalPage::_OpenHyperlinkHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::OpenHyperlinkEventArgs eventArgs)
|
||||
safe_void_coroutine TerminalPage::_OpenHyperlinkHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::OpenHyperlinkEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto parsed = winrt::Windows::Foundation::Uri(eventArgs.Uri());
|
||||
auto uriString{ eventArgs.Uri() };
|
||||
auto parsed = winrt::Windows::Foundation::Uri(uriString);
|
||||
if (_IsUriSupported(parsed))
|
||||
{
|
||||
ShellExecute(nullptr, L"open", eventArgs.Uri().c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
bool shouldLaunch{ _IsUriConsideredSomewhatSafe(parsed) };
|
||||
|
||||
if (!shouldLaunch)
|
||||
{
|
||||
if (auto presenter{ _dialogPresenter.get() })
|
||||
{
|
||||
// FindName needs to be called first to actually load the xaml object
|
||||
auto unopenedUriDialog = FindName(L"UriErrorDialog").try_as<WUX::Controls::ContentDialog>();
|
||||
|
||||
// Insert the reason and the URI
|
||||
unopenedUriDialog.SecondaryButtonText(RS_(L"UnsafeUrlConfirmAllowAction"));
|
||||
CouldNotOpenUriReason().Text(RS_(L"UnsafeUrlConfirmText"));
|
||||
UnopenedUri().Text(uriString);
|
||||
|
||||
// Show the dialog
|
||||
auto result = co_await presenter.ShowDialog(unopenedUriDialog);
|
||||
shouldLaunch = result == ContentDialogResult::Secondary;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldLaunch)
|
||||
{
|
||||
ShellExecuteW(nullptr, L"open", uriString.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_ShowCouldNotOpenDialog(RS_(L"UnsupportedSchemeText"), eventArgs.Uri());
|
||||
_ShowCouldNotOpenDialog(RS_(L"UnsupportedSchemeText"), uriString);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@@ -3116,9 +3140,10 @@ namespace winrt::TerminalApp::implementation
|
||||
if (auto presenter{ _dialogPresenter.get() })
|
||||
{
|
||||
// FindName needs to be called first to actually load the xaml object
|
||||
auto unopenedUriDialog = FindName(L"CouldNotOpenUriDialog").try_as<WUX::Controls::ContentDialog>();
|
||||
auto unopenedUriDialog = FindName(L"UriErrorDialog").try_as<WUX::Controls::ContentDialog>();
|
||||
|
||||
// Insert the reason and the URI
|
||||
unopenedUriDialog.SecondaryButtonText({});
|
||||
CouldNotOpenUriReason().Text(reason);
|
||||
UnopenedUri().Text(uri);
|
||||
|
||||
@@ -3171,6 +3196,30 @@ namespace winrt::TerminalApp::implementation
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TerminalPage::_IsUriConsideredSomewhatSafe(const winrt::Windows::Foundation::Uri& parsedUri)
|
||||
{
|
||||
if (parsedUri.SchemeName() == L"http" || parsedUri.SchemeName() == L"https")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (parsedUri.SchemeName() == L"file")
|
||||
{
|
||||
static const auto pathext{ wil::TryGetEnvironmentVariableW<std::wstring>(L"PATHEXT") };
|
||||
const auto filename = parsedUri.Path();
|
||||
for (const auto& e : til::split_iterator{ std::wstring_view{ pathext }, L';' })
|
||||
{
|
||||
if (til::ends_with_insensitive_ascii(filename, e))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Important! Don't take this eventArgs by reference, we need to extend the
|
||||
// lifetime of it to the other side of the co_await!
|
||||
safe_void_coroutine TerminalPage::_ControlNoticeRaisedHandler(const IInspectable /*sender*/,
|
||||
|
||||
@@ -422,8 +422,9 @@ namespace winrt::TerminalApp::implementation
|
||||
safe_void_coroutine _PasteFromClipboardHandler(const IInspectable sender,
|
||||
const Microsoft::Terminal::Control::PasteFromClipboardEventArgs eventArgs);
|
||||
|
||||
void _OpenHyperlinkHandler(const IInspectable sender, const Microsoft::Terminal::Control::OpenHyperlinkEventArgs eventArgs);
|
||||
bool _IsUriSupported(const winrt::Windows::Foundation::Uri& parsedUri);
|
||||
safe_void_coroutine _OpenHyperlinkHandler(const IInspectable sender, const Microsoft::Terminal::Control::OpenHyperlinkEventArgs eventArgs);
|
||||
static bool _IsUriSupported(const winrt::Windows::Foundation::Uri& parsedUri);
|
||||
static bool _IsUriConsideredSomewhatSafe(const winrt::Windows::Foundation::Uri& parsedUri);
|
||||
|
||||
void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri);
|
||||
bool _CopyText(bool dismissSelection, bool singleLine, bool withControlSequences, Microsoft::Terminal::Control::CopyFormat formats);
|
||||
|
||||
@@ -144,17 +144,17 @@
|
||||
</TextBlock>
|
||||
</ContentDialog>
|
||||
|
||||
<ContentDialog x:Name="CouldNotOpenUriDialog"
|
||||
x:Uid="CouldNotOpenUriDialog"
|
||||
<ContentDialog x:Name="UriErrorDialog"
|
||||
x:Uid="UriErrorDialog"
|
||||
Grid.Row="2"
|
||||
x:Load="False"
|
||||
DefaultButton="Primary">
|
||||
DefaultButton="Close">
|
||||
<TextBlock IsTextSelectionEnabled="True"
|
||||
TextWrapping="WrapWholeWords">
|
||||
<TextBlock.ContextFlyout>
|
||||
<mtu:TextMenuFlyout />
|
||||
</TextBlock.ContextFlyout>
|
||||
<Run x:Name="CouldNotOpenUriReason" /> <LineBreak />
|
||||
<Run x:Name="CouldNotOpenUriReason" /> <LineBreak /> <LineBreak />
|
||||
<Run x:Name="UnopenedUri"
|
||||
FontFamily="Cascadia Mono" />
|
||||
</TextBlock>
|
||||
|
||||
@@ -1935,8 +1935,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - args: event data
|
||||
void TermControl::_TappedHandler(const IInspectable& /*sender*/, const TappedRoutedEventArgs& e)
|
||||
{
|
||||
Focus(FocusState::Pointer);
|
||||
|
||||
if (e.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch)
|
||||
{
|
||||
// Normally TSF would be responsible for showing the touch keyboard, but it's buggy for us:
|
||||
@@ -2908,8 +2906,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do we ever get here (= uninitialized terminal)? If so: How?
|
||||
assert(false);
|
||||
return { 10, 10 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>Tippen, um Symbole zu filtern</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Trennzeichen per Drag &amp; Drop</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Dieser Text wird zwischen den Pfaden mehrerer in das Terminal gezogener Dateien eingefügt.</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2610,19 +2610,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>Escriba para filtrar iconos</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Delimitador de arrastrar y colocar</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Este texto se insertará entre las rutas de acceso de varios archivos colocados en el terminal.</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C :\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C :\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>Taper pour filtrer les icônes</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Glisser-déplacer le délimiteur</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Ce texte sera inséré entre les chemins d’accès de plusieurs fichiers déposés dans le terminal.</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>Digita per filtrare icone</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Trascina e rilascia il delimitatore</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Questo testo verrà inserito tra i percorsi di più file trascinati nel terminale.</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>入力してアイコンをフィルター処理します</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>ドラッグ アンド ドロップ区切り記号</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>このテキストは、ターミナルにドロップされた複数のファイルのパスの間に挿入されます。</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL(C:\ -> /mnt/c)</value>
|
||||
<value>WSL(C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin(C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin(C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2(C:\ -> /c)</value>
|
||||
<value>MSYS2(C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW(C:\ -> C:/)</value>
|
||||
<value>MinGW(C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>입력하여 아이콘 필터링</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>끌어서 놓기 구분 기호</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>이 텍스트는 터미널에 놓인 여러 파일의 경로 사이에 삽입됩니다.</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>Digite para filtrar ícones</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Delimitador de Arrastar e soltar</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Este texto será inserido entre os caminhos de vários arquivos descartados no terminal.</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2610,19 +2610,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c) !!! !!!</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c) !!! !!!</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c) !!! !!! !!</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c) !!! !!! !!</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c) !!! !!</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c) !!! !!</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/) !!! !!</value>
|
||||
<value>MinGW (C:\ 🡒 C:/) !!! !!</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2748,4 +2748,12 @@
|
||||
<value>Тÿρě ţθ ƒíŀŧēŗ īçōйš !!! !!!</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
</root>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Đґâġ ąńð δŗορ ďèŀιмïţ℮я !!! !!! </value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Тĥїś ťэхť ẃĭŀł вё îⁿŝέŗŧеď вēťщ℮ěπ τĥę ρªτħѕ óƒ мџĺţīрℓé ƒĭļèś đяǿρрεδ ιйţθ ţħê ţèřмĭлªŀ. !!! !!! !!! !!! !!! !!! !!! !!! !!!</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2610,19 +2610,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c) !!! !!!</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c) !!! !!!</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c) !!! !!! !!</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c) !!! !!! !!</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c) !!! !!</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c) !!! !!</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/) !!! !!</value>
|
||||
<value>MinGW (C:\ 🡒 C:/) !!! !!</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2748,4 +2748,12 @@
|
||||
<value>Тÿρě ţθ ƒíŀŧēŗ īçōйš !!! !!!</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
</root>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Đґâġ ąńð δŗορ ďèŀιмïţ℮я !!! !!! </value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Тĥїś ťэхť ẃĭŀł вё îⁿŝέŗŧеď вēťщ℮ěπ τĥę ρªτħѕ óƒ мџĺţīрℓé ƒĭļèś đяǿρрεδ ιйţθ ţħê ţèřмĭлªŀ. !!! !!! !!! !!! !!! !!! !!! !!! !!!</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2610,19 +2610,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c) !!! !!!</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c) !!! !!!</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c) !!! !!! !!</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c) !!! !!! !!</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c) !!! !!</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c) !!! !!</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/) !!! !!</value>
|
||||
<value>MinGW (C:\ 🡒 C:/) !!! !!</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2748,4 +2748,12 @@
|
||||
<value>Тÿρě ţθ ƒíŀŧēŗ īçōйš !!! !!!</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
</root>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Đґâġ ąńð δŗορ ďèŀιмïţ℮я !!! !!! </value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Тĥїś ťэхť ẃĭŀł вё îⁿŝέŗŧеď вēťщ℮ěπ τĥę ρªτħѕ óƒ мџĺţīрℓé ƒĭļèś đяǿρрεδ ιйţθ ţħê ţèřмĭлªŀ. !!! !!! !!! !!! !!! !!! !!! !!! !!!</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>Введите текст для фильтрации значков</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>Перетащите разделитель</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>Этот текст будет вставлен между путями нескольких файлов, перетащенных в терминал.</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>键入以筛选图标</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>拖放分隔符</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>此文本将在放置到终端的多个文件的路径之间插入。</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2606,19 +2606,19 @@
|
||||
<comment>An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleWsl.Content" xml:space="preserve">
|
||||
<value>WSL (C:\ -> /mnt/c)</value>
|
||||
<value>WSL (C:\ 🡒 /mnt/c)</value>
|
||||
<comment>{Locked="WSL","C:\","/mnt/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleCygwin.Content" xml:space="preserve">
|
||||
<value>Cygwin (C:\ -> /cygdrive/c)</value>
|
||||
<value>Cygwin (C:\ 🡒 /cygdrive/c)</value>
|
||||
<comment>{Locked="Cygwin","C:\","/cygdrive/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMsys2.Content" xml:space="preserve">
|
||||
<value>MSYS2 (C:\ -> /c)</value>
|
||||
<value>MSYS2 (C:\ 🡒 /c)</value>
|
||||
<comment>{Locked="MSYS2","C:\","/c"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_PathTranslationStyleMinGW.Content" xml:space="preserve">
|
||||
<value>MinGW (C:\ -> C:/)</value>
|
||||
<value>MinGW (C:\ 🡒 C:/)</value>
|
||||
<comment>{Locked="MinGW","C:\","C:/"} An option to choose from for the "path translation" setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_Delete_Orphaned.Header" xml:space="preserve">
|
||||
@@ -2744,4 +2744,12 @@
|
||||
<value>輸入以篩選圖示</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.Header" xml:space="preserve">
|
||||
<value>拖放分隔符號</value>
|
||||
<comment>Header for a control to set the delimiter used when dragging multiple files into the terminal.</comment>
|
||||
</data>
|
||||
<data name="Profile_DragDropDelimiter.HelpText" xml:space="preserve">
|
||||
<value>這些文字會插入多個丟入終端機的檔案路徑之間。</value>
|
||||
<comment>A description for what the "drag drop delimiter" setting does.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -105,9 +105,10 @@ namespace SettingsModelUnitTests
|
||||
TEST_METHOD(RealResolverUrlCases);
|
||||
TEST_METHOD(RealResolverUNCCases);
|
||||
|
||||
static constexpr std::wstring_view pingCommandline{ LR"(C:\Windows\System32\PING.EXE)" }; // Normalized by Profile (this is the casing that Windows stores on disk)
|
||||
static constexpr std::wstring_view overrideCommandline{ LR"(C:\Windows\System32\cscript.exe)" };
|
||||
static constexpr std::wstring_view cmdCommandline{ LR"(C:\Windows\System32\cmd.exe)" }; // The default commandline for a profile
|
||||
// These are normalized by NormalizeCommandLine, which resolves to the on-disk casing.
|
||||
// They are used in test cases where media paths fall back to profile command lines.
|
||||
static inline std::wstring overrideCommandline;
|
||||
static inline std::wstring cmdCommandline;
|
||||
static constexpr std::wstring_view fragmentBasePath1{ LR"(C:\Windows\Media)" };
|
||||
|
||||
private:
|
||||
@@ -218,6 +219,9 @@ namespace SettingsModelUnitTests
|
||||
// Some of our tests use paths under system32. Just don't redirect them.
|
||||
Wow64DisableWow64FsRedirection(&redirectionFlag);
|
||||
#endif
|
||||
// Normalize these AFTER the call above so that we get the correctly redirected paths.
|
||||
overrideCommandline = implementation::Profile::NormalizeCommandLine(LR"(C:\Windows\System32\cscript.exe)");
|
||||
cmdCommandline = implementation::Profile::NormalizeCommandLine(LR"(C:\Windows\System32\cmd.exe)");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ void FontTests::TestCurrentFontAPIsInvalid()
|
||||
}
|
||||
else
|
||||
{
|
||||
hConsoleOutput = (HANDLE)dwConsoleOutput;
|
||||
hConsoleOutput = ULongToHandle(dwConsoleOutput);
|
||||
}
|
||||
|
||||
if (strOperation == L"Get")
|
||||
@@ -107,7 +107,7 @@ void FontTests::TestGetFontSizeInvalid()
|
||||
// Need to make sure that last error is cleared so that we can verify that lasterror was set by GetConsoleFontSize
|
||||
SetLastError(0);
|
||||
|
||||
auto coordFontSize = OneCoreDelay::GetConsoleFontSize((HANDLE)dwConsoleOutput, 0);
|
||||
auto coordFontSize = OneCoreDelay::GetConsoleFontSize(ULongToHandle(dwConsoleOutput), 0);
|
||||
VERIFY_ARE_EQUAL(coordFontSize, c_coordZero, L"Ensure (0,0) coord returned to indicate failure");
|
||||
VERIFY_ARE_EQUAL(GetLastError(), (DWORD)ERROR_INVALID_HANDLE, L"Ensure last error was set appropriately");
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ void ConhostInternalGetSet::UnknownSequence() noexcept
|
||||
// us from using a more conservative solution (e.g. always fetching the cursor position).
|
||||
if (gci.IsInVtIoMode())
|
||||
{
|
||||
gci.GetActiveOutputBuffer().SetConptyCursorPositionMayBeWrong();
|
||||
gci.GetActiveOutputBuffer().GetActiveBuffer().SetConptyCursorPositionMayBeWrong();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
constexpr bool ends_with_insensitive_ascii(const std::basic_string_view<T, Traits>& str, const std::basic_string_view<T, Traits>& suffix) noexcept
|
||||
{
|
||||
#pragma warning(suppress : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
|
||||
return str.size() >= suffix.size() && equals_insensitive_ascii<>({ str.data() - suffix.size(), suffix.size() }, suffix);
|
||||
return str.size() >= suffix.size() && equals_insensitive_ascii<>({ str.data() + str.size() - suffix.size(), suffix.size() }, suffix);
|
||||
}
|
||||
|
||||
constexpr bool ends_with_insensitive_ascii(const std::string_view& str, const std::string_view& prefix) noexcept
|
||||
@@ -251,7 +251,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
|
||||
constexpr bool ends_with_insensitive_ascii(const std::wstring_view& str, const std::wstring_view& prefix) noexcept
|
||||
{
|
||||
return ends_with<>(str, prefix);
|
||||
return ends_with_insensitive_ascii<>(str, prefix);
|
||||
}
|
||||
|
||||
template<typename T, typename Traits>
|
||||
|
||||
@@ -6,8 +6,3 @@
|
||||
|
||||
TARGETNAME = ConInteractivityOneCoreLib
|
||||
TARGETTYPE = LIBRARY
|
||||
|
||||
# VSTS 14847240: Locally suppress individual -Wv:17 compiler warnings.
|
||||
# For more information, visit https://osgwiki.com/wiki/Windows_C%2B%2B_Toolset_Status.
|
||||
USER_C_FLAGS=$(USER_C_FLAGS) /wd4302 # 'conversion': truncation from 'type1' to 'type2'
|
||||
USER_C_FLAGS=$(USER_C_FLAGS) /wd4311 # 'variable': pointer truncation from 'type 1' to 'type 2'
|
||||
|
||||
@@ -119,12 +119,15 @@ DWORD WINAPI Renderer::s_renderThread(void* param) noexcept
|
||||
|
||||
DWORD Renderer::_renderThread() noexcept
|
||||
{
|
||||
while (true)
|
||||
while (_threadKeepRunning.load(std::memory_order_relaxed))
|
||||
{
|
||||
_enable.wait();
|
||||
_waitUntilCanRender();
|
||||
_waitUntilTimerOrRedraw();
|
||||
|
||||
// We just completed what could have been a long wait;
|
||||
// eagerly check again to prevent rendering if we don't
|
||||
// need to.
|
||||
if (!_threadKeepRunning.load(std::memory_order_relaxed))
|
||||
{
|
||||
break;
|
||||
@@ -1058,38 +1061,7 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine)
|
||||
ROW* rowBackup = nullptr;
|
||||
if (row == compositionRow)
|
||||
{
|
||||
auto& scratch = buffer.GetScratchpadRow();
|
||||
scratch.CopyFrom(r);
|
||||
rowBackup = &scratch;
|
||||
|
||||
std::wstring_view text{ activeComposition.text };
|
||||
RowWriteState state{
|
||||
.columnLimit = r.GetReadableColumnCount(),
|
||||
.columnEnd = _compositionCache->absoluteOrigin.x,
|
||||
};
|
||||
|
||||
size_t off = 0;
|
||||
for (const auto& range : activeComposition.attributes)
|
||||
{
|
||||
const auto len = range.len;
|
||||
auto attr = range.attr;
|
||||
|
||||
// Use the color at the cursor if TSF didn't specify any explicit color.
|
||||
if (attr.GetBackground().IsDefault())
|
||||
{
|
||||
attr.SetBackground(_compositionCache->baseAttribute.GetBackground());
|
||||
}
|
||||
if (attr.GetForeground().IsDefault())
|
||||
{
|
||||
attr.SetForeground(_compositionCache->baseAttribute.GetForeground());
|
||||
}
|
||||
|
||||
state.text = text.substr(off, len);
|
||||
state.columnBegin = state.columnEnd;
|
||||
const_cast<ROW&>(r).ReplaceText(state);
|
||||
const_cast<ROW&>(r).ReplaceAttributes(state.columnBegin, state.columnEnd, attr);
|
||||
off += len;
|
||||
}
|
||||
rowBackup = _PaintBufferOutputComposition(buffer, r, activeComposition);
|
||||
}
|
||||
const auto restore = wil::scope_exit([&] {
|
||||
if (rowBackup)
|
||||
@@ -1129,6 +1101,107 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine)
|
||||
}
|
||||
}
|
||||
|
||||
ROW* Renderer::_PaintBufferOutputComposition(TextBuffer& buffer, const ROW& r, const Composition& activeComposition)
|
||||
{
|
||||
auto& scratch = buffer.GetScratchpadRow();
|
||||
scratch.CopyFrom(r);
|
||||
|
||||
// *Overwrite* the original text with the active composition...
|
||||
til::CoordType compositionEnd = 0;
|
||||
{
|
||||
std::wstring_view text{ activeComposition.text };
|
||||
RowWriteState state{
|
||||
.columnLimit = r.GetReadableColumnCount(),
|
||||
.columnEnd = _compositionCache->absoluteOrigin.x,
|
||||
};
|
||||
|
||||
size_t off = 0;
|
||||
for (const auto& range : activeComposition.attributes)
|
||||
{
|
||||
const auto len = range.len;
|
||||
auto attr = range.attr;
|
||||
|
||||
// Use the color at the cursor if TSF didn't specify any explicit color.
|
||||
if (attr.GetBackground().IsDefault())
|
||||
{
|
||||
attr.SetBackground(_compositionCache->baseAttribute.GetBackground());
|
||||
}
|
||||
if (attr.GetForeground().IsDefault())
|
||||
{
|
||||
attr.SetForeground(_compositionCache->baseAttribute.GetForeground());
|
||||
}
|
||||
|
||||
state.text = text.substr(off, len);
|
||||
state.columnBegin = state.columnEnd;
|
||||
const_cast<ROW&>(r).ReplaceText(state);
|
||||
const_cast<ROW&>(r).ReplaceAttributes(state.columnBegin, state.columnEnd, attr);
|
||||
off += len;
|
||||
}
|
||||
|
||||
compositionEnd = state.columnEnd;
|
||||
}
|
||||
|
||||
// The text we've overwritten may have been crucial to the user,
|
||||
// so copy it back by absorbing available whitespace to the right
|
||||
// and re-inserting the non-whitespace characters instead.
|
||||
const auto compositionWidth = compositionEnd - _compositionCache->absoluteOrigin.x;
|
||||
const auto colLimit = r.GetReadableColumnCount();
|
||||
if (compositionWidth > 0 && compositionEnd < colLimit)
|
||||
{
|
||||
const auto text = scratch.GetText();
|
||||
auto srcCol = _compositionCache->absoluteOrigin.x;
|
||||
auto dstCol = compositionEnd;
|
||||
auto remaining = compositionWidth;
|
||||
size_t i = scratch.GetCharOffset(srcCol);
|
||||
|
||||
while (i < text.size() && dstCol < colLimit)
|
||||
{
|
||||
// Treat whitespace we encounter as a credit towards our composition width.
|
||||
// This loop essentially absorbs the whitespace.
|
||||
while (i < text.size() && til::at(text, i) == L' ' && remaining > 0)
|
||||
{
|
||||
remaining--;
|
||||
srcCol++;
|
||||
i++;
|
||||
}
|
||||
if (remaining <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Find the end of the non-whitespace span: Our span of text to insert.
|
||||
auto spanEnd = i;
|
||||
while (spanEnd < text.size() && til::at(text, spanEnd) != L' ')
|
||||
{
|
||||
spanEnd++;
|
||||
}
|
||||
|
||||
// Copy the non-whitespace segment from the original text (scratch) back in.
|
||||
RowCopyTextFromState state{
|
||||
.source = scratch,
|
||||
.columnBegin = dstCol,
|
||||
.columnLimit = colLimit,
|
||||
.sourceColumnBegin = srcCol,
|
||||
.sourceColumnLimit = scratch.GetLeadingColumnAtCharOffset(spanEnd),
|
||||
};
|
||||
const_cast<ROW&>(r).CopyTextFrom(state);
|
||||
|
||||
const auto srcBeg = gsl::narrow_cast<uint16_t>(srcCol);
|
||||
const auto srcEnd = gsl::narrow_cast<uint16_t>(state.sourceColumnEnd);
|
||||
const auto attr = scratch.Attributes().slice(srcBeg, srcEnd);
|
||||
const auto dstBeg = gsl::narrow_cast<uint16_t>(dstCol);
|
||||
const auto dstEnd = gsl::narrow_cast<uint16_t>(dstCol + attr.size());
|
||||
const_cast<ROW&>(r).Attributes().replace(dstBeg, dstEnd, attr);
|
||||
|
||||
dstCol = state.columnEnd;
|
||||
srcCol = state.sourceColumnEnd;
|
||||
i = spanEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return &scratch;
|
||||
}
|
||||
|
||||
static bool _IsAllSpaces(const std::wstring_view v)
|
||||
{
|
||||
// first non-space char is not found (is npos)
|
||||
|
||||
@@ -121,6 +121,7 @@ namespace Microsoft::Console::Render
|
||||
void _scheduleRenditionBlink();
|
||||
[[nodiscard]] HRESULT _PaintBackground(_In_ IRenderEngine* const pEngine);
|
||||
void _PaintBufferOutput(_In_ IRenderEngine* const pEngine);
|
||||
ROW* _PaintBufferOutputComposition(TextBuffer& buffer, const ROW& r, const Composition& activeComposition);
|
||||
void _PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, TextBufferCellIterator it, const til::point target);
|
||||
void _PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine, const TextAttribute textAttribute, const size_t cchLine, const til::point coordTarget);
|
||||
bool _isHoveredHyperlink(const TextAttribute& textAttribute) const noexcept;
|
||||
|
||||
@@ -595,9 +595,12 @@ constexpr T saturate(auto val)
|
||||
RETURN_IF_FAILED(pObjectHandle->GetScreenBuffer(GENERIC_READ, &pObj));
|
||||
|
||||
// See ConptyCursorPositionMayBeWrong() for details.
|
||||
if (pObj->ConptyCursorPositionMayBeWrong())
|
||||
auto& activeBuffer = pObj->GetActiveBuffer();
|
||||
// GetConsoleScreenBufferInfoExImpl uses GetActiveBuffer internally, but
|
||||
// under the console lock.
|
||||
if (activeBuffer.ConptyCursorPositionMayBeWrong())
|
||||
{
|
||||
pObj->WaitForConptyCursorPositionToBeSynchronized();
|
||||
activeBuffer.WaitForConptyCursorPositionToBeSynchronized();
|
||||
}
|
||||
|
||||
m->_pApiRoutines->GetConsoleScreenBufferInfoExImpl(*pObj, ex);
|
||||
|
||||
@@ -166,7 +166,7 @@ void InteractDispatch::MoveCursor(const VTInt row, const VTInt col)
|
||||
|
||||
// Unblock any callers inside SCREEN_INFORMATION::WaitForConptyCursorPositionToBeSynchronized().
|
||||
// The cursor position has now been updated to the terminal's.
|
||||
info.ResetConptyCursorPositionMayBeWrong();
|
||||
info.GetActiveBuffer().ResetConptyCursorPositionMayBeWrong();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
||||
Reference in New Issue
Block a user