Add support for the VT answerback capability (#17660)
The answerback feature allows for the user to define a message that the terminal will transmit to the host whenever an `ENQ` (enquiry) control character is received. ## Detailed Description of the Pull Request / Additional comments In Windows Terminal, the message can be configured at the profile level of the settings file, as a string property named `AnswerbackMessage`. In ConHost, the message can be configured in the registry, again as a string value with the name `AnswerbackMessage`. ## Validation Steps Performed I've confirmed that the control is working as intended in both Windows Terminal and ConHost using Vttest. Closes #11946
This commit is contained in:
parent
2c452e0fd6
commit
746cf1f148
|
@ -38,6 +38,7 @@ ANSISYS
|
|||
ANSISYSRC
|
||||
ANSISYSSC
|
||||
answerback
|
||||
ANSWERBACKMESSAGE
|
||||
antialiasing
|
||||
ANull
|
||||
anycpu
|
||||
|
|
|
@ -104,6 +104,7 @@ GetConsoleKeyboardLayoutNameW(
|
|||
#define CONSOLE_REGISTRY_DEFAULTFOREGROUND L"DefaultForeground"
|
||||
#define CONSOLE_REGISTRY_DEFAULTBACKGROUND L"DefaultBackground"
|
||||
#define CONSOLE_REGISTRY_TERMINALSCROLLING L"TerminalScrolling"
|
||||
#define CONSOLE_REGISTRY_ANSWERBACKMESSAGE L"AnswerbackMessage"
|
||||
// end V2 console settings
|
||||
|
||||
/*
|
||||
|
|
|
@ -3032,6 +3032,10 @@
|
|||
"description": "By default Windows treats Ctrl+Alt as an alias for AltGr. When altGrAliasing is set to false, this behavior will be disabled.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"answerbackMessage": {
|
||||
"description": "The response that is sent when an ENQ control character is received.",
|
||||
"type": "string"
|
||||
},
|
||||
"source": {
|
||||
"description": "Stores the name of the profile generator that originated this profile.",
|
||||
"type": [
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Microsoft.Terminal.Core
|
|||
|
||||
Boolean SnapOnInput;
|
||||
Boolean AltGrAliasing;
|
||||
String AnswerbackMessage;
|
||||
|
||||
String StartingTitle;
|
||||
Boolean SuppressApplicationTitle;
|
||||
|
|
|
@ -82,6 +82,7 @@ void Terminal::UpdateSettings(ICoreSettings settings)
|
|||
|
||||
_snapOnInput = settings.SnapOnInput();
|
||||
_altGrAliasing = settings.AltGrAliasing();
|
||||
_answerbackMessage = settings.AnswerbackMessage();
|
||||
_wordDelimiters = settings.WordDelimiters();
|
||||
_suppressApplicationTitle = settings.SuppressApplicationTitle();
|
||||
_startingTitle = settings.StartingTitle();
|
||||
|
|
|
@ -135,6 +135,7 @@ public:
|
|||
void SetTextAttributes(const TextAttribute& attrs) noexcept override;
|
||||
void SetSystemMode(const Mode mode, const bool enabled) noexcept override;
|
||||
bool GetSystemMode(const Mode mode) const noexcept override;
|
||||
void ReturnAnswerback() override;
|
||||
void WarningBell() override;
|
||||
void SetWindowTitle(const std::wstring_view title) override;
|
||||
CursorType GetUserDefaultCursorStyle() const noexcept override;
|
||||
|
@ -371,6 +372,7 @@ private:
|
|||
|
||||
size_t _hyperlinkPatternId = 0;
|
||||
|
||||
std::wstring _answerbackMessage;
|
||||
std::wstring _workingDirectory;
|
||||
|
||||
// This default fake font value is only used to check if the font is a raster font.
|
||||
|
|
|
@ -71,6 +71,11 @@ bool Terminal::GetSystemMode(const Mode mode) const noexcept
|
|||
return _systemMode.test(mode);
|
||||
}
|
||||
|
||||
void Terminal::ReturnAnswerback()
|
||||
{
|
||||
ReturnResponse(_answerbackMessage);
|
||||
}
|
||||
|
||||
void Terminal::WarningBell()
|
||||
{
|
||||
_pfnWarningBell();
|
||||
|
|
|
@ -81,6 +81,7 @@ Author(s):
|
|||
X(int32_t, HistorySize, "historySize", DEFAULT_HISTORY_SIZE) \
|
||||
X(bool, SnapOnInput, "snapOnInput", true) \
|
||||
X(bool, AltGrAliasing, "altGrAliasing", true) \
|
||||
X(hstring, AnswerbackMessage, "answerbackMessage") \
|
||||
X(hstring, Commandline, "commandline", L"%SystemRoot%\\System32\\cmd.exe") \
|
||||
X(Microsoft::Terminal::Control::ScrollbarState, ScrollState, "scrollbarState", Microsoft::Terminal::Control::ScrollbarState::Visible) \
|
||||
X(Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, "antialiasingMode", Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_PROFILE_SETTING(Int32, HistorySize);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing);
|
||||
INHERITABLE_PROFILE_SETTING(String, AnswerbackMessage);
|
||||
INHERITABLE_PROFILE_SETTING(BellStyle, BellStyle);
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Windows.Foundation.Collections.IMap<String COMMA String>, EnvironmentVariables);
|
||||
|
|
|
@ -284,6 +284,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
_HistorySize = profile.HistorySize();
|
||||
_SnapOnInput = profile.SnapOnInput();
|
||||
_AltGrAliasing = profile.AltGrAliasing();
|
||||
_AnswerbackMessage = profile.AnswerbackMessage();
|
||||
|
||||
// Fill in the remaining properties from the profile
|
||||
_ProfileName = profile.Name();
|
||||
|
|
|
@ -86,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, bool, SnapOnInput, true);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, bool, AltGrAliasing, true);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, AnswerbackMessage);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, til::color, CursorColor, DEFAULT_CURSOR_COLOR);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Core::CursorStyle, CursorShape, Core::CursorStyle::Vintage);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
X(int32_t, InitialCols, 80) \
|
||||
X(bool, SnapOnInput, true) \
|
||||
X(bool, AltGrAliasing, true) \
|
||||
X(winrt::hstring, AnswerbackMessage) \
|
||||
X(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS) \
|
||||
X(bool, CopyOnSelect, false) \
|
||||
X(bool, FocusFollowMouse, false) \
|
||||
|
|
|
@ -146,6 +146,16 @@ bool ConhostInternalGetSet::GetSystemMode(const Mode mode) const
|
|||
}
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Sends the configured answerback message in response to an ENQ query.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ConhostInternalGetSet::ReturnAnswerback()
|
||||
{
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
ReturnResponse(gci.GetAnswerbackMessage());
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Sends a notify message to play the "SystemHand" sound event.
|
||||
// Return Value:
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
void SetSystemMode(const Mode mode, const bool enabled) override;
|
||||
bool GetSystemMode(const Mode mode) const override;
|
||||
|
||||
void ReturnAnswerback() override;
|
||||
void WarningBell() override;
|
||||
|
||||
void SetWindowTitle(const std::wstring_view title) override;
|
||||
|
|
|
@ -765,6 +765,11 @@ void Settings::SetTerminalScrolling(const bool terminalScrollingEnabled) noexcep
|
|||
_TerminalScrolling = terminalScrollingEnabled;
|
||||
}
|
||||
|
||||
std::wstring_view Settings::GetAnswerbackMessage() const noexcept
|
||||
{
|
||||
return _answerbackMessage;
|
||||
}
|
||||
|
||||
// Determines whether our primary renderer should be DirectX or GDI.
|
||||
// This is based on user preference and velocity hold back state.
|
||||
bool Settings::GetUseDx() const noexcept
|
||||
|
|
|
@ -176,6 +176,8 @@ public:
|
|||
bool IsTerminalScrolling() const noexcept;
|
||||
void SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept;
|
||||
|
||||
std::wstring_view GetAnswerbackMessage() const noexcept;
|
||||
|
||||
bool GetUseDx() const noexcept;
|
||||
bool GetCopyColor() const noexcept;
|
||||
SettingsTextMeasurementMode GetTextMeasurementMode() const noexcept;
|
||||
|
@ -236,5 +238,6 @@ private:
|
|||
bool _fInterceptCopyPaste;
|
||||
|
||||
bool _TerminalScrolling;
|
||||
WCHAR _answerbackMessage[32] = {};
|
||||
friend class RegistrySerialization;
|
||||
};
|
||||
|
|
|
@ -60,6 +60,7 @@ const RegistrySerialization::_RegPropertyMap RegistrySerialization::s_PropertyMa
|
|||
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_CURSORTYPE, SET_FIELD_AND_SIZE(_CursorType) },
|
||||
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_INTERCEPTCOPYPASTE, SET_FIELD_AND_SIZE(_fInterceptCopyPaste) },
|
||||
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_TERMINALSCROLLING, SET_FIELD_AND_SIZE(_TerminalScrolling) },
|
||||
{ _RegPropertyType::String, CONSOLE_REGISTRY_ANSWERBACKMESSAGE, SET_FIELD_AND_SIZE(_answerbackMessage) },
|
||||
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) },
|
||||
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_COPYCOLOR, SET_FIELD_AND_SIZE(_fCopyColor) },
|
||||
{ _RegPropertyType::Dword, L"TextMeasurement", SET_FIELD_AND_SIZE(_textMeasurement) },
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
virtual bool SetAnsiMode(const bool ansiMode) = 0; // DECANM
|
||||
virtual bool SetTopBottomScrollingMargins(const VTInt topMargin, const VTInt bottomMargin) = 0; // DECSTBM
|
||||
virtual bool SetLeftRightScrollingMargins(const VTInt leftMargin, const VTInt rightMargin) = 0; // DECSLRM
|
||||
virtual bool EnquireAnswerback() = 0; // ENQ
|
||||
virtual bool WarningBell() = 0; // BEL
|
||||
virtual bool CarriageReturn() = 0; // CR
|
||||
virtual bool LineFeed(const DispatchTypes::LineFeedType lineFeedType) = 0; // IND, NEL, LF, FF, VT
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace Microsoft::Console::VirtualTerminal
|
|||
virtual void SetSystemMode(const Mode mode, const bool enabled) = 0;
|
||||
virtual bool GetSystemMode(const Mode mode) const = 0;
|
||||
|
||||
virtual void ReturnAnswerback() = 0;
|
||||
virtual void WarningBell() = 0;
|
||||
virtual void SetWindowTitle(const std::wstring_view title) = 0;
|
||||
virtual void UseAlternateScreenBuffer(const TextAttribute& attrs) = 0;
|
||||
|
|
|
@ -2476,6 +2476,18 @@ bool AdaptDispatch::SetLeftRightScrollingMargins(const VTInt leftMargin,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - ENQ - Directs the terminal to send the answerback message.
|
||||
// Arguments:
|
||||
// - None
|
||||
// Return Value:
|
||||
// - True.
|
||||
bool AdaptDispatch::EnquireAnswerback()
|
||||
{
|
||||
_api.ReturnAnswerback();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - BEL - Rings the warning bell.
|
||||
// Causes the terminal to emit an audible tone of brief duration.
|
||||
|
|
|
@ -101,6 +101,7 @@ namespace Microsoft::Console::VirtualTerminal
|
|||
const VTInt bottomMargin) override; // DECSTBM
|
||||
bool SetLeftRightScrollingMargins(const VTInt leftMargin,
|
||||
const VTInt rightMargin) override; // DECSLRM
|
||||
bool EnquireAnswerback() override; // ENQ
|
||||
bool WarningBell() override; // BEL
|
||||
bool CarriageReturn() override; // CR
|
||||
bool LineFeed(const DispatchTypes::LineFeedType lineFeedType) override; // IND, NEL, LF, FF, VT
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
bool SetAnsiMode(const bool /*ansiMode*/) override { return false; } // DECANM
|
||||
bool SetTopBottomScrollingMargins(const VTInt /*topMargin*/, const VTInt /*bottomMargin*/) override { return false; } // DECSTBM
|
||||
bool SetLeftRightScrollingMargins(const VTInt /*leftMargin*/, const VTInt /*rightMargin*/) override { return false; } // DECSLRM
|
||||
bool EnquireAnswerback() override { return false; } // ENQ
|
||||
bool WarningBell() override { return false; } // BEL
|
||||
bool CarriageReturn() override { return false; } // CR
|
||||
bool LineFeed(const DispatchTypes::LineFeedType /*lineFeedType*/) override { return false; } // IND, NEL, LF, FF, VT
|
||||
|
|
|
@ -118,6 +118,11 @@ public:
|
|||
return _systemMode.test(mode);
|
||||
}
|
||||
|
||||
void ReturnAnswerback()
|
||||
{
|
||||
Log::Comment(L"ReturnAnswerback MOCK called...");
|
||||
}
|
||||
|
||||
void WarningBell() override
|
||||
{
|
||||
Log::Comment(L"WarningBell MOCK called...");
|
||||
|
|
|
@ -49,9 +49,7 @@ bool OutputStateMachineEngine::ActionExecute(const wchar_t wch)
|
|||
switch (wch)
|
||||
{
|
||||
case AsciiChars::ENQ:
|
||||
// GH#11946: At some point we may want to add support for the VT
|
||||
// answerback feature, which requires responding to an ENQ control
|
||||
// with a user-defined reply, but until then we just ignore it.
|
||||
_dispatch->EnquireAnswerback();
|
||||
break;
|
||||
case AsciiChars::BEL:
|
||||
_dispatch->WarningBell();
|
||||
|
|
Loading…
Reference in New Issue