[A11y] Treat last character as 'end of buffer' (#11122)
## Summary of the Pull Request Updates our `UiaTextRange` to no longer treat the end of the buffer as the "document end". Instead, we consider the "document end" to be the line beneath the cursor or last legible character (whichever is further down). In the event where the last legible character is on the last line of the buffer, we use the "end exclusive" position (left-most point on a line one past the end of the buffer). When movement of any kind occurs, we clamp each endpoint to the document end. Since the document end is an actual spot in the buffer (most of the time), this should improve stability because we shouldn't be pointing out-of-bounds anymore. The biggest benefit is that this significantly improves the performance of word navigation because screen readers no longer have to take into account the whitespace following the end of the prompt. Word navigation tests were added to the `TestTableWriter` (see #10886). 24 of the 85 tests were failing, however, they don't seem to interact with the document end, so I've marked them as skip and will fix them in a follow-up. This PR is large enough as-is, so I'm hoping I can take time in the follow-up to clean some things on the side (aka `preventBoundary` and `allowBottomExclusive` being used interchangeably). ## References #7000 - Epic Closes #6986 Closes #10925 ## Validation Steps Performed - [X] Tests pass - [X] @codeofdusk has been personally testing this build (and others)
This commit is contained in:
parent
4793541c90
commit
d08afc4e88
|
@ -35,6 +35,9 @@ liga
|
|||
lje
|
||||
locl
|
||||
lorem
|
||||
Llast
|
||||
Lmid
|
||||
Lorigin
|
||||
maxed
|
||||
mkmk
|
||||
mru
|
||||
|
|
|
@ -1057,9 +1057,10 @@ const DelimiterClass TextBuffer::_GetDelimiterClassAt(const COORD pos, const std
|
|||
// - accessibilityMode - when enabled, we continue expanding left until we are at the beginning of a readable word.
|
||||
// Otherwise, expand left until a character of a new delimiter class is found
|
||||
// (or a row boundary is encountered)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - The COORD for the first character on the "word" (inclusive)
|
||||
const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode) const
|
||||
const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// Consider a buffer with this text in it:
|
||||
// " word other "
|
||||
|
@ -1072,10 +1073,9 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
|
|||
// NOTE: the start anchor (this one) is inclusive, whereas the end anchor (GetWordEnd) is exclusive
|
||||
|
||||
#pragma warning(suppress : 26496)
|
||||
// GH#7664: Treat EndExclusive as EndInclusive so
|
||||
// that it actually points to a space in the buffer
|
||||
auto copy{ target };
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (target == bufferSize.Origin())
|
||||
{
|
||||
// can't expand left
|
||||
|
@ -1083,9 +1083,15 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
|
|||
}
|
||||
else if (target == bufferSize.EndExclusive())
|
||||
{
|
||||
// treat EndExclusive as EndInclusive
|
||||
// GH#7664: Treat EndExclusive as EndInclusive so
|
||||
// that it actually points to a space in the buffer
|
||||
copy = { bufferSize.RightInclusive(), bufferSize.BottomInclusive() };
|
||||
}
|
||||
else if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
// if at/past the limit --> clamp to limit
|
||||
copy = *limitOptional;
|
||||
}
|
||||
|
||||
if (accessibilityMode)
|
||||
{
|
||||
|
@ -1179,9 +1185,10 @@ const COORD TextBuffer::_GetWordStartForSelection(const COORD target, const std:
|
|||
// - accessibilityMode - when enabled, we continue expanding right until we are at the beginning of the next READABLE word
|
||||
// Otherwise, expand right until a character of a new delimiter class is found
|
||||
// (or a row boundary is encountered)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - The COORD for the last character on the "word" (inclusive)
|
||||
const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode) const
|
||||
const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// Consider a buffer with this text in it:
|
||||
// " word other "
|
||||
|
@ -1193,16 +1200,17 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w
|
|||
// so the words in the example include ["word ", "other "]
|
||||
// NOTE: the end anchor (this one) is exclusive, whereas the start anchor (GetWordStart) is inclusive
|
||||
|
||||
// Already at the end. Can't move forward.
|
||||
if (target == GetSize().EndExclusive())
|
||||
// Already at/past the limit. Can't move forward.
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
if (accessibilityMode)
|
||||
{
|
||||
const auto lastCharPos{ GetLastNonSpaceCharacter() };
|
||||
return _GetWordEndForAccessibility(target, wordDelimiters, lastCharPos);
|
||||
return _GetWordEndForAccessibility(target, wordDelimiters, limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1215,44 +1223,46 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w
|
|||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - lastCharPos - the position of the last nonspace character in the text buffer (to improve performance)
|
||||
// - limit - the last "valid" position in the text buffer (to improve performance)
|
||||
// Return Value:
|
||||
// - The COORD for the first character of the next readable "word". If no next word, return one past the end of the buffer
|
||||
const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD lastCharPos) const
|
||||
const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
COORD result = target;
|
||||
const auto bufferSize{ GetSize() };
|
||||
COORD result{ target };
|
||||
|
||||
// Check if we're already on/past the last RegularChar
|
||||
if (bufferSize.CompareInBounds(result, lastCharPos, true) >= 0)
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
return bufferSize.EndExclusive();
|
||||
// if we're already on/past the last RegularChar,
|
||||
// clamp result to that position
|
||||
result = limit;
|
||||
|
||||
// make the result exclusive
|
||||
bufferSize.IncrementInBounds(result, true);
|
||||
}
|
||||
|
||||
// ignore right boundary. Continue through readable text found
|
||||
while (_GetDelimiterClassAt(result, wordDelimiters) == DelimiterClass::RegularChar)
|
||||
else
|
||||
{
|
||||
if (!bufferSize.IncrementInBounds(result, true))
|
||||
auto iter{ GetCellDataAt(result, bufferSize) };
|
||||
while (iter && iter.Pos() != limit && _GetDelimiterClassAt(iter.Pos(), wordDelimiters) == DelimiterClass::RegularChar)
|
||||
{
|
||||
break;
|
||||
// Iterate through readable text
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
// we are already on/past the last RegularChar
|
||||
if (bufferSize.CompareInBounds(result, lastCharPos, true) >= 0)
|
||||
{
|
||||
return bufferSize.EndExclusive();
|
||||
}
|
||||
|
||||
// make sure we expand to the beginning of the NEXT word
|
||||
while (_GetDelimiterClassAt(result, wordDelimiters) != DelimiterClass::RegularChar)
|
||||
{
|
||||
if (!bufferSize.IncrementInBounds(result, true))
|
||||
while (iter && iter.Pos() != limit && _GetDelimiterClassAt(iter.Pos(), wordDelimiters) != DelimiterClass::RegularChar)
|
||||
{
|
||||
// we are at the EndInclusive COORD
|
||||
// this signifies that we must include the last char in the buffer
|
||||
// but the position of the COORD points to nothing
|
||||
break;
|
||||
// expand to the beginning of the NEXT word
|
||||
++iter;
|
||||
}
|
||||
|
||||
result = iter.Pos();
|
||||
|
||||
// Special case: we tried to move one past the end of the buffer,
|
||||
// but iter prevented that (because that pos doesn't exist).
|
||||
// Manually increment onto the EndExclusive point.
|
||||
if (!iter)
|
||||
{
|
||||
bufferSize.IncrementInBounds(result, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1345,18 +1355,20 @@ void TextBuffer::_PruneHyperlinks()
|
|||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - lastCharPos - the position of the last nonspace character in the text buffer (to improve performance)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first character on the "word" (inclusive)
|
||||
bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, COORD lastCharPos) const
|
||||
bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// move to the beginning of the next word
|
||||
// NOTE: _GetWordEnd...() returns the exclusive position of the "end of the word"
|
||||
// This is also the inclusive start of the next word.
|
||||
auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, lastCharPos) };
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit) };
|
||||
|
||||
if (copy == GetSize().EndExclusive())
|
||||
if (bufferSize.CompareInBounds(copy, limit, true) >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1393,19 +1405,23 @@ bool TextBuffer::MoveToPreviousWord(COORD& pos, std::wstring_view wordDelimiters
|
|||
// - Update pos to be the beginning of the current glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
const til::point TextBuffer::GetGlyphStart(const til::point pos) const
|
||||
const til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (resultPos == bufferSize.EndExclusive())
|
||||
// Clamp pos to limit
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
bufferSize.DecrementInBounds(resultPos, true);
|
||||
resultPos = limit;
|
||||
}
|
||||
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
// limit is exclusive, so we need to move back to be within valid bounds
|
||||
if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
{
|
||||
bufferSize.DecrementInBounds(resultPos, true);
|
||||
}
|
||||
|
@ -1419,12 +1435,19 @@ const til::point TextBuffer::GetGlyphStart(const til::point pos) const
|
|||
// - pos - a COORD on the word you are currently on
|
||||
// Return Value:
|
||||
// - pos - The COORD for the last cell of the current glyph (exclusive)
|
||||
const til::point TextBuffer::GetGlyphEnd(const til::point pos) const
|
||||
const til::point TextBuffer::GetGlyphEnd(const til::point pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
|
||||
const auto bufferSize = GetSize();
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
resultPos = limit;
|
||||
}
|
||||
|
||||
if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, true);
|
||||
}
|
||||
|
@ -1438,29 +1461,43 @@ const til::point TextBuffer::GetGlyphEnd(const til::point pos) const
|
|||
// - Update pos to be the beginning of the next glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - allowBottomExclusive - allow the nonexistent end-of-buffer cell to be encountered
|
||||
// - allowExclusiveEnd - allow result to be the exclusive limit (one past limit)
|
||||
// - limit - boundaries for the iterator to operate within
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowBottomExclusive) const
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (resultPos == GetSize().EndExclusive())
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit, true) };
|
||||
if (distanceToLimit >= 0)
|
||||
{
|
||||
// we're already at the end
|
||||
// Corner Case: we're on/past the limit
|
||||
// Clamp us to the limit
|
||||
pos = limit;
|
||||
return false;
|
||||
}
|
||||
else if (!allowExclusiveEnd && distanceToLimit == -1)
|
||||
{
|
||||
// Corner Case: we're just before the limit
|
||||
// and we are not allowed onto the exclusive end.
|
||||
// Fail to move.
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to move. If we can't, we're done.
|
||||
const bool success = bufferSize.IncrementInBounds(resultPos, allowBottomExclusive);
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
// Try to move forward, but if we hit the buffer boundary, we fail to move.
|
||||
auto iter{ GetCellDataAt(pos, bufferSize) };
|
||||
const bool success{ ++iter };
|
||||
|
||||
// Move again if we're on a wide glyph
|
||||
if (success && iter->DbcsAttr().IsTrailing())
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, allowBottomExclusive);
|
||||
++iter;
|
||||
}
|
||||
|
||||
pos = resultPos;
|
||||
pos = iter.Pos();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -1471,12 +1508,21 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowBottomExclusive) con
|
|||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the previous glyph (inclusive)
|
||||
bool TextBuffer::MoveToPreviousGlyph(til::point& pos) const
|
||||
bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (bufferSize.CompareInBounds(pos, limit, true) > 0)
|
||||
{
|
||||
// we're past the end
|
||||
// clamp us to the limit
|
||||
pos = limit;
|
||||
return true;
|
||||
}
|
||||
|
||||
// try to move. If we can't, we're done.
|
||||
const auto bufferSize = GetSize();
|
||||
const bool success = bufferSize.DecrementInBounds(resultPos, true);
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
{
|
||||
|
|
|
@ -141,15 +141,15 @@ public:
|
|||
|
||||
Microsoft::Console::Render::IRenderTarget& GetRenderTarget() noexcept;
|
||||
|
||||
const COORD GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false) const;
|
||||
const COORD GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false) const;
|
||||
bool MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, COORD lastCharPos) const;
|
||||
const COORD GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
const COORD GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToPreviousWord(COORD& pos, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
const til::point GetGlyphStart(const til::point pos) const;
|
||||
const til::point GetGlyphEnd(const til::point pos) const;
|
||||
bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false) const;
|
||||
bool MoveToPreviousGlyph(til::point& pos) const;
|
||||
const til::point GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
const til::point GetGlyphEnd(const til::point pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
|
||||
const std::vector<SMALL_RECT> GetTextRects(COORD start, COORD end, bool blockSelection, bool bufferCoordinates) const;
|
||||
|
||||
|
@ -242,7 +242,7 @@ private:
|
|||
const DelimiterClass _GetDelimiterClassAt(const COORD pos, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordStartForAccessibility(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordStartForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD lastCharPos) const;
|
||||
const COORD _GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const;
|
||||
const COORD _GetWordEndForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
void _PruneHyperlinks();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -349,14 +349,29 @@ class UiaTextRangeTests
|
|||
_pTextBuffer = &_pScreenInfo->GetTextBuffer();
|
||||
_pUiaData = &gci.renderData;
|
||||
|
||||
// fill text buffer with text
|
||||
for (UINT i = 0; i < _pTextBuffer->TotalRowCount(); ++i)
|
||||
// GH#6986: document end now limits the navigation to be
|
||||
// within the document end bounds _as opposed to_ the buffer bounds.
|
||||
// As a result, let's populate the buffer partially to define a document end.
|
||||
// Additionally, add spaces to create "words" in the buffer.
|
||||
|
||||
// LOAD BEARING: make sure we fill it halfway so that we can reuse most of
|
||||
// the variables from the generated tests.
|
||||
|
||||
// fill first half of text buffer with text
|
||||
for (UINT i = 0; i < _pTextBuffer->TotalRowCount() / 2; ++i)
|
||||
{
|
||||
ROW& row = _pTextBuffer->GetRowByOffset(i);
|
||||
auto& charRow = row.GetCharRow();
|
||||
for (auto& cell : charRow)
|
||||
{
|
||||
cell.Char() = L' ';
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
cell.Char() = L' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.Char() = L'X';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,9 +734,13 @@ class UiaTextRangeTests
|
|||
|
||||
TEST_METHOD(CanMoveByCharacter)
|
||||
{
|
||||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().RightInclusive();
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveTest> testData
|
||||
{
|
||||
|
@ -749,6 +768,18 @@ class UiaTextRangeTests
|
|||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can't move past the end of the 'document'",
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
5,
|
||||
{
|
||||
0,
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can move to a new row when necessary when moving forward",
|
||||
{ lastColumnIndex, 0 },
|
||||
|
@ -782,7 +813,7 @@ class UiaTextRangeTests
|
|||
int amountMoved;
|
||||
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, test.start, test.end));
|
||||
utr->Move(TextUnit::TextUnit_Character, test.moveAmt, &amountMoved);
|
||||
THROW_IF_FAILED(utr->Move(TextUnit::TextUnit_Character, test.moveAmt, &amountMoved));
|
||||
|
||||
VERIFY_ARE_EQUAL(test.expected.moveAmt, amountMoved);
|
||||
VERIFY_ARE_EQUAL(test.expected.start, utr->_start);
|
||||
|
@ -795,6 +826,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveTest> testData
|
||||
{
|
||||
|
@ -810,15 +845,27 @@ class UiaTextRangeTests
|
|||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can't move past the end of the 'document'",
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
5,
|
||||
{
|
||||
0,
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can move backward from bottom row",
|
||||
{0, bottomRow},
|
||||
{lastColumnIndex, bottomRow},
|
||||
{0, documentEnd.Y},
|
||||
{lastColumnIndex, documentEnd.Y},
|
||||
-3,
|
||||
{
|
||||
-3,
|
||||
{0, bottomRow - 3},
|
||||
{0, bottomRow - 2}
|
||||
{0, base::ClampSub(documentEnd.Y, 3)},
|
||||
{0, base::ClampSub(documentEnd.Y, 3)}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -868,6 +915,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = static_cast<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().RightInclusive(), _pTextBuffer->GetLastNonSpaceCharacter().Y };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveEndpointTest> testData
|
||||
{
|
||||
|
@ -910,6 +961,19 @@ class UiaTextRangeTests
|
|||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end past the end of the document",
|
||||
{0, 0},
|
||||
documentEnd,
|
||||
5,
|
||||
TextPatternRangeEndpoint_End,
|
||||
{
|
||||
1,
|
||||
{0,0},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)}
|
||||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"_start follows _end when passed during movement",
|
||||
{5, 0},
|
||||
|
@ -925,40 +989,40 @@ class UiaTextRangeTests
|
|||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end past the beginning of the document when _end is positioned at the end",
|
||||
{0, bottomRow},
|
||||
{0, bottomRow+1},
|
||||
{0, documentEnd.Y},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
1,
|
||||
TextPatternRangeEndpoint_End,
|
||||
{
|
||||
0,
|
||||
{0, bottomRow},
|
||||
{0, bottomRow+1},
|
||||
{0, documentEnd.Y},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can partially move _end to the end of the document when it is closer than the move count requested",
|
||||
{0, 0},
|
||||
{lastColumnIndex - 3, bottomRow},
|
||||
{base::ClampSub(lastColumnIndex, 3), documentEnd.Y},
|
||||
5,
|
||||
TextPatternRangeEndpoint_End,
|
||||
{
|
||||
4,
|
||||
{0, 0},
|
||||
{0, bottomRow+1},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _start past the end of the document",
|
||||
{lastColumnIndex - 4, bottomRow},
|
||||
{0, bottomRow+1},
|
||||
{base::ClampSub(lastColumnIndex, 4), documentEnd.Y},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
5,
|
||||
TextPatternRangeEndpoint_Start,
|
||||
{
|
||||
5,
|
||||
{0, bottomRow+1},
|
||||
{0, bottomRow+1},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -997,6 +1061,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveEndpointTest> testData
|
||||
{
|
||||
|
@ -1067,36 +1135,36 @@ class UiaTextRangeTests
|
|||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can move _end forwards when it's on the bottom row",
|
||||
L"can't move _end forwards when it's on the bottom row (past doc end)",
|
||||
{0, 0},
|
||||
{lastColumnIndex - 3, bottomRow},
|
||||
1,
|
||||
TextPatternRangeEndpoint_End,
|
||||
1,
|
||||
0,
|
||||
{0, 0},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end forwards when it's at the end of the document already",
|
||||
L"can't move _end forwards when it's at the end of the buffer already (past doc end)",
|
||||
{0, 0},
|
||||
{0, bottomRow+1},
|
||||
1,
|
||||
TextPatternRangeEndpoint_End,
|
||||
0,
|
||||
{0, 0},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"moving _start forward when it's already on the bottom row creates a degenerate range at the document end",
|
||||
L"moving _start forward when it's already on the bottom row (past doc end) creates a degenerate range at the document end",
|
||||
{0, bottomRow},
|
||||
{lastColumnIndex, bottomRow},
|
||||
1,
|
||||
TextPatternRangeEndpoint_Start,
|
||||
1,
|
||||
{0, bottomRow+1},
|
||||
{0, bottomRow+1}
|
||||
0,
|
||||
documentEnd,
|
||||
documentEnd
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
|
@ -1132,6 +1200,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveEndpointTest> testData =
|
||||
{
|
||||
|
@ -1144,7 +1216,7 @@ class UiaTextRangeTests
|
|||
{
|
||||
1,
|
||||
{0, 4},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1162,7 +1234,7 @@ class UiaTextRangeTests
|
|||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end forward when it's already at the end of the document",
|
||||
L"can't move _end forward when it's already at the end of the buffer (past doc end)",
|
||||
{3, 2},
|
||||
{0, bottomRow+1},
|
||||
1,
|
||||
|
@ -1170,7 +1242,7 @@ class UiaTextRangeTests
|
|||
{
|
||||
0,
|
||||
{3, 2},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1208,8 +1280,8 @@ class UiaTextRangeTests
|
|||
TextPatternRangeEndpoint_Start,
|
||||
{
|
||||
1,
|
||||
{0, bottomRow+1},
|
||||
{0, bottomRow+1}
|
||||
documentEnd,
|
||||
documentEnd
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1235,51 +1307,64 @@ class UiaTextRangeTests
|
|||
// GH#7664: When attempting to expand to an enclosing unit
|
||||
// at the end exclusive, the UTR should refuse to move past
|
||||
// the end.
|
||||
const auto lastNonspaceCharPos{ _pTextBuffer->GetLastNonSpaceCharacter() };
|
||||
const COORD documentEnd{ 0, lastNonspaceCharPos.Y + 1 };
|
||||
|
||||
const til::point endInclusive{ bufferEnd };
|
||||
|
||||
// Iterate over each TextUnit. If the we don't support
|
||||
// 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.
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Data:textUnit", L"{0, 1, 2, 3, 4, 5, 6}")
|
||||
END_TEST_METHOD_PROPERTIES();
|
||||
|
||||
int textUnit;
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"textUnit", textUnit), L"Get textUnit variant");
|
||||
|
||||
Microsoft::WRL::ComPtr<UiaTextRange> utr;
|
||||
for (int unit = TextUnit::TextUnit_Character; unit != TextUnit::TextUnit_Document; ++unit)
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(L"%s", toString(static_cast<TextUnit>(unit))));
|
||||
Log::Comment(NoThrowString().Format(L"%s", toString(static_cast<TextUnit>(textUnit))));
|
||||
|
||||
// Create a degenerate UTR at EndExclusive
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endInclusive, endExclusive));
|
||||
THROW_IF_FAILED(utr->ExpandToEnclosingUnit(static_cast<TextUnit>(unit)));
|
||||
// Create a degenerate UTR at EndExclusive
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, bufferEnd, endExclusive));
|
||||
THROW_IF_FAILED(utr->ExpandToEnclosingUnit(static_cast<TextUnit>(textUnit)));
|
||||
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
}
|
||||
VERIFY_ARE_EQUAL(documentEnd, til::point{ utr->_end });
|
||||
}
|
||||
|
||||
TEST_METHOD(MovementAtExclusiveEnd)
|
||||
{
|
||||
// GH#7663: When attempting to move from end exclusive,
|
||||
// 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)
|
||||
_pTextBuffer->Reset();
|
||||
const til::point writeTarget{ 2, 2 };
|
||||
_pTextBuffer->Write({ L"temp" }, writeTarget);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEndInclusive{ base::ClampSub<short, short>(static_cast<short>(bufferSize.right()), 1), _pTextBuffer->GetLastNonSpaceCharacter().Y };
|
||||
const COORD documentEndExclusive{ static_cast<short>(bufferSize.left()), base::ClampAdd(documentEndInclusive.Y, 1) };
|
||||
|
||||
const COORD lastLineStart{ static_cast<short>(bufferSize.left()), documentEndInclusive.Y };
|
||||
const auto secondToLastLinePos{ point_offset_by_line(lastLineStart, bufferSize, -1) };
|
||||
const COORD secondToLastCharacterPos{ documentEndInclusive.X - 1, documentEndInclusive.Y };
|
||||
|
||||
// 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.
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Data:textUnit", L"{0, 1, 2, 3, 4, 5, 6}")
|
||||
TEST_METHOD_PROPERTY(L"Data:degenerate", L"{false, true}")
|
||||
TEST_METHOD_PROPERTY(L"Data:atDocumentEnd", L"{false, true}")
|
||||
END_TEST_METHOD_PROPERTIES();
|
||||
|
||||
int unit;
|
||||
bool degenerate;
|
||||
bool atDocumentEnd;
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"textUnit", unit), L"Get TextUnit variant");
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"degenerate", degenerate), L"Get degenerate variant");
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"atDocumentEnd", atDocumentEnd), L"Get atDocumentEnd variant");
|
||||
TextUnit textUnit{ static_cast<TextUnit>(unit) };
|
||||
|
||||
Microsoft::WRL::ComPtr<UiaTextRange> utr;
|
||||
|
@ -1287,17 +1372,22 @@ class UiaTextRangeTests
|
|||
Log::Comment(NoThrowString().Format(L"Forward by %s", toString(textUnit)));
|
||||
|
||||
// Create an UTR at EndExclusive
|
||||
const auto utrEnd{ atDocumentEnd ? documentEndExclusive : endExclusive };
|
||||
if (degenerate)
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endExclusive, endExclusive));
|
||||
// UTR: (exclusive, exclusive) range
|
||||
const auto utrStart{ atDocumentEnd ? documentEndExclusive : endExclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endInclusive, endExclusive));
|
||||
// UTR: (inclusive, exclusive) range
|
||||
const auto utrStart{ atDocumentEnd ? documentEndInclusive : endInclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
THROW_IF_FAILED(utr->Move(textUnit, 1, &moveAmt));
|
||||
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
VERIFY_ARE_EQUAL(0, moveAmt);
|
||||
|
||||
// Verify expansion works properly
|
||||
|
@ -1305,33 +1395,35 @@ class UiaTextRangeTests
|
|||
THROW_IF_FAILED(utr->ExpandToEnclosingUnit(textUnit));
|
||||
if (textUnit <= TextUnit::TextUnit_Character)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(endInclusive, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndInclusive, utr->_start);
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
else if (textUnit <= TextUnit::TextUnit_Word)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(writeTarget, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
else if (textUnit <= TextUnit::TextUnit_Line)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(lastLineStart, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(lastLineStart, utr->_start);
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
else // textUnit <= TextUnit::TextUnit_Document:
|
||||
{
|
||||
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
|
||||
// reset the UTR
|
||||
if (degenerate)
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endExclusive, endExclusive));
|
||||
const auto utrStart{ atDocumentEnd ? documentEndExclusive : endExclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endInclusive, endExclusive));
|
||||
const auto utrStart{ atDocumentEnd ? documentEndInclusive : endInclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
|
||||
// Verify that moving backwards still works properly
|
||||
|
@ -1345,26 +1437,26 @@ class UiaTextRangeTests
|
|||
// - 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 });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? documentEndInclusive : secondToLastCharacterPos, utr->_start);
|
||||
VERIFY_ARE_EQUAL(documentEndInclusive, 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 });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? origin : writeTarget, til::point{ utr->_end });
|
||||
}
|
||||
else if (textUnit <= TextUnit::TextUnit_Line)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(-1, moveAmt);
|
||||
VERIFY_ARE_EQUAL(degenerate ? lastLineStart : secondToLastLinePos, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? 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(degenerate || !atDocumentEnd ? -1 : 0, moveAmt);
|
||||
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(degenerate ? origin : endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? origin : documentEndExclusive, til::point{ utr->_end });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1829,37 +1921,38 @@ class UiaTextRangeTests
|
|||
TEST_METHOD(GeneratedMovementTests)
|
||||
{
|
||||
// Populate the buffer with...
|
||||
// - 9 segments of alternating text
|
||||
// - 10 segments of alternating text
|
||||
// - up to half of the buffer (vertically)
|
||||
// It'll look something like this
|
||||
// +---------------------------+
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +---------------------------+
|
||||
// +------------------------------+
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +------------------------------+
|
||||
{
|
||||
short i = 0;
|
||||
auto iter{ _pTextBuffer->GetCellDataAt(bufferSize.origin()) };
|
||||
const auto segment{ bufferSize.width() / 9 };
|
||||
const auto segment{ bufferSize.width() / 10 };
|
||||
bool fill{ true };
|
||||
while (iter.Pos() != docEnd)
|
||||
{
|
||||
bool fill{ true };
|
||||
if (i % segment == 0)
|
||||
if (iter.Pos().X == bufferSize.left())
|
||||
{
|
||||
fill = true;
|
||||
}
|
||||
else if (i % segment == 0)
|
||||
{
|
||||
fill = !fill;
|
||||
}
|
||||
|
||||
if (fill)
|
||||
{
|
||||
_pTextBuffer->Write({ L"X" }, iter.Pos());
|
||||
}
|
||||
_pTextBuffer->Write({ fill ? L"X" : L" " }, iter.Pos());
|
||||
|
||||
++i;
|
||||
++iter;
|
||||
|
|
|
@ -280,52 +280,50 @@ IFACEMETHODIMP UiaTextRangeBase::ExpandToEnclosingUnit(_In_ TextUnit unit) noexc
|
|||
void UiaTextRangeBase::_expandToEnclosingUnit(TextUnit unit)
|
||||
{
|
||||
const auto& buffer = _pData->GetTextBuffer();
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferEnd = bufferSize.EndExclusive();
|
||||
const auto bufferSize{ buffer.GetSize() };
|
||||
const auto documentEnd{ _getDocumentEnd() };
|
||||
|
||||
// If we're past document end,
|
||||
// set us to ONE BEFORE the document end.
|
||||
// This allows us to expand properly.
|
||||
if (bufferSize.CompareInBounds(_start, documentEnd, true) >= 0)
|
||||
{
|
||||
_start = documentEnd;
|
||||
bufferSize.DecrementInBounds(_start, true);
|
||||
}
|
||||
|
||||
if (unit == TextUnit_Character)
|
||||
{
|
||||
_start = buffer.GetGlyphStart(_start);
|
||||
_end = buffer.GetGlyphEnd(_start);
|
||||
_start = buffer.GetGlyphStart(_start, documentEnd);
|
||||
_end = buffer.GetGlyphEnd(_start, documentEnd);
|
||||
}
|
||||
else if (unit <= TextUnit_Word)
|
||||
{
|
||||
// expand to word
|
||||
_start = buffer.GetWordStart(_start, _wordDelimiters, true);
|
||||
_end = buffer.GetWordEnd(_start, _wordDelimiters, true);
|
||||
|
||||
// GetWordEnd may return the actual end of the TextBuffer.
|
||||
// If so, just set it to this value of bufferEnd
|
||||
if (!bufferSize.IsInBounds(_end))
|
||||
{
|
||||
_end = bufferEnd;
|
||||
}
|
||||
_start = buffer.GetWordStart(_start, _wordDelimiters, true, documentEnd);
|
||||
_end = buffer.GetWordEnd(_start, _wordDelimiters, true, documentEnd);
|
||||
}
|
||||
else if (unit <= TextUnit_Line)
|
||||
{
|
||||
if (_start == bufferEnd)
|
||||
// expand to line
|
||||
_start.X = 0;
|
||||
if (_start.Y == documentEnd.y())
|
||||
{
|
||||
// Special case: if we are at the bufferEnd,
|
||||
// move _start back one, instead of _end forward
|
||||
_start.X = 0;
|
||||
_start.Y = base::ClampSub(_start.Y, 1);
|
||||
_end = bufferEnd;
|
||||
// we're on the last line
|
||||
_end = documentEnd;
|
||||
bufferSize.IncrementInBounds(_end, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// expand to line
|
||||
_start.X = 0;
|
||||
_end.X = 0;
|
||||
_end.Y = base::ClampAdd(_start.Y, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO GH#6986: properly handle "end of buffer" as last character
|
||||
// instead of last cell
|
||||
// expand to document
|
||||
_start = bufferSize.Origin();
|
||||
_end = bufferSize.EndExclusive();
|
||||
_end = documentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,7 +606,7 @@ try
|
|||
*ppRetVal = nullptr;
|
||||
|
||||
const std::wstring queryText{ text, SysStringLen(text) };
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = _getOptimizedBufferSize();
|
||||
const auto sensitivity = ignoreCase ? Search::Sensitivity::CaseInsensitive : Search::Sensitivity::CaseSensitive;
|
||||
|
||||
auto searchDirection = Search::Direction::Forward;
|
||||
|
@ -1016,11 +1014,24 @@ try
|
|||
_pData->UnlockConsole();
|
||||
});
|
||||
|
||||
// We can abstract this movement by moving _start
|
||||
// GH#7342: check if we're past the documentEnd
|
||||
// If so, clamp each endpoint to the end of the document.
|
||||
constexpr auto endpoint = TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start;
|
||||
const auto bufferSize{ _pData->GetTextBuffer().GetSize() };
|
||||
const COORD documentEnd = _getDocumentEnd();
|
||||
if (bufferSize.CompareInBounds(_start, documentEnd, true) > 0)
|
||||
{
|
||||
_start = documentEnd;
|
||||
}
|
||||
if (bufferSize.CompareInBounds(_end, documentEnd, true) > 0)
|
||||
{
|
||||
_end = documentEnd;
|
||||
}
|
||||
|
||||
const auto wasDegenerate = IsDegenerate();
|
||||
if (count != 0)
|
||||
{
|
||||
// We can abstract this movement by moving _start
|
||||
constexpr auto endpoint = TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start;
|
||||
const auto preventBoundary = !wasDegenerate;
|
||||
if (unit == TextUnit::TextUnit_Character)
|
||||
{
|
||||
|
@ -1028,13 +1039,7 @@ try
|
|||
}
|
||||
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);
|
||||
_moveEndpointByUnitWord(count, endpoint, pRetVal, preventBoundary);
|
||||
}
|
||||
else if (unit <= TextUnit::TextUnit_Line)
|
||||
{
|
||||
|
@ -1080,6 +1085,26 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByUnit(_In_ TextPatternRangeEndpoin
|
|||
_pData->UnlockConsole();
|
||||
});
|
||||
|
||||
// GH#7342: check if we're past the documentEnd
|
||||
// If so, clamp each endpoint to the end of the document.
|
||||
const auto bufferSize{ _pData->GetTextBuffer().GetSize() };
|
||||
|
||||
auto documentEnd = bufferSize.EndExclusive();
|
||||
try
|
||||
{
|
||||
documentEnd = _getDocumentEnd();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
if (bufferSize.CompareInBounds(_start, documentEnd, true) > 0)
|
||||
{
|
||||
_start = documentEnd;
|
||||
}
|
||||
if (bufferSize.CompareInBounds(_end, documentEnd, true) > 0)
|
||||
{
|
||||
_end = documentEnd;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (unit == TextUnit::TextUnit_Character)
|
||||
|
@ -1307,7 +1332,7 @@ const unsigned int UiaTextRangeBase::_getViewportHeight(const SMALL_RECT viewpor
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - A viewport representing the portion of the TextBuffer that has valid text
|
||||
const Viewport UiaTextRangeBase::_getBufferSize() const noexcept
|
||||
const Viewport UiaTextRangeBase::_getOptimizedBufferSize() const noexcept
|
||||
{
|
||||
// we need to add 1 to the X/Y of textBufferEnd
|
||||
// because we want the returned viewport to include this COORD
|
||||
|
@ -1318,6 +1343,20 @@ const Viewport UiaTextRangeBase::_getBufferSize() const noexcept
|
|||
return Viewport::FromDimensions({ 0, 0 }, width, height);
|
||||
}
|
||||
|
||||
// We consider the "document end" to be the line beneath the cursor or
|
||||
// last legible character (whichever is further down). In the event where
|
||||
// the last legible character is on the last line of the buffer,
|
||||
// we use the "end exclusive" position (left-most point on a line one past the end of the buffer).
|
||||
// NOTE: "end exclusive" is naturally computed using the heuristic above.
|
||||
const til::point UiaTextRangeBase::_getDocumentEnd() const
|
||||
{
|
||||
const auto optimizedBufferSize{ _getOptimizedBufferSize() };
|
||||
const auto& buffer{ _pData->GetTextBuffer() };
|
||||
const auto lastCharPos{ buffer.GetLastNonSpaceCharacter(optimizedBufferSize) };
|
||||
const auto cursorPos{ buffer.GetCursor().GetPosition() };
|
||||
return { optimizedBufferSize.Left(), std::max(lastCharPos.Y, cursorPos.Y) + 1 };
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - adds the relevant coordinate points from the row to coords.
|
||||
// - it is assumed that startAnchor and endAnchor are within the same row
|
||||
|
@ -1388,19 +1427,20 @@ void UiaTextRangeBase::_moveEndpointByUnitCharacter(_In_ const int moveCount,
|
|||
|
||||
bool success = true;
|
||||
til::point target = GetEndpoint(endpoint);
|
||||
const auto documentEnd{ _getDocumentEnd() };
|
||||
while (std::abs(*pAmountMoved) < std::abs(moveCount) && success)
|
||||
{
|
||||
switch (moveDirection)
|
||||
{
|
||||
case MovementDirection::Forward:
|
||||
success = buffer.MoveToNextGlyph(target, allowBottomExclusive);
|
||||
success = buffer.MoveToNextGlyph(target, allowBottomExclusive, documentEnd);
|
||||
if (success)
|
||||
{
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
break;
|
||||
case MovementDirection::Backward:
|
||||
success = buffer.MoveToPreviousGlyph(target);
|
||||
success = buffer.MoveToPreviousGlyph(target, documentEnd);
|
||||
if (success)
|
||||
{
|
||||
(*pAmountMoved)--;
|
||||
|
@ -1441,10 +1481,9 @@ void UiaTextRangeBase::_moveEndpointByUnitWord(_In_ const int moveCount,
|
|||
const bool allowBottomExclusive = !preventBufferEnd;
|
||||
const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward;
|
||||
const auto& buffer = _pData->GetTextBuffer();
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = buffer.GetSize();
|
||||
const auto bufferOrigin = bufferSize.Origin();
|
||||
const auto bufferEnd = bufferSize.EndExclusive();
|
||||
const auto lastCharPos = buffer.GetLastNonSpaceCharacter(bufferSize);
|
||||
const auto documentEnd = _getDocumentEnd();
|
||||
|
||||
auto resultPos = GetEndpoint(endpoint);
|
||||
auto nextPos = resultPos;
|
||||
|
@ -1457,18 +1496,18 @@ void UiaTextRangeBase::_moveEndpointByUnitWord(_In_ const int moveCount,
|
|||
{
|
||||
case MovementDirection::Forward:
|
||||
{
|
||||
if (nextPos == bufferEnd)
|
||||
if (bufferSize.CompareInBounds(nextPos, documentEnd, true) >= 0)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
else if (buffer.MoveToNextWord(nextPos, _wordDelimiters, lastCharPos))
|
||||
else if (buffer.MoveToNextWord(nextPos, _wordDelimiters, documentEnd))
|
||||
{
|
||||
resultPos = nextPos;
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
else if (allowBottomExclusive)
|
||||
{
|
||||
resultPos = bufferEnd;
|
||||
resultPos = documentEnd;
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
else
|
||||
|
@ -1529,10 +1568,18 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
|
|||
|
||||
const bool allowBottomExclusive = !preventBoundary;
|
||||
const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward;
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = _getOptimizedBufferSize();
|
||||
|
||||
auto documentEnd{ bufferSize.EndExclusive() };
|
||||
try
|
||||
{
|
||||
documentEnd = _getDocumentEnd();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
bool success = true;
|
||||
auto resultPos = GetEndpoint(endpoint);
|
||||
|
||||
while (std::abs(*pAmountMoved) < std::abs(moveCount) && success)
|
||||
{
|
||||
auto nextPos = resultPos;
|
||||
|
@ -1540,22 +1587,29 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
|
|||
{
|
||||
case MovementDirection::Forward:
|
||||
{
|
||||
// can't move past end
|
||||
if (nextPos.Y >= bufferSize.BottomInclusive())
|
||||
if (nextPos.Y >= documentEnd.Y)
|
||||
{
|
||||
if (preventBoundary || nextPos == bufferSize.EndExclusive())
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
// Corner Case: we're past the limit
|
||||
// Clamp us to the limit
|
||||
resultPos = documentEnd;
|
||||
success = false;
|
||||
}
|
||||
|
||||
nextPos.X = bufferSize.RightInclusive();
|
||||
success = bufferSize.IncrementInBounds(nextPos, allowBottomExclusive);
|
||||
if (success)
|
||||
else if (preventBoundary && nextPos.Y == base::ClampSub(documentEnd.Y, 1))
|
||||
{
|
||||
resultPos = nextPos;
|
||||
(*pAmountMoved)++;
|
||||
// Corner Case: we're just before the limit
|
||||
// and we're not allowed onto the exclusive end.
|
||||
// Fail to move.
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextPos.X = bufferSize.RightInclusive();
|
||||
success = bufferSize.IncrementInBounds(nextPos, allowBottomExclusive);
|
||||
if (success)
|
||||
{
|
||||
resultPos = nextPos;
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1621,15 +1675,21 @@ void UiaTextRangeBase::_moveEndpointByUnitDocument(_In_ const int moveCount,
|
|||
}
|
||||
|
||||
const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward;
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = _getOptimizedBufferSize();
|
||||
|
||||
const auto target = GetEndpoint(endpoint);
|
||||
switch (moveDirection)
|
||||
{
|
||||
case MovementDirection::Forward:
|
||||
{
|
||||
const auto documentEnd = bufferSize.EndExclusive();
|
||||
if (preventBoundary || target == documentEnd)
|
||||
auto documentEnd{ bufferSize.EndExclusive() };
|
||||
try
|
||||
{
|
||||
documentEnd = _getDocumentEnd();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
if (preventBoundary || bufferSize.CompareInBounds(target, documentEnd, true) >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,8 @@ namespace Microsoft::Console::Types
|
|||
virtual const COORD _getScreenFontSize() const;
|
||||
|
||||
const unsigned int _getViewportHeight(const SMALL_RECT viewport) const noexcept;
|
||||
const Viewport _getBufferSize() const noexcept;
|
||||
const Viewport _getOptimizedBufferSize() const noexcept;
|
||||
const til::point _getDocumentEnd() const;
|
||||
|
||||
void _getBoundingRect(const til::rectangle textRect, _Inout_ std::vector<double>& coords) const;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ $result = "// Copyright (c) Microsoft Corporation.
|
|||
// These were generated by tools\TestTableWriter\GenerateTests.ps1
|
||||
// Read tools\TestTableWriter\README.md for more details"
|
||||
|
||||
# TODO: THIS IS PROBABLY WRONG. Bottom/Right are exclusive (I think?)
|
||||
# 1. Define a few helpful variables to make life easier.
|
||||
$result += "
|
||||
// Define a few helpful variables
|
||||
|
@ -29,11 +28,16 @@ constexpr til::rectangle bufferSize{ 0, 0, 80, 300 };
|
|||
constexpr short midX{ 40 };
|
||||
constexpr short midY{ 150 };
|
||||
constexpr short midPopulatedY{ 75 };
|
||||
constexpr short segment0{ 0 };
|
||||
constexpr short segment1{ 16 };
|
||||
constexpr short segment2{ 32 };
|
||||
constexpr short segment3{ 48 };
|
||||
constexpr short segment4{ 64 };
|
||||
constexpr til::point origin{ 0, 0 };
|
||||
constexpr til::point midTop{ midX, 0 };
|
||||
constexpr til::point midHistory{ midX, midPopulatedY };
|
||||
constexpr til::point midDocEnd{ midX, midY };
|
||||
constexpr til::point lastCharPos{ 79, midY };
|
||||
constexpr til::point lastCharPos{ 72, midY };
|
||||
constexpr til::point docEnd{ 0, midY + 1 };
|
||||
constexpr til::point midEmptySpace{ midX, midY + midPopulatedY };
|
||||
constexpr til::point bufferEnd{ 79, 299 };
|
||||
|
@ -55,17 +59,33 @@ foreach ($test in $tests)
|
|||
$vars.Remove("origin") > $null;
|
||||
$vars.Remove("midTop") > $null;
|
||||
$vars.Remove("midHistory") > $null;
|
||||
$vars.Remove("midDocEnd") > $null;
|
||||
$vars.Remove("lastCharPos") > $null;
|
||||
$vars.Remove("docEnd") > $null;
|
||||
$vars.Remove("midEmptySpace") > $null;
|
||||
$vars.Remove("bufferEnd") > $null;
|
||||
$vars.Remove("endExclusive") > $null;
|
||||
|
||||
# 3.b. Now all of the remaining vars can be deduced from standard vars
|
||||
foreach ($var in $vars)
|
||||
{
|
||||
# Extract the standard var from the name
|
||||
$standardVar = $var.Contains("Left") ? $var.Split("Left") : $var.Substring(0, $var.length - 3);
|
||||
# Figure out what heuristic to use
|
||||
$segmentHeuristic = $var.Contains("segment");
|
||||
$leftHeuristic = $var.Contains("Left");
|
||||
$movementHeuristic = $var -match ".*\d+.*";
|
||||
|
||||
# i. Contains number --> requires movement
|
||||
if ($var -match ".*\d+.*")
|
||||
# i. Contains "segment" --> define point at the beginning of a text segment
|
||||
if ($segmentHeuristic)
|
||||
{
|
||||
$result += "constexpr til::point {0}{{ {1}, {2}.y() }};" -f $var, $var.Substring(0, 8), $var.Substring(9, $var.Length - $var.IndexOf("L") - 1);
|
||||
}
|
||||
# ii. Contains number --> requires movement
|
||||
elseif ($movementHeuristic)
|
||||
{
|
||||
# everything excluding last 3 characters denotes the standard variable
|
||||
# we're based on.
|
||||
$standardVar = $var.Substring(0, $var.length - 3);
|
||||
|
||||
# 3rd to last character denotes the movement direction
|
||||
# P --> plus/forwards
|
||||
# M --> minus/backwards
|
||||
|
@ -101,10 +121,11 @@ foreach ($var in $vars)
|
|||
Default { Write-Host "Error: unknown variable movement type" -ForegroundColor Red }
|
||||
}
|
||||
}
|
||||
# ii. Contains "Left" --> set X to left
|
||||
elseif ($var.Contains("Left"))
|
||||
# iii. Contains "Left" --> set X to left
|
||||
elseif ($leftHeuristic)
|
||||
{
|
||||
$result += "constexpr til::point " + $var + "{ bufferSize.left(), " + $standardVar + ".y() };";
|
||||
$standardVar = $var.Split("Left")[0]
|
||||
$result += "constexpr til::point {0}{{ bufferSize.left(), {1}.y() }};" -f $var, $standardVar;
|
||||
}
|
||||
$result += "`n";
|
||||
}
|
||||
|
|
|
@ -44,21 +44,21 @@ The Test Table Writer was written as a method to generate UI Automation tests fo
|
|||
- "Command Arguments" --> `$(TargetPath) /name:*uiatextrange*generated* /inproc`
|
||||
|
||||
# Position chart
|
||||
The text buffer is assumed to be partially filled. Specifically, the top half of the text buffer contains text, and each row is filled with 9 segments of alternating text. For visualization,
|
||||
The text buffer is assumed to be partially filled. Specifically, the top half of the text buffer contains text, and each row is filled with 10 segments of alternating text. For visualization,
|
||||
the ascii diagram below shows what the text buffer may look like.
|
||||
```
|
||||
+---------------------------+
|
||||
|1XX XXX X2X XXX XXX|
|
||||
|XXX XXX XXX XXX XXX|
|
||||
|XXX XXX X3X XXX XXX|
|
||||
|XXX XXX XXX XXX XXX|
|
||||
|XXX XXX X4X XXX XX5|
|
||||
|6 |
|
||||
| |
|
||||
| 7 |
|
||||
| |
|
||||
| 8|
|
||||
+---------------------------+
|
||||
+------------------------------+
|
||||
|1XX XXX X2X XXX XXX |
|
||||
|XXX XXX XXX XXX XXX |
|
||||
|XXX XXX X3X XXX XXX |
|
||||
|XXX XXX XXX XXX XXX |
|
||||
|XXX XXX X4X XXX XX5 |
|
||||
|6 |
|
||||
| |
|
||||
| 7 |
|
||||
| |
|
||||
| 8|
|
||||
+------------------------------+
|
||||
9
|
||||
```
|
||||
The following positions are being tested:
|
||||
|
@ -84,6 +84,11 @@ Each position above already has a predefined variable name. However, a few heuri
|
|||
- `C`: move by character. For simplicity, assumes that each character is one-cell wide.
|
||||
- `<name>P<number>L`, `<name>M<number>L`:
|
||||
- same as above, except move by line. For simplicity, assumes that you won't hit a buffer boundary.
|
||||
- `segment#L<name>`
|
||||
- This is mainly used for word navigation to target a segment of text in the buffer.
|
||||
- `segment#` refers to the beginning of a segment of text in a row. The leftmost run of text is `segment0`, whereas the rightmost run of text is `segment4`.
|
||||
- `L<name>` refers to the line number we're targeting, relative to the `<name>` variable. For example, `Lorigin` means that the y-position should be that of `origin`.
|
||||
- Overall, this allows us to target the beginning of segments of text. `segment0Lorigin` and `segment0LmidTop` both refer to the beginning of the first segment of text on the top line (aka `origin`).
|
||||
|
||||
# Helpful terms and concepts
|
||||
- *degenerate*: the text range encompasses no text. Also, means the start and end endpoints are the same.
|
||||
|
|
|
@ -62,195 +62,280 @@ FALSE,3,TextUnit_Line,5,midHistory,midHistoryP1C,5,midHistoryP5L,midHistoryP6L,F
|
|||
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,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,1,TextUnit_Document,1,origin,origin,1,docEnd,docEnd,FALSE
|
||||
TRUE,1,TextUnit_Document,5,origin,origin,1,docEnd,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,-5,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,-1,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,0,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,1,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,5,origin,originP1C,0,origin,docEnd,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,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,2,TextUnit_Document,1,midTop,midTop,1,docEnd,docEnd,FALSE
|
||||
TRUE,2,TextUnit_Document,5,midTop,midTop,1,docEnd,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,-5,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,-1,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,0,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,1,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,5,midTop,midTopP1C,0,origin,docEnd,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,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
|
||||
TRUE,8,TextUnit_Character,1,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
TRUE,8,TextUnit_Character,5,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Character,-5,bufferEnd,endExclusive,-5,bufferEndM5C,bufferEndM4C,FALSE
|
||||
FALSE,8,TextUnit_Character,-1,bufferEnd,endExclusive,-1,bufferEndM1C,bufferEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,0,bufferEnd,endExclusive,0,bufferEnd,endExclusive,FALSE
|
||||
FALSE,8,TextUnit_Character,1,bufferEnd,endExclusive,0,bufferEnd,endExclusive,FALSE
|
||||
FALSE,8,TextUnit_Character,5,bufferEnd,endExclusive,0,bufferEnd,endExclusive,FALSE
|
||||
TRUE,8,TextUnit_Line,-5,bufferEnd,bufferEnd,-5,bufferEndM4L,bufferEndM4L,FALSE
|
||||
TRUE,8,TextUnit_Line,-1,bufferEnd,bufferEnd,-1,bufferEndLeft,bufferEndLeft,FALSE
|
||||
TRUE,8,TextUnit_Line,0,bufferEnd,bufferEnd,0,bufferEnd,bufferEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,1,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
TRUE,8,TextUnit_Line,5,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Line,-5,bufferEnd,endExclusive,-5,bufferEndM5L,bufferEndM4L,TRUE
|
||||
FALSE,8,TextUnit_Line,-1,bufferEnd,endExclusive,-1,bufferEndM1L,bufferEndLeft,TRUE
|
||||
FALSE,8,TextUnit_Line,0,bufferEnd,endExclusive,0,bufferEndLeft,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Line,1,bufferEnd,endExclusive,0,bufferEndLeft,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Line,5,bufferEnd,endExclusive,0,bufferEndLeft,endExclusive,TRUE
|
||||
TRUE,3,TextUnit_Document,1,midHistory,midHistory,1,docEnd,docEnd,FALSE
|
||||
TRUE,3,TextUnit_Document,5,midHistory,midHistory,1,docEnd,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,-5,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,-1,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,0,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,1,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,5,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Character,-5,bufferEnd,bufferEnd,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,8,TextUnit_Character,-1,bufferEnd,bufferEnd,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,8,TextUnit_Character,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Character,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Character,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,-5,bufferEnd,endExclusive,-5,docEndM5C,docEndM5C,FALSE
|
||||
FALSE,8,TextUnit_Character,-1,bufferEnd,endExclusive,-1,docEndM1C,docEndM1C,FALSE
|
||||
FALSE,8,TextUnit_Character,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,-5,bufferEnd,bufferEnd,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,8,TextUnit_Line,-1,bufferEnd,bufferEnd,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,8,TextUnit_Line,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Line,-5,bufferEnd,endExclusive,-5,docEndM5L,docEndM5L,FALSE
|
||||
FALSE,8,TextUnit_Line,-1,bufferEnd,endExclusive,-1,docEndM1L,docEndM1L,FALSE
|
||||
FALSE,8,TextUnit_Line,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Line,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Line,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,-5,bufferEnd,bufferEnd,-1,origin,origin,FALSE
|
||||
TRUE,8,TextUnit_Document,-1,bufferEnd,bufferEnd,-1,origin,origin,FALSE
|
||||
TRUE,8,TextUnit_Document,0,bufferEnd,bufferEnd,0,bufferEnd,bufferEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,1,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
TRUE,8,TextUnit_Document,5,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,-5,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,-1,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,0,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,1,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,5,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
TRUE,9,TextUnit_Character,-5,endExclusive,endExclusive,-5,bufferEndM4C,bufferEndM4C,FALSE
|
||||
TRUE,9,TextUnit_Character,-1,endExclusive,endExclusive,-1,bufferEnd,bufferEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,0,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Character,1,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Character,5,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Line,-5,endExclusive,endExclusive,-5,bufferEndM4L,bufferEndM4L,FALSE
|
||||
TRUE,9,TextUnit_Line,-1,endExclusive,endExclusive,-1,bufferEndLeft,bufferEndLeft,FALSE
|
||||
TRUE,9,TextUnit_Line,0,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Line,1,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Line,5,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,8,TextUnit_Document,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Document,-5,bufferEnd,endExclusive,-1,origin,origin,FALSE
|
||||
FALSE,8,TextUnit_Document,-1,bufferEnd,endExclusive,-1,origin,origin,FALSE
|
||||
FALSE,8,TextUnit_Document,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Document,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Document,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,-5,endExclusive,endExclusive,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,9,TextUnit_Character,-1,endExclusive,endExclusive,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,9,TextUnit_Character,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Line,-5,endExclusive,endExclusive,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,9,TextUnit_Line,-1,endExclusive,endExclusive,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,9,TextUnit_Line,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Line,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Line,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Document,-5,endExclusive,endExclusive,-1,origin,origin,FALSE
|
||||
TRUE,9,TextUnit_Document,-1,endExclusive,endExclusive,-1,origin,origin,FALSE
|
||||
TRUE,9,TextUnit_Document,0,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Document,1,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Document,5,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,4,TextUnit_Character,-5,midDocEnd,midDocEnd,-5,midDocEndM5C,midDocEndM5C,TRUE
|
||||
TRUE,4,TextUnit_Character,-1,midDocEnd,midDocEnd,-1,midDocEndM1C,midDocEndM1C,TRUE
|
||||
TRUE,4,TextUnit_Character,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Character,1,midDocEnd,midDocEnd,1,midDocEndP1C,midDocEndP1C,TRUE
|
||||
TRUE,4,TextUnit_Character,5,midDocEnd,midDocEnd,5,midDocEndP5C,midDocEndP5C,TRUE
|
||||
FALSE,4,TextUnit_Character,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5C,midDocEndM4C,TRUE
|
||||
FALSE,4,TextUnit_Character,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1C,midDocEnd,TRUE
|
||||
FALSE,4,TextUnit_Character,0,midDocEnd,midDocEndP1C,0,midDocEnd,midDocEndP1C,TRUE
|
||||
FALSE,4,TextUnit_Character,1,midDocEnd,midDocEndP1C,1,midDocEndP1C,midDocEndP2C,TRUE
|
||||
FALSE,4,TextUnit_Character,5,midDocEnd,midDocEndP1C,5,midDocEndP5C,midDocEndP6C,TRUE
|
||||
TRUE,4,TextUnit_Line,-5,midDocEnd,midDocEnd,-5,midDocEndM4L,midDocEndM4L,TRUE
|
||||
TRUE,4,TextUnit_Line,-1,midDocEnd,midDocEnd,-1,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,4,TextUnit_Line,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Line,1,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
TRUE,4,TextUnit_Line,5,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Line,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5L,midDocEndM4L,TRUE
|
||||
FALSE,4,TextUnit_Line,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1L,midDocEndLeft,TRUE
|
||||
FALSE,4,TextUnit_Line,0,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Line,1,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Line,5,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,TRUE
|
||||
TRUE,4,TextUnit_Document,-5,midDocEnd,midDocEnd,-1,origin,origin,TRUE
|
||||
TRUE,4,TextUnit_Document,-1,midDocEnd,midDocEnd,-1,origin,origin,TRUE
|
||||
TRUE,4,TextUnit_Document,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Document,1,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
TRUE,4,TextUnit_Document,5,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,-5,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,-1,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,0,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,1,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,5,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Character,-5,lastCharPos,lastCharPos,-5,lastCharPosM5C,lastCharPosM5C,TRUE
|
||||
TRUE,5,TextUnit_Character,-1,lastCharPos,lastCharPos,-1,lastCharPosM1C,lastCharPosM1C,TRUE
|
||||
TRUE,5,TextUnit_Character,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,TRUE
|
||||
TRUE,5,TextUnit_Character,1,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Character,5,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Character,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5C,lastCharPosM4C,TRUE
|
||||
FALSE,5,TextUnit_Character,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1C,lastCharPos,TRUE
|
||||
FALSE,5,TextUnit_Character,0,lastCharPos,lastCharPosP1C,0,lastCharPos,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Character,1,lastCharPos,lastCharPosP1C,0,lastCharPos,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Character,5,lastCharPos,lastCharPosP1C,0,lastCharPos,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Line,-5,lastCharPos,lastCharPos,-5,lastCharPosM4L,lastCharPosM4L,TRUE
|
||||
TRUE,5,TextUnit_Line,-1,lastCharPos,lastCharPos,-1,lastCharPosLeft,lastCharPosLeft,TRUE
|
||||
TRUE,5,TextUnit_Line,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,TRUE
|
||||
TRUE,5,TextUnit_Line,1,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Line,5,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Line,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5L,lastCharPosM4L,TRUE
|
||||
FALSE,5,TextUnit_Line,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1L,lastCharPosLeft,TRUE
|
||||
FALSE,5,TextUnit_Line,0,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Line,1,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Line,5,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Document,-5,lastCharPos,lastCharPos,-1,origin,origin,TRUE
|
||||
TRUE,5,TextUnit_Document,-1,lastCharPos,lastCharPos,-1,origin,origin,TRUE
|
||||
TRUE,5,TextUnit_Document,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,TRUE
|
||||
TRUE,5,TextUnit_Document,1,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Document,5,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,-5,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,-1,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,0,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,1,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,5,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Character,-5,docEnd,docEnd,-5,docEndM5C,docEndM5C,TRUE
|
||||
TRUE,6,TextUnit_Character,-1,docEnd,docEnd,-1,docEndM1C,docEndM1C,TRUE
|
||||
TRUE,6,TextUnit_Character,0,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Character,1,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Character,5,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Character,-5,docEnd,docEndP1C,-5,docEndM5C,docEndM5C,TRUE
|
||||
FALSE,6,TextUnit_Character,-1,docEnd,docEndP1C,-1,docEndM1C,docEndM1C,TRUE
|
||||
FALSE,6,TextUnit_Character,0,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Character,1,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Character,5,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Line,-5,docEnd,docEnd,-5,docEndM4L,docEndM4L,TRUE
|
||||
TRUE,6,TextUnit_Line,-1,docEnd,docEnd,-1,docEndLeft,docEndLeft,TRUE
|
||||
TRUE,6,TextUnit_Line,0,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Line,1,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Line,5,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Line,-5,docEnd,docEndP1C,-5,docEndM4L,docEndM4L,TRUE
|
||||
FALSE,6,TextUnit_Line,-1,docEnd,docEndP1C,-1,docEndLeft,docEndLeft,TRUE
|
||||
FALSE,6,TextUnit_Line,0,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Line,1,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Line,5,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Document,-5,docEnd,docEnd,-1,origin,origin,TRUE
|
||||
TRUE,6,TextUnit_Document,-1,docEnd,docEnd,-1,origin,origin,TRUE
|
||||
TRUE,6,TextUnit_Document,0,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Document,1,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Document,5,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Document,-5,docEnd,docEndP1C,-1,origin,origin,TRUE
|
||||
FALSE,6,TextUnit_Document,-1,docEnd,docEndP1C,-1,origin,origin,TRUE
|
||||
FALSE,6,TextUnit_Document,0,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Document,1,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Document,5,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpace,-5,docEndM5C,docEndM5C,TRUE
|
||||
TRUE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpace,-1,docEndM1C,docEndM1C,TRUE
|
||||
TRUE,7,TextUnit_Character,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Character,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Character,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM5C,docEndM5C,TRUE
|
||||
FALSE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndM1C,docEndM1C,TRUE
|
||||
FALSE,7,TextUnit_Character,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Character,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Character,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpace,-5,docEndM4L,docEndM4L,TRUE
|
||||
TRUE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpace,-1,docEndLeft,docEndLeft,TRUE
|
||||
TRUE,7,TextUnit_Line,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Line,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Line,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM4L,docEndM4L,TRUE
|
||||
FALSE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndLeft,docEndLeft,TRUE
|
||||
FALSE,7,TextUnit_Line,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Line,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Line,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpace,-1,origin,origin,TRUE
|
||||
TRUE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpace,-1,origin,origin,TRUE
|
||||
TRUE,7,TextUnit_Document,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Document,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Document,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,TRUE
|
||||
FALSE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,TRUE
|
||||
FALSE,7,TextUnit_Document,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Document,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Document,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,9,TextUnit_Document,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Document,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Document,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Character,-5,midDocEnd,midDocEnd,-5,midDocEndM5C,midDocEndM5C,FALSE
|
||||
TRUE,4,TextUnit_Character,-1,midDocEnd,midDocEnd,-1,midDocEndM1C,midDocEndM1C,FALSE
|
||||
TRUE,4,TextUnit_Character,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Character,1,midDocEnd,midDocEnd,1,midDocEndP1C,midDocEndP1C,FALSE
|
||||
TRUE,4,TextUnit_Character,5,midDocEnd,midDocEnd,5,midDocEndP5C,midDocEndP5C,FALSE
|
||||
FALSE,4,TextUnit_Character,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5C,midDocEndM4C,FALSE
|
||||
FALSE,4,TextUnit_Character,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1C,midDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Character,0,midDocEnd,midDocEndP1C,0,midDocEnd,midDocEndP1C,FALSE
|
||||
FALSE,4,TextUnit_Character,1,midDocEnd,midDocEndP1C,1,midDocEndP1C,midDocEndP2C,FALSE
|
||||
FALSE,4,TextUnit_Character,5,midDocEnd,midDocEndP1C,5,midDocEndP5C,midDocEndP6C,FALSE
|
||||
TRUE,4,TextUnit_Line,-5,midDocEnd,midDocEnd,-5,midDocEndM4L,midDocEndM4L,FALSE
|
||||
TRUE,4,TextUnit_Line,-1,midDocEnd,midDocEnd,-1,midDocEndLeft,midDocEndLeft,FALSE
|
||||
TRUE,4,TextUnit_Line,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Line,1,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Line,5,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Line,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5L,midDocEndM4L,FALSE
|
||||
FALSE,4,TextUnit_Line,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1L,midDocEndLeft,FALSE
|
||||
FALSE,4,TextUnit_Line,0,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Line,1,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Line,5,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Document,-5,midDocEnd,midDocEnd,-1,origin,origin,FALSE
|
||||
TRUE,4,TextUnit_Document,-1,midDocEnd,midDocEnd,-1,origin,origin,FALSE
|
||||
TRUE,4,TextUnit_Document,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Document,1,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Document,5,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,-5,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,-1,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,0,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,1,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,5,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Character,-5,lastCharPos,lastCharPos,-5,lastCharPosM5C,lastCharPosM5C,FALSE
|
||||
TRUE,5,TextUnit_Character,-1,lastCharPos,lastCharPos,-1,lastCharPosM1C,lastCharPosM1C,FALSE
|
||||
TRUE,5,TextUnit_Character,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Character,1,lastCharPos,lastCharPos,1,lastCharPosP1C,lastCharPosP1C,FALSE
|
||||
TRUE,5,TextUnit_Character,5,lastCharPos,lastCharPos,5,lastCharPosP5C,lastCharPosP5C,FALSE
|
||||
FALSE,5,TextUnit_Character,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5C,lastCharPosM4C,FALSE
|
||||
FALSE,5,TextUnit_Character,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1C,lastCharPos,FALSE
|
||||
FALSE,5,TextUnit_Character,0,lastCharPos,lastCharPosP1C,0,lastCharPos,lastCharPosP1C,FALSE
|
||||
FALSE,5,TextUnit_Character,1,lastCharPos,lastCharPosP1C,1,lastCharPosP1C,lastCharPosP2C,FALSE
|
||||
FALSE,5,TextUnit_Character,5,lastCharPos,lastCharPosP1C,5,lastCharPosP5C,lastCharPosP6C,FALSE
|
||||
TRUE,5,TextUnit_Line,-5,lastCharPos,lastCharPos,-5,lastCharPosM4L,lastCharPosM4L,FALSE
|
||||
TRUE,5,TextUnit_Line,-1,lastCharPos,lastCharPos,-1,lastCharPosLeft,lastCharPosLeft,FALSE
|
||||
TRUE,5,TextUnit_Line,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Line,1,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Line,5,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Line,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5L,lastCharPosM4L,FALSE
|
||||
FALSE,5,TextUnit_Line,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1L,lastCharPosLeft,FALSE
|
||||
FALSE,5,TextUnit_Line,0,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Line,1,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Line,5,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Document,-5,lastCharPos,lastCharPos,-1,origin,origin,FALSE
|
||||
TRUE,5,TextUnit_Document,-1,lastCharPos,lastCharPos,-1,origin,origin,FALSE
|
||||
TRUE,5,TextUnit_Document,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Document,1,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Document,5,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,-5,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,-1,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,0,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,1,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,5,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Character,-5,docEnd,docEnd,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,6,TextUnit_Character,-1,docEnd,docEnd,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,6,TextUnit_Character,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Character,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Character,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Character,-5,docEnd,docEndP1C,-5,docEndM5C,docEndM5C,FALSE
|
||||
FALSE,6,TextUnit_Character,-1,docEnd,docEndP1C,-1,docEndM1C,docEndM1C,FALSE
|
||||
FALSE,6,TextUnit_Character,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Character,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Character,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Line,-5,docEnd,docEnd,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,6,TextUnit_Line,-1,docEnd,docEnd,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,6,TextUnit_Line,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Line,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Line,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Line,-5,docEnd,docEndP1C,-5,docEndM5L,docEndM5L,FALSE
|
||||
FALSE,6,TextUnit_Line,-1,docEnd,docEndP1C,-1,docEndM1L,docEndM1L,FALSE
|
||||
FALSE,6,TextUnit_Line,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Line,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Line,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Document,-5,docEnd,docEnd,-1,origin,origin,FALSE
|
||||
TRUE,6,TextUnit_Document,-1,docEnd,docEnd,-1,origin,origin,FALSE
|
||||
TRUE,6,TextUnit_Document,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Document,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Document,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Document,-5,docEnd,docEndP1C,-1,origin,origin,FALSE
|
||||
FALSE,6,TextUnit_Document,-1,docEnd,docEndP1C,-1,origin,origin,FALSE
|
||||
FALSE,6,TextUnit_Document,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Document,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Document,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpace,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpace,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,7,TextUnit_Character,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Character,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Character,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM5C,docEndM5C,FALSE
|
||||
FALSE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndM1C,docEndM1C,FALSE
|
||||
FALSE,7,TextUnit_Character,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Character,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Character,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpace,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpace,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,7,TextUnit_Line,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Line,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Line,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM5L,docEndM5L,FALSE
|
||||
FALSE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndM1L,docEndM1L,FALSE
|
||||
FALSE,7,TextUnit_Line,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Line,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Line,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpace,-1,origin,origin,FALSE
|
||||
TRUE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpace,-1,origin,origin,FALSE
|
||||
TRUE,7,TextUnit_Document,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Document,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Document,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,FALSE
|
||||
FALSE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,FALSE
|
||||
FALSE,7,TextUnit_Document,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Document,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Document,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,1,TextUnit_Word,-5,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Word,-1,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Word,0,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Word,1,origin,origin,1,segment1LmidTop,segment1LmidTop,FALSE
|
||||
TRUE,1,TextUnit_Word,5,origin,origin,5,segment0LmidTopP1L,segment0LmidTopP1L,FALSE
|
||||
FALSE,1,TextUnit_Word,-5,origin,originP1C,0,origin,segment1LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,-1,origin,originP1C,0,origin,segment1LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,0,origin,originP1C,0,origin,segment1LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,1,origin,originP1C,1,segment1LmidTop,segment2LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,5,origin,originP1C,5,segment0LmidTopP1L,segment1LmidTopP1L,FALSE
|
||||
TRUE,2,TextUnit_Word,-5,midTop,midTop,-3,origin,origin,TRUE
|
||||
TRUE,2,TextUnit_Word,-1,midTop,midTop,-1,segment2LmidTop,segment2LmidTop,TRUE
|
||||
TRUE,2,TextUnit_Word,0,midTop,midTop,0,midTop,midTop,FALSE
|
||||
TRUE,2,TextUnit_Word,1,midTop,midTop,1,segment3LmidTop,segment3LmidTop,FALSE
|
||||
TRUE,2,TextUnit_Word,5,midTop,midTop,5,segment2LmidTopP1L,segment2LmidTopP1L,FALSE
|
||||
FALSE,2,TextUnit_Word,-5,midTop,midTopP1C,-2,origin,segment1LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,-1,midTop,midTopP1C,-1,segment1LmidTop,segment2LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,0,midTop,midTopP1C,0,segment2LmidTop,segment3LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,1,midTop,midTopP1C,1,segment3LmidTop,segment4LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,5,midTop,midTopP1C,5,segment2LmidTopP1L,segment3LmidTopP1L,FALSE
|
||||
TRUE,3,TextUnit_Word,-5,midHistory,midHistory,-5,segment3LmidHistoryM1L,segment3LmidHistoryM1L,TRUE
|
||||
TRUE,3,TextUnit_Word,-1,midHistory,midHistory,-1,segment2LmidHistory,segment2LmidHistory,TRUE
|
||||
TRUE,3,TextUnit_Word,0,midHistory,midHistory,0,midHistory,midHistory,FALSE
|
||||
TRUE,3,TextUnit_Word,1,midHistory,midHistory,1,segment3LmidHistory,segment3LmidHistory,FALSE
|
||||
TRUE,3,TextUnit_Word,5,midHistory,midHistory,5,segment2LmidHistoryP1L,segment2LmidHistoryP1L,FALSE
|
||||
FALSE,3,TextUnit_Word,-5,midHistory,midHistoryP1C,-5,segment3LmidHistoryM1L,segment4LmidHistoryM1L,TRUE
|
||||
FALSE,3,TextUnit_Word,-1,midHistory,midHistoryP1C,-1,segment1LmidHistory,segment2LmidHistory,FALSE
|
||||
FALSE,3,TextUnit_Word,0,midHistory,midHistoryP1C,0,segment2LmidHistory,segment3LmidHistory,FALSE
|
||||
FALSE,3,TextUnit_Word,1,midHistory,midHistoryP1C,1,segment3LmidHistory,segment4LmidHistory,FALSE
|
||||
FALSE,3,TextUnit_Word,5,midHistory,midHistoryP1C,5,segment2LmidHistoryP1L,segment3LmidHistoryP1L,FALSE
|
||||
TRUE,4,TextUnit_Word,-5,midDocEnd,midDocEnd,-5,segment3LmidDocEndM1L,segment3LmidDocEndM1L,TRUE
|
||||
TRUE,4,TextUnit_Word,-1,midDocEnd,midDocEnd,-1,segment2LmidDocEnd,segment2LmidDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Word,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Word,1,midDocEnd,midDocEnd,1,segment3LmidDocEnd,segment3LmidDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Word,5,midDocEnd,midDocEnd,3,docEnd,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,-5,midDocEnd,midDocEndP1C,-5,segment3LmidDocEndM1L,segment4LmidDocEndM1L,TRUE
|
||||
FALSE,4,TextUnit_Word,-1,midDocEnd,midDocEndP1C,-1,segment1LmidDocEnd,segment2LmidDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,0,midDocEnd,midDocEndP1C,0,segment2LmidDocEnd,segment3LmidDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,1,midDocEnd,midDocEndP1C,1,segment3LmidDocEnd,segment4LmidDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,5,midDocEnd,midDocEndP1C,2,segment4LmidDocEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Word,-5,lastCharPos,lastCharPos,-5,lastCharPosLeft,lastCharPosLeft,TRUE
|
||||
TRUE,5,TextUnit_Word,-1,lastCharPos,lastCharPos,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,5,TextUnit_Word,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Word,1,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Word,5,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,-5,lastCharPos,lastCharPosP1C,-5,segment4LlastCharPosM1L,lastCharPosLeft,FALSE
|
||||
FALSE,5,TextUnit_Word,-1,lastCharPos,lastCharPosP1C,-1,segment3LmidDocEnd,segment4LmidDocEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,0,lastCharPos,lastCharPosP1C,0,segment4LmidDocEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,1,lastCharPos,lastCharPosP1C,0,segment4LmidDocEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,5,lastCharPos,lastCharPosP1C,0,segment4LmidDocEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Word,-5,docEnd,docEnd,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,6,TextUnit_Word,-1,docEnd,docEnd,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,6,TextUnit_Word,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Word,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Word,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Word,-5,docEnd,docEndP1C,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
FALSE,6,TextUnit_Word,-1,docEnd,docEndP1C,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
FALSE,6,TextUnit_Word,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Word,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Word,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Word,-5,midEmptySpace,midEmptySpace,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,7,TextUnit_Word,-1,midEmptySpace,midEmptySpace,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,7,TextUnit_Word,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Word,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Word,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Word,-5,midEmptySpace,midEmptySpaceP1C,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
FALSE,7,TextUnit_Word,-1,midEmptySpace,midEmptySpaceP1C,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
FALSE,7,TextUnit_Word,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Word,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Word,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Word,-5,bufferEnd,bufferEnd,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,8,TextUnit_Word,-1,bufferEnd,bufferEnd,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,8,TextUnit_Word,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Word,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Word,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Word,-5,bufferEnd,endExclusive,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
FALSE,8,TextUnit_Word,-1,bufferEnd,endExclusive,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
FALSE,8,TextUnit_Word,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Word,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Word,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Word,-5,endExclusive,endExclusive,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,9,TextUnit_Word,-1,endExclusive,endExclusive,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,9,TextUnit_Word,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Word,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Word,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
|
|
|
Loading…
Reference in New Issue