瀏覽代碼

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 查看文件

{ {
get get
{ {
StringBuilder sb = new StringBuilder();
HelperFunctions.GetText(Xml, sb);
return sb.ToString();
return HelperFunctions.GetText(Xml);
} }
} }

+ 30
- 11
DocX/HelperFunctions.cs 查看文件

{ {
internal static class HelperFunctions 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) internal static string ToText(XElement e)

+ 60
- 40
DocX/Paragraph.cs 查看文件

// Returns the underlying XElement's Value property. // Returns the underlying XElement's Value property.
get get
{ {
StringBuilder sb = new StringBuilder();
HelperFunctions.GetText(Xml, sb);
return sb.ToString();
return HelperFunctions.GetText(Xml);
} }
} }
public Picture InsertPicture(int index, string imageID, string name, string description) public Picture InsertPicture(int index, string imageID, string name, string description)
{ {
Picture picture = CreatePicture(Document, imageID, name, description); Picture picture = CreatePicture(Document, imageID, name, description);
Run run = GetFirstRunEffectedByEdit(index);
Run run = GetFirstRunEffectedByInsert(index);
if (run == null) if (run == null)
Xml.Add(picture.Xml); Xml.Add(picture.Xml);
); );
} }
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);
} }
/// <!-- /// <!--
internal XElement[] SplitEdit(XElement edit, int index, EditType type) 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); XElement[] splitRun = Run.SplitRun(run, index);
// Get the first run effected by this Insert // Get the first run effected by this Insert
Run run = GetFirstRunEffectedByInsert(index); Run run = GetFirstRunEffectedByInsert(index);
if (run == null) if (run == null)
{ {
object insert; object insert;
do do
{ {
// Get the first run effected by this Remove // Get the first run effected by this Remove
Run run = GetFirstRunEffectedByEdit(index + processed);
Run run = GetFirstRunEffectedByInsert(index + processed);
// The parent of this Run // The parent of this Run
XElement parentElement = run.Xml.Parent; XElement parentElement = run.Xml.Parent;
do do
{ {
// Get the next run effected // Get the next run effected
Run run = GetFirstRunEffectedByEdit(m.Index + processed);
Run run = GetFirstRunEffectedByInsert(m.Index + processed);
// Get this runs properties // Get this runs properties
XElement rPr = run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName)); XElement rPr = run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName));
static internal XElement[] SplitRun(Run r, int index) 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[] 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]); 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]);
); );
} }
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 查看文件


Loading…
取消
儲存