diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineElement.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineElement.cs index c20cba8040..d7ec8f2e83 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineElement.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineElement.cs @@ -80,6 +80,15 @@ namespace ICSharpCode.AvalonEdit.Rendering /// public abstract TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context); + /// + /// Retrieves the text span immediately before the visual column. + /// + /// This method is used for word-wrapping in bidirectional text. + public virtual TextSpan GetPrecedingText(int visualColumnLimit, ITextRunConstructionContext context) + { + return null; + } + /// /// Gets if this VisualLineElement can be split. /// diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineText.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineText.cs index 2b074bdca6..7b6f1c28fe 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineText.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineText.cs @@ -57,6 +57,18 @@ namespace ICSharpCode.AvalonEdit.Rendering return new TextCharacters(text, 0, text.Length, this.TextRunProperties); } + /// + public override TextSpan GetPrecedingText(int visualColumnLimit, ITextRunConstructionContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + int relativeOffset = visualColumnLimit - VisualColumn; + string text = context.Document.GetText(context.VisualLine.FirstDocumentLine.Offset + RelativeTextOffset, relativeOffset); + CharacterBufferRange range = new CharacterBufferRange(text, 0, text.Length); + return new TextSpan(range.Length, new CultureSpecificCharacterBufferRange(this.TextRunProperties.CultureInfo, range)); + } + /// public override bool CanSplit { get { return true; } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs index cfc5559db6..fa6fa6f1c2 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs @@ -56,12 +56,31 @@ namespace ICSharpCode.AvalonEdit.Rendering public override TextSpan GetPrecedingText(int textSourceCharacterIndexLimit) { - throw new NotImplementedException(); + try { + foreach (VisualLineElement element in VisualLine.Elements) { + if (textSourceCharacterIndexLimit > element.VisualColumn + && textSourceCharacterIndexLimit <= element.VisualColumn + element.VisualLength) + { + TextSpan span = element.GetPrecedingText(textSourceCharacterIndexLimit, this); + if (span == null) + break; + int relativeOffset = textSourceCharacterIndexLimit - element.VisualColumn; + if (span.Length > relativeOffset) + throw new ArgumentException("The returned TextSpan is too long.", element.GetType().Name + ".GetPrecedingText"); + return span; + } + } + CharacterBufferRange empty = CharacterBufferRange.Empty; + return new TextSpan(empty.Length, new CultureSpecificCharacterBufferRange(null, empty)); + } catch (Exception ex) { + Debug.WriteLine(ex.ToString()); + throw; + } } public override int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int textSourceCharacterIndex) { - throw new NotImplementedException(); + throw new NotSupportedException(); } } }