Browse Source

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 years ago
parent
commit
52ecd5f349
4 changed files with 91 additions and 54 deletions
  1. 1
    3
      DocX/DocX.cs
  2. 30
    11
      DocX/HelperFunctions.cs
  3. 60
    40
      DocX/Paragraph.cs
  4. BIN
      DocX/StrongNameKey.pfx

+ 1
- 3
DocX/DocX.cs View File

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

+ 30
- 11
DocX/HelperFunctions.cs View File

{ {
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 View File

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

BIN
DocX/StrongNameKey.pfx View File


Loading…
Cancel
Save