TextRange.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_TextRage_h_
  6. #define mozilla_TextRage_h_
  7. #include <stdint.h>
  8. #include "mozilla/EventForwards.h"
  9. #include "nsColor.h"
  10. #include "nsISelectionController.h"
  11. #include "nsITextInputProcessor.h"
  12. #include "nsStyleConsts.h"
  13. #include "nsTArray.h"
  14. namespace mozilla {
  15. /******************************************************************************
  16. * mozilla::TextRangeStyle
  17. ******************************************************************************/
  18. struct TextRangeStyle
  19. {
  20. enum
  21. {
  22. LINESTYLE_NONE = NS_STYLE_TEXT_DECORATION_STYLE_NONE,
  23. LINESTYLE_SOLID = NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
  24. LINESTYLE_DOTTED = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED,
  25. LINESTYLE_DASHED = NS_STYLE_TEXT_DECORATION_STYLE_DASHED,
  26. LINESTYLE_DOUBLE = NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE,
  27. LINESTYLE_WAVY = NS_STYLE_TEXT_DECORATION_STYLE_WAVY
  28. };
  29. enum
  30. {
  31. DEFINED_NONE = 0x00,
  32. DEFINED_LINESTYLE = 0x01,
  33. DEFINED_FOREGROUND_COLOR = 0x02,
  34. DEFINED_BACKGROUND_COLOR = 0x04,
  35. DEFINED_UNDERLINE_COLOR = 0x08
  36. };
  37. // Initialize all members, because TextRange instances may be compared by
  38. // memcomp.
  39. TextRangeStyle()
  40. {
  41. Clear();
  42. }
  43. void Clear()
  44. {
  45. mDefinedStyles = DEFINED_NONE;
  46. mLineStyle = LINESTYLE_NONE;
  47. mIsBoldLine = false;
  48. mForegroundColor = mBackgroundColor = mUnderlineColor = NS_RGBA(0, 0, 0, 0);
  49. }
  50. bool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
  51. bool IsLineStyleDefined() const
  52. {
  53. return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
  54. }
  55. bool IsForegroundColorDefined() const
  56. {
  57. return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
  58. }
  59. bool IsBackgroundColorDefined() const
  60. {
  61. return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
  62. }
  63. bool IsUnderlineColorDefined() const
  64. {
  65. return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
  66. }
  67. bool IsNoChangeStyle() const
  68. {
  69. return !IsForegroundColorDefined() && !IsBackgroundColorDefined() &&
  70. IsLineStyleDefined() && mLineStyle == LINESTYLE_NONE;
  71. }
  72. bool Equals(const TextRangeStyle& aOther) const
  73. {
  74. if (mDefinedStyles != aOther.mDefinedStyles)
  75. return false;
  76. if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
  77. !mIsBoldLine != !aOther.mIsBoldLine))
  78. return false;
  79. if (IsForegroundColorDefined() &&
  80. (mForegroundColor != aOther.mForegroundColor))
  81. return false;
  82. if (IsBackgroundColorDefined() &&
  83. (mBackgroundColor != aOther.mBackgroundColor))
  84. return false;
  85. if (IsUnderlineColorDefined() &&
  86. (mUnderlineColor != aOther.mUnderlineColor))
  87. return false;
  88. return true;
  89. }
  90. bool operator !=(const TextRangeStyle &aOther) const
  91. {
  92. return !Equals(aOther);
  93. }
  94. bool operator ==(const TextRangeStyle &aOther) const
  95. {
  96. return Equals(aOther);
  97. }
  98. uint8_t mDefinedStyles;
  99. uint8_t mLineStyle; // DEFINED_LINESTYLE
  100. bool mIsBoldLine; // DEFINED_LINESTYLE
  101. nscolor mForegroundColor; // DEFINED_FOREGROUND_COLOR
  102. nscolor mBackgroundColor; // DEFINED_BACKGROUND_COLOR
  103. nscolor mUnderlineColor; // DEFINED_UNDERLINE_COLOR
  104. };
  105. /******************************************************************************
  106. * mozilla::TextRange
  107. ******************************************************************************/
  108. enum class TextRangeType : RawTextRangeType
  109. {
  110. eUninitialized = 0x00,
  111. eCaret = 0x01,
  112. eRawClause = nsITextInputProcessor::ATTR_RAW_CLAUSE,
  113. eSelectedRawClause = nsITextInputProcessor::ATTR_SELECTED_RAW_CLAUSE,
  114. eConvertedClause = nsITextInputProcessor::ATTR_CONVERTED_CLAUSE,
  115. eSelectedClause = nsITextInputProcessor::ATTR_SELECTED_CLAUSE
  116. };
  117. bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeValue);
  118. RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType);
  119. TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType);
  120. const char* ToChar(TextRangeType aTextRangeType);
  121. SelectionType ToSelectionType(TextRangeType aTextRangeType);
  122. inline RawSelectionType ToRawSelectionType(TextRangeType aTextRangeType)
  123. {
  124. return ToRawSelectionType(ToSelectionType(aTextRangeType));
  125. }
  126. struct TextRange
  127. {
  128. TextRange()
  129. : mStartOffset(0)
  130. , mEndOffset(0)
  131. , mRangeType(TextRangeType::eUninitialized)
  132. {
  133. }
  134. uint32_t mStartOffset;
  135. // XXX Storing end offset makes the initializing code very complicated.
  136. // We should replace it with mLength.
  137. uint32_t mEndOffset;
  138. TextRangeStyle mRangeStyle;
  139. TextRangeType mRangeType;
  140. uint32_t Length() const { return mEndOffset - mStartOffset; }
  141. bool IsClause() const
  142. {
  143. return mRangeType != TextRangeType::eCaret;
  144. }
  145. bool Equals(const TextRange& aOther) const
  146. {
  147. return mStartOffset == aOther.mStartOffset &&
  148. mEndOffset == aOther.mEndOffset &&
  149. mRangeType == aOther.mRangeType &&
  150. mRangeStyle == aOther.mRangeStyle;
  151. }
  152. void RemoveCharacter(uint32_t aOffset)
  153. {
  154. if (mStartOffset > aOffset) {
  155. --mStartOffset;
  156. --mEndOffset;
  157. } else if (mEndOffset > aOffset) {
  158. --mEndOffset;
  159. }
  160. }
  161. };
  162. /******************************************************************************
  163. * mozilla::TextRangeArray
  164. ******************************************************************************/
  165. class TextRangeArray final : public AutoTArray<TextRange, 10>
  166. {
  167. friend class WidgetCompositionEvent;
  168. ~TextRangeArray() {}
  169. NS_INLINE_DECL_REFCOUNTING(TextRangeArray)
  170. const TextRange* GetTargetClause() const
  171. {
  172. for (uint32_t i = 0; i < Length(); ++i) {
  173. const TextRange& range = ElementAt(i);
  174. if (range.mRangeType == TextRangeType::eSelectedRawClause ||
  175. range.mRangeType == TextRangeType::eSelectedClause) {
  176. return &range;
  177. }
  178. }
  179. return nullptr;
  180. }
  181. // Returns target clause offset. If there are selected clauses, this returns
  182. // the first selected clause offset. Otherwise, 0.
  183. uint32_t TargetClauseOffset() const
  184. {
  185. const TextRange* range = GetTargetClause();
  186. return range ? range->mStartOffset : 0;
  187. }
  188. // Returns target clause length. If there are selected clauses, this returns
  189. // the first selected clause length. Otherwise, UINT32_MAX.
  190. uint32_t TargetClauseLength() const
  191. {
  192. const TextRange* range = GetTargetClause();
  193. return range ? range->Length() : UINT32_MAX;
  194. }
  195. public:
  196. bool IsComposing() const
  197. {
  198. for (uint32_t i = 0; i < Length(); ++i) {
  199. if (ElementAt(i).IsClause()) {
  200. return true;
  201. }
  202. }
  203. return false;
  204. }
  205. bool Equals(const TextRangeArray& aOther) const
  206. {
  207. size_t len = Length();
  208. if (len != aOther.Length()) {
  209. return false;
  210. }
  211. for (size_t i = 0; i < len; i++) {
  212. if (!ElementAt(i).Equals(aOther.ElementAt(i))) {
  213. return false;
  214. }
  215. }
  216. return true;
  217. }
  218. void RemoveCharacter(uint32_t aOffset)
  219. {
  220. for (size_t i = 0, len = Length(); i < len; i++) {
  221. ElementAt(i).RemoveCharacter(aOffset);
  222. }
  223. }
  224. bool HasCaret() const
  225. {
  226. for (const TextRange& range : *this) {
  227. if (range.mRangeType == TextRangeType::eCaret) {
  228. return true;
  229. }
  230. }
  231. return false;
  232. }
  233. bool HasClauses() const
  234. {
  235. for (const TextRange& range : *this) {
  236. if (range.IsClause()) {
  237. return true;
  238. }
  239. }
  240. return false;
  241. }
  242. uint32_t GetCaretPosition() const
  243. {
  244. for (const TextRange& range : *this) {
  245. if (range.mRangeType == TextRangeType::eCaret) {
  246. return range.mStartOffset;
  247. }
  248. }
  249. return UINT32_MAX;
  250. }
  251. const TextRange* GetFirstClause() const
  252. {
  253. for (const TextRange& range : *this) {
  254. // Look for the range of a clause whose start offset is 0 because the
  255. // first clause's start offset is always 0.
  256. if (range.IsClause() && !range.mStartOffset) {
  257. return &range;
  258. }
  259. }
  260. MOZ_ASSERT(!HasClauses());
  261. return nullptr;
  262. }
  263. };
  264. } // namespace mozilla
  265. #endif // mozilla_TextRage_h_