Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Xml.Linq;
  6. namespace Novacode
  7. {
  8. public class Text
  9. {
  10. private int startIndex;
  11. private int endIndex;
  12. private string text;
  13. private XElement e;
  14. /// <summary>
  15. /// Gets the start index of this Text (text length before this text)
  16. /// </summary>
  17. public int StartIndex { get { return startIndex; } }
  18. /// <summary>
  19. /// Gets the end index of this Text (text length before this text + this texts length)
  20. /// </summary>
  21. public int EndIndex { get { return endIndex; } }
  22. /// <summary>
  23. /// The text value of this text element
  24. /// </summary>
  25. public string Value { get { return text; } }
  26. /// <summary>
  27. /// The underlying XElement of this run
  28. /// </summary>
  29. public XElement Xml { get { return e; } }
  30. /// <summary>
  31. /// A Text element
  32. /// </summary>
  33. /// <param name="startIndex">The index this text starts at</param>
  34. /// <param name="text">The index this text ends at</param>
  35. /// <param name="e">The underlying xml element that this text wraps</param>
  36. internal Text(int startIndex, XElement e)
  37. {
  38. this.startIndex = startIndex;
  39. this.e = e;
  40. switch (e.Name.LocalName)
  41. {
  42. case "t":
  43. {
  44. goto case "delText";
  45. }
  46. case "delText":
  47. {
  48. endIndex = startIndex + e.Value.Length;
  49. text = e.Value;
  50. break;
  51. }
  52. case "br":
  53. {
  54. text = "\n";
  55. endIndex = startIndex + 1;
  56. break;
  57. }
  58. case "tab":
  59. {
  60. text = "\t";
  61. endIndex = startIndex + 1;
  62. break;
  63. }
  64. default:
  65. {
  66. break;
  67. }
  68. }
  69. }
  70. /// <summary>
  71. /// Splits a text element at a specified index
  72. /// </summary>
  73. /// <param name="e">The text element to split</param>
  74. /// <param name="index">The index to split at</param>
  75. /// <returns>A two element array which contains both sides of the split</returns>
  76. public static XElement[] SplitText(Text t, int index)
  77. {
  78. if (index < t.startIndex || index > t.EndIndex)
  79. throw new ArgumentOutOfRangeException("index");
  80. XElement splitLeft = null, splitRight = null;
  81. if (t.e.Name.LocalName == "t" || t.e.Name.LocalName == "delText")
  82. {
  83. // The origional text element, now containing only the text before the index point.
  84. splitLeft = new XElement(t.e.Name, t.e.Attributes(), t.e.Value.Substring(0, index - t.startIndex));
  85. if (splitLeft.Value.Length == 0)
  86. splitLeft = null;
  87. else
  88. PreserveSpace(splitLeft);
  89. // The origional text element, now containing only the text after the index point.
  90. splitRight = new XElement(t.e.Name, t.e.Attributes(), t.e.Value.Substring(index - t.startIndex, t.e.Value.Length - (index - t.startIndex)));
  91. if (splitRight.Value.Length == 0)
  92. splitRight = null;
  93. else
  94. PreserveSpace(splitRight);
  95. }
  96. else
  97. {
  98. if (index == t.StartIndex)
  99. splitLeft = t.e;
  100. else
  101. splitRight = t.e;
  102. }
  103. return
  104. (
  105. new XElement[]
  106. {
  107. splitLeft,
  108. splitRight
  109. }
  110. );
  111. }
  112. /// <summary>
  113. /// If a text element or delText element, starts or ends with a space,
  114. /// it must have the attribute space, otherwise it must not have it.
  115. /// </summary>
  116. /// <param name="e">The (t or delText) element check</param>
  117. public static void PreserveSpace(XElement e)
  118. {
  119. // PreserveSpace should only be used on (t or delText) elements
  120. if (!e.Name.Equals(DocX.w + "t") && !e.Name.Equals(DocX.w + "delText"))
  121. throw new ArgumentException("SplitText can only split elements of type t or delText", "e");
  122. // Check if this w:t contains a space atribute
  123. XAttribute space = e.Attributes().Where(a => a.Name.Equals(XNamespace.Xml + "space")).SingleOrDefault();
  124. // This w:t's text begins or ends with whitespace
  125. if (e.Value.StartsWith(" ") || e.Value.EndsWith(" "))
  126. {
  127. // If this w:t contains no space attribute, add one.
  128. if (space == null)
  129. e.Add(new XAttribute(XNamespace.Xml + "space", "preserve"));
  130. }
  131. // This w:t's text does not begin or end with a space
  132. else
  133. {
  134. // If this w:r contains a space attribute, remove it.
  135. if (space != null)
  136. space.Remove();
  137. }
  138. }
  139. }
  140. }