ソースを参照

Rewrote the core behind (Insert and Remove)Text() functions. Most if not all issues with XElement splitting have been fixed by this changeset.

Major new functions are listed below.

Paragraph
-----------
GetFirstRunEffectedByInsert()
GetFirstRunEffectedByInsertRecursive()

Run
----
GetFirstTextEffectedByInsert()
GetFirstTextEffectedByInsertRecursive()

HelperFunctions
-----------------
GetText
GetTextRecursive
GetSize(XElement Xml)

This new recursive search method does not return the same Paragraph multiple times thus the problem with Textbox's has also been fixed.
master
coffeycathal_cp 15年前
コミット
52ecd5f349
4個のファイルの変更91行の追加54行の削除
  1. 1
    3
      DocX/DocX.cs
  2. 30
    11
      DocX/HelperFunctions.cs
  3. 60
    40
      DocX/Paragraph.cs
  4. バイナリ
      DocX/StrongNameKey.pfx

+ 1
- 3
DocX/DocX.cs ファイルの表示

@@ -478,9 +478,7 @@ namespace Novacode
{
get
{
StringBuilder sb = new StringBuilder();
HelperFunctions.GetText(Xml, sb);
return sb.ToString();
return HelperFunctions.GetText(Xml);
}
}

+ 30
- 11
DocX/HelperFunctions.cs ファイルの表示

@@ -13,22 +13,41 @@ namespace Novacode
{
internal static class HelperFunctions
{
internal static void GetText(XElement e, StringBuilder sb)
internal static int GetSize(XElement Xml)
{
if (e.HasElements)
switch (Xml.Name.LocalName)
{
XElement clone = CloneElement(e);
case "tab":
return 1;
case "br":
return 0;
case "t":
goto case "delText";
case "delText":
return Xml.Value.Length;
case "tr":
goto case "br";
case "tc":
goto case "br";
default:
return 0;
}
}
IEnumerable<XElement> children = clone.Elements();
children.Remove();
internal static string GetText(XElement e)
{
StringBuilder sb = new StringBuilder();
GetTextRecursive(e, ref sb);
return sb.ToString();
}
sb.Append(ToText(clone));
foreach (XElement elem in e.Elements())
GetText(elem, sb);
}
internal static void GetTextRecursive(XElement Xml, ref StringBuilder sb)
{
sb.Append(ToText(Xml));
else
sb.Append(ToText(e));
if (Xml.HasElements)
foreach (XElement e in Xml.Elements())
GetTextRecursive(e, ref sb);
}
internal static string ToText(XElement e)

+ 60
- 40
DocX/Paragraph.cs ファイルの表示

@@ -1138,9 +1138,7 @@ namespace Novacode
// Returns the underlying XElement's Value property.
get
{
StringBuilder sb = new StringBuilder();
HelperFunctions.GetText(Xml, sb);
return sb.ToString();
return HelperFunctions.GetText(Xml);
}
}
@@ -1278,8 +1276,8 @@ namespace Novacode
public Picture InsertPicture(int index, string imageID, string name, string description)
{
Picture picture = CreatePicture(Document, imageID, name, description);
Run run = GetFirstRunEffectedByEdit(index);
Run run = GetFirstRunEffectedByInsert(index);
if (run == null)
Xml.Add(picture.Xml);
@@ -1408,33 +1406,41 @@ namespace Novacode
);
}
internal Run GetFirstRunEffectedByEdit(int index)
internal Run GetFirstRunEffectedByInsert(int index)
{
foreach (int runEndIndex in runLookup.Keys)
{
if (runEndIndex > index)
return runLookup[runEndIndex];
}
// Make sure we are looking within an acceptable index range.
if (index < 0 || index > HelperFunctions.GetText(Xml).Length)
throw new ArgumentOutOfRangeException();
if (runLookup.Last().Value.EndIndex == index)
return runLookup.Last().Value;
// Need some memory that can be updated by the recursive search for the XElement to Split.
int count = 0;
Run theOne = null;
throw new ArgumentOutOfRangeException();
GetFirstRunEffectedByInsertRecursive(Xml, index, ref count, ref theOne);
return theOne;
}
internal Run GetFirstRunEffectedByInsert(int index)
internal void GetFirstRunEffectedByInsertRecursive(XElement Xml, int index, ref int count, ref Run theOne)
{
// This paragraph contains no Runs and insertion is at index 0
if (runLookup.Keys.Count() == 0 && index == 0)
return null;
foreach (int runEndIndex in runLookup.Keys)
count += HelperFunctions.GetSize(Xml);
if (count > 0 && count >= index)
{
if (runEndIndex >= index)
return runLookup[runEndIndex];
// We have found the element, now find the run it belongs to.
while (Xml.Name.LocalName != "r")
{
count -= HelperFunctions.GetSize(Xml);
Xml = Xml.Parent;
}
theOne = new Run(Document, Xml, count);
return;
}
throw new ArgumentOutOfRangeException();
if (Xml.HasElements)
foreach (XElement e in Xml.Elements())
if (theOne == null)
GetFirstRunEffectedByInsertRecursive(e, index, ref count, ref theOne);
}
/// <!--
@@ -1466,11 +1472,7 @@ namespace Novacode
internal XElement[] SplitEdit(XElement edit, int index, EditType type)
{
Run run;
if(type == EditType.del)
run = GetFirstRunEffectedByEdit(index);
else
run = GetFirstRunEffectedByInsert(index);
Run run = GetFirstRunEffectedByInsert(index);
XElement[] splitRun = Run.SplitRun(run, index);
@@ -1725,7 +1727,7 @@ namespace Novacode
// Get the first run effected by this Insert
Run run = GetFirstRunEffectedByInsert(index);
if (run == null)
{
object insert;
@@ -2781,7 +2783,7 @@ namespace Novacode
do
{
// Get the first run effected by this Remove
Run run = GetFirstRunEffectedByEdit(index + processed);
Run run = GetFirstRunEffectedByInsert(index + processed);
// The parent of this Run
XElement parentElement = run.Xml.Parent;
@@ -3048,7 +3050,7 @@ namespace Novacode
do
{
// Get the next run effected
Run run = GetFirstRunEffectedByEdit(m.Index + processed);
Run run = GetFirstRunEffectedByInsert(m.Index + processed);
// Get this runs properties
XElement rPr = run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName));
@@ -3293,7 +3295,9 @@ namespace Novacode
static internal XElement[] SplitRun(Run r, int index)
{
Text t = r.GetFirstTextEffectedByEdit(index);
index = index - r.StartIndex;
Text t = r.GetFirstTextEffectedByInsert(index);
XElement[] splitText = Text.SplitText(t, index);
XElement splitLeft = new XElement(r.Xml.Name, r.Xml.Attributes(), r.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName)), t.Xml.ElementsBeforeSelf().Where(n => n.Name.LocalName != "rPr"), splitText[0]);
@@ -3314,18 +3318,34 @@ namespace Novacode
);
}
internal Text GetFirstTextEffectedByEdit(int index)
internal Text GetFirstTextEffectedByInsert(int index)
{
foreach (int textEndIndex in textLookup.Keys)
// Make sure we are looking within an acceptable index range.
if (index < 0 || index > HelperFunctions.GetText(Xml).Length)
throw new ArgumentOutOfRangeException();
// Need some memory that can be updated by the recursive search for the XElement to Split.
int count = 0;
Text theOne = null;
GetFirstTextEffectedByInsertRecursive(Xml, index, ref count, ref theOne);
return theOne;
}
internal void GetFirstTextEffectedByInsertRecursive(XElement Xml, int index, ref int count, ref Text theOne)
{
count += HelperFunctions.GetSize(Xml);
if (count > 0 && count >= index)
{
if (textEndIndex > index)
return textLookup[textEndIndex];
theOne = new Text(Document, Xml, 0);
return;
}
if (textLookup.Last().Value.EndIndex == index)
return textLookup.Last().Value;
throw new ArgumentOutOfRangeException();
if (Xml.HasElements)
foreach (XElement e in Xml.Elements())
if (theOne == null)
GetFirstTextEffectedByInsertRecursive(e, index, ref count, ref theOne);
}
}

バイナリ
DocX/StrongNameKey.pfx ファイルの表示


読み込み中…
キャンセル
保存