Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add support for LNM (Line Feed/New Line Mode) #15261

Merged
merged 3 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ void Terminal::EraseScrollback()

bool Terminal::IsXtermBracketedPasteModeEnabled() const noexcept
{
return _bracketedPasteMode;
return _systemMode.test(Mode::BracketedPaste);
}

std::wstring_view Terminal::GetWorkingDirectory() noexcept
Expand Down
10 changes: 4 additions & 6 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,14 @@ class Microsoft::Terminal::Core::Terminal final :
til::rect GetViewport() const noexcept override;
void SetViewportPosition(const til::point position) noexcept override;
void SetTextAttributes(const TextAttribute& attrs) noexcept override;
void SetAutoWrapMode(const bool wrapAtEOL) noexcept override;
bool GetAutoWrapMode() const noexcept override;
void SetSystemMode(const Mode mode, const bool enabled) noexcept override;
bool GetSystemMode(const Mode mode) const noexcept override;
void WarningBell() override;
bool GetLineFeedMode() const noexcept override;
void SetWindowTitle(const std::wstring_view title) override;
CursorType GetUserDefaultCursorStyle() const noexcept override;
bool ResizeWindow(const til::CoordType width, const til::CoordType height) noexcept override;
void SetConsoleOutputCP(const unsigned int codepage) noexcept override;
unsigned int GetConsoleOutputCP() const noexcept override;
void SetBracketedPasteMode(const bool enabled) noexcept override;
bool GetBracketedPasteMode() const noexcept override;
void CopyToClipboard(std::wstring_view content) override;
void SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) override;
void SetWorkingDirectory(std::wstring_view uri) override;
Expand Down Expand Up @@ -320,10 +317,11 @@ class Microsoft::Terminal::Core::Terminal final :

CursorType _defaultCursorShape = CursorType::Legacy;

til::enumset<Mode> _systemMode{ Mode::AutoWrap };

bool _snapOnInput = true;
bool _altGrAliasing = true;
bool _suppressApplicationTitle = false;
bool _bracketedPasteMode = false;
bool _trimBlockSelection = false;
bool _autoMarkPrompts = false;

Expand Down
25 changes: 4 additions & 21 deletions src/cascadia/TerminalCore/TerminalApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,28 +61,21 @@ void Terminal::SetTextAttributes(const TextAttribute& attrs) noexcept
_activeBuffer().SetCurrentAttributes(attrs);
}

void Terminal::SetAutoWrapMode(const bool /*wrapAtEOL*/) noexcept
void Terminal::SetSystemMode(const Mode mode, const bool enabled) noexcept
{
// TODO: This will be needed to support DECAWM.
_systemMode.set(mode, enabled);
}

bool Terminal::GetAutoWrapMode() const noexcept
bool Terminal::GetSystemMode(const Mode mode) const noexcept
{
// TODO: This will be needed to support DECAWM.
return true;
return _systemMode.test(mode);
}

void Terminal::WarningBell()
{
_pfnWarningBell();
}

bool Terminal::GetLineFeedMode() const noexcept
{
// TODO: This will be needed to support LNM.
return false;
}

void Terminal::SetWindowTitle(const std::wstring_view title)
{
if (!_suppressApplicationTitle)
Expand Down Expand Up @@ -114,16 +107,6 @@ unsigned int Terminal::GetConsoleOutputCP() const noexcept
return CP_UTF8;
}

void Terminal::SetBracketedPasteMode(const bool enabled) noexcept
{
_bracketedPasteMode = enabled;
}

bool Terminal::GetBracketedPasteMode() const noexcept
{
return _bracketedPasteMode;
}

void Terminal::CopyToClipboard(std::wstring_view content)
{
_pfnCopyToClipboard(content);
Expand Down
78 changes: 32 additions & 46 deletions src/host/outputStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,40 +114,49 @@ void ConhostInternalGetSet::SetTextAttributes(const TextAttribute& attrs)
}

// Routine Description:
// - Sets the ENABLE_WRAP_AT_EOL_OUTPUT mode. This controls whether the cursor moves
// to the beginning of the next row when it reaches the end of the current row.
// - Sets the state of one of the system modes.
// Arguments:
// - wrapAtEOL - set to true to wrap, false to overwrite the last character.
// - mode - The mode being updated.
// - enabled - True to enable the mode, false to disable it.
// Return Value:
// - <none>
void ConhostInternalGetSet::SetAutoWrapMode(const bool wrapAtEOL)
void ConhostInternalGetSet::SetSystemMode(const Mode mode, const bool enabled)
{
auto& outputMode = _io.GetActiveOutputBuffer().OutputMode;
WI_UpdateFlag(outputMode, ENABLE_WRAP_AT_EOL_OUTPUT, wrapAtEOL);
switch (mode)
{
case Mode::AutoWrap:
WI_UpdateFlag(_io.GetActiveOutputBuffer().OutputMode, ENABLE_WRAP_AT_EOL_OUTPUT, enabled);
break;
case Mode::LineFeed:
WI_UpdateFlag(_io.GetActiveOutputBuffer().OutputMode, DISABLE_NEWLINE_AUTO_RETURN, !enabled);
break;
case Mode::BracketedPaste:
ServiceLocator::LocateGlobals().getConsoleInformation().SetBracketedPasteMode(enabled);
break;
default:
THROW_HR(E_INVALIDARG);
}
}

// Routine Description:
// - Retrieves the current state of ENABLE_WRAP_AT_EOL_OUTPUT mode.
// - Retrieves the current state of one of the system modes.
// Arguments:
// - <none>
// - mode - The mode being queried.
// Return Value:
// - true if the mode is enabled. false otherwise.
bool ConhostInternalGetSet::GetAutoWrapMode() const
bool ConhostInternalGetSet::GetSystemMode(const Mode mode) const
{
const auto outputMode = _io.GetActiveOutputBuffer().OutputMode;
return WI_IsFlagSet(outputMode, ENABLE_WRAP_AT_EOL_OUTPUT);
}

// Method Description:
// - Retrieves the current Line Feed/New Line (LNM) mode.
// Arguments:
// - None
// Return Value:
// - true if a line feed also produces a carriage return. false otherwise.
bool ConhostInternalGetSet::GetLineFeedMode() const
{
auto& screenInfo = _io.GetActiveOutputBuffer();
return WI_IsFlagClear(screenInfo.OutputMode, DISABLE_NEWLINE_AUTO_RETURN);
switch (mode)
{
case Mode::AutoWrap:
return WI_IsFlagSet(_io.GetActiveOutputBuffer().OutputMode, ENABLE_WRAP_AT_EOL_OUTPUT);
case Mode::LineFeed:
return WI_IsFlagClear(_io.GetActiveOutputBuffer().OutputMode, DISABLE_NEWLINE_AUTO_RETURN);
case Mode::BracketedPaste:
return ServiceLocator::LocateGlobals().getConsoleInformation().GetBracketedPasteMode();
default:
THROW_HR(E_INVALIDARG);
}
}

// Routine Description:
Expand Down Expand Up @@ -245,29 +254,6 @@ unsigned int ConhostInternalGetSet::GetConsoleOutputCP() const
return ServiceLocator::LocateGlobals().getConsoleInformation().OutputCP;
}

// Routine Description:
// - Sets the XTerm bracketed paste mode. This controls whether pasted content is
// bracketed with control sequences to differentiate it from typed text.
// Arguments:
// - enable - set to true to enable bracketing, false to disable.
// Return Value:
// - <none>
void ConhostInternalGetSet::SetBracketedPasteMode(const bool enabled)
{
ServiceLocator::LocateGlobals().getConsoleInformation().SetBracketedPasteMode(enabled);
}

// Routine Description:
// - Gets the current state of XTerm bracketed paste mode.
// Arguments:
// - <none>
// Return Value:
// - true if the mode is enabled, false if not.
bool ConhostInternalGetSet::GetBracketedPasteMode() const
{
return ServiceLocator::LocateGlobals().getConsoleInformation().GetBracketedPasteMode();
}

// Routine Description:
// - Copies the given content to the clipboard.
// Arguments:
Expand Down
8 changes: 2 additions & 6 deletions src/host/outputStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,11 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::

void SetTextAttributes(const TextAttribute& attrs) override;

void SetAutoWrapMode(const bool wrapAtEOL) override;
bool GetAutoWrapMode() const override;
void SetSystemMode(const Mode mode, const bool enabled) override;
bool GetSystemMode(const Mode mode) const override;

void WarningBell() override;

bool GetLineFeedMode() const override;

void SetWindowTitle(const std::wstring_view title) override;

void UseAlternateScreenBuffer() override;
Expand All @@ -60,8 +58,6 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::
void SetConsoleOutputCP(const unsigned int codepage) override;
unsigned int GetConsoleOutputCP() const override;

void SetBracketedPasteMode(const bool enabled) override;
bool GetBracketedPasteMode() const override;
void CopyToClipboard(const std::wstring_view content) override;
void SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) override;
void SetWorkingDirectory(const std::wstring_view uri) override;
Expand Down
23 changes: 23 additions & 0 deletions src/host/ut_host/ScreenBufferTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ class ScreenBufferTests

TEST_METHOD(ScrollLines256Colors);

TEST_METHOD(SetLineFeedMode);
TEST_METHOD(SetScreenMode);
TEST_METHOD(SetOriginMode);
TEST_METHOD(SetAutoWrapMode);
Expand Down Expand Up @@ -5156,6 +5157,28 @@ void ScreenBufferTests::ScrollLines256Colors()
}
}

void ScreenBufferTests::SetLineFeedMode()
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto& si = gci.GetActiveOutputBuffer();
auto& stateMachine = si.GetStateMachine();
const auto& terminalInput = gci.GetActiveInputBuffer()->GetTerminalInput();

// We need to start with newline auto return disabled for LNM to be active.
WI_SetFlag(si.OutputMode, DISABLE_NEWLINE_AUTO_RETURN);
auto restoreMode = wil::scope_exit([&] { WI_ClearFlag(si.OutputMode, DISABLE_NEWLINE_AUTO_RETURN); });

Log::Comment(L"When LNM is set, newline auto return and line feed mode are enabled.");
stateMachine.ProcessString(L"\x1B[20h");
VERIFY_IS_TRUE(WI_IsFlagClear(si.OutputMode, DISABLE_NEWLINE_AUTO_RETURN));
VERIFY_IS_TRUE(terminalInput.GetInputMode(TerminalInput::Mode::LineFeed));

Log::Comment(L"When LNM is reset, newline auto return and line feed mode are disabled.");
stateMachine.ProcessString(L"\x1B[20l");
VERIFY_IS_FALSE(WI_IsFlagClear(si.OutputMode, DISABLE_NEWLINE_AUTO_RETURN));
VERIFY_IS_FALSE(terminalInput.GetInputMode(TerminalInput::Mode::LineFeed));
}

void ScreenBufferTests::SetScreenMode()
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/DispatchTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
enum ModeParams : VTInt
{
IRM_InsertReplaceMode = ANSIStandardMode(4),
LNM_LineFeedNewLineMode = ANSIStandardMode(20),
DECCKM_CursorKeysMode = DECPrivateMode(1),
DECANM_AnsiMode = DECPrivateMode(2),
DECCOLM_SetNumberOfColumns = DECPrivateMode(3),
Expand Down
14 changes: 9 additions & 5 deletions src/terminal/adapter/ITerminalApi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,17 @@ namespace Microsoft::Console::VirtualTerminal

virtual void SetTextAttributes(const TextAttribute& attrs) = 0;

virtual void SetAutoWrapMode(const bool wrapAtEOL) = 0;
virtual bool GetAutoWrapMode() const = 0;
enum class Mode : size_t
{
AutoWrap,
LineFeed,
BracketedPaste
};

virtual void SetSystemMode(const Mode mode, const bool enabled) = 0;
virtual bool GetSystemMode(const Mode mode) const = 0;

virtual void WarningBell() = 0;
virtual bool GetLineFeedMode() const = 0;
virtual void SetWindowTitle(const std::wstring_view title) = 0;
virtual void UseAlternateScreenBuffer() = 0;
virtual void UseMainScreenBuffer() = 0;
Expand All @@ -64,8 +70,6 @@ namespace Microsoft::Console::VirtualTerminal
virtual void SetConsoleOutputCP(const unsigned int codepage) = 0;
virtual unsigned int GetConsoleOutputCP() const = 0;

virtual void SetBracketedPasteMode(const bool enabled) = 0;
virtual bool GetBracketedPasteMode() const = 0;
virtual void CopyToClipboard(const std::wstring_view content) = 0;
virtual void SetTaskbarProgress(const DispatchTypes::TaskbarState state, const size_t progress) = 0;
virtual void SetWorkingDirectory(const std::wstring_view uri) = 0;
Expand Down
Loading