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();
}
}
}