void ITextRangeProvider.ExpandToEnclosingUnit(TextUnit unit)
        {
            Misc.SetFocus(_provider._hwnd);

            switch (unit)
            {
            case TextUnit.Character:
                // if it is a degenerate range then expand it to be one character.
                // otherwise, leave it as it is.
                if (Start == End)
                {
                    int moved;
                    End = MoveEndpointForward(End, TextUnit.Character, 1, out moved);
                }
                break;

            case TextUnit.Word:
            {
                // this works same as paragraph except we look for word boundaries instead of paragraph boundaries.

                // get the text so we can figure out where the boundaries are
                string text = _provider.GetText();
                ValidateEndpoints();

#if WCP_NLS_ENABLED
                // use the same word breaker that Avalon Text uses.
                WordBreaker   breaker   = new WordBreaker();
                TextContainer container = new TextContainer(text);
                // if the starting point of the range is not already at a word break
                // then move it backwards to the nearest word break.
                TextNavigator startNavigator = new TextNavigator(Start, container);
                if (!breaker.IsAtWordBreak(startNavigator))
                {
                    breaker.MoveToPreviousWordBreak(startNavigator);
                    Start = startNavigator.Position;
                }

                // if the range is degenerate or the ending point of the range is not already at a word break
                // then move it forwards to the nearest word break.
                TextNavigator endNavigator = new TextNavigator(End, container);
                if (Start == End || !breaker.IsAtWordBreak(endNavigator))
                {
                    breaker.MoveToNextWordBreak(endNavigator);
                    End = endNavigator.Position;
                }
#else
                // move start left until we reach a word boundary.
                for (; !AtWordBoundary(text, Start); Start--)
                {
                    ;
                }

                // move end right until we reach word boundary (different from Start).
                End = Math.Min(Math.Max(End, Start + 1), text.Length);
                for (; !AtWordBoundary(text, End); End++)
                {
                    ;
                }
#endif
            }
            break;

            case TextUnit.Line:
            {
                if (_provider.GetLineCount() != 1)
                {
                    int startLine = _provider.LineFromChar(Start);
                    int endLine   = _provider.LineFromChar(End);

                    MoveTo(_provider.LineIndex(startLine), _provider.LineIndex(endLine + 1));
                }
                else
                {
                    MoveTo(0, _provider.GetTextLength());
                }
            }
            break;

            case TextUnit.Paragraph:
            {
                // this works same as paragraph except we look for word boundaries instead of paragraph boundaries.

                // get the text so we can figure out where the boundaries are
                string text = _provider.GetText();
                ValidateEndpoints();

                // move start left until we reach a paragraph boundary.
                for (; !AtParagraphBoundary(text, Start); Start--)
                {
                    ;
                }

                // move end right until we reach a paragraph boundary (different from Start).
                End = Math.Min(Math.Max(End, Start + 1), text.Length);
                for (; !AtParagraphBoundary(text, End); End++)
                {
                    ;
                }
            }
            break;

            case TextUnit.Format:
            case TextUnit.Page:
            case TextUnit.Document:
                MoveTo(0, _provider.GetTextLength());
                break;

            //break;
            default:
                throw new System.ComponentModel.InvalidEnumArgumentException("unit", (int)unit, typeof(TextUnit));
            }
        }
        // moves an endpoint forward a certain number of units.
        // the endpoint is just an index into the text so it could represent either
        // the endpoint.
        private int MoveEndpointForward(int index, TextUnit unit, int count, out int moved)
        {
            switch (unit)
            {
            case TextUnit.Character:
            {
                int limit = _provider.GetTextLength();
                ValidateEndpoints();

                moved = Math.Min(count, limit - index);
                index = index + moved;

                index = index > limit ? limit : index;
            }
            break;

            case TextUnit.Word:
            {
                string text = _provider.GetText();
                ValidateEndpoints();

#if WCP_NLS_ENABLED
                // use the same word breaker as Avalon Text.
                WordBreaker   breaker   = new WordBreaker();
                TextContainer container = new TextContainer(text);
                TextNavigator navigator = new TextNavigator(index, container);

                // move forward one word break for each count
                for (moved = 0; moved < count && index < text.Length; moved++)
                {
                    if (!breaker.MoveToNextWordBreak(navigator))
                    {
                        break;
                    }
                }

                index = navigator.Position;
#else
                for (moved = 0; moved < count && index < text.Length; moved++)
                {
                    for (index++; !AtWordBoundary(text, index); index++)
                    {
                        ;
                    }
                }
#endif
            }
            break;

            case TextUnit.Line:
            {
                // figure out what line we are on.  if we are in the middle of a line and
                // are moving left then we'll round up to the next line so that we move
                // to the beginning of the current line.
                int line = _provider.LineFromChar(index);

                // limit the number of lines moved to the number of lines available to move
                // Note lineMax is always >= 1.
                int lineMax = _provider.GetLineCount();
                moved = Math.Min(count, lineMax - line - 1);

                if (moved > 0)
                {
                    // move the endpoint to the beginning of the destination line.
                    index = _provider.LineIndex(line + moved);
                }
                else if (moved == 0 && lineMax == 1)
                {
                    // There is only one line so get the text length as endpoint
                    index = _provider.GetTextLength();
                    moved = 1;
                }
            }
            break;

            case TextUnit.Paragraph:
            {
                // just like moving words but we look for paragraph boundaries instead of
                // word boundaries.
                string text = _provider.GetText();
                ValidateEndpoints();

                for (moved = 0; moved < count && index < text.Length; moved++)
                {
                    for (index++; !AtParagraphBoundary(text, index); index++)
                    {
                        ;
                    }
                }
            }
            break;

            case TextUnit.Format:
            case TextUnit.Page:
            case TextUnit.Document:
            {
                // since edit controls are plain text moving one uniform format unit will
                // take us all the way to the end of the document, just like
                // "pages" and document.
                int limit = _provider.GetTextLength();
                ValidateEndpoints();

                // we'll move 1 format unit if we aren't already at the end of the
                // document.  Otherwise, we won't move at all.
                moved = index < limit ? 1 : 0;
                index = limit;
            }
            break;

            default:
                throw new System.ComponentModel.InvalidEnumArgumentException("unit", (int)unit, typeof(TextUnit));
            }

            return(index);
        }