Esempio n. 1
0
void TestSetConsoleCursorPositionImpl(WORD wCursorX, WORD wCursorY, BOOL bExpectedResult)
{
    COORD coordCursor;
    coordCursor.X = wCursorX;
    coordCursor.Y = wCursorY;

    // Get initial position data
    CONSOLE_SCREEN_BUFFER_INFOEX sbiInitial = { 0 };
    sbiInitial.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
    BOOL bResult = GetConsoleScreenBufferInfoEx(Common::_hConsole, &sbiInitial);
    VERIFY_WIN32_BOOL_SUCCEEDED(bResult, L"Get the initial buffer data.");

    // Attempt to set cursor into valid area
    bResult = SetConsoleCursorPosition(Common::_hConsole, coordCursor);
    VERIFY_ARE_EQUAL(bResult, bExpectedResult, L"Ensure that return from SET matches success/failure state we were expecting.");

    CONSOLE_SCREEN_BUFFER_INFOEX sbiTest = { 0 };
    sbiTest.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
    bResult = GetConsoleScreenBufferInfoEx(Common::_hConsole, &sbiTest);
    VERIFY_WIN32_BOOL_SUCCEEDED(bResult, L"GET the values back to ensure they were set properly.");

    // Cursor is where it was set to if we were supposed to be successful
    if (bExpectedResult)
    {
        VERIFY_ARE_EQUAL(coordCursor, sbiTest.dwCursorPosition, L"If SET was TRUE, we expect the cursor to be where we SET it.");
    }
    else
    {
        // otherwise, it's at where it was before
        VERIFY_ARE_EQUAL(sbiInitial.dwCursorPosition, sbiTest.dwCursorPosition, L"If SET was FALSE, we expect the cursor to not have moved.");
    }

    // Verify the viewport.
    bool fViewportMoveExpected = false;

    // If we expected the cursor to be set successfully, the viewport might have moved.
    if (bExpectedResult)
    {
        // If the position we set was outside the initial rectangle, then the viewport should have moved.
        if (coordCursor.X > sbiInitial.srWindow.Right ||
            coordCursor.X < sbiInitial.srWindow.Left ||
            coordCursor.Y > sbiInitial.srWindow.Bottom ||
            coordCursor.Y < sbiInitial.srWindow.Top)
        {
            fViewportMoveExpected = true;
        }
    }

    if (fViewportMoveExpected)
    {
        // Something had to have changed in the viewport
        VERIFY_ARE_NOT_EQUAL(sbiInitial.srWindow, sbiTest.srWindow, L"The viewports must have changed if we set the cursor outside the current area.");
    }
    else
    {
        VERIFY_ARE_EQUAL(sbiInitial.srWindow, sbiTest.srWindow, L"The viewports must remain the same if the cursor was set inside the existing one.");
    }
}
Esempio n. 2
0
void FileTests::TestWriteFileWrapEOL()
{
    bool fFlagOn;
    VERIFY_SUCCEEDED(TestData::TryGetValue(L"fFlagOn", fFlagOn));

    HANDLE const hOut = GetStdOutputHandle();
    VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle.");

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 };
    csbiexOriginal.cbSize = sizeof(csbiexOriginal);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test.");

    if (fFlagOn)
    {
        VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT), L"Set wrap at EOL.");
    }
    else
    {
        VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, 0), L"Make sure wrap at EOL is off.");
    }

    COORD const coordZero = { 0 };
    VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer.");

    // Fill first row of the buffer with Z characters until 1 away from the end.
    for (SHORT i = 0; i < csbiexOriginal.dwSize.X - 1; i++)
    {
        WriteFile(hOut, "Z", 1, nullptr, nullptr);
    }

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 };
    csbiexBefore.cbSize = sizeof(csbiexBefore);
    CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 };
    csbiexAfter.cbSize = sizeof(csbiexAfter);
    COORD coordExpected = { 0 };

    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexBefore), L"Get cursor position information before attempting to wrap at end of line.");
    VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, "Y", 1, nullptr, nullptr), L"Write of final character in line succeeded.");
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexAfter), L"Get cursor position information after attempting to wrap at end of line.");

    if (fFlagOn)
    {
        Log::Comment(L"Cursor should go down a row if we tried to print at end of line.");
        coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.Y++;
        coordExpected.X = 0;
    }
    else
    {
        Log::Comment(L"Cursor shouldn't move when printing at end of line.");
        coordExpected = csbiexBefore.dwCursorPosition;
    }

    VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved as expected based on flag state.");
}
Esempio n. 3
0
void FileTests::TestWriteFileSuspended()
{
    HANDLE const hOut = GetStdOutputHandle();
    VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle.");

    HANDLE const hIn = GetStdInputHandle();
    VERIFY_IS_NOT_NULL(hIn, L"Verify we have the standard input handle.");

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 };
    csbiexOriginal.cbSize = sizeof(csbiexOriginal);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test.");

    DWORD dwMode = 0;
    VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, dwMode), L"Set console mode for test.");

    COORD const coordZero = { 0 };
    VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer.");

    VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, "abc", 3, nullptr, nullptr), L"Test first write success.");
    PauseHelper(hIn);

    auto BlockedWrite = std::async([&] {
        Log::Comment(L"Background WriteFile scheduled.");
        VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, "def", 3, nullptr, nullptr), L"Test second write success.");
    });

    UnpauseHelper(hIn);

    BlockedWrite.wait();
}
Esempio n. 4
0
void WriteFileHelper(HANDLE hOut,
                     CONSOLE_SCREEN_BUFFER_INFOEX& csbiexBefore,
                     CONSOLE_SCREEN_BUFFER_INFOEX& csbiexAfter,
                     PCSTR psTest,
                     DWORD cchTest)
{
    csbiexBefore.cbSize = sizeof(csbiexBefore);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexBefore), L"Retrieve screen buffer properties before writing.");

    DWORD dwWritten = 0;
    VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, psTest, cchTest, &dwWritten, nullptr), L"Write text into buffer using WriteFile");
    VERIFY_ARE_EQUAL(cchTest, dwWritten, L"Verify all characters were written.");

    csbiexAfter.cbSize = sizeof(csbiexAfter);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexAfter), L"Retrieve screen buffer properties after writing.");
}
Esempio n. 5
0
void FileTests::TestWriteFileRaw()
{
    // \x7 is bell
    // \x8 is backspace
    // \x9 is tab
    // \xa is linefeed
    // \xd is carriage return
    // All should be ignored/printed in raw mode.
    PCSTR strTest = "z\x7y\x8z\x9y\xaz\xdy";
    DWORD const cchTest = (DWORD)strlen(strTest);
    String strReadBackExpected(strTest);

    HANDLE const hOut = GetStdOutputHandle();
    VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle.");

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 };
    csbiexBefore.cbSize = sizeof(csbiexBefore);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexBefore), L"Retrieve screen buffer properties before writing.");

    VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, 0), L"Set raw write mode.");

    COORD const coordZero = { 0 };
    VERIFY_ARE_EQUAL(coordZero, csbiexBefore.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer.");

    DWORD dwWritten = 0;
    VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, strTest, cchTest, &dwWritten, nullptr), L"Write text into buffer using WriteFile");
    VERIFY_ARE_EQUAL(cchTest, dwWritten);

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 };
    csbiexAfter.cbSize = sizeof(csbiexAfter);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexAfter), L"Retrieve screen buffer properties after writing.");

    csbiexBefore.dwCursorPosition.X += (SHORT)cchTest;
    VERIFY_ARE_EQUAL(csbiexBefore.dwCursorPosition, csbiexAfter.dwCursorPosition, L"Verify cursor moved expected number of squares for the write length.");

    DWORD const cbReadBackBuffer = cchTest + 2; // +1 so we can read back a "space" that should be after what we wrote. +1 more so this can be null terminated for String class comparison.
    wistd::unique_ptr<char[]> strReadBack = wil::make_unique_failfast<char[]>(cbReadBackBuffer);
    ZeroMemory(strReadBack.get(), cbReadBackBuffer * sizeof(char));

    DWORD dwRead = 0;
    VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterA(hOut, strReadBack.get(), cchTest + 1, coordZero, &dwRead), L"Read back the data in the buffer.");
    // +1 to read back the space that should be after the text we wrote

    strReadBackExpected += " "; // add in the space that should appear after the written text (buffer should be space filled when empty)

    VERIFY_ARE_EQUAL(strReadBackExpected, String(strReadBack.get()), L"Ensure that the buffer contents match what we expected based on what we wrote.");
}
Esempio n. 6
0
void FileTests::TestWriteFileDisableNewlineAutoReturn()
{
    bool fDisableAutoReturn;
    VERIFY_SUCCEEDED(TestData::TryGetValue(L"fDisableAutoReturn", fDisableAutoReturn));

    bool fProcessedOn;
    VERIFY_SUCCEEDED(TestData::TryGetValue(L"fProcessedOn", fProcessedOn));

    HANDLE const hOut = GetStdOutputHandle();
    VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle.");

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 };
    csbiexOriginal.cbSize = sizeof(csbiexOriginal);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test.");

    DWORD dwMode = 0;
    WI_SetFlagIf(dwMode, DISABLE_NEWLINE_AUTO_RETURN, fDisableAutoReturn);
    WI_SetFlagIf(dwMode, ENABLE_PROCESSED_OUTPUT, fProcessedOn);
    VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, dwMode), L"Set console mode for test.");

    COORD const coordZero = { 0 };
    VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer.");

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 };
    csbiexBefore.cbSize = sizeof(csbiexBefore);
    CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 };
    csbiexAfter.cbSize = sizeof(csbiexAfter);
    COORD coordExpected = { 0 };

    WriteFileHelper(hOut, csbiexBefore, csbiexAfter, "abc", 3);
    coordExpected = csbiexBefore.dwCursorPosition;
    coordExpected.X += 3;
    VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Cursor should have moved right to the end of the text written.");

    WriteFileHelper(hOut, csbiexBefore, csbiexAfter, "\n", 1);

    if (fProcessedOn)
    {
        if (fDisableAutoReturn)
        {
            coordExpected = csbiexBefore.dwCursorPosition;
            coordExpected.Y += 1;
        }
        else
        {
            coordExpected = csbiexBefore.dwCursorPosition;
            coordExpected.Y += 1;
            coordExpected.X = 0;
        }
    }
    else
    {
        coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.X += 1;
    }

    VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Cursor should move to expected position.");
}
Esempio n. 7
0
void FileTests::TestWriteFileVTProcessing()
{
    bool fVtOn;
    VERIFY_SUCCEEDED(TestData::TryGetValue(L"fVtOn", fVtOn));

    bool fProcessedOn;
    VERIFY_SUCCEEDED(TestData::TryGetValue(L"fProcessedOn", fProcessedOn));

    HANDLE const hOut = GetStdOutputHandle();
    VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle.");

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 };
    csbiexOriginal.cbSize = sizeof(csbiexOriginal);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test.");

    DWORD dwFlags = 0;
    WI_SetFlagIf(dwFlags, ENABLE_VIRTUAL_TERMINAL_PROCESSING, fVtOn);
    WI_SetFlagIf(dwFlags, ENABLE_PROCESSED_OUTPUT, fProcessedOn);
    VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, dwFlags), L"Turn on relevant flags for test.");

    COORD const coordZero = { 0 };
    VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer.");

    PCSTR pszTestString = "\x1b" "[14m";
    DWORD const cchTest = (DWORD)strlen(pszTestString);

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 };
    csbiexBefore.cbSize = sizeof(csbiexBefore);
    CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 };
    csbiexAfter.cbSize = sizeof(csbiexAfter);

    WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTestString, cchTest);

    // We only expect characters to be processed and not printed if both processed mode and VT mode are on.
    bool const fProcessedNotPrinted = fProcessedOn && fVtOn;

    if (fProcessedNotPrinted)
    {
        PCSTR pszReadBackExpected = "      ";
        DWORD const cchReadBackExpected = (DWORD)strlen(pszReadBackExpected);

        VERIFY_ARE_EQUAL(csbiexBefore.dwCursorPosition, csbiexAfter.dwCursorPosition, L"Verify cursor didn't move because the VT sequence was processed instead of printed.");

        wistd::unique_ptr<char[]> pszReadBack;
        ReadBackHelper(hOut, coordZero, cchReadBackExpected, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify that nothing was printed into the buffer.");
    }
    else
    {
        COORD coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.X += (SHORT)cchTest;
        VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved as characters should have been emitted, not consumed.");

        wistd::unique_ptr<char[]> pszReadBack;
        ReadBackHelper(hOut, coordZero, cchTest, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszTestString), String(pszReadBack.get()), L"Verify that original test string was printed into the buffer.");
    }
}
Esempio n. 8
0
void CursorTests::TestSetConsoleCursorPosition()
{
    // Get initial buffer value for boundaries
    CONSOLE_SCREEN_BUFFER_INFOEX sbiInitial = { 0 };
    sbiInitial.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
    BOOL bResult = GetConsoleScreenBufferInfoEx(Common::_hConsole, &sbiInitial);
    VERIFY_WIN32_BOOL_SUCCEEDED(bResult, L"Retrieve the initial buffer information to calculate the boundaries for testing.");

    // Try several cases
    TestSetConsoleCursorPositionImpl(0, 0, TRUE); // Top left corner of buffer
    TestSetConsoleCursorPositionImpl(sbiInitial.dwSize.X - 1, sbiInitial.dwSize.Y - 1, TRUE); // Bottom right corner of buffer
    TestSetConsoleCursorPositionImpl(sbiInitial.dwSize.X, sbiInitial.dwSize.Y, FALSE); // 1 beyond bottom right corner (the size is 1 larger than the array indicies)
    TestSetConsoleCursorPositionImpl(MAXWORD, MAXWORD, FALSE); // Max values
}
Esempio n. 9
0
	int ColorTableLookup(unsigned int ColorArgb)
	{
		if (m_ColorTable.IsEmpty())
		{
			CONSOLE_SCREEN_BUFFER_INFOEX ConsoleInfo;
			ConsoleInfo.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
			GetConsoleScreenBufferInfoEx(m_ConsoleHandle, &ConsoleInfo);

			for (int i = 0; i < 16; i++)
			{
				m_ColorTable.Add(Color::FromAbgr(ConsoleInfo.ColorTable[i]));
			}
		}

		Color TargetColor(ColorArgb);
		return TargetColor.FindClosestPaletteIndex(m_ColorTable);
	}
Esempio n. 10
0
JNIEXPORT void JNICALL Java_com_yifanlu_Josh_Josh_SETCONSOLESCREENBUFFERINFOEX
  (JNIEnv *env, jclass jcls, jlong pointer, jint sizeX, jint sizeY, jint cursorX, jint cursorY, jint attributes, jint windowLeft, jint windowTop, jint windowRight, jint windowBottom, jint maxX, jint maxY)
{
    HANDLE hConsole = pointerToHandle(pointer);

	COORD dwSize = {sizeX, sizeY};
	COORD dwCursorPosition = {cursorX, cursorY};
	WORD wAttributes = attributes;
	SMALL_RECT srWindow = {windowLeft, windowTop, windowRight, windowBottom};
	COORD dwMaximumWindowSize = {maxX, maxY};

	CONSOLE_SCREEN_BUFFER_INFOEX bufferInfo;
	GetConsoleScreenBufferInfoEx(hConsole, &bufferInfo);

	bufferInfo.dwSize = dwSize;
	bufferInfo.dwCursorPosition = dwCursorPosition;
	bufferInfo.wAttributes = wAttributes;
	bufferInfo.srWindow = srWindow;
	bufferInfo.dwMaximumWindowSize = dwMaximumWindowSize;

	SetConsoleScreenBufferInfoEx(hConsole, &bufferInfo);
}
Esempio n. 11
0
void FileTests::TestWriteFileProcessed()
{
    // \x7 is bell
    // \x8 is backspace
    // \x9 is tab
    // \xa is linefeed
    // \xd is carriage return
    // All should cause activity in processed mode.

    HANDLE const hOut = GetStdOutputHandle();
    VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle.");

    CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 };
    csbiexOriginal.cbSize = sizeof(csbiexOriginal);
    VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test.");

    VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, ENABLE_PROCESSED_OUTPUT), L"Set processed write mode.");

    COORD const coordZero = { 0 };
    VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer.");

    // Declare variables needed for each character test.
    CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 };
    CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 };
    COORD coordExpected = { 0 };
    PCSTR pszTest;
    DWORD cchTest;
    PCSTR pszReadBackExpected;
    DWORD cchReadBack;
    wistd::unique_ptr<char[]> pszReadBack;

    // 1. Test bell (\x7)
    {
        pszTest = "z\x7";
        cchTest = (DWORD)strlen(pszTest);
        pszReadBackExpected = "z ";
        cchReadBack = (DWORD)strlen(pszReadBackExpected);

        // Write z and a bell. Cursor should move once as bell should have made audible noise (can't really test) and not moved or printed anything.
        WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest);
        coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.X += 1;
        VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved once for printable character and not for bell.");

        // Read back written data.
        ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer.");
    }


    // 2. Test backspace (\x8)
    {
        pszTest = "yx\x8";
        cchTest = (DWORD)strlen(pszTest);
        pszReadBackExpected = "yx ";
        cchReadBack = (DWORD)strlen(pszReadBackExpected);

        // Write two characters and a backspace. Cursor should move only one forward as the backspace should have moved the cursor back one after printing the second character.
        // The backspace character itself is typically non-destructive so it should only affect the cursor, not the buffer contents.
        WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest);
        coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.X += 1;
        VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved twice forward for printable characters and once backward for backspace.");

        // Read back written data.
        ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer.");
    }

    // 3. Test tab (\x9)
    {
        // The tab character will space pad out the buffer to the next multiple-of-8 boundary.
        // NOTE: This is dependent on the previous tests running first.
        pszTest = "\x9";
        cchTest = (DWORD)strlen(pszTest);
        pszReadBackExpected = "     ";
        cchReadBack = (DWORD)strlen(pszReadBackExpected);

        // Write tab character. Cursor should move out to the next multiple-of-8 and leave space characters in its wake.
        WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest);
        coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.X = 8;
        VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved forward to position 8 for tab.");

        // Read back written data.
        ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer.");
    }

    // 4. Test linefeed (\xa)
    {
        // The line feed character should move us down to the next line.
        pszTest = "\xaQ";
        cchTest = (DWORD)strlen(pszTest);
        pszReadBackExpected = "Q ";
        cchReadBack = (DWORD)strlen(pszReadBackExpected);

        // Write line feed character. Cursor should move down a line and then the Q from our string should be printed.
        WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest);
        coordExpected.X = 1;
        coordExpected.Y = 1;
        VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved down a line and then one character over for linefeed + Q.");

        // Read back written data from the 2nd line.
        COORD coordRead;
        coordRead.Y = 1;
        coordRead.X = 0;
        ReadBackHelper(hOut, coordRead, cchReadBack, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer.");
    }

    // 5. Test carriage return (\xd)
    {
        // The carriage return character should move us to the front of the line.
        pszTest = "J\xd";
        cchTest = (DWORD)strlen(pszTest);
        pszReadBackExpected = "QJ "; // J written, then move to beginning of line.
        cchReadBack = (DWORD)strlen(pszReadBackExpected);

        // Write text and carriage return character. Cursor should end up at the beginning of this line. The J should have been printed in the line before we moved.
        WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest);
        coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.X = 0;
        VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved to beginning of line for carriage return character.");

        // Read back text written from the 2nd line.
        ReadBackHelper(hOut, csbiexAfter.dwCursorPosition, cchReadBack, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer.");
    }

    // 6. Print a character over the top of the existing
    {
        // After the carriage return, try typing on top of the Q with a K
        pszTest = "K";
        cchTest = (DWORD)strlen(pszTest);
        pszReadBackExpected = "KJ "; // NOTE: This is based on the previous test(s).
        cchReadBack = (DWORD)strlen(pszReadBackExpected);

        // Write text. Cursor should end up on top of the J.
        WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest);
        coordExpected = csbiexBefore.dwCursorPosition;
        coordExpected.X += 1;
        VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved over one for printing character.");

        // Read back text written from the 2nd line.
        ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack);
        VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer.");
    }
}
Esempio n. 12
0
void CnsMgr::Init()
{
	// get std handles
	h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
	if(h_stdout == INVALID_HANDLE_VALUE)
	{
		throw cyerr("failed to get stdout handle", 8002);
	}
	h_stdin = GetStdHandle(STD_INPUT_HANDLE);
	if(h_stdin == INVALID_HANDLE_VALUE)
	{
		throw cyerr("failed to get stdin handle", 8003);
	}
	
	// create mysb, set as active
	h_mysb = CreateConsoleScreenBuffer(
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		CONSOLE_TEXTMODE_BUFFER,
		NULL);
	if(h_mysb == INVALID_HANDLE_VALUE)
	{
		throw cyerr("failed to create screen buffer", 8004);
	}
	{ // cursor info
		CONSOLE_CURSOR_INFO cci;
		cci.dwSize = 1; // anything 1-100 because not visible anyway
		cci.bVisible = FALSE;
		if(!SetConsoleCursorInfo(h_mysb, &cci))
		{
			throw cyerr("failed to set screen buffer cursor info", 8005);
		}
	}
	{ // screen buffer/window size
		// set both at once
		CONSOLE_SCREEN_BUFFER_INFOEX new_csbi;
		new_csbi.cbSize = sizeof(new_csbi);
		if(!GetConsoleScreenBufferInfoEx(h_mysb, &new_csbi))
		{
			throw cyerr("failed to get screen buffer info", 8007);
		}
		if(new_csbi.dwMaximumWindowSize.X < WND_W || new_csbi.dwMaximumWindowSize.Y < WND_H)
		{
			throw cyerr("maximum window size too small", 8008);
		}
		new_csbi.dwSize = {WND_W, WND_H};
		new_csbi.dwCursorPosition = {0, 0};
		new_csbi.srWindow = {0, 0, WND_W-1, WND_H-1};
		new_csbi.wAttributes = 0;
		if(!SetConsoleScreenBufferInfoEx(h_mysb, &new_csbi))
		{
			throw cyerr("failed to set window/buffer size", 8006);
		}
	}
	if(!SetConsoleMode(h_mysb, NULL)) // no output processing
	{
		throw cyerr("failed to set console output mode", 8010);
	}
	if(!SetConsoleActiveScreenBuffer(h_mysb))
	{
		throw cyerr("failed to set active screen buffer", 8009);
	}
	
	// change settings of stdin
	if(!GetConsoleMode(h_stdin, &ori_stdin_mode))
	{
		SetConsoleActiveScreenBuffer(h_stdout);
		throw cyerr("failed to get stdin console mode", 8011);
	}
	if(!SetConsoleMode(h_stdin, ENABLE_EXTENDED_FLAGS | ENABLE_MOUSE_INPUT))
	{
		SetConsoleActiveScreenBuffer(h_stdout);
		throw cyerr("failed to set console input mode", 8012);
	}
	
	// try to change window title
	ori_title = new char[100];
	if(GetConsoleOriginalTitle(ori_title, 100))
	{
		if(!SetConsoleTitle("CCA"))
		{
			title_changed = false;
		}
		else
		{
			title_changed = true;
		}
	}
	else
	{
		title_changed = false;
	}
	
	// create (our) buffer
	buf = new CHAR_INFO[WND_W * WND_H];

	// done.
	initialized = true;
	
	// clear screen
	Fill(' ', 0); // black|black
	Flip();
}