// ...................................................... 
        //
        //  Handling Text Input 
        // 
        // ......................................................
 
        /// <summary>
        /// This is a single method used to insert user input characters.
        /// It takes care of typing undo, springload formatting, overtype mode etc.
        /// </summary> 
        /// <param name="This"></param>
        /// <param name="textData"> 
        /// Text to insert. 
        /// </param>
        /// <param name="isInsertKeyToggled"> 
        /// Reflects a state of Insert key at the moment of textData input.
        /// </param>
        /// <param name="acceptControlCharacters">
        /// True indicates that control characters like '\t' or '\r' etc. can be inserted. 
        /// False means that all control characters are filtered out.
        /// </param> 
        private static void DoTextInput(TextEditor This, string textData, bool isInsertKeyToggled, bool acceptControlCharacters) 
        {
            // Hide the mouse cursor on user input. 
            HideCursor(This);

            // Remove control characters. Note that this is not included into _FilterText,
            // because we want such kind of filtering only for real input, 
            // not for copy/paste.
            if (!acceptControlCharacters) 
            { 
                for (int i = 0; i < textData.Length; i++)
                { 
                    if (Char.IsControl(textData[i]))
                    {
                        textData = textData.Remove(i--, 1);  // decrement i to compensate for character removal
                    } 
                }
            } 
 
            string filteredText = This._FilterText(textData, This.Selection);
            if (filteredText.Length == 0) 
            {
                return;
            }
 
            TextEditorTyping.OpenTypingUndoUnit(This);
 
            UndoCloseAction closeAction = UndoCloseAction.Rollback; 

            try 
            {
                using (This.Selection.DeclareChangeBlock())
                {
                    This.Selection.ApplyTypingHeuristics(This.AllowOvertype && This._OvertypeMode && filteredText != "\t"); 

                    This.SetSelectedText(filteredText, InputLanguageManager.Current.CurrentInputLanguage); 
 
                    // Create caret position normalized backward to keep formatting of a character just typed
                    ITextPointer caretPosition = This.Selection.End.CreatePointer(LogicalDirection.Backward); 

                    // Set selection at the end of input content
                    This.Selection.SetCaretToPosition(caretPosition, LogicalDirection.Backward, /*allowStopAtLineEnd:*/true, /*allowStopNearSpace:*/true);
                    // Note: Using explicit backward orientation we keep formatting with 
                    // a previous character during typing.
 
                    closeAction = UndoCloseAction.Commit; 
                }
            } 
            finally
            {
                TextEditorTyping.CloseTypingUndoUnit(This, closeAction);
            } 
        }
        // Helper for plain text filtering when pasted into rich or plain destination
        private static bool PastePlainText(TextEditor This, string pastedText)
        {
            pastedText = This._FilterText(pastedText, This.Selection);

            if (pastedText.Length > 0)
            {
                if (This.AcceptsRichContent && This.Selection.Start is TextPointer)
                {
                    // Clear selection content
                    This.Selection.Text = String.Empty;

                    // Ensure that text is insertable at current selection
                    TextPointer start = TextRangeEditTables.EnsureInsertionPosition((TextPointer)This.Selection.Start);

                    // Store boundaries of inserted text
                    start = start.GetPositionAtOffset(0, LogicalDirection.Backward);
                    TextPointer end = start.GetPositionAtOffset(0, LogicalDirection.Forward);

                    // For rich text we need to remove control characters and
                    // replace linebreaks by paragraphs
                    int currentLineStart = 0;
                    for (int i = 0; i < pastedText.Length; i++)
                    {
                        if (pastedText[i] == '\r' || pastedText[i] == '\n')
                        {
                            end.InsertTextInRun(pastedText.Substring(currentLineStart, i - currentLineStart));
                            if (!This.AcceptsReturn)
                            {
                                return true; // All lined except for the first one are ignored when TextBox does not accept Return key
                            }

                            if (end.HasNonMergeableInlineAncestor)
                            {
                                // We cannot split a Hyperlink or other non-mergeable Inline element,
                                // so insert a space character instead (similar to embedded object).
                                // Note that this means, Paste operation would loose
                                // paragraph break information in this case.
                                end.InsertTextInRun(" ");
                            }
                            else
                            {
                                end = end.InsertParagraphBreak();
                            }

                            if (pastedText[i] == '\r' && i + 1 < pastedText.Length && pastedText[i + 1] == '\n')
                            {
                                i++;
                            }
                            currentLineStart = i + 1;
                        }
                    }
                    end.InsertTextInRun(pastedText.Substring(currentLineStart, pastedText.Length - currentLineStart));

                    // Select all pasted content
                    This.Selection.Select(start, end);
                }
                else
                {
                    // For plain text we insert the content as is (including control characters)
                    This.Selection.Text = pastedText;
                }
                return true;
            }

            return false;
        }
        // Helper for OnEnterBreak for plain text case
        private static bool HandleEnterBreakForPlainText(TextEditor This) 
        { 
            bool wasSelectionChanged = true;
 
            // Filter Environment.NewLine based on TextBox.MaxLength
            string filteredText = This._FilterText(Environment.NewLine, This.Selection);

            if (filteredText != String.Empty) 
            {
                This.Selection.Text = Environment.NewLine; 
            } 
            else
            { 
                // Do not update selection if Environment.NewLine can not fit in.
                wasSelectionChanged = false;
            }
 
            return wasSelectionChanged;
        }