TextCaret IVisualLine <TextCaret> .FindClosestTo(double xPosition)
        {
            var container  = GetContainer();
            var lineBounds = GetCachedLineBounds(container);

            double DistanceTo(TextCaret caretToMeasure)
            => Math.Abs(xPosition - TextCaretMeasurerHelper.Measure(caretToMeasure).Left);

            var caret = TextCaret.FromOffset(container.Content, container.Offset.GraphemeOffset);

            var closest =
                (caret : caret,
                 index : 0,
                 distance : DistanceTo(caret)
                );

            for (int i = 1; i < lineBounds.Length; i++)
            {
                caret = caret.GetNextPosition();
                var diff = DistanceTo(caret);

                if (diff <= closest.distance)
                {
                    closest = (caret, i, diff);
                }
                else
                {
                    // we're getting bigger
                    break;
                }
            }

            return(closest.caret);
        }
        private double UpdateMovementMode(CaretMovementMode movementMode, TextCaret caret)
        {
            switch (movementMode.CurrentMode)
            {
            case CaretMovementMode.Mode.None:
                var position = TextCaretMeasurerHelper.Measure(caret).Left;
                movementMode.SetModeToPosition(position);
                return(position);

            case CaretMovementMode.Mode.Position:
                return(movementMode.Position);

            case CaretMovementMode.Mode.Home:
                return(0);

            case CaretMovementMode.Mode.End:
                return(double.MaxValue);

            default:
                throw new ArgumentOutOfRangeException();
            }
        }