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_
11 #include "mozilla/EventForwards.h"
14 #include "nsISelectionController.h"
15 #include "nsITextInputProcessor.h"
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
{
35 inline static LineStyle
ToLineStyle(RawTextRangeType aRawLineStyle
) {
36 switch (static_cast<LineStyle
>(aRawLineStyle
)) {
38 case LineStyle::Solid
:
39 case LineStyle::Dotted
:
40 case LineStyle::Dashed
:
41 case LineStyle::Double
:
43 return static_cast<LineStyle
>(aRawLineStyle
);
45 MOZ_ASSERT_UNREACHABLE("aRawLineStyle value is invalid");
46 return LineStyle::None
;
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
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(); }
65 mDefinedStyles
= DEFINED_NONE
;
66 mLineStyle
= LineStyle::None
;
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
))
99 if (IsForegroundColorDefined() &&
100 (mForegroundColor
!= aOther
.mForegroundColor
))
102 if (IsBackgroundColorDefined() &&
103 (mBackgroundColor
!= aOther
.mBackgroundColor
))
105 if (IsUnderlineColorDefined() &&
106 (mUnderlineColor
!= aOther
.mUnderlineColor
))
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 /******************************************************************************
129 ******************************************************************************/
131 enum class TextRangeType
: RawTextRangeType
{
132 eUninitialized
= 0x00,
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
);
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.
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
) {
175 } else if (mEndOffset
> aOffset
) {
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
) {
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
;
217 bool IsComposing() const {
218 for (uint32_t i
= 0; i
< Length(); ++i
) {
219 if (ElementAt(i
).IsClause()) {
226 bool Equals(const TextRangeArray
& aOther
) const {
227 size_t len
= Length();
228 if (len
!= aOther
.Length()) {
231 for (size_t i
= 0; i
< len
; i
++) {
232 if (!ElementAt(i
).Equals(aOther
.ElementAt(i
))) {
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
) {
254 bool HasClauses() const {
255 for (const TextRange
& range
: *this) {
256 if (range
.IsClause()) {
263 uint32_t GetCaretPosition() const {
264 for (const TextRange
& range
: *this) {
265 if (range
.mRangeType
== TextRangeType::eCaret
) {
266 return range
.mStartOffset
;
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
) {
280 MOZ_ASSERT(!HasClauses());
285 } // namespace mozilla
287 #endif // mozilla_TextRage_h_