Bug 1523562 [wpt PR 14965] - Sync Mozilla CSS tests as of 2019-01-20, a=testonly
[gecko.git] / widget / TextRange.h
blob24a5a3a119ee322bf1355b4b697406654e992e67
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 "nsStyleConsts.h"
17 #include "nsTArray.h"
19 namespace mozilla {
21 /******************************************************************************
22 * mozilla::TextRangeStyle
23 ******************************************************************************/
25 struct TextRangeStyle {
26 enum {
27 LINESTYLE_NONE = NS_STYLE_TEXT_DECORATION_STYLE_NONE,
28 LINESTYLE_SOLID = NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
29 LINESTYLE_DOTTED = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED,
30 LINESTYLE_DASHED = NS_STYLE_TEXT_DECORATION_STYLE_DASHED,
31 LINESTYLE_DOUBLE = NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE,
32 LINESTYLE_WAVY = NS_STYLE_TEXT_DECORATION_STYLE_WAVY
35 enum {
36 DEFINED_NONE = 0x00,
37 DEFINED_LINESTYLE = 0x01,
38 DEFINED_FOREGROUND_COLOR = 0x02,
39 DEFINED_BACKGROUND_COLOR = 0x04,
40 DEFINED_UNDERLINE_COLOR = 0x08
43 // Initialize all members, because TextRange instances may be compared by
44 // memcomp.
45 TextRangeStyle() { Clear(); }
47 void Clear() {
48 mDefinedStyles = DEFINED_NONE;
49 mLineStyle = LINESTYLE_NONE;
50 mIsBoldLine = false;
51 mForegroundColor = mBackgroundColor = mUnderlineColor = NS_RGBA(0, 0, 0, 0);
54 bool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
56 bool IsLineStyleDefined() const {
57 return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
60 bool IsForegroundColorDefined() const {
61 return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
64 bool IsBackgroundColorDefined() const {
65 return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
68 bool IsUnderlineColorDefined() const {
69 return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
72 bool IsNoChangeStyle() const {
73 return !IsForegroundColorDefined() && !IsBackgroundColorDefined() &&
74 IsLineStyleDefined() && mLineStyle == LINESTYLE_NONE;
77 bool Equals(const TextRangeStyle& aOther) const {
78 if (mDefinedStyles != aOther.mDefinedStyles) return false;
79 if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
80 !mIsBoldLine != !aOther.mIsBoldLine))
81 return false;
82 if (IsForegroundColorDefined() &&
83 (mForegroundColor != aOther.mForegroundColor))
84 return false;
85 if (IsBackgroundColorDefined() &&
86 (mBackgroundColor != aOther.mBackgroundColor))
87 return false;
88 if (IsUnderlineColorDefined() &&
89 (mUnderlineColor != aOther.mUnderlineColor))
90 return false;
91 return true;
94 bool operator!=(const TextRangeStyle& aOther) const {
95 return !Equals(aOther);
98 bool operator==(const TextRangeStyle& aOther) const { return Equals(aOther); }
100 uint8_t mDefinedStyles;
101 uint8_t mLineStyle; // DEFINED_LINESTYLE
103 bool mIsBoldLine; // DEFINED_LINESTYLE
105 nscolor mForegroundColor; // DEFINED_FOREGROUND_COLOR
106 nscolor mBackgroundColor; // DEFINED_BACKGROUND_COLOR
107 nscolor mUnderlineColor; // DEFINED_UNDERLINE_COLOR
110 /******************************************************************************
111 * mozilla::TextRange
112 ******************************************************************************/
114 enum class TextRangeType : RawTextRangeType {
115 eUninitialized = 0x00,
116 eCaret = 0x01,
117 eRawClause = nsITextInputProcessor::ATTR_RAW_CLAUSE,
118 eSelectedRawClause = nsITextInputProcessor::ATTR_SELECTED_RAW_CLAUSE,
119 eConvertedClause = nsITextInputProcessor::ATTR_CONVERTED_CLAUSE,
120 eSelectedClause = nsITextInputProcessor::ATTR_SELECTED_CLAUSE
123 bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeValue);
124 RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType);
125 TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType);
126 const char* ToChar(TextRangeType aTextRangeType);
127 SelectionType ToSelectionType(TextRangeType aTextRangeType);
129 struct TextRange {
130 TextRange()
131 : mStartOffset(0),
132 mEndOffset(0),
133 mRangeType(TextRangeType::eUninitialized) {}
135 uint32_t mStartOffset;
136 // XXX Storing end offset makes the initializing code very complicated.
137 // We should replace it with mLength.
138 uint32_t mEndOffset;
140 TextRangeStyle mRangeStyle;
142 TextRangeType mRangeType;
144 uint32_t Length() const { return mEndOffset - mStartOffset; }
146 bool IsClause() const { return mRangeType != TextRangeType::eCaret; }
148 bool Equals(const TextRange& aOther) const {
149 return mStartOffset == aOther.mStartOffset &&
150 mEndOffset == aOther.mEndOffset && mRangeType == aOther.mRangeType &&
151 mRangeStyle == aOther.mRangeStyle;
154 void RemoveCharacter(uint32_t aOffset) {
155 if (mStartOffset > aOffset) {
156 --mStartOffset;
157 --mEndOffset;
158 } else if (mEndOffset > aOffset) {
159 --mEndOffset;
164 /******************************************************************************
165 * mozilla::TextRangeArray
166 ******************************************************************************/
167 class TextRangeArray final : public AutoTArray<TextRange, 10> {
168 friend class WidgetCompositionEvent;
170 ~TextRangeArray() {}
172 NS_INLINE_DECL_REFCOUNTING(TextRangeArray)
174 const TextRange* GetTargetClause() const {
175 for (uint32_t i = 0; i < Length(); ++i) {
176 const TextRange& range = ElementAt(i);
177 if (range.mRangeType == TextRangeType::eSelectedRawClause ||
178 range.mRangeType == TextRangeType::eSelectedClause) {
179 return &range;
182 return nullptr;
185 // Returns target clause offset. If there are selected clauses, this returns
186 // the first selected clause offset. Otherwise, 0.
187 uint32_t TargetClauseOffset() const {
188 const TextRange* range = GetTargetClause();
189 return range ? range->mStartOffset : 0;
192 // Returns target clause length. If there are selected clauses, this returns
193 // the first selected clause length. Otherwise, UINT32_MAX.
194 uint32_t TargetClauseLength() const {
195 const TextRange* range = GetTargetClause();
196 return range ? range->Length() : UINT32_MAX;
199 public:
200 bool IsComposing() const {
201 for (uint32_t i = 0; i < Length(); ++i) {
202 if (ElementAt(i).IsClause()) {
203 return true;
206 return false;
209 bool Equals(const TextRangeArray& aOther) const {
210 size_t len = Length();
211 if (len != aOther.Length()) {
212 return false;
214 for (size_t i = 0; i < len; i++) {
215 if (!ElementAt(i).Equals(aOther.ElementAt(i))) {
216 return false;
219 return true;
222 void RemoveCharacter(uint32_t aOffset) {
223 for (size_t i = 0, len = Length(); i < len; i++) {
224 ElementAt(i).RemoveCharacter(aOffset);
228 bool HasCaret() const {
229 for (const TextRange& range : *this) {
230 if (range.mRangeType == TextRangeType::eCaret) {
231 return true;
234 return false;
237 bool HasClauses() const {
238 for (const TextRange& range : *this) {
239 if (range.IsClause()) {
240 return true;
243 return false;
246 uint32_t GetCaretPosition() const {
247 for (const TextRange& range : *this) {
248 if (range.mRangeType == TextRangeType::eCaret) {
249 return range.mStartOffset;
252 return UINT32_MAX;
255 const TextRange* GetFirstClause() const {
256 for (const TextRange& range : *this) {
257 // Look for the range of a clause whose start offset is 0 because the
258 // first clause's start offset is always 0.
259 if (range.IsClause() && !range.mStartOffset) {
260 return &range;
263 MOZ_ASSERT(!HasClauses());
264 return nullptr;
268 } // namespace mozilla
270 #endif // mozilla_TextRage_h_