選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Text.cs 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. internal class Text
  9. {
  10. private int startIndex;
  11. private int endIndex;
  12. private string text;
  13. internal XElement xml;
  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. internal Text(int startIndex, XElement e)
  27. {
  28. this.startIndex = startIndex;
  29. this.xml = e;
  30. switch (e.Name.LocalName)
  31. {
  32. case "t":
  33. {
  34. goto case "delText";
  35. }
  36. case "delText":
  37. {
  38. endIndex = startIndex + e.Value.Length;
  39. text = e.Value;
  40. break;
  41. }
  42. case "br":
  43. {
  44. text = "\n";
  45. endIndex = startIndex + 1;
  46. break;
  47. }
  48. case "tab":
  49. {
  50. text = "\t";
  51. endIndex = startIndex + 1;
  52. break;
  53. }
  54. default:
  55. {
  56. break;
  57. }
  58. }
  59. }
  60. internal static XElement[] SplitText(Text t, int index)
  61. {
  62. if (index < t.startIndex || index > t.EndIndex)
  63. throw new ArgumentOutOfRangeException("index");
  64. XElement splitLeft = null, splitRight = null;
  65. if (t.xml.Name.LocalName == "t" || t.xml.Name.LocalName == "delText")
  66. {
  67. // The origional text element, now containing only the text before the index point.
  68. splitLeft = new XElement(t.xml.Name, t.xml.Attributes(), t.xml.Value.Substring(0, index - t.startIndex));
  69. if (splitLeft.Value.Length == 0)
  70. splitLeft = null;
  71. else
  72. PreserveSpace(splitLeft);
  73. // The origional text element, now containing only the text after the index point.
  74. splitRight = new XElement(t.xml.Name, t.xml.Attributes(), t.xml.Value.Substring(index - t.startIndex, t.xml.Value.Length - (index - t.startIndex)));
  75. if (splitRight.Value.Length == 0)
  76. splitRight = null;
  77. else
  78. PreserveSpace(splitRight);
  79. }
  80. else
  81. {
  82. if (index == t.StartIndex)
  83. splitLeft = t.xml;
  84. else
  85. splitRight = t.xml;
  86. }
  87. return
  88. (
  89. new XElement[]
  90. {
  91. splitLeft,
  92. splitRight
  93. }
  94. );
  95. }
  96. /// <summary>
  97. /// If a text element or delText element, starts or ends with a space,
  98. /// it must have the attribute space, otherwise it must not have it.
  99. /// </summary>
  100. /// <param name="e">The (t or delText) element check</param>
  101. public static void PreserveSpace(XElement e)
  102. {
  103. // PreserveSpace should only be used on (t or delText) elements
  104. if (!e.Name.Equals(DocX.w + "t") && !e.Name.Equals(DocX.w + "delText"))
  105. throw new ArgumentException("SplitText can only split elements of type t or delText", "e");
  106. // Check if this w:t contains a space atribute
  107. XAttribute space = e.Attributes().Where(a => a.Name.Equals(XNamespace.Xml + "space")).SingleOrDefault();
  108. // This w:t's text begins or ends with whitespace
  109. if (e.Value.StartsWith(" ") || e.Value.EndsWith(" "))
  110. {
  111. // If this w:t contains no space attribute, add one.
  112. if (space == null)
  113. e.Add(new XAttribute(XNamespace.Xml + "space", "preserve"));
  114. }
  115. // This w:t's text does not begin or end with a space
  116. else
  117. {
  118. // If this w:r contains a space attribute, remove it.
  119. if (space != null)
  120. space.Remove();
  121. }
  122. }
  123. }
  124. }