mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 14:19:45 +00:00
Compare commits
20 Commits
dev/migrie
...
v1.3.2651.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4614bf041 | ||
|
|
847d878c5e | ||
|
|
4204d2535c | ||
|
|
e46ba65665 | ||
|
|
9767abd3f3 | ||
|
|
e1421ced89 | ||
|
|
361d4f559a | ||
|
|
9d34507a67 | ||
|
|
74feda108f | ||
|
|
ba91ae4eb8 | ||
|
|
420d7142fb | ||
|
|
267bb289a7 | ||
|
|
a064931f37 | ||
|
|
f77d47648b | ||
|
|
1a7d934ec9 | ||
|
|
6c869ebb26 | ||
|
|
88e843d474 | ||
|
|
7886f16714 | ||
|
|
7967e1740c | ||
|
|
744bc2190c |
@@ -1,17 +1,19 @@
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
#AllowAllArgumentsOnNextLine: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
#AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
#AllowShortLambdasOnASingleLine: Inline
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
@@ -20,6 +22,7 @@ AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
@@ -47,6 +50,7 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
FixNamespaceComments: false
|
||||
IncludeBlocks: Regroup
|
||||
@@ -73,7 +77,7 @@ ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
#SpaceAfterLogicalNot: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
@@ -88,6 +92,6 @@ SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
Standard: Latest
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
|
||||
@@ -4,7 +4,6 @@ alignof
|
||||
bitfield
|
||||
bitfields
|
||||
CLASSNOTAVAILABLE
|
||||
environstrings
|
||||
EXPCMDFLAGS
|
||||
EXPCMDSTATE
|
||||
fullkbd
|
||||
|
||||
@@ -2,6 +2,7 @@ ACLs
|
||||
altform
|
||||
appendwttlogging
|
||||
backplating
|
||||
CPRs
|
||||
DACL
|
||||
DACLs
|
||||
dotnetfeed
|
||||
|
||||
@@ -6,6 +6,7 @@ ABANDONFONT
|
||||
ABCDEFGHIJKLMNO
|
||||
ABCG
|
||||
abf
|
||||
abgr
|
||||
abi
|
||||
ACCESSTOKEN
|
||||
acec
|
||||
|
||||
Binary file not shown.
@@ -67,7 +67,6 @@
|
||||
"toggleAlwaysOnTop",
|
||||
"toggleFocusMode",
|
||||
"toggleFullscreen",
|
||||
"togglePaneZoom",
|
||||
"toggleRetroEffect",
|
||||
"wt",
|
||||
"unbound"
|
||||
@@ -370,7 +369,7 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [ "name" ]
|
||||
"required": [ "colorScheme" ]
|
||||
},
|
||||
"WtAction": {
|
||||
"description": "Arguments corresponding to a wt Action",
|
||||
@@ -397,14 +396,16 @@
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "closeOtherTabs" },
|
||||
"index": {
|
||||
"type": "integer",
|
||||
"oneOf": [
|
||||
{ "type": "integer" },
|
||||
{ "type": null }
|
||||
],
|
||||
"default": "",
|
||||
"description": "close the tabs following the tab at this index"
|
||||
"description": "Close the tabs other than the one at this index. If no index is provided, use the focused tab's index."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [ "index" ]
|
||||
]
|
||||
},
|
||||
"CloseTabsAfterAction": {
|
||||
"description": "Arguments for a closeTabsAfter action",
|
||||
@@ -414,14 +415,16 @@
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "closeTabsAfter" },
|
||||
"index": {
|
||||
"type": "integer",
|
||||
"oneOf": [
|
||||
{ "type": "integer" },
|
||||
{ "type": null }
|
||||
],
|
||||
"default": "",
|
||||
"description": "close the tabs other than the one at this index"
|
||||
"description": "Close the tabs following the tab at this index. If no index is provided, use the focused tab's index."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [ "index" ]
|
||||
]
|
||||
},
|
||||
"Keybinding": {
|
||||
"additionalProperties": false,
|
||||
|
||||
BIN
res/Cascadia.ttf
BIN
res/Cascadia.ttf
Binary file not shown.
Binary file not shown.
@@ -17,5 +17,5 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi
|
||||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2007.15)
|
||||
* from microsoft/cascadia-code@2a54363b2c867f7ae811b9a034c0024cef67de96
|
||||
* Cascadia Code, Cascadia Mono (2009.21)
|
||||
* from microsoft/cascadia-code@32f84124db1970fa5d032f0fe9019e6922961beb
|
||||
|
||||
@@ -242,7 +242,7 @@ HRESULT HwndTerminal::Initialize()
|
||||
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
|
||||
_terminal->SetDefaultBackground(RGB(12, 12, 12));
|
||||
_terminal->SetDefaultForeground(RGB(204, 204, 204));
|
||||
_terminal->SetWriteInputCallback([=](std::wstring & input) noexcept { _WriteTextToConnection(input); });
|
||||
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
|
||||
localPointerToThread->EnablePainting();
|
||||
|
||||
_multiClickTime = std::chrono::milliseconds{ GetDoubleClickTime() };
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{ ToggleCommandPaletteKey, ShortcutAction::ToggleCommandPalette },
|
||||
{ ToggleFocusModeKey, ShortcutAction::ToggleFocusMode },
|
||||
{ ToggleFullscreenKey, ShortcutAction::ToggleFullscreen },
|
||||
{ TogglePaneZoomKey, ShortcutAction::TogglePaneZoom },
|
||||
// { TogglePaneZoomKey, ShortcutAction::TogglePaneZoom }, // TODO GH#7252: Re-enable pane zooming
|
||||
{ ToggleRetroEffectKey, ShortcutAction::ToggleRetroEffect },
|
||||
{ UnboundKey, ShortcutAction::Invalid },
|
||||
};
|
||||
|
||||
@@ -339,19 +339,27 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::hstring CloseOtherTabsArgs::GenerateName() const
|
||||
{
|
||||
// "Close tabs other than index {0}"
|
||||
return winrt::hstring{
|
||||
fmt::format(std::wstring_view(RS_(L"CloseOtherTabsCommandKey")),
|
||||
_Index)
|
||||
};
|
||||
if (_Index)
|
||||
{
|
||||
// "Close tabs other than index {0}"
|
||||
return winrt::hstring{
|
||||
fmt::format(std::wstring_view(RS_(L"CloseOtherTabsCommandKey")),
|
||||
_Index.Value())
|
||||
};
|
||||
}
|
||||
return RS_(L"CloseOtherTabsDefaultCommandKey");
|
||||
}
|
||||
|
||||
winrt::hstring CloseTabsAfterArgs::GenerateName() const
|
||||
{
|
||||
// "Close tabs after index {0}"
|
||||
return winrt::hstring{
|
||||
fmt::format(std::wstring_view(RS_(L"CloseTabsAfterCommandKey")),
|
||||
_Index)
|
||||
};
|
||||
if (_Index)
|
||||
{
|
||||
// "Close tabs after index {0}"
|
||||
return winrt::hstring{
|
||||
fmt::format(std::wstring_view(RS_(L"CloseTabsAfterCommandKey")),
|
||||
_Index.Value())
|
||||
};
|
||||
}
|
||||
return RS_(L"CloseTabsAfterDefaultCommandKey");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,7 +495,7 @@ namespace winrt::TerminalApp::implementation
|
||||
struct CloseOtherTabsArgs : public CloseOtherTabsArgsT<CloseOtherTabsArgs>
|
||||
{
|
||||
CloseOtherTabsArgs() = default;
|
||||
GETSET_PROPERTY(uint32_t, Index, 0);
|
||||
GETSET_PROPERTY(winrt::Windows::Foundation::IReference<uint32_t>, Index, nullptr);
|
||||
|
||||
static constexpr std::string_view IndexKey{ "index" };
|
||||
|
||||
@@ -523,7 +523,7 @@ namespace winrt::TerminalApp::implementation
|
||||
struct CloseTabsAfterArgs : public CloseTabsAfterArgsT<CloseTabsAfterArgs>
|
||||
{
|
||||
CloseTabsAfterArgs() = default;
|
||||
GETSET_PROPERTY(uint32_t, Index, 0);
|
||||
GETSET_PROPERTY(winrt::Windows::Foundation::IReference<uint32_t>, Index, nullptr);
|
||||
|
||||
static constexpr std::string_view IndexKey{ "index" };
|
||||
|
||||
|
||||
@@ -134,11 +134,11 @@ namespace TerminalApp
|
||||
|
||||
[default_interface] runtimeclass CloseOtherTabsArgs : IActionArgs
|
||||
{
|
||||
UInt32 Index { get; };
|
||||
Windows.Foundation.IReference<UInt32> Index { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass CloseTabsAfterArgs : IActionArgs
|
||||
{
|
||||
UInt32 Index { get; };
|
||||
Windows.Foundation.IReference<UInt32> Index { get; };
|
||||
};
|
||||
}
|
||||
|
||||
@@ -415,7 +415,21 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = actionArgs.ActionArgs().try_as<TerminalApp::CloseOtherTabsArgs>())
|
||||
{
|
||||
uint32_t index = realArgs.Index();
|
||||
uint32_t index;
|
||||
if (realArgs.Index())
|
||||
{
|
||||
index = realArgs.Index().Value();
|
||||
}
|
||||
else if (auto focusedTabIndex = _GetFocusedTabIndex())
|
||||
{
|
||||
index = *focusedTabIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do nothing
|
||||
actionArgs.Handled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove tabs after the current one
|
||||
while (_tabs.Size() > index + 1)
|
||||
@@ -438,7 +452,21 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = actionArgs.ActionArgs().try_as<TerminalApp::CloseTabsAfterArgs>())
|
||||
{
|
||||
uint32_t index = realArgs.Index();
|
||||
uint32_t index;
|
||||
if (realArgs.Index())
|
||||
{
|
||||
index = realArgs.Index().Value();
|
||||
}
|
||||
else if (auto focusedTabIndex = _GetFocusedTabIndex())
|
||||
{
|
||||
index = *focusedTabIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do nothing
|
||||
actionArgs.Handled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove tabs after the current one
|
||||
while (_tabs.Size() > index + 1)
|
||||
|
||||
@@ -37,8 +37,6 @@ std::vector<TerminalApp::Profile> AzureCloudShellGenerator::GenerateProfiles()
|
||||
azureCloudShellProfile.SetCommandline(L"Azure");
|
||||
azureCloudShellProfile.SetStartingDirectory(DEFAULT_STARTING_DIRECTORY);
|
||||
azureCloudShellProfile.SetColorScheme({ L"Vintage" });
|
||||
azureCloudShellProfile.SetAcrylicOpacity(0.6);
|
||||
azureCloudShellProfile.SetUseAcrylic(true);
|
||||
azureCloudShellProfile.SetConnectionType(AzureConnectionType);
|
||||
profiles.emplace_back(azureCloudShellProfile);
|
||||
}
|
||||
|
||||
@@ -646,4 +646,10 @@
|
||||
<data name="DarkGrayColorButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Dark Gray</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="CloseOtherTabsDefaultCommandKey" xml:space="preserve">
|
||||
<value>Close all other tabs</value>
|
||||
</data>
|
||||
<data name="CloseTabsAfterDefaultCommandKey" xml:space="preserve">
|
||||
<value>Close all tabs after the current tab</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1304,9 +1304,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// Method Description:
|
||||
// - Returns the index in our list of tabs of the currently focused tab. If
|
||||
// no tab is currently selected, returns -1.
|
||||
// no tab is currently selected, returns nullopt.
|
||||
// Return Value:
|
||||
// - the index of the currently focused tab if there is one, else -1
|
||||
// - the index of the currently focused tab if there is one, else nullopt
|
||||
std::optional<uint32_t> TerminalPage::_GetFocusedTabIndex() const noexcept
|
||||
{
|
||||
// GH#1117: This is a workaround because _tabView.SelectedIndex()
|
||||
|
||||
@@ -291,6 +291,8 @@
|
||||
// Tab Management
|
||||
// "command": "closeTab" is unbound by default.
|
||||
// The closeTab command closes a tab without confirmation, even if it has multiple panes.
|
||||
{ "command": "closeOtherTabs" },
|
||||
{ "command": "closeTabsAfter" },
|
||||
{ "command": "newTab", "keys": "ctrl+shift+t" },
|
||||
{ "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+shift+1" },
|
||||
{ "command": { "action": "newTab", "index": 1 }, "keys": "ctrl+shift+2" },
|
||||
@@ -326,7 +328,6 @@
|
||||
{ "command": { "action": "moveFocus", "direction": "left" }, "keys": "alt+left" },
|
||||
{ "command": { "action": "moveFocus", "direction": "right" }, "keys": "alt+right" },
|
||||
{ "command": { "action": "moveFocus", "direction": "up" }, "keys": "alt+up" },
|
||||
{ "command": "togglePaneZoom" },
|
||||
|
||||
// Clipboard Integration
|
||||
{ "command": { "action": "copy", "singleLine": false }, "keys": "ctrl+shift+c" },
|
||||
|
||||
@@ -52,10 +52,10 @@
|
||||
// To learn more about color schemes, visit https://aka.ms/terminal-color-schemes
|
||||
"schemes": [],
|
||||
|
||||
// Add custom keybindings to this array.
|
||||
// Add custom actions and keybindings to this array.
|
||||
// To unbind a key combination from your defaults.json, set the command to "unbound".
|
||||
// To learn more about keybindings, visit https://aka.ms/terminal-keybindings
|
||||
"keybindings":
|
||||
// To learn more about actions and keybindings, visit https://aka.ms/terminal-keybindings
|
||||
"actions":
|
||||
[
|
||||
// Copy and paste are bound to Ctrl+Shift+C and Ctrl+Shift+V in your defaults.json.
|
||||
// These two lines additionally bind them to Ctrl+C and Ctrl+V.
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "ConptyConnection.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <userenv.h>
|
||||
|
||||
#include "ConptyConnection.g.cpp"
|
||||
|
||||
@@ -98,11 +97,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
environment.clear();
|
||||
});
|
||||
|
||||
{
|
||||
const auto newEnvironmentBlock{ Utils::CreateEnvironmentBlock() };
|
||||
// Populate the environment map with the current environment.
|
||||
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment, newEnvironmentBlock.get()));
|
||||
}
|
||||
// Populate the environment map with the current environment.
|
||||
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
|
||||
|
||||
{
|
||||
// Convert connection Guid to string and ignore the enclosing '{}'.
|
||||
@@ -455,4 +451,23 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - This function will be called (by C++/WinRT) after the final outstanding reference to
|
||||
// any given connection instance is released.
|
||||
// When a client application exits, its termination will wait for the output thread to
|
||||
// run down. However, because our teardown is somewhat complex, our last reference may
|
||||
// be owned by the very output thread that the client wait threadpool is blocked on.
|
||||
// During destruction, we'll try to release any outstanding handles--including the one
|
||||
// we have to the threadpool wait. As you might imagine, this takes us right to deadlock
|
||||
// city.
|
||||
// Deferring the final destruction of the connection to a background thread that can't
|
||||
// be awaiting our destruction breaks the deadlock.
|
||||
// Arguments:
|
||||
// - connection: the final living reference to an outgoing connection
|
||||
winrt::fire_and_forget ConptyConnection::final_release(std::unique_ptr<ConptyConnection> connection)
|
||||
{
|
||||
co_await winrt::resume_background(); // move to background
|
||||
connection.reset(); // explicitly destruct
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
const uint32_t rows,
|
||||
const uint32_t cols,
|
||||
const guid& guid);
|
||||
static winrt::fire_and_forget final_release(std::unique_ptr<ConptyConnection> connection);
|
||||
|
||||
void Start();
|
||||
void WriteInput(hstring const& data);
|
||||
|
||||
@@ -457,7 +457,6 @@ bool Terminal::SendKeyEvent(const WORD vkey,
|
||||
}
|
||||
|
||||
const auto isAltOnlyPressed = states.IsAltPressed() && !states.IsCtrlPressed();
|
||||
const auto isSuppressedAltGrAlias = !_altGrAliasing && states.IsAltPressed() && states.IsCtrlPressed();
|
||||
|
||||
// DON'T manually handle Alt+Space - the system will use this to bring up
|
||||
// the system menu for restore, min/maximize, size, move, close.
|
||||
@@ -477,6 +476,7 @@ bool Terminal::SendKeyEvent(const WORD vkey,
|
||||
// as TerminalInput::HandleKey will then fall back to using the vkey which
|
||||
// is the underlying ASCII character (e.g. A-Z) on the keyboard in our case.
|
||||
// See GH#5525/GH#6211 for more details
|
||||
const auto isSuppressedAltGrAlias = !_altGrAliasing && states.IsAltPressed() && states.IsCtrlPressed() && !states.IsAltGrPressed();
|
||||
const auto ch = isSuppressedAltGrAlias ? UNICODE_NULL : _CharacterFromKeyEvent(vkey, scanCode, states);
|
||||
|
||||
// Delegate it to the character event handler if this key event can be
|
||||
|
||||
@@ -534,41 +534,6 @@ void EventsToUnicode(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents,
|
||||
CATCH_RETURN();
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Writes the input records to the beginning of the input buffer. This is used
|
||||
// by VT sequences that need a response immediately written back to the
|
||||
// input.
|
||||
// Arguments:
|
||||
// - pInputBuffer - the input buffer to write to
|
||||
// - events - the events to written
|
||||
// - eventsWritten - on output, the number of events written
|
||||
// Return Value:
|
||||
// - HRESULT indicating success or failure
|
||||
[[nodiscard]] HRESULT DoSrvPrivatePrependConsoleInput(_Inout_ InputBuffer* const pInputBuffer,
|
||||
_Inout_ std::deque<std::unique_ptr<IInputEvent>>& events,
|
||||
_Out_ size_t& eventsWritten)
|
||||
{
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
|
||||
eventsWritten = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// add partial byte event if necessary
|
||||
if (pInputBuffer->IsWritePartialByteSequenceAvailable())
|
||||
{
|
||||
events.push_front(pInputBuffer->FetchWritePartialByteSequence(false));
|
||||
}
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
// add to InputBuffer
|
||||
eventsWritten = pInputBuffer->Prepend(events);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Writes the input KeyEvent to the console as a console control event. This
|
||||
// can be used for potentially generating Ctrl-C events, as
|
||||
|
||||
@@ -31,9 +31,5 @@ class SCREEN_INFORMATION;
|
||||
_In_ PCD_CREATE_OBJECT_INFORMATION Information,
|
||||
_In_ PCONSOLE_CREATESCREENBUFFER_MSG a);
|
||||
|
||||
[[nodiscard]] NTSTATUS DoSrvPrivatePrependConsoleInput(_Inout_ InputBuffer* const pInputBuffer,
|
||||
_Inout_ std::deque<std::unique_ptr<IInputEvent>>& events,
|
||||
_Out_ size_t& eventsWritten);
|
||||
|
||||
[[nodiscard]] NTSTATUS DoSrvPrivateWriteConsoleControlInput(_Inout_ InputBuffer* const pInputBuffer,
|
||||
_In_ KeyEvent key);
|
||||
|
||||
@@ -527,22 +527,6 @@ bool ConhostInternalGetSet::SetCursorStyle(const CursorType style)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Connects the PrivatePrependConsoleInput API call directly into our Driver Message servicing call inside Conhost.exe
|
||||
// Arguments:
|
||||
// - events - the input events to be copied into the head of the input
|
||||
// buffer for the underlying attached process
|
||||
// - eventsWritten - on output, the number of events written
|
||||
// Return Value:
|
||||
// - true if successful (see DoSrvPrivatePrependConsoleInput). false otherwise.
|
||||
bool ConhostInternalGetSet::PrivatePrependConsoleInput(std::deque<std::unique_ptr<IInputEvent>>& events,
|
||||
size_t& eventsWritten)
|
||||
{
|
||||
return SUCCEEDED(DoSrvPrivatePrependConsoleInput(_io.GetActiveInputBuffer(),
|
||||
events,
|
||||
eventsWritten));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Connects the PrivatePrependConsoleInput API call directly into our Driver Message servicing call inside Conhost.exe
|
||||
// Arguments:
|
||||
|
||||
@@ -104,9 +104,6 @@ public:
|
||||
bool PrivateEnableAlternateScroll(const bool enabled) override;
|
||||
bool PrivateEraseAll() override;
|
||||
|
||||
bool PrivatePrependConsoleInput(std::deque<std::unique_ptr<IInputEvent>>& events,
|
||||
size_t& eventsWritten) override;
|
||||
|
||||
bool SetCursorStyle(CursorType const style) override;
|
||||
bool SetCursorColor(COLORREF const color) override;
|
||||
|
||||
|
||||
@@ -12,7 +12,27 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
#pragma warning(disable : 26472)
|
||||
struct color
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
// Clang (10) has no trouble optimizing the COLORREF conversion operator, below, to a
|
||||
// simple 32-bit load with mask (!) even though it's a series of bit shifts across
|
||||
// multiple struct members.
|
||||
// CL (19.24) doesn't make the same optimization decision, and it emits three 8-bit loads
|
||||
// and some shifting.
|
||||
// In any case, the optimization only applies at -O2 (clang) and above.
|
||||
// Here, we leverage the spec-legality of using unions for type conversions and the
|
||||
// overlap of four uint8_ts and a uint32_t to make the conversion very obvious to
|
||||
// both compilers.
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ // Clang, GCC
|
||||
uint8_t a, b, g, r;
|
||||
#else
|
||||
uint8_t r, g, b, a;
|
||||
#endif
|
||||
};
|
||||
uint32_t abgr;
|
||||
};
|
||||
|
||||
constexpr color() noexcept :
|
||||
r{ 0 },
|
||||
@@ -40,16 +60,13 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
|
||||
#ifdef _WINDEF_
|
||||
constexpr color(COLORREF c) :
|
||||
r{ static_cast<uint8_t>(c & 0xFF) },
|
||||
g{ static_cast<uint8_t>((c & 0xFF00) >> 8) },
|
||||
b{ static_cast<uint8_t>((c & 0xFF0000) >> 16) },
|
||||
a{ 255 }
|
||||
abgr{ static_cast<uint32_t>(c | 0xFF000000u) }
|
||||
{
|
||||
}
|
||||
|
||||
operator COLORREF() const noexcept
|
||||
{
|
||||
return static_cast<COLORREF>(r) | (static_cast<COLORREF>(g) << 8) | (static_cast<COLORREF>(b) << 16);
|
||||
return static_cast<COLORREF>(abgr & 0x00FFFFFFu);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -137,7 +154,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
|
||||
constexpr bool operator==(const til::color& other) const
|
||||
{
|
||||
return r == other.r && g == other.g && b == other.b && a == other.a;
|
||||
return abgr == other.abgr;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const til::color& other) const
|
||||
@@ -171,6 +188,8 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
static_assert(sizeof(til::color) == sizeof(uint32_t));
|
||||
|
||||
#ifdef __WEX_COMMON_H__
|
||||
namespace WEX::TestExecution
|
||||
{
|
||||
|
||||
@@ -70,5 +70,5 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
// 1. static_map's member types are all the same
|
||||
// 2. static_map's fourth template argument (otherwise undeduced) is how many pairs it contains
|
||||
template<typename First, typename... Rest>
|
||||
static_map(First, Rest...)->static_map<std::conditional_t<std::conjunction_v<std::is_same<First, Rest>...>, typename First::first_type, void>, typename First::second_type, std::less<typename First::first_type>, 1 + sizeof...(Rest)>;
|
||||
static_map(First, Rest...) -> static_map<std::conditional_t<std::conjunction_v<std::is_same<First, Rest>...>, typename First::first_type, void>, typename First::second_type, std::less<typename First::first_type>, 1 + sizeof...(Rest)>;
|
||||
}
|
||||
|
||||
@@ -583,7 +583,7 @@ class UiaTextRangeTests
|
||||
{
|
||||
5,
|
||||
{4 , 0 + 1},
|
||||
{5 , 0 + 1}
|
||||
{4 , 0 + 1}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -694,6 +694,30 @@ class UiaTextRangeTests
|
||||
{0, bottomRow},
|
||||
{0, bottomRow}
|
||||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can move to a new row when necessary when moving forward",
|
||||
{ lastColumnIndex, 0 },
|
||||
{ lastColumnIndex, 0 },
|
||||
5,
|
||||
{
|
||||
5,
|
||||
{0, 0 + 5},
|
||||
{0, 0 + 5}
|
||||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can move to a new row when necessary when moving backward",
|
||||
{ 0, 7 },
|
||||
{ 0, 7 },
|
||||
-5,
|
||||
{
|
||||
-5,
|
||||
{0, 7 - 5},
|
||||
{0, 7 - 5}
|
||||
}
|
||||
}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
}
|
||||
|
||||
// IPersist
|
||||
STDMETHODIMP GetClassID(_Out_ CLSID* clsid) override
|
||||
STDMETHODIMP GetClassID(_Out_ CLSID * clsid) override
|
||||
{
|
||||
*clsid = __uuidof(this);
|
||||
return S_OK;
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
// IShellExtInit
|
||||
// Shell QI's for IShellExtInit and calls Initialize first. If we return a succeeding HRESULT, the shell will QI for
|
||||
// IShellPropSheetExt and call AddPages. A failing HRESULT causes the shell to skip us.
|
||||
STDMETHODIMP Initialize(_In_ PCIDLIST_ABSOLUTE /*pidlFolder*/, _In_ IDataObject* pdtobj, _In_ HKEY /*hkeyProgID*/)
|
||||
STDMETHODIMP Initialize(_In_ PCIDLIST_ABSOLUTE /*pidlFolder*/, _In_ IDataObject * pdtobj, _In_ HKEY /*hkeyProgID*/)
|
||||
{
|
||||
WCHAR szLinkFileName[MAX_PATH];
|
||||
HRESULT hr = _ShouldAddPropertySheet(pdtobj, szLinkFileName, ARRAYSIZE(szLinkFileName));
|
||||
@@ -139,7 +139,7 @@ private:
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CODE FROM THE SHELL DEPOT'S `idllib.h`
|
||||
// get a link target item without resolving it.
|
||||
HRESULT GetTargetIdList(_In_ IShellItem* psiLink, _COM_Outptr_ PIDLIST_ABSOLUTE* ppidl)
|
||||
HRESULT GetTargetIdList(_In_ IShellItem * psiLink, _COM_Outptr_ PIDLIST_ABSOLUTE * ppidl)
|
||||
{
|
||||
*ppidl = nullptr;
|
||||
|
||||
@@ -156,7 +156,7 @@ private:
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
HRESULT GetTargetItem(_In_ IShellItem* psiLink, _In_ REFIID riid, _COM_Outptr_ void** ppv)
|
||||
HRESULT GetTargetItem(_In_ IShellItem * psiLink, _In_ REFIID riid, _COM_Outptr_ void** ppv)
|
||||
{
|
||||
*ppv = nullptr;
|
||||
|
||||
@@ -171,7 +171,7 @@ private:
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HRESULT _GetShellItemLinkTargetExpanded(_In_ IShellItem* pShellItem,
|
||||
HRESULT _GetShellItemLinkTargetExpanded(_In_ IShellItem * pShellItem,
|
||||
_Out_writes_(cchFilePathExtended) PWSTR pszFilePathExtended,
|
||||
const size_t cchFilePathExtended)
|
||||
{
|
||||
@@ -190,7 +190,7 @@ private:
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT _ShouldAddPropertySheet(_In_ IDataObject* pdtobj,
|
||||
HRESULT _ShouldAddPropertySheet(_In_ IDataObject * pdtobj,
|
||||
_Out_writes_(cchLinkFileName) PWSTR pszLinkFileName,
|
||||
const size_t cchLinkFileName)
|
||||
{
|
||||
|
||||
@@ -1488,8 +1488,7 @@ try
|
||||
const D2D_POINT_2F target = { coordTarget.X * font.width, coordTarget.Y * font.height };
|
||||
const auto fullRunWidth = font.width * gsl::narrow_cast<unsigned>(cchLine);
|
||||
|
||||
const auto DrawLine = [=](const auto x0, const auto y0, const auto x1, const auto y1, const auto strokeWidth) noexcept
|
||||
{
|
||||
const auto DrawLine = [=](const auto x0, const auto y0, const auto x1, const auto y1, const auto strokeWidth) noexcept {
|
||||
_d2dDeviceContext->DrawLine({ x0, y0 }, { x1, y1 }, _d2dBrushForeground.Get(), strokeWidth, _strokeStyle.Get());
|
||||
};
|
||||
|
||||
|
||||
@@ -855,7 +855,11 @@ bool AdaptDispatch::_WriteResponse(const std::wstring_view reply) const
|
||||
}
|
||||
|
||||
size_t eventsWritten;
|
||||
success = _pConApi->PrivatePrependConsoleInput(inEvents, eventsWritten);
|
||||
// TODO GH#4954 During the input refactor we may want to add a "priority" input list
|
||||
// to make sure that "response" input is spooled directly into the application.
|
||||
// We switched this to an append (vs. a prepend) to fix GH#1637, a bug where two CPR
|
||||
// could collide with eachother.
|
||||
success = _pConApi->PrivateWriteConsoleInputW(inEvents, eventsWritten);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -72,8 +72,6 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
virtual bool PrivateEraseAll() = 0;
|
||||
virtual bool SetCursorStyle(const CursorType style) = 0;
|
||||
virtual bool SetCursorColor(const COLORREF color) = 0;
|
||||
virtual bool PrivatePrependConsoleInput(std::deque<std::unique_ptr<IInputEvent>>& events,
|
||||
size_t& eventsWritten) = 0;
|
||||
virtual bool PrivateWriteConsoleControlInput(const KeyEvent key) = 0;
|
||||
virtual bool PrivateRefreshWindow() = 0;
|
||||
|
||||
|
||||
@@ -259,32 +259,21 @@ public:
|
||||
// move all the input events we were given into local storage so we can test against them
|
||||
Log::Comment(NoThrowString().Format(L"Moving %zu input events into local storage...", events.size()));
|
||||
|
||||
_events.clear();
|
||||
_events.swap(events);
|
||||
if (_retainInput)
|
||||
{
|
||||
std::move(events.begin(), events.end(), std::back_inserter(_events));
|
||||
}
|
||||
else
|
||||
{
|
||||
_events.clear();
|
||||
_events.swap(events);
|
||||
}
|
||||
eventsWritten = _events.size();
|
||||
}
|
||||
|
||||
return _privateWriteConsoleInputWResult;
|
||||
}
|
||||
|
||||
bool PrivatePrependConsoleInput(std::deque<std::unique_ptr<IInputEvent>>& events,
|
||||
size_t& eventsWritten) override
|
||||
{
|
||||
Log::Comment(L"PrivatePrependConsoleInput MOCK called...");
|
||||
|
||||
if (_privatePrependConsoleInputResult)
|
||||
{
|
||||
// move all the input events we were given into local storage so we can test against them
|
||||
Log::Comment(NoThrowString().Format(L"Moving %zu input events into local storage...", events.size()));
|
||||
|
||||
_events.clear();
|
||||
_events.swap(events);
|
||||
eventsWritten = _events.size();
|
||||
}
|
||||
|
||||
return _privatePrependConsoleInputResult;
|
||||
}
|
||||
|
||||
bool PrivateWriteConsoleControlInput(_In_ KeyEvent key) override
|
||||
{
|
||||
Log::Comment(L"PrivateWriteConsoleControlInput MOCK called...");
|
||||
@@ -613,7 +602,6 @@ public:
|
||||
_privateGetTextAttributesResult = TRUE;
|
||||
_privateSetTextAttributesResult = TRUE;
|
||||
_privateWriteConsoleInputWResult = TRUE;
|
||||
_privatePrependConsoleInputResult = TRUE;
|
||||
_privateWriteConsoleControlInputResult = TRUE;
|
||||
_setConsoleWindowInfoResult = TRUE;
|
||||
_moveToBottomResult = true;
|
||||
@@ -639,6 +627,9 @@ public:
|
||||
// Attribute default is gray on black.
|
||||
_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED };
|
||||
_expectedAttribute = _attribute;
|
||||
|
||||
_events.clear();
|
||||
_retainInput = false;
|
||||
}
|
||||
|
||||
void PrepCursor(CursorX xact, CursorY yact)
|
||||
@@ -726,6 +717,16 @@ public:
|
||||
static const WORD s_defaultFill = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; // dark gray on black.
|
||||
|
||||
std::deque<std::unique_ptr<IInputEvent>> _events;
|
||||
bool _retainInput{ false };
|
||||
|
||||
auto EnableInputRetentionInScope()
|
||||
{
|
||||
auto oldRetainValue{ _retainInput };
|
||||
_retainInput = true;
|
||||
return wil::scope_exit([oldRetainValue, this] {
|
||||
_retainInput = oldRetainValue;
|
||||
});
|
||||
}
|
||||
|
||||
COORD _bufferSize = { 0, 0 };
|
||||
SMALL_RECT _viewport = { 0, 0, 0, 0 };
|
||||
@@ -755,7 +756,6 @@ public:
|
||||
bool _privateGetTextAttributesResult = false;
|
||||
bool _privateSetTextAttributesResult = false;
|
||||
bool _privateWriteConsoleInputWResult = false;
|
||||
bool _privatePrependConsoleInputResult = false;
|
||||
bool _privateWriteConsoleControlInputResult = false;
|
||||
|
||||
bool _setConsoleWindowInfoResult = false;
|
||||
@@ -1694,25 +1694,59 @@ public:
|
||||
{
|
||||
Log::Comment(L"Starting test...");
|
||||
|
||||
Log::Comment(L"Test 1: Verify normal cursor response position.");
|
||||
_testGetSet->PrepData(CursorX::XCENTER, CursorY::YCENTER);
|
||||
{
|
||||
Log::Comment(L"Test 1: Verify normal cursor response position.");
|
||||
_testGetSet->PrepData(CursorX::XCENTER, CursorY::YCENTER);
|
||||
|
||||
// start with the cursor position in the buffer.
|
||||
COORD coordCursorExpected = _testGetSet->_cursorPos;
|
||||
// start with the cursor position in the buffer.
|
||||
COORD coordCursorExpected = _testGetSet->_cursorPos;
|
||||
|
||||
// to get to VT, we have to adjust it to its position relative to the viewport top.
|
||||
coordCursorExpected.Y -= _testGetSet->_viewport.Top;
|
||||
// to get to VT, we have to adjust it to its position relative to the viewport top.
|
||||
coordCursorExpected.Y -= _testGetSet->_viewport.Top;
|
||||
|
||||
// Then note that VT is 1,1 based for the top left, so add 1. (The rest of the console uses 0,0 for array index bases.)
|
||||
coordCursorExpected.X++;
|
||||
coordCursorExpected.Y++;
|
||||
// Then note that VT is 1,1 based for the top left, so add 1. (The rest of the console uses 0,0 for array index bases.)
|
||||
coordCursorExpected.X++;
|
||||
coordCursorExpected.Y++;
|
||||
|
||||
VERIFY_IS_TRUE(_pDispatch.get()->DeviceStatusReport(DispatchTypes::AnsiStatusType::CPR_CursorPositionReport));
|
||||
VERIFY_IS_TRUE(_pDispatch.get()->DeviceStatusReport(DispatchTypes::AnsiStatusType::CPR_CursorPositionReport));
|
||||
|
||||
wchar_t pwszBuffer[50];
|
||||
wchar_t pwszBuffer[50];
|
||||
|
||||
swprintf_s(pwszBuffer, ARRAYSIZE(pwszBuffer), L"\x1b[%d;%dR", coordCursorExpected.Y, coordCursorExpected.X);
|
||||
_testGetSet->ValidateInputEvent(pwszBuffer);
|
||||
swprintf_s(pwszBuffer, ARRAYSIZE(pwszBuffer), L"\x1b[%d;%dR", coordCursorExpected.Y, coordCursorExpected.X);
|
||||
_testGetSet->ValidateInputEvent(pwszBuffer);
|
||||
}
|
||||
|
||||
{
|
||||
Log::Comment(L"Test 2: Verify multiple CPRs with a cursor move between them");
|
||||
_testGetSet->PrepData(CursorX::XCENTER, CursorY::YCENTER);
|
||||
|
||||
// enable retention so that the two DSR responses don't delete eachother
|
||||
auto retentionScope{ _testGetSet->EnableInputRetentionInScope() };
|
||||
|
||||
// start with the cursor position in the buffer.
|
||||
til::point coordCursorExpectedFirst{ _testGetSet->_cursorPos };
|
||||
|
||||
// to get to VT, we have to adjust it to its position relative to the viewport top.
|
||||
coordCursorExpectedFirst -= til::point{ 0, _testGetSet->_viewport.Top };
|
||||
|
||||
// Then note that VT is 1,1 based for the top left, so add 1. (The rest of the console uses 0,0 for array index bases.)
|
||||
coordCursorExpectedFirst += til::point{ 1, 1 };
|
||||
|
||||
VERIFY_IS_TRUE(_pDispatch.get()->DeviceStatusReport(DispatchTypes::AnsiStatusType::CPR_CursorPositionReport));
|
||||
|
||||
_testGetSet->_cursorPos.X++;
|
||||
_testGetSet->_cursorPos.Y++;
|
||||
|
||||
auto coordCursorExpectedSecond{ coordCursorExpectedFirst };
|
||||
coordCursorExpectedSecond += til::point{ 1, 1 };
|
||||
|
||||
VERIFY_IS_TRUE(_pDispatch.get()->DeviceStatusReport(DispatchTypes::AnsiStatusType::CPR_CursorPositionReport));
|
||||
|
||||
wchar_t pwszBuffer[50];
|
||||
|
||||
swprintf_s(pwszBuffer, ARRAYSIZE(pwszBuffer), L"\x1b[%d;%dR\x1b[%d;%dR", coordCursorExpectedFirst.y<int>(), coordCursorExpectedFirst.x<int>(), coordCursorExpectedSecond.y<int>(), coordCursorExpectedSecond.x<int>());
|
||||
_testGetSet->ValidateInputEvent(pwszBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(DeviceAttributesTests)
|
||||
@@ -1728,7 +1762,7 @@ public:
|
||||
|
||||
Log::Comment(L"Test 2: Verify failure when WriteConsoleInput doesn't work.");
|
||||
_testGetSet->PrepData();
|
||||
_testGetSet->_privatePrependConsoleInputResult = FALSE;
|
||||
_testGetSet->_privateWriteConsoleInputWResult = FALSE;
|
||||
|
||||
VERIFY_IS_FALSE(_pDispatch.get()->DeviceAttributes());
|
||||
}
|
||||
@@ -1746,7 +1780,7 @@ public:
|
||||
|
||||
Log::Comment(L"Test 2: Verify failure when WriteConsoleInput doesn't work.");
|
||||
_testGetSet->PrepData();
|
||||
_testGetSet->_privatePrependConsoleInputResult = FALSE;
|
||||
_testGetSet->_privateWriteConsoleInputWResult = FALSE;
|
||||
|
||||
VERIFY_IS_FALSE(_pDispatch.get()->SecondaryDeviceAttributes());
|
||||
}
|
||||
@@ -1764,7 +1798,7 @@ public:
|
||||
|
||||
Log::Comment(L"Test 2: Verify failure when WriteConsoleInput doesn't work.");
|
||||
_testGetSet->PrepData();
|
||||
_testGetSet->_privatePrependConsoleInputResult = FALSE;
|
||||
_testGetSet->_privateWriteConsoleInputWResult = FALSE;
|
||||
|
||||
VERIFY_IS_FALSE(_pDispatch.get()->TertiaryDeviceAttributes());
|
||||
}
|
||||
|
||||
@@ -588,8 +588,7 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent)
|
||||
}
|
||||
}
|
||||
|
||||
const auto senderFunc = [this](const std::wstring_view seq) noexcept
|
||||
{
|
||||
const auto senderFunc = [this](const std::wstring_view seq) noexcept {
|
||||
_SendInputSequence(seq);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,42 +9,30 @@ using namespace ::Microsoft::Console::Utils;
|
||||
// We cannot use spand or not_null because we're dealing with \0\0-terminated buffers of unknown length
|
||||
#pragma warning(disable : 26481 26429)
|
||||
|
||||
// Function Description:
|
||||
// - Wraps win32's CreateEnvironmentBlock to return a smart pointer.
|
||||
EnvironmentBlockPtr Microsoft::Console::Utils::CreateEnvironmentBlock()
|
||||
{
|
||||
void* newEnvironmentBlock{ nullptr };
|
||||
if (!::CreateEnvironmentBlock(&newEnvironmentBlock, GetCurrentProcessToken(), FALSE))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return EnvironmentBlockPtr{ newEnvironmentBlock };
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Updates an EnvironmentVariableMapW with the current process's unicode
|
||||
// environment variables ignoring ones already set in the provided map.
|
||||
// Arguments:
|
||||
// - map: The map to populate with the current processes's environment variables.
|
||||
// - environmentBlock: Optional environment block to use when filling map. If omitted,
|
||||
// defaults to the current environment.
|
||||
// Return Value:
|
||||
// - S_OK if we succeeded, or an appropriate HRESULT for failing
|
||||
HRESULT Microsoft::Console::Utils::UpdateEnvironmentMapW(EnvironmentVariableMapW& map, void* environmentBlock) noexcept
|
||||
HRESULT Microsoft::Console::Utils::UpdateEnvironmentMapW(EnvironmentVariableMapW& map) noexcept
|
||||
try
|
||||
{
|
||||
wchar_t const* activeEnvironmentBlock{ static_cast<wchar_t const*>(environmentBlock) };
|
||||
LPWCH currentEnvVars{};
|
||||
auto freeCurrentEnv = wil::scope_exit([&] {
|
||||
if (currentEnvVars)
|
||||
{
|
||||
FreeEnvironmentStringsW(currentEnvVars);
|
||||
currentEnvVars = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
wil::unique_environstrings_ptr currentEnvVars;
|
||||
if (!activeEnvironmentBlock)
|
||||
{
|
||||
currentEnvVars.reset(::GetEnvironmentStringsW());
|
||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, currentEnvVars);
|
||||
activeEnvironmentBlock = currentEnvVars.get();
|
||||
}
|
||||
currentEnvVars = ::GetEnvironmentStringsW();
|
||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, currentEnvVars);
|
||||
|
||||
// Each entry is NULL-terminated; block is guaranteed to be double-NULL terminated at a minimum.
|
||||
for (wchar_t const* lastCh{ activeEnvironmentBlock }; *lastCh != '\0'; ++lastCh)
|
||||
for (wchar_t const* lastCh{ currentEnvVars }; *lastCh != '\0'; ++lastCh)
|
||||
{
|
||||
// Copy current entry into temporary map.
|
||||
const size_t cchEntry{ ::wcslen(lastCh) };
|
||||
|
||||
@@ -579,6 +579,7 @@ IFACEMETHODIMP UiaTextRangeBase::Move(_In_ TextUnit unit,
|
||||
// We can abstract this movement by moving _start, but disallowing moving to the end of the buffer
|
||||
constexpr auto endpoint = TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start;
|
||||
constexpr auto preventBufferEnd = true;
|
||||
const auto wasDegenerate = IsDegenerate();
|
||||
try
|
||||
{
|
||||
if (unit == TextUnit::TextUnit_Character)
|
||||
@@ -603,8 +604,17 @@ IFACEMETHODIMP UiaTextRangeBase::Move(_In_ TextUnit unit,
|
||||
// If we actually moved...
|
||||
if (*pRetVal != 0)
|
||||
{
|
||||
// then just expand to get our _end
|
||||
ExpandToEnclosingUnit(unit);
|
||||
if (wasDegenerate)
|
||||
{
|
||||
// GH#7342: The range was degenerate before the move.
|
||||
// To keep it that way, move _end to the new _start.
|
||||
_end = _start;
|
||||
}
|
||||
else
|
||||
{
|
||||
// then just expand to get our _end
|
||||
ExpandToEnclosingUnit(unit);
|
||||
}
|
||||
}
|
||||
|
||||
UiaTracing::TextRange::Move(unit, count, *pRetVal, *this);
|
||||
@@ -702,8 +712,13 @@ try
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto bufferSize = _pData->GetTextBuffer().GetSize();
|
||||
if (!bufferSize.IsInBounds(_start, true) || !bufferSize.IsInBounds(_end, true))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
auto inclusiveEnd = _end;
|
||||
_pData->GetTextBuffer().GetSize().DecrementInBounds(inclusiveEnd);
|
||||
bufferSize.DecrementInBounds(inclusiveEnd);
|
||||
_pData->SelectNewRegion(_start, inclusiveEnd);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@ static const WORD leftShiftScanCode = 0x2A;
|
||||
THROW_IF_FAILED(SizeTToInt(source.size(), &iSource));
|
||||
|
||||
// Ask how much space we will need.
|
||||
// In certain codepages, Mb2Wc will "successfully" produce zero characters (like in CP50220, where a SHIFT-IN character
|
||||
// is consumed but not transformed into anything) without explicitly failing. When it does this, GetLastError will return
|
||||
// the last error encountered by the last function that actually did have an error.
|
||||
// This is arguably correct (as the documentation says "The function returns 0 if it does not succeed"). There is a
|
||||
// difference that we **don't actually care about** between failing and successfully producing zero characters.,
|
||||
// Anyway: we need to clear the last error so that we can fail out and IGNORE_BAD_GLE after it inevitably succeed-fails.
|
||||
SetLastError(0);
|
||||
int const iTarget = MultiByteToWideChar(codePage, 0, source.data(), iSource, nullptr, 0);
|
||||
THROW_LAST_ERROR_IF_AND_IGNORE_BAD_GLE(0 == iTarget);
|
||||
|
||||
|
||||
@@ -21,12 +21,9 @@ namespace Microsoft::Console::Utils
|
||||
}
|
||||
};
|
||||
|
||||
using EnvironmentBlockPtr = wil::unique_any<void*, decltype(::DestroyEnvironmentBlock), ::DestroyEnvironmentBlock>;
|
||||
[[nodiscard]] EnvironmentBlockPtr CreateEnvironmentBlock();
|
||||
|
||||
using EnvironmentVariableMapW = std::map<std::wstring, std::wstring, WStringCaseInsensitiveCompare>;
|
||||
|
||||
[[nodiscard]] HRESULT UpdateEnvironmentMapW(EnvironmentVariableMapW& map, void* environmentBlock = nullptr) noexcept;
|
||||
[[nodiscard]] HRESULT UpdateEnvironmentMapW(EnvironmentVariableMapW& map) noexcept;
|
||||
|
||||
[[nodiscard]] HRESULT EnvironmentMapToEnvironmentStringsW(EnvironmentVariableMapW& map,
|
||||
std::vector<wchar_t>& newEnvVars) noexcept;
|
||||
|
||||
@@ -29,7 +29,6 @@ Abstract:
|
||||
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <userenv.h>
|
||||
#include <combaseapi.h>
|
||||
#include <UIAutomation.h>
|
||||
#include <objbase.h>
|
||||
|
||||
@@ -323,7 +323,10 @@ function Invoke-ClangFormat {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[string[]]$Path
|
||||
[string[]]$Path,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$ClangFormatPath = "clang-format" # (whichever one is in $PATH)
|
||||
)
|
||||
|
||||
Begin {
|
||||
@@ -340,7 +343,7 @@ function Invoke-ClangFormat {
|
||||
End {
|
||||
For($i = [int]0; $i -Lt $Paths.Length; $i += $BatchSize) {
|
||||
Try {
|
||||
& "$env:OpenconsoleRoot/dep/llvm/clang-format" -i $Paths[$i .. ($i + $BatchSize - 1)]
|
||||
& $ClangFormatPath -i $Paths[$i .. ($i + $BatchSize - 1)]
|
||||
} Catch {
|
||||
Write-Error $_
|
||||
}
|
||||
@@ -351,9 +354,12 @@ function Invoke-ClangFormat {
|
||||
#.SYNOPSIS
|
||||
# runs code formatting on all c++ files
|
||||
function Invoke-CodeFormat() {
|
||||
& "$env:OpenConsoleRoot\dep\nuget\nuget.exe" restore "$env:OpenConsoleRoot\tools\packages.config"
|
||||
$clangPackage = ([xml](Get-Content "$env:OpenConsoleRoot\tools\packages.config")).packages.package | Where-Object id -like "clang-format*"
|
||||
$clangFormatPath = "$env:OpenConsoleRoot\packages\$($clangPackage.id).$($clangPackage.version)\tools\clang-format.exe"
|
||||
Get-ChildItem -Recurse "$env:OpenConsoleRoot/src" -Include *.cpp, *.hpp, *.h |
|
||||
Where FullName -NotLike "*Generated Files*" |
|
||||
Invoke-ClangFormat
|
||||
Invoke-ClangFormat -ClangFormatPath $clangFormatPath
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Set-MsbuildDevEnvironment,Invoke-OpenConsoleTests,Invoke-OpenConsoleBuild,Start-OpenConsole,Debug-OpenConsole,Invoke-CodeFormat
|
||||
|
||||
4
tools/packages.config
Normal file
4
tools/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="clang-format.win-x86" version="10.0.0" targetFramework="native" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user