/// <summary> /// Handles text input event. /// </summary> /// <exception cref="InvalidOperationException"> /// This object is already disposed. /// </exception> /// <exception cref="ArgumentNullException">Parameter 'text' is null.</exception> internal void HandleTextInput(string text) { if (_IsDisposed) { throw new InvalidOperationException("This object is already disposed."); } if (text == null) { throw new ArgumentNullException("text"); } var doc = Document; var input = new StringBuilder(Math.Max(64, text.Length)); IGraphics g = null; // if in read only mode, just notify and return if (doc.IsReadOnly) { Plat.Inst.MessageBeep(); return; } // ignore if input is an empty text if (text.Length == 0) { return; } try { int newCaretIndex; int selBegin, selEnd; g = _UI.GetIGraphics(); // begin grouping UNDO action doc.BeginUndo(); // clear rectangle selection if (doc.RectSelectRanges != null) { doc.DeleteRectSelectText(); } // handle input characters foreach (char ch in text) { // try to use hook delegate if (AutoIndentHook != null && AutoIndentHook(_UI, ch) == true) { // Do nothing if this was handled by the hook continue; } // execute built-in hook logic if (TextUtil.IsEolChar(ch)) { // if an EOL code was found, stop consuming and discard // following inputs if (IsSingleLineMode) { break; } // change all EOL code in the text input.Append(doc.EolCode); } else if (ch == '\t' && _UsesTabForIndent == false) { string spaces = GetTabEquivalentSpaces(_UI, doc.CaretIndex); if (spaces == "") { // When the caret position is close to next tab // stop, an empty string will be the equivalent to // a tab. In this case we should think as if the // caret is just on the next tab stop. for (int i = 0; i < View.TabWidth; i++) { spaces += ' '; } } input.Append(spaces); } else if (ch == '\x3000' && ConvertsFullWidthSpaceToSpace) { input.Append('\x0020'); } else { // remember this character input.Append(ch); } } // calculate new caret position doc.GetSelection(out selBegin, out selEnd); newCaretIndex = selBegin + input.Length; // calc replacement target range if (IsOverwriteMode && selBegin == selEnd && selEnd + 1 < doc.Length && TextUtil.IsEolChar(doc[selBegin]) != true) { selEnd++; } // replace selection to input char doc.Replace(input.ToString(), selBegin, selEnd); doc.SetSelection(newCaretIndex, newCaretIndex); // set desired column if (UsesStickyCaret == false) { _View.SetDesiredColumn(g); } // update graphic _View.ScrollToCaret(g); //NO_NEED//_View.Invalidate( xxx ); // Doc_ContentChanged will do invalidation well. } finally { doc.EndUndo(); input.Length = 0; if (g != null) { g.Dispose(); } } }