public static bool GuessSemicolonInsertionOffset(IReadonlyTextDocument data, MonoDevelop.Core.Text.ISegment curLine, int caretOffset, out int outOffset)
        {
            int  lastNonWsOffset = caretOffset;
            char lastNonWsChar   = '\0';

            outOffset = caretOffset;

            int max = curLine.EndOffset;

            int end = caretOffset;

            while (end > 1 && char.IsWhiteSpace(data.GetCharAt(end)))
            {
                end--;
            }
            int end2 = end;

            while (end2 > 1 && char.IsLetter(data.GetCharAt(end2 - 1)))
            {
                end2--;
            }
            if (end != end2)
            {
                string token = data.GetTextBetween(end2, end + 1);
                // guess property context
                if (token == "get" || token == "set")
                {
                    return(false);
                }
            }

            var    offset   = curLine.Offset;
            string lineText = data.GetTextAt(caretOffset, max - caretOffset);
            var    lexer    = new ICSharpCode.NRefactory.CSharp.Completion.CSharpCompletionEngineBase.MiniLexer(lineText);

            lexer.Parse((ch, i) => {
                if (lexer.IsInSingleComment || lexer.IsInMultiLineComment)
                {
                    return(true);
                }
                if (ch == '}' && lexer.IsFistNonWs && !IsSemicolonalreadyPlaced(data, caretOffset))
                {
                    lastNonWsChar = ';';
                    return(true);
                }
                if (!char.IsWhiteSpace(ch))
                {
                    lastNonWsOffset = caretOffset + i;
                    lastNonWsChar   = ch;
                }
                return(false);
            });
            // if the line ends with ';' the line end is not the correct place for a new semicolon.
            if (lastNonWsChar == ';')
            {
                return(false);
            }
            outOffset = lastNonWsOffset;
            return(true);
        }
        public bool FixLineStart(TextEditor textEditorData, ICSharpCode.NRefactory6.CSharp.IStateMachineIndentEngine stateTracker, int lineNumber)
        {
            if (lineNumber > 1)
            {
                var line = textEditorData.GetLine(lineNumber);
                if (line == null)
                {
                    return(false);
                }

                var prevLine = textEditorData.GetLine(lineNumber - 1);
                if (prevLine == null)
                {
                    return(false);
                }
                string trimmedPreviousLine = textEditorData.GetTextAt(prevLine).TrimStart();

                //xml doc comments
                //check previous line was a doc comment
                //check there's a following line?
                if (trimmedPreviousLine.StartsWith("///", StringComparison.Ordinal))
                {
                    if (textEditorData.GetTextAt(line.Offset, line.Length).TrimStart().StartsWith("///", StringComparison.Ordinal))
                    {
                        return(false);
                    }
                    //check that the newline command actually inserted a newline
                    textEditorData.EnsureCaretIsNotVirtual();
                    var    nextLineSegment = textEditorData.GetLine(lineNumber + 1);
                    string nextLine        = nextLineSegment != null?textEditorData.GetTextAt(nextLineSegment).TrimStart() : "";

                    if (trimmedPreviousLine.Length > "///".Length || nextLine.StartsWith("///", StringComparison.Ordinal))
                    {
                        var insertionPoint = textEditorData.CaretOffset;
                        textEditorData.InsertText(insertionPoint, "/// ");
                        textEditorData.CaretOffset = insertionPoint + "/// ".Length;
                        return(true);
                    }
                    //multi-line comments
                }
                else if (stateTracker.IsInsideMultiLineComment)
                {
                    if (textEditorData.GetTextAt(line.Offset, line.Length).TrimStart().StartsWith("*", StringComparison.Ordinal))
                    {
                        return(false);
                    }
                    textEditorData.EnsureCaretIsNotVirtual();
                    string commentPrefix = string.Empty;
                    if (trimmedPreviousLine.StartsWith("* ", StringComparison.Ordinal))
                    {
                        commentPrefix = "* ";
                    }
                    else if (trimmedPreviousLine.StartsWith("/**", StringComparison.Ordinal) || trimmedPreviousLine.StartsWith("/*", StringComparison.Ordinal))
                    {
                        commentPrefix = " * ";
                    }
                    else if (trimmedPreviousLine.StartsWith("*", StringComparison.Ordinal))
                    {
                        commentPrefix = "*";
                    }

                    int indentSize   = line.GetIndentation(textEditorData).Length;
                    var insertedText = prevLine.GetIndentation(textEditorData) + commentPrefix;
                    textEditorData.ReplaceText(line.Offset, indentSize, insertedText);
                    textEditorData.CaretOffset = line.Offset + insertedText.Length;
                    return(true);
                }
                else if (wasInStringLiteral)
                {
                    var lexer = new ICSharpCode.NRefactory.CSharp.Completion.CSharpCompletionEngineBase.MiniLexer(textEditorData.GetTextAt(0, prevLine.EndOffset).TrimEnd());
                    lexer.Parse();
                    if (!lexer.IsInString)
                    {
                        return(false);
                    }
                    textEditorData.EnsureCaretIsNotVirtual();
                    var insertedText = "\" +";
                    textEditorData.InsertText(prevLine.Offset + prevLine.Length, insertedText);
                    var lineOffset = line.Offset + insertedText.Length;
                    int indentSize = textEditorData.CaretOffset - lineOffset;
                    insertedText = prevLine.GetIndentation(textEditorData) + (trimmedPreviousLine.StartsWith("\"", StringComparison.Ordinal) ? "" : "\t") + "\"";
                    textEditorData.ReplaceText(lineOffset, indentSize, insertedText);
                    return(true);
                }
            }
            return(false);
        }
        public override bool KeyPress(KeyDescriptor descriptor)
        {
            completionWindowWasVisible   = CompletionWindowManager.IsVisible;
            cursorPositionBeforeKeyPress = Editor.CaretOffset;
            bool isSomethingSelected = Editor.IsSomethingSelected;

            if (descriptor.SpecialKey == SpecialKey.BackSpace && Editor.CaretOffset == lastInsertedSemicolon)
            {
                EditActions.Undo(Editor);
                lastInsertedSemicolon = -1;
                return(false);
            }

            lastInsertedSemicolon = -1;
            if (descriptor.KeyChar == ';' && Editor.EditMode == EditMode.Edit && !DoInsertTemplate() && !isSomethingSelected && PropertyService.Get(
                    "SmartSemicolonPlacement",
                    false
                    ) && !(stateTracker.IsInsideComment || stateTracker.IsInsideString))
            {
                bool   retval  = base.KeyPress(descriptor);
                var    curLine = Editor.GetLine(Editor.CaretLine);
                string text    = Editor.GetTextAt(curLine);
                if (!(text.EndsWith(";", StringComparison.Ordinal) || text.Trim().StartsWith("for", StringComparison.Ordinal)))
                {
                    int guessedOffset;

                    if (GuessSemicolonInsertionOffset(Editor, curLine, Editor.CaretOffset, out guessedOffset))
                    {
                        using (var undo = Editor.OpenUndoGroup()) {
                            Editor.RemoveText(Editor.CaretOffset - 1, 1);
                            Editor.CaretOffset    = guessedOffset;
                            lastInsertedSemicolon = Editor.CaretOffset + 1;
                            retval = base.KeyPress(descriptor);
                        }
                    }
                }
                return(retval);
            }

            if (descriptor.SpecialKey == SpecialKey.Tab && descriptor.ModifierKeys == ModifierKeys.None && !CompletionWindowManager.IsVisible)
            {
                SafeUpdateIndentEngine(Editor.CaretOffset);
                if (stateTracker.IsInsideStringLiteral && !Editor.IsSomethingSelected)
                {
                    var lexer = new ICSharpCode.NRefactory.CSharp.Completion.CSharpCompletionEngineBase.MiniLexer(Editor.GetTextAt(0, Editor.CaretOffset));
                    lexer.Parse();
                    if (lexer.IsInString)
                    {
                        Editor.InsertAtCaret("\\t");
                        return(false);
                    }
                }
            }


            if (descriptor.SpecialKey == SpecialKey.Tab && DefaultSourceEditorOptions.Instance.TabIsReindent && !CompletionWindowManager.IsVisible && Editor.EditMode == EditMode.Edit && !DoInsertTemplate() && !isSomethingSelected)
            {
                ReindentOnTab();

                return(false);
            }

            SafeUpdateIndentEngine(Editor.CaretOffset);
            if (!stateTracker.IsInsideOrdinaryCommentOrString)
            {
                if (descriptor.KeyChar == '@')
                {
                    var retval = base.KeyPress(descriptor);
                    int cursor = Editor.CaretOffset;
                    if (cursor < Editor.Length && Editor.GetCharAt(cursor) == '"')
                    {
                        ConvertNormalToVerbatimString(Editor, cursor + 1);
                    }
                    return(retval);
                }
            }


            //do the smart indent
            if (!indentationDisabled)
            {
                bool retval;
                //capture some of the current state
                int  oldBufLen = Editor.Length;
                int  oldLine   = Editor.CaretLine + 1;
                bool reIndent  = false;

                //pass through to the base class, which actually inserts the character
                //and calls HandleCodeCompletion etc to handles completion
                using (var undo = Editor.OpenUndoGroup()) {
                    DoPreInsertionSmartIndent(descriptor.SpecialKey);
                }
                wasInStringLiteral = stateTracker.IsInsideStringLiteral;


                bool returnBetweenBraces =
                    descriptor.SpecialKey == SpecialKey.Return &&
                    descriptor.ModifierKeys == ModifierKeys.None &&
                    Editor.CaretOffset > 0 && Editor.CaretOffset < Editor.Length &&
                    Editor.GetCharAt(Editor.CaretOffset - 1) == '{' && Editor.GetCharAt(Editor.CaretOffset) == '}' && !stateTracker.IsInsideOrdinaryCommentOrString;

                bool automaticReindent;
                // need to be outside of an undo group - otherwise it interferes with other text editor extension
                // esp. the documentation insertion undo steps.
                retval = base.KeyPress(descriptor);


                if (descriptor.KeyChar == '/' && stateTracker.IsInsideMultiLineComment)
                {
                    if (Editor.CaretOffset - 3 >= 0 && Editor.GetCharAt(Editor.CaretOffset - 3) == '*' && Editor.GetCharAt(Editor.CaretOffset - 2) == ' ')
                    {
                        using (var undo = Editor.OpenUndoGroup()) {
                            Editor.RemoveText(Editor.CaretOffset - 2, 1);
                        }
                    }
                }

                //handle inserted characters
                if (Editor.CaretOffset <= 0 || Editor.IsSomethingSelected)
                {
                    return(retval);
                }

                lastCharInserted = TranslateKeyCharForIndenter(descriptor.SpecialKey, descriptor.KeyChar, Editor.GetCharAt(Editor.CaretOffset - 1));
                if (lastCharInserted == '\0')
                {
                    return(retval);
                }
                using (var undo = Editor.OpenUndoGroup()) {
                    if (returnBetweenBraces)
                    {
                        var oldOffset = Editor.CaretOffset;
                        Editor.InsertAtCaret(Editor.EolMarker);
                        DoReSmartIndent();
                        Editor.CaretOffset = oldOffset;
                    }

                    SafeUpdateIndentEngine(Editor.CaretOffset);

                    if (descriptor.SpecialKey == SpecialKey.Return && descriptor.ModifierKeys == ModifierKeys.Control)
                    {
                        FixLineStart(Editor, stateTracker, Editor.CaretLine + 1);
                    }
                    else
                    {
                        if (!(oldLine == Editor.CaretLine + 1 && lastCharInserted == '\n') && (oldBufLen != Editor.Length || lastCharInserted != '\0'))
                        {
                            DoPostInsertionSmartIndent(lastCharInserted, out reIndent);
                        }
                        else
                        {
                            reIndent = lastCharInserted == '\n';
                        }
                    }
                    //reindent the line after the insertion, if needed
                    //N.B. if the engine says we need to reindent, make sure that it's because a char was
                    //inserted rather than just updating the stack due to moving around

                    SafeUpdateIndentEngine(Editor.CaretOffset);
                    // Automatically reindent in text link mode will cause the mode exiting, therefore we need to prevent that.
                    automaticReindent = (stateTracker.NeedsReindent && lastCharInserted != '\0') && Editor.EditMode == EditMode.Edit;
                    if (descriptor.SpecialKey == SpecialKey.Return && (reIndent || automaticReindent))
                    {
                        if (Editor.Options.IndentStyle == IndentStyle.Virtual)
                        {
                            if (Editor.GetLine(Editor.CaretLine).Length == 0)
                            {
                                Editor.CaretColumn = Editor.GetVirtualIndentationColumn(Editor.CaretLine);
                            }
                        }
                        else
                        {
                            DoReSmartIndent();
                        }
                    }
                }

                SafeUpdateIndentEngine(Editor.CaretOffset);
                lastCharInserted = '\0';
                CheckXmlCommentCloseTag(descriptor.KeyChar);
                return(retval);
            }

            if (Editor.Options.IndentStyle == IndentStyle.Auto && DefaultSourceEditorOptions.Instance.TabIsReindent && descriptor.SpecialKey == SpecialKey.Tab)
            {
                bool retval = base.KeyPress(descriptor);
                DoReSmartIndent();
                CheckXmlCommentCloseTag(descriptor.KeyChar);
                return(retval);
            }

            //pass through to the base class, which actually inserts the character
            //and calls HandleCodeCompletion etc to handles completion
            var result = base.KeyPress(descriptor);

            CheckXmlCommentCloseTag(descriptor.KeyChar);

            return(result);
        }
		public bool FixLineStart (TextEditor textEditorData, ICSharpCode.NRefactory6.CSharp.IStateMachineIndentEngine stateTracker, int lineNumber)
		{
			if (lineNumber > 1) {
				var line = textEditorData.GetLine (lineNumber);
				if (line == null)
					return false;

				var prevLine = textEditorData.GetLine (lineNumber - 1);
				if (prevLine == null)
					return false;
				string trimmedPreviousLine = textEditorData.GetTextAt (prevLine).TrimStart ();

				//xml doc comments
				//check previous line was a doc comment
				//check there's a following line?
				if (trimmedPreviousLine.StartsWith ("///", StringComparison.Ordinal)) {
					if (textEditorData.GetTextAt (line.Offset, line.Length).TrimStart ().StartsWith ("///", StringComparison.Ordinal))
						return false;
					//check that the newline command actually inserted a newline
					textEditorData.EnsureCaretIsNotVirtual ();
					var nextLineSegment = textEditorData.GetLine (lineNumber + 1);
					string nextLine = nextLineSegment != null ? textEditorData.GetTextAt (nextLineSegment).TrimStart () : "";

					if (trimmedPreviousLine.Length > "///".Length || nextLine.StartsWith ("///", StringComparison.Ordinal)) {
						var insertionPoint = textEditorData.CaretOffset;
						textEditorData.InsertText (insertionPoint, "/// ");
						textEditorData.CaretOffset = insertionPoint + "/// ".Length;
						return true;
					}
					//multi-line comments
				} else if (stateTracker.IsInsideMultiLineComment) {
					if (textEditorData.GetTextAt (line.Offset, line.Length).TrimStart ().StartsWith ("*", StringComparison.Ordinal))
						return false;
					textEditorData.EnsureCaretIsNotVirtual ();
					string commentPrefix = string.Empty;
					if (trimmedPreviousLine.StartsWith ("* ", StringComparison.Ordinal)) {
						commentPrefix = "* ";
					} else if (trimmedPreviousLine.StartsWith ("/**", StringComparison.Ordinal) || trimmedPreviousLine.StartsWith ("/*", StringComparison.Ordinal)) {
						commentPrefix = " * ";
					} else if (trimmedPreviousLine.StartsWith ("*", StringComparison.Ordinal)) {
						commentPrefix = "*";
					}

					int indentSize = line.GetIndentation (textEditorData).Length;
					var insertedText = prevLine.GetIndentation (textEditorData) + commentPrefix;
					textEditorData.ReplaceText (line.Offset, indentSize, insertedText);
					textEditorData.CaretOffset = line.Offset + insertedText.Length;
					return true;
				} else if (wasInStringLiteral) {
					var lexer = new ICSharpCode.NRefactory.CSharp.Completion.CSharpCompletionEngineBase.MiniLexer (textEditorData.GetTextAt (0, prevLine.EndOffset).TrimEnd ());
					lexer.Parse ();
					if (!lexer.IsInString)
						return false;
					textEditorData.EnsureCaretIsNotVirtual ();
					textEditorData.InsertText (prevLine.Offset + prevLine.Length, "\" +");

					int indentSize = textEditorData.CaretOffset - line.Offset;
					var insertedText = prevLine.GetIndentation (textEditorData) + (trimmedPreviousLine.StartsWith ("\"", StringComparison.Ordinal) ? "" : "\t") + "\"";
					textEditorData.ReplaceText (line.Offset, indentSize, insertedText);
					return true;
				}
			}
			return false;
		}
		public static bool GuessSemicolonInsertionOffset (IReadonlyTextDocument data, MonoDevelop.Core.Text.ISegment curLine, int caretOffset, out int outOffset)
		{
			int lastNonWsOffset = caretOffset;
			char lastNonWsChar = '\0';
			outOffset = caretOffset;

			int max = curLine.EndOffset;

			int end = caretOffset;
			while (end > 1 && char.IsWhiteSpace (data.GetCharAt (end)))
				end--;
			int end2 = end;
			while (end2 > 1 && char.IsLetter (data.GetCharAt (end2 - 1)))
				end2--;
			if (end != end2) {
				string token = data.GetTextBetween (end2, end + 1);
				// guess property context
				if (token == "get" || token == "set")
					return false;
			}

			var offset = curLine.Offset;
			string lineText = data.GetTextAt (caretOffset, max - caretOffset);
			var lexer = new ICSharpCode.NRefactory.CSharp.Completion.CSharpCompletionEngineBase.MiniLexer (lineText);
			lexer.Parse ((ch, i) => {
				if (lexer.IsInSingleComment || lexer.IsInMultiLineComment)
					return true;
				if (ch == '}' && lexer.IsFistNonWs && !IsSemicolonalreadyPlaced (data, caretOffset)) {
					lastNonWsChar = ';';
					return true;
				}
				if (!char.IsWhiteSpace (ch)) {
					lastNonWsOffset = caretOffset + i;
					lastNonWsChar = ch;
				}
				return false;
			}); 
			// if the line ends with ';' the line end is not the correct place for a new semicolon.
			if (lastNonWsChar == ';')
				return false;
			outOffset = lastNonWsOffset;
			return true;
		}
		public override bool KeyPress (KeyDescriptor descriptor)
		{
			completionWindowWasVisible = CompletionWindowManager.IsVisible;
			cursorPositionBeforeKeyPress = Editor.CaretOffset;
			bool isSomethingSelected = Editor.IsSomethingSelected;
			if (descriptor.SpecialKey == SpecialKey.BackSpace && Editor.CaretOffset == lastInsertedSemicolon) {
				EditActions.Undo (Editor);
				lastInsertedSemicolon = -1;
				return false;
			}

			lastInsertedSemicolon = -1;
			if (descriptor.KeyChar == ';' && Editor.EditMode == EditMode.Edit && !DoInsertTemplate () && !isSomethingSelected && PropertyService.Get (
				    "SmartSemicolonPlacement",
				    false
			    ) && !(stateTracker.IsInsideComment || stateTracker.IsInsideString)) {
				bool retval = base.KeyPress (descriptor);
				var curLine = Editor.GetLine (Editor.CaretLine);
				string text = Editor.GetTextAt (curLine);
				if (!(text.EndsWith (";", StringComparison.Ordinal) || text.Trim ().StartsWith ("for", StringComparison.Ordinal))) {
					int guessedOffset;

					if (GuessSemicolonInsertionOffset (Editor, curLine, Editor.CaretOffset, out guessedOffset)) {
						using (var undo = Editor.OpenUndoGroup ()) {
							Editor.RemoveText (Editor.CaretOffset - 1, 1);
							Editor.CaretOffset = guessedOffset;
							lastInsertedSemicolon = Editor.CaretOffset + 1;
							retval = base.KeyPress (descriptor);
						}
					}
				}
				using (var undo = Editor.OpenUndoGroup ()) {
					if (OnTheFlyFormatting && Editor != null && Editor.EditMode == EditMode.Edit) {
						OnTheFlyFormatter.FormatStatmentAt (Editor, DocumentContext, Editor.CaretLocation, optionSet: optionSet);
					}
				}
				return retval;
			}
			
			if (descriptor.SpecialKey == SpecialKey.Tab && descriptor.ModifierKeys == ModifierKeys.None && !CompletionWindowManager.IsVisible) {
				SafeUpdateIndentEngine (Editor.CaretOffset);
				if (stateTracker.IsInsideStringLiteral && !Editor.IsSomethingSelected) {
					var lexer = new ICSharpCode.NRefactory.CSharp.Completion.CSharpCompletionEngineBase.MiniLexer (Editor.GetTextAt (0, Editor.CaretOffset));
					lexer.Parse ();
					if (lexer.IsInString) {
						Editor.InsertAtCaret ("\\t");
						return false;
					}
				}
			}


			if (descriptor.SpecialKey == SpecialKey.Tab && DefaultSourceEditorOptions.Instance.TabIsReindent && !CompletionWindowManager.IsVisible && Editor.EditMode == EditMode.Edit && !DoInsertTemplate () && !isSomethingSelected) {
				ReindentOnTab ();

				return false;
			}

			SafeUpdateIndentEngine (Editor.CaretOffset);
			if (!stateTracker.IsInsideOrdinaryCommentOrString) {
				if (descriptor.KeyChar == '@') {
					var retval = base.KeyPress (descriptor);
					int cursor = Editor.CaretOffset;
					if (cursor < Editor.Length && Editor.GetCharAt (cursor) == '"')
						ConvertNormalToVerbatimString (Editor, cursor + 1);
					return retval;
				}
			}


			//do the smart indent
			if (!indentationDisabled) {
				bool retval;
				//capture some of the current state
				int oldBufLen = Editor.Length;
				int oldLine = Editor.CaretLine + 1;
				bool reIndent = false;

				//pass through to the base class, which actually inserts the character
				//and calls HandleCodeCompletion etc to handles completion
				using (var undo = Editor.OpenUndoGroup ()) {
					DoPreInsertionSmartIndent (descriptor.SpecialKey);
				}
				wasInStringLiteral = stateTracker.IsInsideStringLiteral;
				bool automaticReindent;
				// need to be outside of an undo group - otherwise it interferes with other text editor extension
				// esp. the documentation insertion undo steps.
				retval = base.KeyPress (descriptor);
				//handle inserted characters
				if (Editor.CaretOffset <= 0 || Editor.IsSomethingSelected)
					return retval;
				
				lastCharInserted = TranslateKeyCharForIndenter (descriptor.SpecialKey, descriptor.KeyChar, Editor.GetCharAt (Editor.CaretOffset - 1));
				if (lastCharInserted == '\0')
					return retval;
				using (var undo = Editor.OpenUndoGroup ()) {
					SafeUpdateIndentEngine (Editor.CaretOffset);

					if (descriptor.SpecialKey == SpecialKey.Return && descriptor.ModifierKeys == ModifierKeys.Control) {
						FixLineStart (Editor, stateTracker, Editor.CaretLine + 1);
					} else {
						if (!(oldLine == Editor.CaretLine + 1 && lastCharInserted == '\n') && (oldBufLen != Editor.Length || lastCharInserted != '\0')) {
							DoPostInsertionSmartIndent (lastCharInserted, out reIndent);
						} else {
							reIndent = lastCharInserted == '\n';
						}
					}
					//reindent the line after the insertion, if needed
					//N.B. if the engine says we need to reindent, make sure that it's because a char was 
					//inserted rather than just updating the stack due to moving around

					SafeUpdateIndentEngine (Editor.CaretOffset);
					// Automatically reindent in text link mode will cause the mode exiting, therefore we need to prevent that.
					automaticReindent = (stateTracker.NeedsReindent && lastCharInserted != '\0') && Editor.EditMode == EditMode.Edit;
					if (descriptor.SpecialKey == SpecialKey.Return && (reIndent || automaticReindent)) {
						if (Editor.Options.IndentStyle == IndentStyle.Virtual) {
							if (Editor.GetLine (Editor.CaretLine).Length == 0)
								Editor.CaretColumn = Editor.GetVirtualIndentationColumn (Editor.CaretLine);
						} else {
							DoReSmartIndent ();
						}
					}
				}

				const string reindentChars = ";){}";
				if (reIndent || descriptor.SpecialKey != SpecialKey.Return && descriptor.SpecialKey != SpecialKey.Tab && automaticReindent && reindentChars.Contains (descriptor.KeyChar)) {
					using (var undo = Editor.OpenUndoGroup ()) {
						DoReSmartIndent ();
					}
				}

				HandleOnTheFlyFormatting (descriptor);
				SafeUpdateIndentEngine (Editor.CaretOffset);
				lastCharInserted = '\0';
				CheckXmlCommentCloseTag (descriptor.KeyChar);
				return retval;
			}

			if (Editor.Options.IndentStyle == IndentStyle.Auto && DefaultSourceEditorOptions.Instance.TabIsReindent && descriptor.SpecialKey == SpecialKey.Tab) {
				bool retval = base.KeyPress (descriptor);
				DoReSmartIndent ();
				CheckXmlCommentCloseTag (descriptor.KeyChar);
				return retval;
			}

			//pass through to the base class, which actually inserts the character
			//and calls HandleCodeCompletion etc to handles completion
			var result = base.KeyPress (descriptor);

			if (!indentationDisabled && (descriptor.SpecialKey == SpecialKey.Return)) {
				DoReSmartIndent ();
			}

			CheckXmlCommentCloseTag (descriptor.KeyChar);

			HandleOnTheFlyFormatting (descriptor);
			
			return result;
		}