bool console::ReadOutput(matrix<FAR_CHAR_INFO>& Buffer, COORD BufferCoord, const SMALL_RECT& ReadRegionRelative) const { if (ExternalConsole.Imports.pReadOutput) { const COORD SizeCoord = { static_cast<SHORT>(Buffer.width()), static_cast<SHORT>(Buffer.height()) }; auto ReadRegion = ReadRegionRelative; return ExternalConsole.Imports.pReadOutput(Buffer.data(), SizeCoord, BufferCoord, &ReadRegion) != FALSE; } const int Delta = sWindowMode? GetDelta() : 0; auto ReadRegion = ReadRegionRelative; ReadRegion.Top += Delta; ReadRegion.Bottom += Delta; const rectangle SubRect{ BufferCoord.X, BufferCoord.Y, BufferCoord.X + (ReadRegion.Right - ReadRegion.Left + 1) - 1, BufferCoord.Y + (ReadRegion.Bottom - ReadRegion.Top + 1) - 1 }; std::vector<CHAR_INFO> ConsoleBuffer(SubRect.width() * SubRect.height()); const COORD BufferSize{ static_cast<SHORT>(SubRect.width()), static_cast<SHORT>(SubRect.height()) }; if (BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO) > MAXSIZE) { const auto HeightStep = std::max(MAXSIZE / (BufferSize.X * sizeof(CHAR_INFO)), size_t(1)); const size_t Height = ReadRegion.Bottom - ReadRegion.Top + 1; for (size_t i = 0; i < Height; i += HeightStep) { auto PartialReadRegion = ReadRegion; PartialReadRegion.Top += static_cast<SHORT>(i); PartialReadRegion.Bottom = std::min(ReadRegion.Bottom, static_cast<SHORT>(PartialReadRegion.Top + HeightStep - 1)); const COORD PartialBufferSize{ BufferSize.X, static_cast<SHORT>(PartialReadRegion.Bottom - PartialReadRegion.Top + 1) }; if (!ReadOutputImpl(ConsoleBuffer.data() + i * PartialBufferSize.X, PartialBufferSize, PartialReadRegion)) return false; } } else { auto ReadRegionCopy = ReadRegion; if (!ReadOutputImpl(ConsoleBuffer.data(), BufferSize, ReadRegionCopy)) return false; } auto ConsoleBufferIterator = ConsoleBuffer.cbegin(); for_submatrix(Buffer, SubRect, [&](FAR_CHAR_INFO& i) { const auto& Cell = *ConsoleBufferIterator++; i = { Cell.Char.UnicodeChar, colors::ConsoleColorToFarColor(Cell.Attributes) }; }); return true; }
virtual bool ReadOutput(matrix<FAR_CHAR_INFO>& Buffer, COORD BufferCoord, SMALL_RECT& ReadRegion) const override { bool Result=false; int Delta=Global->Opt->WindowMode?GetDelta():0; ReadRegion.Top+=Delta; ReadRegion.Bottom+=Delta; COORD BufferSize = { static_cast<SHORT>(Buffer.width()), static_cast<SHORT>(Buffer.height()) }; // skip unused region const size_t Offset = BufferCoord.Y * BufferSize.X; matrix<CHAR_INFO> ConsoleBuffer(BufferSize.Y - BufferCoord.Y, BufferSize.X); BufferSize.Y-=BufferCoord.Y; BufferCoord.Y=0; if(BufferSize.X*BufferSize.Y*sizeof(CHAR_INFO)>MAXSIZE) { auto SavedY = BufferSize.Y; BufferSize.Y = std::max(static_cast<int>(MAXSIZE/(BufferSize.X*sizeof(CHAR_INFO))),1); size_t Height = ReadRegion.Bottom - ReadRegion.Top + 1; int Start=ReadRegion.Top; SMALL_RECT SavedReadRegion=ReadRegion; for(size_t i = 0; i < Height; i += BufferSize.Y) { ReadRegion=SavedReadRegion; ReadRegion.Top = static_cast<SHORT>(Start+i); Result = ReadConsoleOutput(GetOutputHandle(), ConsoleBuffer[i].data(), BufferSize, BufferCoord, &ReadRegion) != FALSE; } BufferSize.Y = SavedY; } else { Result=ReadConsoleOutput(GetOutputHandle(), ConsoleBuffer.data(), BufferSize, BufferCoord, &ReadRegion)!=FALSE; } auto& ConsoleBufferVector = ConsoleBuffer.vector(); std::transform(ConsoleBufferVector.cbegin(), ConsoleBufferVector.cend(), Buffer.data() + Offset, [](CONST_REFERENCE(ConsoleBufferVector) i) { return FAR_CHAR_INFO::make(i.Char.UnicodeChar, colors::ConsoleColorToFarColor(i.Attributes)); });