184919fb24
Related work items: MSFT-32957145 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev bdb25dc99dcb2f1ee483dffe883d0178ea9d18dc
337 lines
12 KiB
C++
337 lines
12 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft Corporation.
|
|
Licensed under the MIT license.
|
|
|
|
Module Name:
|
|
- CommonState.hpp
|
|
|
|
Abstract:
|
|
- This represents common boilerplate state setup required for unit tests to run
|
|
|
|
Author(s):
|
|
- Michael Niksa (miniksa) 18-Jun-2014
|
|
- Paul Campbell (paulcam) 18-Jun-2014
|
|
|
|
Revision History:
|
|
- Transformed to header-only class so it can be included by multiple
|
|
unit testing projects in the codebase without a bunch of overhead.
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
#define VERIFY_SUCCESS_NTSTATUS(x) VERIFY_IS_TRUE(NT_SUCCESS(x))
|
|
|
|
#include "../host/globals.h"
|
|
#include "../host/inputReadHandleData.h"
|
|
#include "../buffer/out/CharRow.hpp"
|
|
#include "../interactivity/inc/ServiceLocator.hpp"
|
|
|
|
class CommonState
|
|
{
|
|
public:
|
|
static const SHORT s_csWindowWidth = 80;
|
|
static const SHORT s_csWindowHeight = 80;
|
|
static const SHORT s_csBufferWidth = 80;
|
|
static const SHORT s_csBufferHeight = 300;
|
|
|
|
CommonState() :
|
|
m_heap(GetProcessHeap()),
|
|
m_hrTextBufferInfo(E_FAIL),
|
|
m_pFontInfo(nullptr),
|
|
m_backupTextBufferInfo(),
|
|
m_readHandle(nullptr)
|
|
{
|
|
}
|
|
|
|
~CommonState()
|
|
{
|
|
m_heap = nullptr;
|
|
}
|
|
|
|
void InitEvents()
|
|
{
|
|
Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().hInputEvent.create(wil::EventOptions::ManualReset);
|
|
}
|
|
|
|
void PrepareReadHandle()
|
|
{
|
|
m_readHandle = std::make_unique<INPUT_READ_HANDLE_DATA>();
|
|
}
|
|
|
|
void CleanupReadHandle()
|
|
{
|
|
m_readHandle.reset(nullptr);
|
|
}
|
|
|
|
void PrepareGlobalFont()
|
|
{
|
|
COORD coordFontSize;
|
|
coordFontSize.X = 8;
|
|
coordFontSize.Y = 12;
|
|
m_pFontInfo = new FontInfo(L"Consolas", 0, 0, coordFontSize, 0);
|
|
}
|
|
|
|
void CleanupGlobalFont()
|
|
{
|
|
if (m_pFontInfo != nullptr)
|
|
{
|
|
delete m_pFontInfo;
|
|
}
|
|
}
|
|
|
|
void PrepareGlobalScreenBuffer(const short viewWidth = s_csWindowWidth,
|
|
const short viewHeight = s_csWindowHeight,
|
|
const short bufferWidth = s_csBufferWidth,
|
|
const short bufferHeight = s_csBufferHeight)
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
COORD coordWindowSize;
|
|
coordWindowSize.X = viewWidth;
|
|
coordWindowSize.Y = viewHeight;
|
|
|
|
COORD coordScreenBufferSize;
|
|
coordScreenBufferSize.X = bufferWidth;
|
|
coordScreenBufferSize.Y = bufferHeight;
|
|
|
|
UINT uiCursorSize = 12;
|
|
|
|
THROW_IF_FAILED(SCREEN_INFORMATION::CreateInstance(coordWindowSize,
|
|
*m_pFontInfo,
|
|
coordScreenBufferSize,
|
|
TextAttribute{},
|
|
TextAttribute{ FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED },
|
|
uiCursorSize,
|
|
&gci.pCurrentScreenBuffer));
|
|
}
|
|
|
|
void CleanupGlobalScreenBuffer()
|
|
{
|
|
const CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
delete gci.pCurrentScreenBuffer;
|
|
}
|
|
|
|
void PrepareGlobalInputBuffer()
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
gci.pInputBuffer = new InputBuffer();
|
|
}
|
|
|
|
void CleanupGlobalInputBuffer()
|
|
{
|
|
const CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
delete gci.pInputBuffer;
|
|
}
|
|
|
|
void PrepareCookedReadData(const std::string_view initialData = {})
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
auto* readData = new COOKED_READ_DATA(gci.pInputBuffer,
|
|
m_readHandle.get(),
|
|
gci.GetActiveOutputBuffer(),
|
|
0,
|
|
nullptr,
|
|
0,
|
|
L"",
|
|
initialData,
|
|
nullptr);
|
|
gci.SetCookedReadData(readData);
|
|
}
|
|
|
|
void CleanupCookedReadData()
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
delete &gci.CookedReadData();
|
|
gci.SetCookedReadData(nullptr);
|
|
}
|
|
|
|
void PrepareNewTextBufferInfo(const bool useDefaultAttributes = false,
|
|
const short bufferWidth = s_csBufferWidth,
|
|
const short bufferHeight = s_csBufferHeight)
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
COORD coordScreenBufferSize;
|
|
coordScreenBufferSize.X = bufferWidth;
|
|
coordScreenBufferSize.Y = bufferHeight;
|
|
|
|
UINT uiCursorSize = 12;
|
|
|
|
auto initialAttributes = useDefaultAttributes ? TextAttribute{} :
|
|
TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY };
|
|
|
|
m_backupTextBufferInfo.swap(gci.pCurrentScreenBuffer->_textBuffer);
|
|
try
|
|
{
|
|
std::unique_ptr<TextBuffer> textBuffer = std::make_unique<TextBuffer>(coordScreenBufferSize,
|
|
initialAttributes,
|
|
uiCursorSize,
|
|
gci.pCurrentScreenBuffer->GetRenderTarget());
|
|
if (textBuffer.get() == nullptr)
|
|
{
|
|
m_hrTextBufferInfo = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
m_hrTextBufferInfo = S_OK;
|
|
}
|
|
gci.pCurrentScreenBuffer->_textBuffer.swap(textBuffer);
|
|
}
|
|
catch (...)
|
|
{
|
|
m_hrTextBufferInfo = wil::ResultFromCaughtException();
|
|
}
|
|
}
|
|
|
|
void CleanupNewTextBufferInfo()
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
VERIFY_IS_TRUE(gci.HasActiveOutputBuffer());
|
|
|
|
gci.pCurrentScreenBuffer->_textBuffer.swap(m_backupTextBufferInfo);
|
|
}
|
|
|
|
void FillTextBuffer()
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
// fill with some assorted text that doesn't consume the whole row
|
|
const SHORT cRowsToFill = 4;
|
|
|
|
VERIFY_IS_TRUE(gci.HasActiveOutputBuffer());
|
|
|
|
TextBuffer& textBuffer = gci.GetActiveOutputBuffer().GetTextBuffer();
|
|
|
|
for (SHORT iRow = 0; iRow < cRowsToFill; iRow++)
|
|
{
|
|
ROW& row = textBuffer.GetRowByOffset(iRow);
|
|
FillRow(&row);
|
|
}
|
|
|
|
textBuffer.GetCursor().SetYPosition(cRowsToFill);
|
|
}
|
|
|
|
void FillTextBufferBisect()
|
|
{
|
|
CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
// fill with some text that fills the whole row and has bisecting double byte characters
|
|
const SHORT cRowsToFill = s_csBufferHeight;
|
|
|
|
VERIFY_IS_TRUE(gci.HasActiveOutputBuffer());
|
|
|
|
TextBuffer& textBuffer = gci.GetActiveOutputBuffer().GetTextBuffer();
|
|
|
|
for (SHORT iRow = 0; iRow < cRowsToFill; iRow++)
|
|
{
|
|
ROW& row = textBuffer.GetRowByOffset(iRow);
|
|
FillBisect(&row);
|
|
}
|
|
|
|
textBuffer.GetCursor().SetYPosition(cRowsToFill);
|
|
}
|
|
|
|
[[nodiscard]] HRESULT GetTextBufferInfoInitResult()
|
|
{
|
|
return m_hrTextBufferInfo;
|
|
}
|
|
|
|
private:
|
|
HANDLE m_heap;
|
|
HRESULT m_hrTextBufferInfo;
|
|
FontInfo* m_pFontInfo;
|
|
std::unique_ptr<TextBuffer> m_backupTextBufferInfo;
|
|
std::unique_ptr<INPUT_READ_HANDLE_DATA> m_readHandle;
|
|
|
|
void FillRow(ROW* pRow)
|
|
{
|
|
// fill a row
|
|
// 9 characters, 6 spaces. 15 total
|
|
// か = \x304b
|
|
// き = \x304d
|
|
const PCWSTR pwszText = L"AB"
|
|
L"\x304b\x304b"
|
|
L"C"
|
|
L"\x304d\x304d"
|
|
L"DE ";
|
|
const size_t length = wcslen(pwszText);
|
|
|
|
std::vector<DbcsAttribute> attrs(length, DbcsAttribute());
|
|
// set double-byte/double-width attributes
|
|
attrs[2].SetLeading();
|
|
attrs[3].SetTrailing();
|
|
attrs[5].SetLeading();
|
|
attrs[6].SetTrailing();
|
|
|
|
CharRow& charRow = pRow->GetCharRow();
|
|
OverwriteColumns(pwszText, pwszText + length, attrs.cbegin(), charRow.begin());
|
|
|
|
// set some colors
|
|
TextAttribute Attr = TextAttribute(0);
|
|
pRow->GetAttrRow().Reset(Attr);
|
|
// A = bright red on dark gray
|
|
// This string starts at index 0
|
|
Attr = TextAttribute(FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
|
|
pRow->GetAttrRow().SetAttrToEnd(0, Attr);
|
|
|
|
// BかC = dark gold on bright blue
|
|
// This string starts at index 1
|
|
Attr = TextAttribute(FOREGROUND_RED | FOREGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
|
|
pRow->GetAttrRow().SetAttrToEnd(1, Attr);
|
|
|
|
// き = bright white on dark purple
|
|
// This string starts at index 5
|
|
Attr = TextAttribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE);
|
|
pRow->GetAttrRow().SetAttrToEnd(5, Attr);
|
|
|
|
// DE = black on dark green
|
|
// This string starts at index 7
|
|
Attr = TextAttribute(BACKGROUND_GREEN);
|
|
pRow->GetAttrRow().SetAttrToEnd(7, Attr);
|
|
|
|
// odd rows forced a wrap
|
|
if (pRow->GetId() % 2 != 0)
|
|
{
|
|
pRow->SetWrapForced(true);
|
|
}
|
|
else
|
|
{
|
|
pRow->SetWrapForced(false);
|
|
}
|
|
}
|
|
|
|
void FillBisect(ROW* pRow)
|
|
{
|
|
const CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
// length 80 string of text with bisecting characters at the beginning and end.
|
|
// positions of き(\x304d) are at 0, 27-28, 39-40, 67-68, 79
|
|
auto pwszText =
|
|
L"\x304d"
|
|
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
L"\x304d\x304d"
|
|
L"0123456789"
|
|
L"\x304d\x304d"
|
|
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
L"\x304d\x304d"
|
|
L"0123456789"
|
|
L"\x304d";
|
|
const size_t length = wcslen(pwszText);
|
|
|
|
std::vector<DbcsAttribute> attrs(length, DbcsAttribute());
|
|
// set double-byte/double-width attributes
|
|
attrs[0].SetTrailing();
|
|
attrs[27].SetLeading();
|
|
attrs[28].SetTrailing();
|
|
attrs[39].SetLeading();
|
|
attrs[40].SetTrailing();
|
|
attrs[67].SetLeading();
|
|
attrs[68].SetTrailing();
|
|
attrs[79].SetLeading();
|
|
|
|
CharRow& charRow = pRow->GetCharRow();
|
|
OverwriteColumns(pwszText, pwszText + length, attrs.cbegin(), charRow.begin());
|
|
|
|
// everything gets default attributes
|
|
pRow->GetAttrRow().Reset(gci.GetActiveOutputBuffer().GetAttributes());
|
|
|
|
pRow->SetWrapForced(true);
|
|
}
|
|
};
|