private void ScrollHorizontallyToPoint(MouseTextPosition position)
        {
            if (position.Horizontal == HorizontalBounds.Inside)
            {
                return;
            }

            // If outside to the left then reset the viewport all the way to the start first
            if (position.Horizontal == HorizontalBounds.Left)
            {
                this.textView.ViewportLeft = 0;
            }

            // Ensure the position is visible, either if we were off the right or if
            // we were off to the left and went too far by resetting the viewport left to 0
            this.textView.ViewScroller.EnsureSpanVisible(
                this.textView.GetTextElementSpan(position.Point));
        }
        private MouseTextPosition GetMouseTextPosition(MouseEventArgs args)
        {
            var mousePoint = args?.GetPosition(this.textView.VisualElement) ??
                             Mouse.GetPosition(this.textView.VisualElement);

            var result = new MouseTextPosition {
                Horizontal = HorizontalBounds.Inside
            };

            // Find the line we are interested in based on mouse position
            ITextViewLine line;

            if (mousePoint.Y <= 0)
            {
                line            = this.textView.TextViewLines.FirstVisibleLine;
                result.Vertical = VerticalBounds.Above;
            }
            else if (mousePoint.Y >= this.textView.ViewportBottom - this.textView.ViewportTop)
            {
                line            = this.textView.TextViewLines.LastVisibleLine;
                result.Vertical = VerticalBounds.Below;
            }
            else
            {
                // If GetTextViewLineContainingYCoordinate returns null in this situation
                // then since we are within the viewport we know we must have scrolled all
                // the way to the end of the document and the mosue must be over the viewport
                // space showing after the end of the document hence in that case we select the
                // last line.
                line = this.textView.TextViewLines.GetTextViewLineContainingYCoordinate(
                    mousePoint.Y + this.textView.ViewportTop)
                       ?? this.textView.TextViewLines.LastVisibleLine;

                result.Vertical = VerticalBounds.Inside;
            }

            var x = mousePoint.X + this.textView.ViewportLeft;

            // If the mouse is outside the viewport to right or left then
            // select the first or last point on the line
            if (x < this.textView.ViewportLeft)
            {
                result.Point = line.Start;
                if (line.TextLeft < this.textView.ViewportLeft)
                {
                    result.Horizontal = HorizontalBounds.Left;
                }
                else if (line.TextLeft > this.textView.ViewportRight)
                {
                    result.Horizontal = HorizontalBounds.Right;
                }

                return(result);
            }

            if (x > this.textView.ViewportRight)
            {
                result.Point = line.End;
                if (line.TextRight > this.textView.ViewportRight)
                {
                    result.Horizontal = HorizontalBounds.Right;
                }
                else if (line.TextRight < this.textView.ViewportLeft)
                {
                    result.Horizontal = HorizontalBounds.Left;
                }

                return(result);
            }

            // Find and adjust the desired point based on x position
            var point = line.GetBufferPositionFromXCoordinate(x);

            if (point.HasValue)
            {
                // The point will always be for the charecter that the mouse is over
                // however it feels far more natural (and VS selection does this) to
                // select a charecter based on the closest start point to the mouse.
                // Here we select the next charecter if its start position is closer.
                var bounds = line.GetCharacterBounds(point.Value);
                if (x > (bounds.Left + (bounds.Width / 2)))
                {
                    result.Point = line.GetBufferPositionFromXCoordinate(x + bounds.Width) ?? point.Value;
                    return(result);
                }

                result.Point = point.Value;
                return(result);
            }

            // If we get here the line does not go all the way to the viewport right
            // side and we are past the end of the line but inside the viewport
            result.Point = line.End;
            if (line.TextRight < this.textView.ViewportLeft)
            {
                result.Horizontal = HorizontalBounds.Left;
            }

            return(result);
        }