Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize start Text pointer to support Text Cursor Indicator #10333

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ static TextRangeAdaptor()
},
delegate(object val1, object val2) { return (double)val1 == (double)val2; })
);
// OutlineStyles
// OutlineStyles
_textPatternAttributes.Add(
TextPatternIdentifiers.OutlineStylesAttribute,
new TextAttributeHelper(
Expand Down Expand Up @@ -466,12 +466,12 @@ internal TextRangeAdaptor(TextAdaptor textAdaptor, ITextPointer start, ITextPoin
_end = end.CreatePointer();
_textPeer = textPeer;
}
#endregion Constructors
#endregion Constructors

#region Internal methods

/// <summary>
/// This wrapper is to cover up a shortcoming in MoveToInsertionPosition code.
/// This wrapper is to cover up a shortcoming in MoveToInsertionPosition code.
/// If the position is inside a Hyperlink, it is being moved out of the hyperlink and to the previous
/// insertion position which can be on the previous line (or unit) and this is creating problems
/// This is a temporary solution until we find a better solution to handle the case
Expand All @@ -487,7 +487,7 @@ internal static bool MoveToInsertionPosition(ITextPointer position, LogicalDirec
return false;
}
#endregion Internal methods




Expand Down Expand Up @@ -545,7 +545,7 @@ private void ExpandToEnclosingUnit(TextUnit unit, bool expandStart, bool expandE
break;

case TextUnit.Format:
// Formatting changes can be introduced by elements. Hence it is fair to
// Formatting changes can be introduced by elements. Hence it is fair to
// assume that formatting boundaries are defined by non-text context.

if (expandStart)
Expand Down Expand Up @@ -749,7 +749,7 @@ private bool MoveToUnitBoundary(ITextPointer position, bool isStart, LogicalDire
break;

case TextUnit.Format:
// Formatting changes can be introduced by elements. Hence it is fair to
// Formatting changes can be introduced by elements. Hence it is fair to
// assume that formatting boundaries are defined by non-text context.
while (position.GetPointerContext(direction) == TextPointerContext.Text)
{
Expand Down Expand Up @@ -915,9 +915,9 @@ private bool MoveToUnitBoundary(ITextPointer position, bool isStart, LogicalDire

if (textSegments != null && textSegments.Count > 0)
{
//When comparing, we need to take into account if the pointer is not right at
//When comparing, we need to take into account if the pointer is not right at
//the end of the page (or beginning) because of normalization

if (direction == LogicalDirection.Forward)
{
while (position.CompareTo(textSegments[textSegments.Count - 1].End) != 0)
Expand Down Expand Up @@ -983,7 +983,7 @@ private bool MoveToUnitBoundary(ITextPointer position, bool isStart, LogicalDire
/// </summary>
/// <param name="position">The position to move</param>
/// <param name="unit">Text units to step by</param>
/// <param name="count">Number of units to step over. Also specifies the direction of moving:
/// <param name="count">Number of units to step over. Also specifies the direction of moving:
/// forward if positive, backward otherwise</param>
/// <returns>The actual number of units the position was moved over</returns>
private int MovePositionByUnits(ITextPointer position, TextUnit unit, int count)
Expand Down Expand Up @@ -1020,7 +1020,7 @@ private int MovePositionByUnits(ITextPointer position, TextUnit unit, int count)
break;

case TextUnit.Format:
// Formatting changes can be introduced by elements. Hence it is fair to
// Formatting changes can be introduced by elements. Hence it is fair to
// assume that formatting boundaries are defined by non-text context.
while (moved < absCount)
{
Expand Down Expand Up @@ -1093,15 +1093,15 @@ private int MovePositionByUnits(ITextPointer position, TextUnit unit, int count)
}

moved = position.MoveToLineBoundary(count);

MoveToInsertionPosition(position, LogicalDirection.Forward);

if (moved < 0)
{
moved = -moved; // Will be reversed below.
}
}
break;
break;

case TextUnit.Paragraph:
// Utilize TextRange logic to determine paragraph boundaries.
Expand Down Expand Up @@ -1337,11 +1337,11 @@ private static TextDecorationLineStyle GetTextDecorationLineStyle(TextDecoration
{
if (lineStyle == TextDecorationLineStyle.None)
{
// There's a whole bunch of all kinds of custom styles defined in TextDecorationLineStyle
// including WordsOnly, Double, Wavy, DoubleWavy, ThickWavy, which we can not determine from
// TextDecoration anyway. Hence, it seems would be too much bang for a buck if we try
// to guess out the other dozen by analyzing TextDecoration.Pen. Let's keep it simple
// and make difference only between solid and dashed lines.
// There's a whole bunch of all kinds of custom styles defined in TextDecorationLineStyle
// including WordsOnly, Double, Wavy, DoubleWavy, ThickWavy, which we can not determine from
// TextDecoration anyway. Hence, it seems would be too much bang for a buck if we try
// to guess out the other dozen by analyzing TextDecoration.Pen. Let's keep it simple
// and make difference only between solid and dashed lines.
if (decor.Pen != null)
{
lineStyle = (decor.Pen.DashStyle.Dashes.Count > 1) ? TextDecorationLineStyle.Dash : TextDecorationLineStyle.Single;
Expand Down Expand Up @@ -1432,8 +1432,8 @@ private List<AutomationPeer> GetAutomationPeersFromRange(AutomationPeer peer, IT
}

/// <summary>
/// Helper function to check if given position is at word boundary. TextPointerBase.IsAtWordBoundary
/// cannot be used for not normalized positions, because it will always return TRUE, but in fact such
/// Helper function to check if given position is at word boundary. TextPointerBase.IsAtWordBoundary
/// cannot be used for not normalized positions, because it will always return TRUE, but in fact such
/// position is not in world boundary.
/// </summary>
private static bool IsAtWordBoundary(ITextPointer position)
Expand All @@ -1447,7 +1447,7 @@ private static bool IsAtWordBoundary(ITextPointer position)
}

/// <summary>
/// Helper function to move given position to word boundary. TextPointerBase.MoveToNextWordBoundary
/// Helper function to move given position to word boundary. TextPointerBase.MoveToNextWordBoundary
/// cannot be used directly, because it does not modify LogicalDirection. Because of that, IsAtWordBoundary
/// for just moved positions may return FALSE.
/// </summary>
Expand Down Expand Up @@ -1490,7 +1490,7 @@ private void Normalize()
{
MoveToInsertionPosition(_start, _start.LogicalDirection);
MoveToInsertionPosition(_end, _end.LogicalDirection);

// If start passes end, move the entire range to the start position.
if (_start.CompareTo(_end) > 0)
{
Expand Down Expand Up @@ -1540,7 +1540,7 @@ private ITextPointer GetInsertionPosition(ITextPointer position, LogicalDirectio
#region Private Types

/// <summary>
///
///
/// </summary>
private class TextAttributeHelper
{
Expand Down Expand Up @@ -1582,7 +1582,7 @@ ITextRangeProvider ITextRangeProvider.Clone()
/// <summary>
/// Compares this range with another range.
/// </summary>
/// <param name="range">A range to compare.
/// <param name="range">A range to compare.
/// The range must have come from the same text provider or an InvalidArgumentException will be thrown.</param>
/// <returns>true if both ranges span the same text.</returns>
bool ITextRangeProvider.Compare(ITextRangeProvider range)
Expand All @@ -1604,8 +1604,8 @@ bool ITextRangeProvider.Compare(ITextRangeProvider range)
/// <param name="targetRange">The range with the other endpoint to compare.
/// The range must have come from the same text provider or an InvalidArgumentException will be thrown.</param>
/// <param name="targetEndpoint">The endpoint on the other range to compare.</param>
/// <returns>Returns &lt;0 if this endpoint occurs earlier in the text than the target endpoint.
/// Returns 0 if this endpoint is at the same location as the target endpoint.
/// <returns>Returns &lt;0 if this endpoint occurs earlier in the text than the target endpoint.
/// Returns 0 if this endpoint is at the same location as the target endpoint.
/// Returns &gt;0 if this endpoint occurs later in the text than the target endpoint.</returns>
int ITextRangeProvider.CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider targetRange, TextPatternRangeEndpoint targetEndpoint)
{
Expand All @@ -1631,7 +1631,7 @@ void ITextRangeProvider.ExpandToEnclosingUnit(TextUnit unit)
{
Normalize();

// TextPattern spec update: End EndPoint moves to the end of the same TextUnit that
// TextPattern spec update: End EndPoint moves to the end of the same TextUnit that
// Start EndPoint is within (whether it was within that unit originally or not).
// To support this scenario always move _end to the next position after _start.
_end.MoveToPosition(_start);
Expand Down Expand Up @@ -1672,7 +1672,7 @@ ITextRangeProvider ITextRangeProvider.FindAttribute(int attributeId, object valu
ITextPointer stop = _start;
ITextPointer position = _end.CreatePointer(LogicalDirection.Backward);

// Go backward from the range end position until we find a position that
// Go backward from the range end position until we find a position that
// has our attribute or we hit the start position of the search range.
attrStart = stop;
while (position.CompareTo(stop) > 0)
Expand Down Expand Up @@ -1703,7 +1703,7 @@ ITextRangeProvider ITextRangeProvider.FindAttribute(int attributeId, object valu
ITextPointer stop = _end;
ITextPointer position = _start.CreatePointer(LogicalDirection.Forward);

// Go backward from the range end position until we find a position that
// Go backward from the range end position until we find a position that
// has our attribute or we hit the start position of the search range.
attrEnd = stop;
while (position.CompareTo(stop) < 0)
Expand Down Expand Up @@ -1782,13 +1782,13 @@ ITextRangeProvider ITextRangeProvider.FindText(string text, bool backward, bool
/// Retrieves the value of a text attribute over the entire range.
/// </summary>
/// <param name="attributeId">The text attribute.</param>
/// <returns>The value of the attribute across the range.
/// <returns>The value of the attribute across the range.
/// If the attribute's value varies over the range then the value is TextPattern.MixedAttributeValue</returns>
object ITextRangeProvider.GetAttributeValue(int attributeId)
{
AutomationTextAttribute attribute = AutomationTextAttribute.LookupById(attributeId);


// In Windows 8, a new text attribute was introduced that WPF does not have any reference for
// this caused WPF to throw an ArgumentException. This code path was strange as we already can
// return NotSupported, which is a valid response. So change this to no longer throw.
Expand All @@ -1811,9 +1811,10 @@ object ITextRangeProvider.GetAttributeValue(int attributeId)
/// This will not return null, but may return an empty array.</returns>
double[] ITextRangeProvider.GetBoundingRectangles()
{
Rect[] rects = _textAdaptor.GetBoundingRectangles(_start, _end, true, true);

Normalize();

Rect[] rects = _textAdaptor.GetBoundingRectangles(_start, _end, true, true);
double[] asDoubles = new double[rects.Length * 4];
for (int i = 0; i < rects.Length; i++)
{
Expand Down Expand Up @@ -1864,18 +1865,18 @@ string ITextRangeProvider.GetText(int maxLength)
/// <summary>
/// Moves the range the specified number of units in the text. Note that the text is not altered. Instead the
/// range spans a different part of the text.
/// If the range is degenerate, this method tries to move the insertion point count units. If the range is nondegenerate
/// and count is greater than zero, this method collapses the range at its end point, moves the resulting range forward
/// to a unit boundary (if it is not already at one), and then tries to move count - 1 units forward. If the range is
/// nondegenerate and count is less than zero, this method collapses the range at the starting point, moves the resulting
/// range backward to a unit boundary (if it isn't already at one), and then tries to move |count| - 1 units backward.
/// Thus, in both cases, collapsing a nondegenerate range, whether or not moving to the start or end of the unit following
/// If the range is degenerate, this method tries to move the insertion point count units. If the range is nondegenerate
/// and count is greater than zero, this method collapses the range at its end point, moves the resulting range forward
/// to a unit boundary (if it is not already at one), and then tries to move count - 1 units forward. If the range is
/// nondegenerate and count is less than zero, this method collapses the range at the starting point, moves the resulting
/// range backward to a unit boundary (if it isn't already at one), and then tries to move |count| - 1 units backward.
/// Thus, in both cases, collapsing a nondegenerate range, whether or not moving to the start or end of the unit following
/// the collapse, counts as a unit.
/// </summary>
/// <param name="unit">The textual unit for moving.</param>
/// <param name="count">The number of units to move. A positive count moves the range forward.
/// <param name="count">The number of units to move. A positive count moves the range forward.
/// A negative count moves backward. A count of 0 has no effect.</param>
/// <returns>The number of units actually moved, which can be less than the number requested if
/// <returns>The number of units actually moved, which can be less than the number requested if
/// moving the range runs into the beginning or end of the document.</returns>
int ITextRangeProvider.Move(TextUnit unit, int count)
{
Expand Down Expand Up @@ -1908,7 +1909,7 @@ int ITextRangeProvider.Move(TextUnit unit, int count)
{
_end.MoveToNextInsertionPosition(LogicalDirection.Forward);
}

ExpandToEnclosingUnit(unit, true, true);
// If endpoint has been moved, but 'movedCount' is 0, it means that we snapped to neariest
// unit boundary. Treat this situation as actual move.
Expand All @@ -1929,9 +1930,9 @@ int ITextRangeProvider.Move(TextUnit unit, int count)
/// </summary>
/// <param name="endpoint">The endpoint to move.</param>
/// <param name="unit">The textual unit for moving.</param>
/// <param name="count">The number of units to move. A positive count moves the endpoint forward.
/// <param name="count">The number of units to move. A positive count moves the endpoint forward.
/// A negative count moves backward. A count of 0 has no effect.</param>
/// <returns>The number of units actually moved, which can be less than the number requested if
/// <returns>The number of units actually moved, which can be less than the number requested if
/// moving the endpoint runs into the beginning or end of the document.</returns>
int ITextRangeProvider.MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, int count)
{
Expand All @@ -1955,7 +1956,7 @@ int ITextRangeProvider.MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, Tex

// If endpoint has been moved at least by one unit, snap it to TextUnit boundary,
// because movement done by MovePositionByUnits does not guarantee position snapping.
if ((count > 0 && position.CompareTo(positionRef) > 0) ||
if ((count > 0 && position.CompareTo(positionRef) > 0) ||
(count < 0 && position.CompareTo(positionRef) < 0) ||
(position.CompareTo(positionRef) == 0 && position.LogicalDirection != positionRef.LogicalDirection))
{
Expand Down Expand Up @@ -2027,7 +2028,7 @@ void ITextRangeProvider.MoveEndpointByRange(TextPatternRangeEndpoint endpoint, I

/// <summary>
/// Selects the text of the range within the provider. If the provider does not have a concept of selection then
/// it should return false for ITextProvider.SupportsTextSelection property and throw an InvalidOperation
/// it should return false for ITextProvider.SupportsTextSelection property and throw an InvalidOperation
/// exception for this method.
/// </summary>
void ITextRangeProvider.Select()
Expand All @@ -2044,7 +2045,7 @@ void ITextRangeProvider.Select()

/// <summary>
/// Adds the text of the range to the current selection. If the provider does not have a concept of selection
/// or does not support multiple disjoint selection then it throw an InvalidOperation
/// or does not support multiple disjoint selection then it throw an InvalidOperation
/// exception for this method.
/// </summary>
void ITextRangeProvider.AddToSelection()
Expand All @@ -2054,7 +2055,7 @@ void ITextRangeProvider.AddToSelection()

/// <summary>
/// Removes the text of the range from the current selection. If the provider does not have a concept of selection
/// or does not support multiple disjoint selection then it throw an InvalidOperation
/// or does not support multiple disjoint selection then it throw an InvalidOperation
/// exception for this method.
/// </summary>
void ITextRangeProvider.RemoveFromSelection()
Expand Down