Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Documents / TextEditorSpelling.cs / 1 / TextEditorSpelling.cs
//----------------------------------------------------------------------------
//
// File: TextEditorSpelling.cs
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// Description: A Component of TextEditor supporting spelling.
//
//---------------------------------------------------------------------------
namespace System.Windows.Documents
{
using MS.Internal;
using System.Windows;
using System.Windows.Input;
using MS.Internal.Commands;
using System.Windows.Controls;
using System.Windows.Markup; // XmlLanguage
// A Component of TextEditor supporting spelling.
internal static class TextEditorSpelling
{
//-----------------------------------------------------
//
// Class Internal Methods
//
//-----------------------------------------------------
#region Class Internal Methods
// Registers all text editing command handlers for a given control type
internal static void _RegisterClassHandlers(Type controlType, bool registerEventListeners)
{
CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.CorrectSpellingError, new ExecutedRoutedEventHandler(OnCorrectSpellingError), new CanExecuteRoutedEventHandler(OnQueryStatusSpellingError));
CommandHelpers.RegisterCommandHandler(controlType, EditingCommands.IgnoreSpellingError, new ExecutedRoutedEventHandler(OnIgnoreSpellingError), new CanExecuteRoutedEventHandler(OnQueryStatusSpellingError));
}
// Worker for TextBox/RichTextBox.GetSpellingErrorAtPosition.
internal static SpellingError GetSpellingErrorAtPosition(TextEditor This, ITextPointer position, LogicalDirection direction)
{
return (This.Speller == null) ? null : This.Speller.GetError(position, direction, true /* forceEvaluation */);
}
// Returns the error (if any) at the current selection.
internal static SpellingError GetSpellingErrorAtSelection(TextEditor This)
{
if (This.Speller == null)
{
return null;
}
if (IsSelectionIgnoringErrors(This.Selection))
{
// Some selection (large ones in particular) ignore errors.
return null;
}
// If the selection is empty, we want to respect its direction
// when poking around for spelling errors.
// If it's non-empty, the selection start direction is always
// backward, which is the opposite of what we want.
LogicalDirection direction = This.Selection.IsEmpty ? This.Selection.Start.LogicalDirection : LogicalDirection.Forward;
char character;
ITextPointer position = GetNextTextPosition(This.Selection.Start, null /* limit */, direction, out character);
if (position == null)
{
// There is no next character -- flip direction.
// This is the end-of-document or end-of-paragraph case.
direction = (direction == LogicalDirection.Forward) ? LogicalDirection.Backward : LogicalDirection.Forward;
position = GetNextTextPosition(This.Selection.Start, null /* limit */, direction, out character);
}
else if (Char.IsWhiteSpace(character))
{
// If direction points to whitespace
// If the selection is empty
// Look in the opposite direction.
// Else
// If the selection contains non-white space
// Look at the first non-white space character forward.
// Else
// Look in the opposite direction.
if (This.Selection.IsEmpty)
{
direction = (direction == LogicalDirection.Forward) ? LogicalDirection.Backward : LogicalDirection.Forward;
position = GetNextTextPosition(This.Selection.Start, null /* limit */, direction, out character);
}
else
{
direction = LogicalDirection.Forward;
position = GetNextNonWhiteSpacePosition(This.Selection.Start, This.Selection.End);
if (position == null)
{
direction = LogicalDirection.Backward;
position = GetNextTextPosition(This.Selection.Start, null /* limit */, direction, out character);
}
}
}
return (position == null) ? null : This.Speller.GetError(position, direction, false /* forceEvaluation */);
}
// Worker for TextBox/RichTextBox.GetNextSpellingErrorPosition.
internal static ITextPointer GetNextSpellingErrorPosition(TextEditor This, ITextPointer position, LogicalDirection direction)
{
return (This.Speller == null) ? null : This.Speller.GetNextSpellingErrorPosition(position, direction);
}
#endregion Class Internal Methods
//------------------------------------------------------
//
// Private Methods
//
//-----------------------------------------------------
#region Private Methods
// Callback for EditingCommands.CorrectSpellingError.
//
// Corrects the error pointed to by Selection.Start with the string
// specified in args.Data.
private static void OnCorrectSpellingError(object target, ExecutedRoutedEventArgs args)
{
TextEditor This = TextEditor._GetTextEditor(target);
if (This == null)
return;
string correctedText = args.Parameter as string;
if (correctedText == null)
return;
SpellingError spellingError = GetSpellingErrorAtSelection(This);
if (spellingError == null)
return;
using (This.Selection.DeclareChangeBlock())
{
ITextPointer textStart;
ITextPointer textEnd;
bool dontUseRange = IsErrorAtNonMergeableInlineEdge(spellingError, out textStart, out textEnd);
ITextPointer caretPosition;
if (dontUseRange && textStart is TextPointer)
{
// We need a cast because ITextPointer's equivalent to DeleteTextInRun (DeleteContentToPostiion)
// will remove empty TextElements, which we do not want.
((TextPointer)textStart).DeleteTextInRun(textStart.GetOffsetToPosition(textEnd));
textStart.InsertTextInRun(correctedText);
caretPosition = textStart.CreatePointer(+correctedText.Length, LogicalDirection.Forward);
}
else
{
This.Selection.Select(spellingError.Start, spellingError.End);
// Setting range.Text to correctedText might inadvertantly apply previous Run's formatting properties.
// Save current formatting to avoid this.
if (This.AcceptsRichContent)
{
((TextSelection)This.Selection).SpringloadCurrentFormatting();
}
// TextEditor.SetSelectedText() replaces current selection with new text and
// also applies any springloaded properties to the text.
XmlLanguage language = (XmlLanguage)spellingError.Start.GetValue(FrameworkElement.LanguageProperty);
This.SetSelectedText(correctedText, language.GetSpecificCulture());
caretPosition = This.Selection.End;
}
// Collapse the selection to a caret following the new text.
This.Selection.Select(caretPosition, caretPosition);
}
}
// Returns true when one or both ends of the error lies at the inner edge of non-mergeable inline
// such as Hyperlink. In this case, a TextRange will normalize its ends outside
// the scope of the inline, and the corrected text will not be covered by it.
//
// We work around the common case, when the error is contained within a single
// Run. In more complex cases we'll fail and fall back to using a TextRange.
private static bool IsErrorAtNonMergeableInlineEdge(SpellingError spellingError, out ITextPointer textStart, out ITextPointer textEnd)
{
bool result = false;
textStart = spellingError.Start.CreatePointer(LogicalDirection.Backward);
while (textStart.CompareTo(spellingError.End) < 0 &&
textStart.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
{
textStart.MoveToNextContextPosition(LogicalDirection.Forward);
}
textEnd = spellingError.End.CreatePointer();
while (textEnd.CompareTo(spellingError.Start) > 0 &&
textEnd.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text)
{
textEnd.MoveToNextContextPosition(LogicalDirection.Backward);
}
if (textStart.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text ||
textStart.CompareTo(spellingError.End) == 0)
{
return false;
}
Invariant.Assert(textEnd.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text &&
textEnd.CompareTo(spellingError.Start) != 0);
if (TextPointerBase.IsAtNonMergeableInlineStart(textStart) ||
TextPointerBase.IsAtNonMergeableInlineEnd(textEnd))
{
if (typeof(Run).IsAssignableFrom(textStart.ParentType) &&
textStart.HasEqualScope(textEnd))
{
result = true;
}
}
return result;
}
// Callback for EditingCommands.IgnoreSpellingError.
//
// Ignores the error pointed to by Selection.Start and all other
// duplicates for the lifetime of the TextEditor.
private static void OnIgnoreSpellingError(object target, ExecutedRoutedEventArgs args)
{
TextEditor This = TextEditor._GetTextEditor(target);
if (This == null)
return;
SpellingError spellingError = GetSpellingErrorAtSelection(This);
if (spellingError == null)
return;
spellingError.IgnoreAll();
}
// Callback for EditingCommands.CorrectSpellingError and EditingCommands.IgnoreSpellingError
// QueryEnabled events.
//
// Both commands are enabled if Selection.Start currently points to a spelling error.
private static void OnQueryStatusSpellingError(object target, CanExecuteRoutedEventArgs args)
{
TextEditor This = TextEditor._GetTextEditor(target);
if (This == null)
return;
SpellingError spellingError = GetSpellingErrorAtSelection(This);
args.CanExecute = (spellingError != null);
}
// Returns the position preceeding the next text character in a specified
// direction, or null if no such position exists.
// The scan will halt if limit is encounted; limit may be null.
private static ITextPointer GetNextTextPosition(ITextPointer position, ITextPointer limit, LogicalDirection direction, out char character)
{
bool foundText = false;
character = (char)0;
while (position != null &&
!foundText &&
(limit == null || position.CompareTo(limit) < 0))
{
switch (position.GetPointerContext(direction))
{
case TextPointerContext.Text:
char[] buffer = new char[1];
position.GetTextInRun(direction, buffer, 0, 1);
character = buffer[0];
foundText = true;
break;
case TextPointerContext.ElementStart:
case TextPointerContext.ElementEnd:
if (TextSchema.IsFormattingType(position.GetElementType(direction)))
{
position = position.CreatePointer(+1);
}
else
{
position = null;
}
break;
case TextPointerContext.EmbeddedElement:
case TextPointerContext.None:
default:
position = null;
break;
}
}
return position;
}
// Returns the next non-white space character in the forward direction
// from position, or null if no such position exists.
// The return value will equal position if position is immediately followed
// by a non-whitespace char.
//
// This method expects that limit is never null. The scan will halt if
// limit is encountered.
private static ITextPointer GetNextNonWhiteSpacePosition(ITextPointer position, ITextPointer limit)
{
char character;
Invariant.Assert(limit != null);
while (true)
{
if (position.CompareTo(limit) == 0)
{
position = null;
break;
}
position = GetNextTextPosition(position, limit, LogicalDirection.Forward, out character);
if (position == null)
break;
if (!Char.IsWhiteSpace(character))
break;
position = position.CreatePointer(+1);
};
return position;
}
// Returns true if an ITextSelection isn't in a state where we want
// to acknowledge spelling errors.
private static bool IsSelectionIgnoringErrors(ITextSelection selection)
{
bool isSelectionIgnoringErrors = false;
// If the selection spans more than a single Block, ignore spelling errors.
if (selection.Start is TextPointer)
{
isSelectionIgnoringErrors = ((TextPointer)selection.Start).ParentBlock != ((TextPointer)selection.End).ParentBlock;
}
// If the selection is large, ignore spelling errors.
if (!isSelectionIgnoringErrors)
{
isSelectionIgnoringErrors = selection.Start.GetOffsetToPosition(selection.End) >= 256;
}
// If the selection contains unicode line breaks, ignore spelling errors.
if (!isSelectionIgnoringErrors)
{
string text = selection.Text;
for (int i = 0; i < text.Length && !isSelectionIgnoringErrors; i++)
{
isSelectionIgnoringErrors = TextPointerBase.IsCharUnicodeNewLine(text[i]);
}
}
return isSelectionIgnoringErrors;
}
#endregion Private Methods
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- OdbcUtils.cs
- SizeKeyFrameCollection.cs
- WebDescriptionAttribute.cs
- ControlValuePropertyAttribute.cs
- Inflater.cs
- BitmapEffectOutputConnector.cs
- InputElement.cs
- MultiSelector.cs
- PrintingPermission.cs
- CustomAttributeFormatException.cs
- xmlformatgeneratorstatics.cs
- SapiGrammar.cs
- BufferedResponseStream.cs
- XmlSchemaInferenceException.cs
- XmlSchemaComplexType.cs
- _SingleItemRequestCache.cs
- StringPropertyBuilder.cs
- LeafCellTreeNode.cs
- ProviderUtil.cs
- GeneralTransform3DGroup.cs
- OleDbException.cs
- InputLanguageEventArgs.cs
- RewritingValidator.cs
- ToolStripManager.cs
- TrackBar.cs
- RelationshipFixer.cs
- MasterPageBuildProvider.cs
- Attributes.cs
- PackageRelationshipCollection.cs
- HttpCapabilitiesSectionHandler.cs
- BitStack.cs
- HttpRawResponse.cs
- XmlStreamNodeWriter.cs
- ClientBuildManagerTypeDescriptionProviderBridge.cs
- DbConnectionPoolIdentity.cs
- DataGridViewToolTip.cs
- ProfessionalColors.cs
- LinqDataSourceUpdateEventArgs.cs
- NavigateUrlConverter.cs
- SecurityHelper.cs
- InternalSafeNativeMethods.cs
- TextBoxBase.cs
- CodeIndexerExpression.cs
- CharacterBuffer.cs
- VirtualDirectoryMappingCollection.cs
- ZoomPercentageConverter.cs
- TagPrefixCollection.cs
- Timer.cs
- ColorConvertedBitmap.cs
- InstanceCreationEditor.cs
- VirtualDirectoryMappingCollection.cs
- XmlFormatReaderGenerator.cs
- CustomAttributeFormatException.cs
- TypeDescriptorFilterService.cs
- IconHelper.cs
- BaseTemplateParser.cs
- MimeObjectFactory.cs
- Size.cs
- Visual3DCollection.cs
- ContentControl.cs
- PriorityBindingExpression.cs
- TemplateManager.cs
- MessageSecurityProtocol.cs
- OracleConnectionString.cs
- PanelDesigner.cs
- ComponentEditorPage.cs
- SQLGuidStorage.cs
- SystemIPGlobalProperties.cs
- Touch.cs
- AmbientValueAttribute.cs
- TraceHandlerErrorFormatter.cs
- ProcessHostConfigUtils.cs
- DeferredElementTreeState.cs
- NodeLabelEditEvent.cs
- ECDiffieHellmanCng.cs
- MemberDomainMap.cs
- TraversalRequest.cs
- FilterElement.cs
- ThemeDirectoryCompiler.cs
- AssemblyAttributes.cs
- SpotLight.cs
- GridViewDeletedEventArgs.cs
- NumericUpDown.cs
- DiscoveryVersionConverter.cs
- PixelFormatConverter.cs
- DiagnosticTrace.cs
- FileStream.cs
- BoolExpressionVisitors.cs
- RegexEditorDialog.cs
- StylusDevice.cs
- PageRequestManager.cs
- PropertyExpression.cs
- WebResourceUtil.cs
- GridSplitter.cs
- ReflectPropertyDescriptor.cs
- MetadataProperty.cs
- PropertyEmitterBase.cs
- AppDomainFactory.cs
- CompleteWizardStep.cs
- TextEditorTables.cs