Skip to content

Commit

Permalink
Use console pages (DECCRA) to preserve content, not supported by Read…
Browse files Browse the repository at this point in the history
…ConsoleOutput

See microsoft/terminal#10810 for details
  • Loading branch information
alabuzhev committed Jul 18, 2024
1 parent 51b108f commit 7374303
Show file tree
Hide file tree
Showing 16 changed files with 148 additions and 120 deletions.
7 changes: 4 additions & 3 deletions far/cmdline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1046,9 +1046,10 @@ void CommandLine::ExecString(execute_info& Info)
ExecutionContext->DrawCommand(Info.DisplayCommand.empty()? Info.Command : Info.DisplayCommand);

ExecutionContext->DoPrologue();
ExecutionContext->Consolise();

if (DoConsolise)
ExecutionContext->Consolise();
if (Info.Echo)
std::wcout << std::endl;
};

if (Info.Command.empty())
Expand Down Expand Up @@ -1286,7 +1287,7 @@ bool CommandLine::ProcessOSCommands(string_view const CmdLine, function_ref<void
ConsoleActivatior(false);

Text(ChcpParams);
ScrollScreen(1);

return true;
}

Expand Down
2 changes: 2 additions & 0 deletions far/colormix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ namespace colors

auto Result = Bottom;

flags::clear(Result.Flags, FCF_FOREIGN);

const auto merge_part = [&](COLORREF FarColor::*ColorAccessor, const FARCOLORFLAGS Flag)
{
const auto TopValue = std::invoke(ColorAccessor, Top);
Expand Down
81 changes: 79 additions & 2 deletions far/console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1637,6 +1637,32 @@ namespace console_detail
// Save cursor position
Str = ANSISYSSC L""sv;

std::vector<rectangle> ForeignBlocks;
std::optional<rectangle> ForeignBlock;

const auto queue_block = [&]
{
if (!ForeignBlock)
return;

for (auto& Block: ForeignBlocks)
{
if (
Block.left == ForeignBlock->left &&
Block.right == ForeignBlock->right &&
Block.bottom == ForeignBlock->top - 1
)
{
Block.bottom = ForeignBlock->bottom;
ForeignBlock.reset();
return;
}
}

ForeignBlocks.emplace_back(*ForeignBlock);
ForeignBlock.reset();
};

for (const auto i: std::views::iota(SubRect.top + SubrectOffset, std::min(SubRect.top + SubrectOffset + ViewportSize.y, SubRect.bottom + 1)))
{
if (i != SubRect.top + SubrectOffset)
Expand All @@ -1653,7 +1679,8 @@ namespace console_detail
LastColor = colors::default_color();
}

make_vt_sequence(Buffer[i].subspan(SubRect.left, SubRect.width()), Str, LastColor);
const auto BlockRow = Buffer[i].subspan(SubRect.left, SubRect.width());
make_vt_sequence(BlockRow, Str, LastColor);

if (SubRect.right == ScrX && i != ScrY)
{
Expand All @@ -1663,13 +1690,40 @@ namespace console_detail
// Surprisingly, it also fixes terminal#15153.
Str += L'\n';
}

for (const auto& Cell: BlockRow)
{
const auto CellIndex = &Cell - BlockRow.data();

if (
Cell.Attributes.Flags & FCF_FOREIGN &&
colors::is_transparent(Cell.Attributes.ForegroundColor) &&
colors::is_transparent(Cell.Attributes.BackgroundColor)
)
{
if (!ForeignBlock)
ForeignBlock.emplace(SubRect.left + CellIndex, i, SubRect.left + CellIndex, i);
else
++ForeignBlock->right;

continue;
}

queue_block();
}

queue_block();
}

queue_block();

if (!::console.Write(Str))
return false;

Str.clear();
for (const auto& Block: ForeignBlocks)
::console.unstash_output(Block);

Str.clear();
}

return ::console.Write(CSI L"m"sv);
Expand Down Expand Up @@ -2661,6 +2715,29 @@ namespace console_detail
send_vt_command(far::format(OSC(L"9;4;{};{}"), state_to_vt(State), Percent));
}

// I'd prefer a more obscure number, but looks like only 1-6 are supported
#define SERVICE_PAGE_NUMBER "3"

void console::stash_output() const
{
send_vt_command(CSI L";;;;1;;;" SERVICE_PAGE_NUMBER "$v"sv);
}

void console::unstash_output(rectangle const Coordinates) const
{
send_vt_command(far::format(
CSI L"{};{};{};{};" SERVICE_PAGE_NUMBER ";{};{};1$v"sv,
1 + Coordinates.top,
1 + Coordinates.left,
1 + Coordinates.bottom,
1 + Coordinates.right,
1 + Coordinates.top,
1 + Coordinates.left
));
}

#undef SERVICE_PAGE_NUMBER

bool console::GetCursorRealPosition(point& Position) const
{
CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
Expand Down
3 changes: 3 additions & 0 deletions far/console.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ namespace console_detail
void set_progress_state(TBPFLAG State) const;
void set_progress_value(TBPFLAG State, size_t Percent) const;

void stash_output() const;
void unstash_output(rectangle Coordinates) const;

[[nodiscard]]
short GetDelta() const;

Expand Down
14 changes: 6 additions & 8 deletions far/console_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,8 @@ class context final: noncopyable, public i_context
void DrawCommand(string_view const Command) override
{
Global->CtrlObject->CmdLine()->DrawFakeCommand(Command);
ScrollScreen(1);

m_Command = Command;
m_ShowCommand = true;
}

void Consolise(bool SetTextColour) override
Expand Down Expand Up @@ -155,7 +153,8 @@ class context final: noncopyable, public i_context

if (Scroll && DoWeReallyHaveToScroll(Global->Opt->ShowKeyBar? 3 : 2))
{
ScrollScreen(1);
std::wcout << std::endl;
Global->ScrBuf->FillBuf();
}

console.ResetViewportPosition();
Expand All @@ -173,7 +172,6 @@ class context final: noncopyable, public i_context

private:
string m_Command;
bool m_ShowCommand{};
bool m_Activated{};
bool m_Finalised{};
bool m_Consolised{};
Expand Down Expand Up @@ -210,13 +208,13 @@ void console_session::LeavePluginContext(bool Scroll)
// FCTL_SETUSERSCREEN without corresponding FCTL_GETUSERSCREEN
// Old (1.x) behaviour emulation:
if (Global->Opt->ShowKeyBar)
{
std::wcout << L'\n';

if (Scroll)
std::wcout << L'\n';
}

std::wcout.flush();
Global->ScrBuf->FillBuf();
if (Scroll)
ScrollScreen(1);
Global->WindowManager->Desktop()->TakeSnapshot();
}

Expand Down
30 changes: 0 additions & 30 deletions far/ctrlobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

ControlObject::ControlObject()
{
SetColor(COL_COMMANDLINEUSERSCREEN);
GotoXY(0, ScrY - 3);
ShowVersion(false);
GotoXY(0, ScrY - 2);
MoveCursor({ 0, ScrY - 1 });

Global->WindowManager->InitDesktop();

filters::InitFilters();
Expand Down Expand Up @@ -144,30 +138,6 @@ void ControlObject::close()
Plugins->UnloadPlugins();
}


void ControlObject::ShowVersion(bool const Direct)
{
if (Direct)
{
std::wcout << build::version_string() << L'\n' << build::copyright() << L'\n' << std::endl;
return;
}

point Size;
console.GetSize(Size);
point CursorPosition;
console.GetCursorPosition(CursorPosition);
const auto FreeSpace = Size.y - CursorPosition.y - 1;

if (FreeSpace < 5 && DoWeReallyHaveToScroll(5))
ScrollScreen(5-FreeSpace);

GotoXY(0,ScrY-4);
Text(build::version_string());
GotoXY(0,ScrY-3);
Text(build::copyright());
}

FilePanels* ControlObject::Cp() const
{
return FPanels.get();
Expand Down
1 change: 0 additions & 1 deletion far/ctrlobj.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ class ControlObject: noncopyable
FilePanels *Cp() const;
window_ptr Panels() const;
void CreateDummyFilePanels();
static void ShowVersion(bool Direct = true);

KeyMacro Macro;
std::unique_ptr<highlight::configuration> HiFiles;
Expand Down
1 change: 1 addition & 0 deletions far/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ static void detach(point const& ConsoleSize, rectangle const& ConsoleWindowRect)
console.Allocate();

InitConsole();
Global->ScrBuf->FillBuf();

console.SetSize(ConsoleSize);
console.SetWindowRect(ConsoleWindowRect);
Expand Down
36 changes: 15 additions & 21 deletions far/far.natvis
Original file line number Diff line number Diff line change
Expand Up @@ -87,34 +87,28 @@
</Type>

<Type Name="array_ptr&lt;*,*&gt;">
<Intrinsic Name="data" Expression="_Mydata" />
<Intrinsic Name="size" Expression="_Mysize" />
<Intrinsic Name="empty" Expression="!size()"/>
<Intrinsic Name="dynamic" Expression="size() &gt; StaticSize"/>
<DisplayString Condition="empty()">empty</DisplayString>
<DisplayString Condition="!empty()">size={size()}, dynamic={dynamic()}</DisplayString>
<Intrinsic Name="index" Expression="m_Buffer.index()" />
<Expand>
<Item Name="[size]">size()</Item>
<Item Name="[dynamic]">dynamic()</Item>
<ArrayItems Condition="!empty()">
<Size>size()</Size>
<ValuePointer>data()</ValuePointer>
</ArrayItems>
<Item Name="[data]" Condition="index() == 0">m_Buffer._Head</Item>
<Item Name="[data]" Condition="index() == 1">m_Buffer._Tail._Head</Item>
<Synthetic Name="[type]">
<DisplayString Condition="index() == 0">static</DisplayString>
<DisplayString Condition="index() == 1">dynamic</DisplayString>
</Synthetic>
<Item Name="[size]">m_Size</Item>
</Expand>
</Type>

<Type Name="block_ptr&lt;*,*&gt;">
<Intrinsic Name="data" Expression="_Mydata" />
<Intrinsic Name="size" Expression="_Mysize" />
<Intrinsic Name="empty" Expression="!size()"/>
<Intrinsic Name="index" Expression="m_Buffer.index()" />
<Expand>
<Synthetic Name="[Buffer]">
<DisplayString>{(array_ptr&lt;char,$T2&gt;&amp;)*this}</DisplayString>
<Expand>
<ExpandedItem>(array_ptr&lt;char,$T2&gt;&amp;)*this</ExpandedItem>
</Expand>
<Item Name="[data]" Condition="index() == 0">*($T1*)m_Buffer._Head._Elems</Item>
<Item Name="[data]" Condition="index() == 1">*($T1*)m_Buffer._Tail._Head._Mypair._Myval2</Item>
<Synthetic Name="[type]">
<DisplayString Condition="index() == 0">static</DisplayString>
<DisplayString Condition="index() == 1">dynamic</DisplayString>
</Synthetic>
<ExpandedItem Condition="!empty()">($T1*)data()</ExpandedItem>
<Item Name="[size]">m_Size</Item>
</Expand>
</Type>

Expand Down
1 change: 1 addition & 0 deletions far/grabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ void Grabber::DisplayObject()
colors::make_invert(Destination.ForegroundColor, Destination.IsFgIndex());
colors::make_invert(Destination.BackgroundColor, Destination.IsBgIndex());
colors::make_invert(Destination.UnderlineColor, Destination.IsUnderlineIndex());
flags::clear(Destination.Flags, FCF_FOREIGN);
}
}

Expand Down
7 changes: 0 additions & 7 deletions far/interf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,6 @@ void InitConsole()
SetPalette();

UpdateScreenSize();
Global->ScrBuf->FillBuf();

consoleicons::instance().update_icon();
}
Expand Down Expand Up @@ -1197,12 +1196,6 @@ const FarColor& GetColor()
return CurColor;
}


void ScrollScreen(int Count)
{
Global->ScrBuf->Scroll(Count);
}

bool DoWeReallyHaveToScroll(short Rows)
{
/*
Expand Down
1 change: 0 additions & 1 deletion far/interf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ void ShowCursor();
void SetInitialCursorType();
void GetCursorType(bool& Visible, size_t& Size);
void MoveRealCursor(int X,int Y);
void ScrollScreen(int Count);
bool DoWeReallyHaveToScroll(short Rows);

struct position_parser_state
Expand Down
25 changes: 24 additions & 1 deletion far/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,26 @@ static bool is_arg(string_view const Str)
return !Str.empty() && any_of(Str.front(), L'-', L'/');
}

static void ShowVersion(bool const Direct)
{
bool EnoughSpace{};

if (!Direct)
{
// Version, copyright, empty line, command line, keybar
if (const auto SpaceNeeded = 5; !DoWeReallyHaveToScroll(SpaceNeeded))
{
EnoughSpace = true;
console.SetCursorPosition({ 0, ScrY - (SpaceNeeded - 1) });
}
}

std::wcout <<
build::version_string() << L'\n' <<
build::copyright() << L"\n\n"sv.substr(Direct || EnoughSpace? 1 : 0) <<
std::endl;
}

static std::optional<int> ProcessServiceModes(std::span<const wchar_t* const> const Args)
{
const auto isArg = [&](string_view const Name)
Expand Down Expand Up @@ -456,7 +476,7 @@ static std::optional<int> ProcessServiceModes(std::span<const wchar_t* const> co

if (Args.size() == 1 && (isArg(L"?") || isArg(L"h")))
{
ControlObject::ShowVersion();
ShowVersion(true);
show_help();
return EXIT_SUCCESS;
}
Expand Down Expand Up @@ -887,6 +907,9 @@ static int mainImpl(std::span<const wchar_t* const> const Args)
}

InitConsole();
Global->ScrBuf->FillBuf();
ShowVersion(false);
Global->ScrBuf->FillBuf();

SCOPE_EXIT
{
Expand Down
Loading

0 comments on commit 7374303

Please sign in to comment.