Migrate OSS up to c53fe1c2b (A11y End Of Buffer)

This commit is contained in:
Dustin Howett 2021-11-09 13:26:44 -06:00
commit 86da0e041f
5 changed files with 154 additions and 213 deletions

View File

@ -539,7 +539,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
originP1L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 -1 times by Line",
GeneratedMovementTestInput{
@ -551,7 +551,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
originP1L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 0 times by Line",
GeneratedMovementTestInput{
@ -563,7 +563,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
originP1L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 1 times by Line",
GeneratedMovementTestInput{
@ -599,7 +599,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
-1,
origin,
origin },
true },
false },
GeneratedMovementTest{
L"Move degenerate range at position 2 -1 times by Line",
GeneratedMovementTestInput{
@ -611,7 +611,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
-1,
origin,
origin },
true },
false },
GeneratedMovementTest{
L"Move degenerate range at position 2 0 times by Line",
GeneratedMovementTestInput{
@ -659,7 +659,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
originP1L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 -1 times by Line",
GeneratedMovementTestInput{
@ -671,7 +671,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
originP1L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 0 times by Line",
GeneratedMovementTestInput{
@ -683,7 +683,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
originP1L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 1 times by Line",
GeneratedMovementTestInput{
@ -779,7 +779,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
-5,
midHistoryM5L,
midHistoryM4L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 -1 times by Line",
GeneratedMovementTestInput{
@ -791,7 +791,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
-1,
midHistoryM1L,
midHistoryLeft },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 0 times by Line",
GeneratedMovementTestInput{
@ -803,7 +803,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
midHistoryLeft,
midHistoryP1L },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 1 times by Line",
GeneratedMovementTestInput{
@ -873,9 +873,9 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
origin },
GeneratedMovementTestExpected{
1,
docEnd,
docEnd },
true },
endExclusive,
endExclusive },
false },
GeneratedMovementTest{
L"Move degenerate range at position 1 5 times by Document",
GeneratedMovementTestInput{
@ -885,9 +885,9 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
origin },
GeneratedMovementTestExpected{
1,
docEnd,
docEnd },
true },
endExclusive,
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 -5 times by Document",
GeneratedMovementTestInput{
@ -898,8 +898,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
docEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 -1 times by Document",
GeneratedMovementTestInput{
@ -910,8 +910,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
docEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 0 times by Document",
GeneratedMovementTestInput{
@ -922,8 +922,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
docEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 1 times by Document",
GeneratedMovementTestInput{
@ -934,8 +934,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
docEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 1 5 times by Document",
GeneratedMovementTestInput{
@ -946,8 +946,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
docEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move degenerate range at position 2 -5 times by Document",
GeneratedMovementTestInput{
@ -993,9 +993,9 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
midTop },
GeneratedMovementTestExpected{
1,
bufferEnd,
bufferEnd },
true },
endExclusive,
endExclusive },
false },
GeneratedMovementTest{
L"Move degenerate range at position 2 5 times by Document",
GeneratedMovementTestInput{
@ -1005,9 +1005,9 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
midTop },
GeneratedMovementTestExpected{
1,
bufferEnd,
bufferEnd },
true },
endExclusive,
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 -5 times by Document",
GeneratedMovementTestInput{
@ -1018,8 +1018,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
bufferEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 -1 times by Document",
GeneratedMovementTestInput{
@ -1030,8 +1030,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
bufferEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 0 times by Document",
GeneratedMovementTestInput{
@ -1042,8 +1042,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
bufferEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 1 times by Document",
GeneratedMovementTestInput{
@ -1054,8 +1054,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
bufferEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 2 5 times by Document",
GeneratedMovementTestInput{
@ -1066,8 +1066,8 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
GeneratedMovementTestExpected{
0,
origin,
bufferEnd },
true },
endExclusive },
false },
GeneratedMovementTest{
L"Move degenerate range at position 3 -5 times by Document",
GeneratedMovementTestInput{
@ -1115,7 +1115,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
1,
endExclusive,
endExclusive },
true },
false },
GeneratedMovementTest{
L"Move degenerate range at position 3 5 times by Document",
GeneratedMovementTestInput{
@ -1127,7 +1127,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
1,
endExclusive,
endExclusive },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 -5 times by Document",
GeneratedMovementTestInput{
@ -1139,7 +1139,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
endExclusive },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 -1 times by Document",
GeneratedMovementTestInput{
@ -1151,7 +1151,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
endExclusive },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 0 times by Document",
GeneratedMovementTestInput{
@ -1163,7 +1163,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
endExclusive },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 1 times by Document",
GeneratedMovementTestInput{
@ -1175,7 +1175,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
endExclusive },
true },
false },
GeneratedMovementTest{
L"Move non-degenerate range at position 3 5 times by Document",
GeneratedMovementTestInput{
@ -1187,7 +1187,7 @@ static constexpr std::array<GeneratedMovementTest, 255> s_movementTests{
0,
origin,
endExclusive },
true },
false },
GeneratedMovementTest{
L"Move degenerate range at position 8 -5 times by Character",
GeneratedMovementTestInput{

View File

@ -725,18 +725,6 @@ class UiaTextRangeTests
// clang-format off
const std::vector<MoveTest> testData
{
MoveTest{
L"can't move backward from (0, 0)",
{ 0, 0 },
{ 2, 0 },
-1,
{
0,
{0,0},
{2,0}
}
},
MoveTest{
L"can move backward within a row",
{ 1, 0 },
@ -761,18 +749,6 @@ class UiaTextRangeTests
}
},
MoveTest{
L"can't move past the last column in the last row",
{ lastColumnIndex, bottomRow },
{ lastColumnIndex, bottomRow },
5,
{
0,
{ lastColumnIndex, bottomRow },
{ lastColumnIndex, bottomRow },
}
},
MoveTest{
L"can move to a new row when necessary when moving forward",
{ lastColumnIndex, 0 },
@ -822,18 +798,6 @@ class UiaTextRangeTests
// clang-format off
const std::vector<MoveTest> testData
{
MoveTest{
L"can't move backward from top row",
{0, 0},
{0, lastColumnIndex},
-4,
{
0,
{0, 0},
{0, lastColumnIndex}
}
},
MoveTest{
L"can move forward from top row",
{0, 0},
@ -846,18 +810,6 @@ class UiaTextRangeTests
}
},
MoveTest{
L"can't move forward from bottom row",
{0, bottomRow},
{lastColumnIndex, bottomRow},
3,
{
0,
{0, bottomRow},
{lastColumnIndex, bottomRow},
}
},
MoveTest{
L"can move backward from bottom row",
{0, bottomRow},
@ -870,30 +822,6 @@ class UiaTextRangeTests
}
},
MoveTest{
L"can't move backward when part of the top row is in the range",
{5, 0},
{lastColumnIndex, 0},
-1,
{
0,
{5, 0},
{lastColumnIndex, 0},
}
},
MoveTest{
L"can't move forward when part of the bottom row is in the range",
{0, bottomRow},
{0, bottomRow},
1,
{
0,
{0, bottomRow},
{0, bottomRow}
}
},
MoveTest{
L"can move to a new row when necessary when moving forward",
{ lastColumnIndex, 0 },
@ -1332,9 +1260,14 @@ class UiaTextRangeTests
// the UTR should refuse to move past the end.
const auto lastLineStart{ bufferEndLeft };
const auto secondToLastLinePos{ point_offset_by_line(lastLineStart, bufferSize, -1) };
const auto secondToLastCharacterPos{ point_offset_by_char(bufferEnd, bufferSize, -1) };
const auto endInclusive{ bufferEnd };
// write "temp" at (2,2)
const til::point writeTarget{ 2, 2 };
_pTextBuffer->Write({ L"temp" }, writeTarget);
// Iterate over each TextUnit. If we don't support
// the given TextUnit, we're supposed to fallback
// to the last one that was defined anyways.
@ -1367,10 +1300,6 @@ class UiaTextRangeTests
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
VERIFY_ARE_EQUAL(0, moveAmt);
// write "temp" at (2,2)
const til::point writeTarget{ 2, 2 };
_pTextBuffer->Write({ L"temp" }, writeTarget);
// Verify expansion works properly
Log::Comment(NoThrowString().Format(L"Expand by %s", toString(textUnit)));
THROW_IF_FAILED(utr->ExpandToEnclosingUnit(textUnit));
@ -1408,7 +1337,6 @@ class UiaTextRangeTests
// Verify that moving backwards still works properly
Log::Comment(NoThrowString().Format(L"Backwards by %s", toString(textUnit)));
THROW_IF_FAILED(utr->Move(textUnit, -1, &moveAmt));
VERIFY_ARE_EQUAL(-1, moveAmt);
// NOTE: If the range is degenerate, _start == _end before AND after the move.
if (textUnit <= TextUnit::TextUnit_Character)
@ -1416,21 +1344,25 @@ class UiaTextRangeTests
// Special case: _end will always be endInclusive, because...
// - degenerate --> it moves with _start to stay degenerate
// - !degenerate --> it excludes the last char, to select the second to last char
VERIFY_ARE_EQUAL(-1, moveAmt);
VERIFY_ARE_EQUAL(degenerate ? endInclusive : secondToLastCharacterPos, til::point{ utr->_start });
VERIFY_ARE_EQUAL(endInclusive, til::point{ utr->_end });
}
else if (textUnit <= TextUnit::TextUnit_Word)
{
VERIFY_ARE_EQUAL(-1, moveAmt);
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
VERIFY_ARE_EQUAL(degenerate ? origin : writeTarget, til::point{ utr->_end });
}
else if (textUnit <= TextUnit::TextUnit_Line)
{
VERIFY_ARE_EQUAL(lastLineStart, til::point{ utr->_start });
VERIFY_ARE_EQUAL(degenerate ? lastLineStart : endExclusive, til::point{ utr->_end });
VERIFY_ARE_EQUAL(-1, moveAmt);
VERIFY_ARE_EQUAL(degenerate ? lastLineStart : secondToLastLinePos, til::point{ utr->_start });
VERIFY_ARE_EQUAL(lastLineStart, til::point{ utr->_end });
}
else // textUnit <= TextUnit::TextUnit_Document:
{
VERIFY_ARE_EQUAL(degenerate ? -1 : 0, moveAmt);
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
VERIFY_ARE_EQUAL(degenerate ? origin : endExclusive, til::point{ utr->_end });
}

View File

@ -1010,51 +1010,52 @@ try
{
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
*pRetVal = 0;
if (count == 0)
{
return S_OK;
}
_pData->LockConsole();
auto Unlock = wil::scope_exit([&]() noexcept {
_pData->UnlockConsole();
});
// We can abstract this movement by moving _start, but disallowing moving to the end of the buffer
constexpr auto endpoint = TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start;
constexpr auto preventBufferEnd = true;
const auto wasDegenerate = IsDegenerate();
if (unit == TextUnit::TextUnit_Character)
if (count != 0)
{
_moveEndpointByUnitCharacter(count, endpoint, pRetVal, preventBufferEnd);
}
else if (unit <= TextUnit::TextUnit_Word)
{
_moveEndpointByUnitWord(count, endpoint, pRetVal, preventBufferEnd);
}
else if (unit <= TextUnit::TextUnit_Line)
{
_moveEndpointByUnitLine(count, endpoint, pRetVal, preventBufferEnd);
}
else if (unit <= TextUnit::TextUnit_Document)
{
_moveEndpointByUnitDocument(count, endpoint, pRetVal, preventBufferEnd);
// We can abstract this movement by moving _start
constexpr auto endpoint = TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start;
const auto preventBoundary = !wasDegenerate;
if (unit == TextUnit::TextUnit_Character)
{
_moveEndpointByUnitCharacter(count, endpoint, pRetVal, preventBoundary);
}
else if (unit <= TextUnit::TextUnit_Word)
{
// TODO GH#10925: passing in "true" instead of "preventBoundary"
// We still need to go through the process of writing
// tests, finding failing cases, and fixing them.
// For now, just use true because we've been doing that so far.
// The tests at the time of writing don't report any failures
// if we use one over the other.
_moveEndpointByUnitWord(count, endpoint, pRetVal, true);
}
else if (unit <= TextUnit::TextUnit_Line)
{
_moveEndpointByUnitLine(count, endpoint, pRetVal, preventBoundary);
}
else if (unit <= TextUnit::TextUnit_Document)
{
_moveEndpointByUnitDocument(count, endpoint, pRetVal, preventBoundary);
}
}
// If we actually moved...
if (*pRetVal != 0)
if (wasDegenerate)
{
if (wasDegenerate)
{
// GH#7342: The range was degenerate before the move.
// To keep it that way, move _end to the new _start.
_end = _start;
}
else
{
// then just expand to get our _end
_expandToEnclosingUnit(unit);
}
// GH#7342: The range was degenerate before the move.
// To keep it that way, move _end to the new _start.
_end = _start;
}
else
{
// then just expand to get our _end
_expandToEnclosingUnit(unit);
}
UiaTracing::TextRange::Move(unit, count, *pRetVal, *this);
@ -1510,15 +1511,14 @@ void UiaTextRangeBase::_moveEndpointByUnitWord(_In_ const int moveCount,
// - moveCount - the number of times to move
// - endpoint - the endpoint to move
// - pAmountMoved - the number of times that the return values are "moved"
// - preventBufferEnd - when enabled, prevent endpoint from being at the end of the buffer
// This is used for general movement, where you are not allowed to
// create a degenerate range
// - preventBoundary - true --> the range encompasses the unit we're on; prevent movement onto boundaries
// false --> act like we're just moving an endpoint; allow movement onto boundaries
// Return Value:
// - <none>
void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
_In_ const TextPatternRangeEndpoint endpoint,
_Out_ gsl::not_null<int*> const pAmountMoved,
_In_ const bool preventBufferEnd) noexcept
_In_ const bool preventBoundary) noexcept
{
*pAmountMoved = 0;
@ -1527,7 +1527,7 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
return;
}
const bool allowBottomExclusive = !preventBufferEnd;
const bool allowBottomExclusive = !preventBoundary;
const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward;
const auto bufferSize = _getBufferSize();
@ -1543,7 +1543,7 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
// can't move past end
if (nextPos.Y >= bufferSize.BottomInclusive())
{
if (preventBufferEnd || nextPos == bufferSize.EndExclusive())
if (preventBoundary || nextPos == bufferSize.EndExclusive())
{
success = false;
break;
@ -1561,11 +1561,21 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
}
case MovementDirection::Backward:
{
// can't move past top
if (!allowBottomExclusive && nextPos.Y == bufferSize.Top())
if (preventBoundary)
{
success = false;
break;
if (nextPos.Y == bufferSize.Top())
{
// can't move past top
success = false;
break;
}
else
{
// GH#10924: as a non-degenerate range, we are supposed to act
// like we already encompass the line.
// Move to the left boundary so we try to wrap around
nextPos.X = bufferSize.Left();
}
}
// NOTE: Automatically detects if we are trying to move past origin
@ -1594,15 +1604,14 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
// - moveCount - the number of times to move
// - endpoint - the endpoint to move
// - pAmountMoved - the number of times that the return values are "moved"
// - preventBufferEnd - when enabled, prevent endpoint from being at the end of the buffer
// This is used for general movement, where you are not allowed to
// create a degenerate range
// - preventBoundary - true --> the range encompasses the unit we're on; prevent movement onto boundaries
// false --> act like we're just moving an endpoint; allow movement onto boundaries
// Return Value:
// - <none>
void UiaTextRangeBase::_moveEndpointByUnitDocument(_In_ const int moveCount,
_In_ const TextPatternRangeEndpoint endpoint,
_Out_ gsl::not_null<int*> const pAmountMoved,
_In_ const bool preventBufferEnd) noexcept
_In_ const bool preventBoundary) noexcept
{
*pAmountMoved = 0;
@ -1620,7 +1629,7 @@ void UiaTextRangeBase::_moveEndpointByUnitDocument(_In_ const int moveCount,
case MovementDirection::Forward:
{
const auto documentEnd = bufferSize.EndExclusive();
if (preventBufferEnd || target == documentEnd)
if (preventBoundary || target == documentEnd)
{
return;
}
@ -1634,7 +1643,7 @@ void UiaTextRangeBase::_moveEndpointByUnitDocument(_In_ const int moveCount,
case MovementDirection::Backward:
{
const auto documentBegin = bufferSize.Origin();
if (target == documentBegin)
if (preventBoundary || target == documentBegin)
{
return;
}

View File

@ -171,13 +171,13 @@ namespace Microsoft::Console::Types
_moveEndpointByUnitLine(_In_ const int moveCount,
_In_ const TextPatternRangeEndpoint endpoint,
gsl::not_null<int*> const pAmountMoved,
_In_ const bool preventBufferEnd = false) noexcept;
_In_ const bool preventBoundary = false) noexcept;
void
_moveEndpointByUnitDocument(_In_ const int moveCount,
_In_ const TextPatternRangeEndpoint endpoint,
gsl::not_null<int*> const pAmountMoved,
_In_ const bool preventBufferEnd = false) noexcept;
_In_ const bool preventBoundary = false) noexcept;
std::optional<bool> _verifyAttr(TEXTATTRIBUTEID attributeId, VARIANT val, const TextAttribute& attr) const;
bool _initializeAttrQuery(TEXTATTRIBUTEID attributeId, VARIANT* pRetVal, const TextAttribute& attr) const;

View File

@ -34,19 +34,19 @@ TRUE,1,TextUnit_Line,-1,origin,origin,0,origin,origin,FALSE
TRUE,1,TextUnit_Line,0,origin,origin,0,origin,origin,FALSE
TRUE,1,TextUnit_Line,1,origin,origin,1,originP1L,originP1L,FALSE
TRUE,1,TextUnit_Line,5,origin,origin,5,originP5L,originP5L,FALSE
FALSE,1,TextUnit_Line,-5,origin,originP1C,0,origin,originP1L,TRUE
FALSE,1,TextUnit_Line,-1,origin,originP1C,0,origin,originP1L,TRUE
FALSE,1,TextUnit_Line,0,origin,originP1C,0,origin,originP1L,TRUE
FALSE,1,TextUnit_Line,-5,origin,originP1C,0,origin,originP1L,FALSE
FALSE,1,TextUnit_Line,-1,origin,originP1C,0,origin,originP1L,FALSE
FALSE,1,TextUnit_Line,0,origin,originP1C,0,origin,originP1L,FALSE
FALSE,1,TextUnit_Line,1,origin,originP1C,1,originP1L,originP2L,FALSE
FALSE,1,TextUnit_Line,5,origin,originP1C,5,originP5L,originP6L,FALSE
TRUE,2,TextUnit_Line,-5,midTop,midTop,-1,origin,origin,TRUE
TRUE,2,TextUnit_Line,-1,midTop,midTop,-1,origin,origin,TRUE
TRUE,2,TextUnit_Line,-5,midTop,midTop,-1,origin,origin,FALSE
TRUE,2,TextUnit_Line,-1,midTop,midTop,-1,origin,origin,FALSE
TRUE,2,TextUnit_Line,0,midTop,midTop,0,midTop,midTop,FALSE
TRUE,2,TextUnit_Line,1,midTop,midTop,1,midTopP1L,midTopP1L,FALSE
TRUE,2,TextUnit_Line,5,midTop,midTop,5,midTopP5L,midTopP5L,FALSE
FALSE,2,TextUnit_Line,-5,midTop,midTopP1C,0,origin,originP1L,TRUE
FALSE,2,TextUnit_Line,-1,midTop,midTopP1C,0,origin,originP1L,TRUE
FALSE,2,TextUnit_Line,0,midTop,midTopP1C,0,origin,originP1L,TRUE
FALSE,2,TextUnit_Line,-5,midTop,midTopP1C,0,origin,originP1L,FALSE
FALSE,2,TextUnit_Line,-1,midTop,midTopP1C,0,origin,originP1L,FALSE
FALSE,2,TextUnit_Line,0,midTop,midTopP1C,0,origin,originP1L,FALSE
FALSE,2,TextUnit_Line,1,midTop,midTopP1C,1,originP1L,originP2L,FALSE
FALSE,2,TextUnit_Line,5,midTop,midTopP1C,5,originP5L,originP6L,FALSE
TRUE,3,TextUnit_Line,-5,midHistory,midHistory,-5,midHistoryM4L,midHistoryM4L,FALSE
@ -54,41 +54,41 @@ TRUE,3,TextUnit_Line,-1,midHistory,midHistory,-1,midHistoryLeft,midHistoryLeft,F
TRUE,3,TextUnit_Line,0,midHistory,midHistory,0,midHistory,midHistory,FALSE
TRUE,3,TextUnit_Line,1,midHistory,midHistory,1,midHistoryP1L,midHistoryP1L,FALSE
TRUE,3,TextUnit_Line,5,midHistory,midHistory,5,midHistoryP5L,midHistoryP5L,FALSE
FALSE,3,TextUnit_Line,-5,midHistory,midHistoryP1C,-5,midHistoryM5L,midHistoryM4L,TRUE
FALSE,3,TextUnit_Line,-1,midHistory,midHistoryP1C,-1,midHistoryM1L,midHistoryLeft,TRUE
FALSE,3,TextUnit_Line,0,midHistory,midHistoryP1C,0,midHistoryLeft,midHistoryP1L,TRUE
FALSE,3,TextUnit_Line,-5,midHistory,midHistoryP1C,-5,midHistoryM5L,midHistoryM4L,FALSE
FALSE,3,TextUnit_Line,-1,midHistory,midHistoryP1C,-1,midHistoryM1L,midHistoryLeft,FALSE
FALSE,3,TextUnit_Line,0,midHistory,midHistoryP1C,0,midHistoryLeft,midHistoryP1L,FALSE
FALSE,3,TextUnit_Line,1,midHistory,midHistoryP1C,1,midHistoryP1L,midHistoryP2L,FALSE
FALSE,3,TextUnit_Line,5,midHistory,midHistoryP1C,5,midHistoryP5L,midHistoryP6L,FALSE
TRUE,1,TextUnit_Document,-5,origin,origin,0,origin,origin,FALSE
TRUE,1,TextUnit_Document,-1,origin,origin,0,origin,origin,FALSE
TRUE,1,TextUnit_Document,0,origin,origin,0,origin,origin,FALSE
TRUE,1,TextUnit_Document,1,origin,origin,1,docEnd,docEnd,TRUE
TRUE,1,TextUnit_Document,5,origin,origin,1,docEnd,docEnd,TRUE
FALSE,1,TextUnit_Document,-5,origin,originP1C,0,origin,docEnd,TRUE
FALSE,1,TextUnit_Document,-1,origin,originP1C,0,origin,docEnd,TRUE
FALSE,1,TextUnit_Document,0,origin,originP1C,0,origin,docEnd,TRUE
FALSE,1,TextUnit_Document,1,origin,originP1C,0,origin,docEnd,TRUE
FALSE,1,TextUnit_Document,5,origin,originP1C,0,origin,docEnd,TRUE
TRUE,1,TextUnit_Document,1,origin,origin,1,endExclusive,endExclusive,FALSE
TRUE,1,TextUnit_Document,5,origin,origin,1,endExclusive,endExclusive,FALSE
FALSE,1,TextUnit_Document,-5,origin,originP1C,0,origin,endExclusive,FALSE
FALSE,1,TextUnit_Document,-1,origin,originP1C,0,origin,endExclusive,FALSE
FALSE,1,TextUnit_Document,0,origin,originP1C,0,origin,endExclusive,FALSE
FALSE,1,TextUnit_Document,1,origin,originP1C,0,origin,endExclusive,FALSE
FALSE,1,TextUnit_Document,5,origin,originP1C,0,origin,endExclusive,FALSE
TRUE,2,TextUnit_Document,-5,midTop,midTop,-1,origin,origin,FALSE
TRUE,2,TextUnit_Document,-1,midTop,midTop,-1,origin,origin,FALSE
TRUE,2,TextUnit_Document,0,midTop,midTop,0,midTop,midTop,FALSE
TRUE,2,TextUnit_Document,1,midTop,midTop,1,bufferEnd,bufferEnd,TRUE
TRUE,2,TextUnit_Document,5,midTop,midTop,1,bufferEnd,bufferEnd,TRUE
FALSE,2,TextUnit_Document,-5,midTop,midTopP1C,0,origin,bufferEnd,TRUE
FALSE,2,TextUnit_Document,-1,midTop,midTopP1C,0,origin,bufferEnd,TRUE
FALSE,2,TextUnit_Document,0,midTop,midTopP1C,0,origin,bufferEnd,TRUE
FALSE,2,TextUnit_Document,1,midTop,midTopP1C,0,origin,bufferEnd,TRUE
FALSE,2,TextUnit_Document,5,midTop,midTopP1C,0,origin,bufferEnd,TRUE
TRUE,2,TextUnit_Document,1,midTop,midTop,1,endExclusive,endExclusive,FALSE
TRUE,2,TextUnit_Document,5,midTop,midTop,1,endExclusive,endExclusive,FALSE
FALSE,2,TextUnit_Document,-5,midTop,midTopP1C,0,origin,endExclusive,FALSE
FALSE,2,TextUnit_Document,-1,midTop,midTopP1C,0,origin,endExclusive,FALSE
FALSE,2,TextUnit_Document,0,midTop,midTopP1C,0,origin,endExclusive,FALSE
FALSE,2,TextUnit_Document,1,midTop,midTopP1C,0,origin,endExclusive,FALSE
FALSE,2,TextUnit_Document,5,midTop,midTopP1C,0,origin,endExclusive,FALSE
TRUE,3,TextUnit_Document,-5,midHistory,midHistory,-1,origin,origin,FALSE
TRUE,3,TextUnit_Document,-1,midHistory,midHistory,-1,origin,origin,FALSE
TRUE,3,TextUnit_Document,0,midHistory,midHistory,0,midHistory,midHistory,FALSE
TRUE,3,TextUnit_Document,1,midHistory,midHistory,1,endExclusive,endExclusive,TRUE
TRUE,3,TextUnit_Document,5,midHistory,midHistory,1,endExclusive,endExclusive,TRUE
FALSE,3,TextUnit_Document,-5,midHistory,midHistoryP1C,0,origin,endExclusive,TRUE
FALSE,3,TextUnit_Document,-1,midHistory,midHistoryP1C,0,origin,endExclusive,TRUE
FALSE,3,TextUnit_Document,0,midHistory,midHistoryP1C,0,origin,endExclusive,TRUE
FALSE,3,TextUnit_Document,1,midHistory,midHistoryP1C,0,origin,endExclusive,TRUE
FALSE,3,TextUnit_Document,5,midHistory,midHistoryP1C,0,origin,endExclusive,TRUE
TRUE,3,TextUnit_Document,1,midHistory,midHistory,1,endExclusive,endExclusive,FALSE
TRUE,3,TextUnit_Document,5,midHistory,midHistory,1,endExclusive,endExclusive,FALSE
FALSE,3,TextUnit_Document,-5,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
FALSE,3,TextUnit_Document,-1,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
FALSE,3,TextUnit_Document,0,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
FALSE,3,TextUnit_Document,1,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
FALSE,3,TextUnit_Document,5,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
TRUE,8,TextUnit_Character,-5,bufferEnd,bufferEnd,-5,bufferEndM5C,bufferEndM5C,FALSE
TRUE,8,TextUnit_Character,-1,bufferEnd,bufferEnd,-1,bufferEndM1C,bufferEndM1C,FALSE
TRUE,8,TextUnit_Character,0,bufferEnd,bufferEnd,0,bufferEnd,bufferEnd,FALSE

1 Degenerate Position TextUnit MoveAmount Start End Result_MoveAmount Result_Start Result_End Skip
34 TRUE 1 TextUnit_Line 0 origin origin 0 origin origin FALSE
35 TRUE 1 TextUnit_Line 1 origin origin 1 originP1L originP1L FALSE
36 TRUE 1 TextUnit_Line 5 origin origin 5 originP5L originP5L FALSE
37 FALSE 1 TextUnit_Line -5 origin originP1C 0 origin originP1L TRUE FALSE
38 FALSE 1 TextUnit_Line -1 origin originP1C 0 origin originP1L TRUE FALSE
39 FALSE 1 TextUnit_Line 0 origin originP1C 0 origin originP1L TRUE FALSE
40 FALSE 1 TextUnit_Line 1 origin originP1C 1 originP1L originP2L FALSE
41 FALSE 1 TextUnit_Line 5 origin originP1C 5 originP5L originP6L FALSE
42 TRUE 2 TextUnit_Line -5 midTop midTop -1 origin origin TRUE FALSE
43 TRUE 2 TextUnit_Line -1 midTop midTop -1 origin origin TRUE FALSE
44 TRUE 2 TextUnit_Line 0 midTop midTop 0 midTop midTop FALSE
45 TRUE 2 TextUnit_Line 1 midTop midTop 1 midTopP1L midTopP1L FALSE
46 TRUE 2 TextUnit_Line 5 midTop midTop 5 midTopP5L midTopP5L FALSE
47 FALSE 2 TextUnit_Line -5 midTop midTopP1C 0 origin originP1L TRUE FALSE
48 FALSE 2 TextUnit_Line -1 midTop midTopP1C 0 origin originP1L TRUE FALSE
49 FALSE 2 TextUnit_Line 0 midTop midTopP1C 0 origin originP1L TRUE FALSE
50 FALSE 2 TextUnit_Line 1 midTop midTopP1C 1 originP1L originP2L FALSE
51 FALSE 2 TextUnit_Line 5 midTop midTopP1C 5 originP5L originP6L FALSE
52 TRUE 3 TextUnit_Line -5 midHistory midHistory -5 midHistoryM4L midHistoryM4L FALSE
54 TRUE 3 TextUnit_Line 0 midHistory midHistory 0 midHistory midHistory FALSE
55 TRUE 3 TextUnit_Line 1 midHistory midHistory 1 midHistoryP1L midHistoryP1L FALSE
56 TRUE 3 TextUnit_Line 5 midHistory midHistory 5 midHistoryP5L midHistoryP5L FALSE
57 FALSE 3 TextUnit_Line -5 midHistory midHistoryP1C -5 midHistoryM5L midHistoryM4L TRUE FALSE
58 FALSE 3 TextUnit_Line -1 midHistory midHistoryP1C -1 midHistoryM1L midHistoryLeft TRUE FALSE
59 FALSE 3 TextUnit_Line 0 midHistory midHistoryP1C 0 midHistoryLeft midHistoryP1L TRUE FALSE
60 FALSE 3 TextUnit_Line 1 midHistory midHistoryP1C 1 midHistoryP1L midHistoryP2L FALSE
61 FALSE 3 TextUnit_Line 5 midHistory midHistoryP1C 5 midHistoryP5L midHistoryP6L FALSE
62 TRUE 1 TextUnit_Document -5 origin origin 0 origin origin FALSE
63 TRUE 1 TextUnit_Document -1 origin origin 0 origin origin FALSE
64 TRUE 1 TextUnit_Document 0 origin origin 0 origin origin FALSE
65 TRUE 1 TextUnit_Document 1 origin origin 1 docEnd endExclusive docEnd endExclusive TRUE FALSE
66 TRUE 1 TextUnit_Document 5 origin origin 1 docEnd endExclusive docEnd endExclusive TRUE FALSE
67 FALSE 1 TextUnit_Document -5 origin originP1C 0 origin docEnd endExclusive TRUE FALSE
68 FALSE 1 TextUnit_Document -1 origin originP1C 0 origin docEnd endExclusive TRUE FALSE
69 FALSE 1 TextUnit_Document 0 origin originP1C 0 origin docEnd endExclusive TRUE FALSE
70 FALSE 1 TextUnit_Document 1 origin originP1C 0 origin docEnd endExclusive TRUE FALSE
71 FALSE 1 TextUnit_Document 5 origin originP1C 0 origin docEnd endExclusive TRUE FALSE
72 TRUE 2 TextUnit_Document -5 midTop midTop -1 origin origin FALSE
73 TRUE 2 TextUnit_Document -1 midTop midTop -1 origin origin FALSE
74 TRUE 2 TextUnit_Document 0 midTop midTop 0 midTop midTop FALSE
75 TRUE 2 TextUnit_Document 1 midTop midTop 1 bufferEnd endExclusive bufferEnd endExclusive TRUE FALSE
76 TRUE 2 TextUnit_Document 5 midTop midTop 1 bufferEnd endExclusive bufferEnd endExclusive TRUE FALSE
77 FALSE 2 TextUnit_Document -5 midTop midTopP1C 0 origin bufferEnd endExclusive TRUE FALSE
78 FALSE 2 TextUnit_Document -1 midTop midTopP1C 0 origin bufferEnd endExclusive TRUE FALSE
79 FALSE 2 TextUnit_Document 0 midTop midTopP1C 0 origin bufferEnd endExclusive TRUE FALSE
80 FALSE 2 TextUnit_Document 1 midTop midTopP1C 0 origin bufferEnd endExclusive TRUE FALSE
81 FALSE 2 TextUnit_Document 5 midTop midTopP1C 0 origin bufferEnd endExclusive TRUE FALSE
82 TRUE 3 TextUnit_Document -5 midHistory midHistory -1 origin origin FALSE
83 TRUE 3 TextUnit_Document -1 midHistory midHistory -1 origin origin FALSE
84 TRUE 3 TextUnit_Document 0 midHistory midHistory 0 midHistory midHistory FALSE
85 TRUE 3 TextUnit_Document 1 midHistory midHistory 1 endExclusive endExclusive TRUE FALSE
86 TRUE 3 TextUnit_Document 5 midHistory midHistory 1 endExclusive endExclusive TRUE FALSE
87 FALSE 3 TextUnit_Document -5 midHistory midHistoryP1C 0 origin endExclusive TRUE FALSE
88 FALSE 3 TextUnit_Document -1 midHistory midHistoryP1C 0 origin endExclusive TRUE FALSE
89 FALSE 3 TextUnit_Document 0 midHistory midHistoryP1C 0 origin endExclusive TRUE FALSE
90 FALSE 3 TextUnit_Document 1 midHistory midHistoryP1C 0 origin endExclusive TRUE FALSE
91 FALSE 3 TextUnit_Document 5 midHistory midHistoryP1C 0 origin endExclusive TRUE FALSE
92 TRUE 8 TextUnit_Character -5 bufferEnd bufferEnd -5 bufferEndM5C bufferEndM5C FALSE
93 TRUE 8 TextUnit_Character -1 bufferEnd bufferEnd -1 bufferEndM1C bufferEndM1C FALSE
94 TRUE 8 TextUnit_Character 0 bufferEnd bufferEnd 0 bufferEnd bufferEnd FALSE