Просмотр исходного кода

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 лет назад
Родитель
Сommit
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 Просмотреть файл


Загрузка…
Отмена
Сохранить