Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / widget / TextRange.h
blob2ad41a6bc618e910fb1f422b9fd0cd4ca7fb538e
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/. */
6 #ifndef mozilla_TextRage_h_
7 #define mozilla_TextRage_h_
9 #include <stdint.h>
11 #include "mozilla/EventForwards.h"
13 #include "nsColor.h"
14 #include "nsISelectionController.h"
15 #include "nsITextInputProcessor.h"
16 #include "nsTArray.h"
18 namespace mozilla {
20 /******************************************************************************
21 * mozilla::TextRangeStyle
22 ******************************************************************************/
24 struct TextRangeStyle {
25 typedef uint8_t LineStyleType;
26 // FYI: Modify IME_RANGE_LINE_* too when you modify LineStyle.
27 enum class LineStyle : LineStyleType {
28 None,
29 Solid,
30 Dotted,
31 Dashed,
32 Double,
33 Wavy,
35 inline static LineStyle ToLineStyle(RawTextRangeType aRawLineStyle) {
36 switch (static_cast<LineStyle>(aRawLineStyle)) {
37 case LineStyle::None:
38 case LineStyle::Solid:
39 case LineStyle::Dotted:
40 case LineStyle::Dashed:
41 case LineStyle::Double:
42 case LineStyle::Wavy:
43 return static_cast<LineStyle>(aRawLineStyle);
45 MOZ_ASSERT_UNREACHABLE("aRawLineStyle value is invalid");
46 return LineStyle::None;
49 enum {
50 DEFINED_NONE = 0x00,
51 DEFINED_LINESTYLE = 0x01,
52 DEFINED_FOREGROUND_COLOR = 0x02,
53 DEFINED_BACKGROUND_COLOR = 0x04,
54 DEFINED_UNDERLINE_COLOR = 0x08
57 // Initialize all members, because TextRange instances may be compared by
58 // memcomp.
60 // FIXME(emilio): I don't think that'd be sound, as it has padding which the
61 // compiler is not guaranteed to initialize.
62 TextRangeStyle() { Clear(); }
64 void Clear() {
65 mDefinedStyles = DEFINED_NONE;
66 mLineStyle = LineStyle::None;
67 mIsBoldLine = false;
68 mForegroundColor = mBackgroundColor = mUnderlineColor = NS_RGBA(0, 0, 0, 0);
71 bool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
73 bool IsLineStyleDefined() const {
74 return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
77 bool IsForegroundColorDefined() const {
78 return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
81 bool IsBackgroundColorDefined() const {
82 return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
85 bool IsUnderlineColorDefined() const {
86 return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
89 bool IsNoChangeStyle() const {
90 return !IsForegroundColorDefined() && !IsBackgroundColorDefined() &&
91 IsLineStyleDefined() && mLineStyle == LineStyle::None;
94 bool Equals(const TextRangeStyle& aOther) const {
95 if (mDefinedStyles != aOther.mDefinedStyles) return false;
96 if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
97 !mIsBoldLine != !aOther.mIsBoldLine))
98 return false;
99 if (IsForegroundColorDefined() &&
100 (mForegroundColor != aOther.mForegroundColor))
101 return false;
102 if (IsBackgroundColorDefined() &&
103 (mBackgroundColor != aOther.mBackgroundColor))
104 return false;
105 if (IsUnderlineColorDefined() &&
106 (mUnderlineColor != aOther.mUnderlineColor))
107 return false;
108 return true;
111 bool operator!=(const TextRangeStyle& aOther) const {
112 return !Equals(aOther);
115 bool operator==(const TextRangeStyle& aOther) const { return Equals(aOther); }
117 uint8_t mDefinedStyles;
118 LineStyle mLineStyle; // DEFINED_LINESTYLE
120 bool mIsBoldLine; // DEFINED_LINESTYLE
122 nscolor mForegroundColor; // DEFINED_FOREGROUND_COLOR
123 nscolor mBackgroundColor; // DEFINED_BACKGROUND_COLOR
124 nscolor mUnderlineColor; // DEFINED_UNDERLINE_COLOR
127 /******************************************************************************
128 * mozilla::TextRange
129 ******************************************************************************/
131 enum class TextRangeType : RawTextRangeType {
132 eUninitialized = 0x00,
133 eCaret = 0x01,
134 eRawClause = nsITextInputProcessor::ATTR_RAW_CLAUSE,
135 eSelectedRawClause = nsITextInputProcessor::ATTR_SELECTED_RAW_CLAUSE,
136 eConvertedClause = nsITextInputProcessor::ATTR_CONVERTED_CLAUSE,
137 eSelectedClause = nsITextInputProcessor::ATTR_SELECTED_CLAUSE
140 bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeValue);
141 RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType);
142 TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType);
143 const char* ToChar(TextRangeType aTextRangeType);
144 SelectionType ToSelectionType(TextRangeType aTextRangeType);
146 struct TextRange {
147 TextRange()
148 : mStartOffset(0),
149 mEndOffset(0),
150 mRangeType(TextRangeType::eUninitialized) {}
152 uint32_t mStartOffset;
153 // XXX Storing end offset makes the initializing code very complicated.
154 // We should replace it with mLength.
155 uint32_t mEndOffset;
157 TextRangeStyle mRangeStyle;
159 TextRangeType mRangeType;
161 uint32_t Length() const { return mEndOffset - mStartOffset; }
163 bool IsClause() const { return mRangeType != TextRangeType::eCaret; }
165 bool Equals(const TextRange& aOther) const {
166 return mStartOffset == aOther.mStartOffset &&
167 mEndOffset == aOther.mEndOffset && mRangeType == aOther.mRangeType &&
168 mRangeStyle == aOther.mRangeStyle;
171 void RemoveCharacter(uint32_t aOffset) {
172 if (mStartOffset > aOffset) {
173 --mStartOffset;
174 --mEndOffset;
175 } else if (mEndOffset > aOffset) {
176 --mEndOffset;
181 /******************************************************************************
182 * mozilla::TextRangeArray
183 ******************************************************************************/
184 class TextRangeArray final : public AutoTArray<TextRange, 10> {
185 friend class WidgetCompositionEvent;
187 ~TextRangeArray() = default;
189 NS_INLINE_DECL_REFCOUNTING(TextRangeArray)
191 const TextRange* GetTargetClause() const {
192 for (uint32_t i = 0; i < Length(); ++i) {
193 const TextRange& range = ElementAt(i);
194 if (range.mRangeType == TextRangeType::eSelectedRawClause ||
195 range.mRangeType == TextRangeType::eSelectedClause) {
196 return &range;
199 return nullptr;
202 // Returns target clause offset. If there are selected clauses, this returns
203 // the first selected clause offset. Otherwise, 0.
204 uint32_t TargetClauseOffset() const {
205 const TextRange* range = GetTargetClause();
206 return range ? range->mStartOffset : 0;
209 // Returns target clause length. If there are selected clauses, this returns
210 // the first selected clause length. Otherwise, UINT32_MAX.
211 uint32_t TargetClauseLength() const {
212 const TextRange* range = GetTargetClause();
213 return range ? range->Length() : UINT32_MAX;
216 public:
217 bool IsComposing() const {
218 for (uint32_t i = 0; i < Length(); ++i) {
219 if (ElementAt(i).IsClause()) {
220 return true;
223 return false;
226 bool Equals(const TextRangeArray& aOther) const {
227 size_t len = Length();
228 if (len != aOther.Length()) {
229 return false;
231 for (size_t i = 0; i < len; i++) {
232 if (!ElementAt(i).Equals(aOther.ElementAt(i))) {
233 return false;
236 return true;
239 void RemoveCharacter(uint32_t aOffset) {
240 for (size_t i = 0, len = Length(); i < len; i++) {
241 ElementAt(i).RemoveCharacter(aOffset);
245 bool HasCaret() const {
246 for (const TextRange& range : *this) {
247 if (range.mRangeType == TextRangeType::eCaret) {
248 return true;
251 return false;
254 bool HasClauses() const {
255 for (const TextRange& range : *this) {
256 if (range.IsClause()) {
257 return true;
260 return false;
263 uint32_t GetCaretPosition() const {
264 for (const TextRange& range : *this) {
265 if (range.mRangeType == TextRangeType::eCaret) {
266 return range.mStartOffset;
269 return UINT32_MAX;
272 const TextRange* GetFirstClause() const {
273 for (const TextRange& range : *this) {
274 // Look for the range of a clause whose start offset is 0 because the
275 // first clause's start offset is always 0.
276 if (range.IsClause() && !range.mStartOffset) {
277 return &range;
280 MOZ_ASSERT(!HasClauses());
281 return nullptr;
285 } // namespace mozilla
287 #endif // mozilla_TextRage_h_