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"
16 #include "nsStyleConsts.h"
21 /******************************************************************************
22 * mozilla::TextRangeStyle
23 ******************************************************************************/
25 struct TextRangeStyle
{
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
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
45 TextRangeStyle() { Clear(); }
48 mDefinedStyles
= DEFINED_NONE
;
49 mLineStyle
= LINESTYLE_NONE
;
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
))
82 if (IsForegroundColorDefined() &&
83 (mForegroundColor
!= aOther
.mForegroundColor
))
85 if (IsBackgroundColorDefined() &&
86 (mBackgroundColor
!= aOther
.mBackgroundColor
))
88 if (IsUnderlineColorDefined() &&
89 (mUnderlineColor
!= aOther
.mUnderlineColor
))
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 /******************************************************************************
112 ******************************************************************************/
114 enum class TextRangeType
: RawTextRangeType
{
115 eUninitialized
= 0x00,
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
);
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.
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
) {
158 } else if (mEndOffset
> aOffset
) {
164 /******************************************************************************
165 * mozilla::TextRangeArray
166 ******************************************************************************/
167 class TextRangeArray final
: public AutoTArray
<TextRange
, 10> {
168 friend class WidgetCompositionEvent
;
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
) {
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
;
200 bool IsComposing() const {
201 for (uint32_t i
= 0; i
< Length(); ++i
) {
202 if (ElementAt(i
).IsClause()) {
209 bool Equals(const TextRangeArray
& aOther
) const {
210 size_t len
= Length();
211 if (len
!= aOther
.Length()) {
214 for (size_t i
= 0; i
< len
; i
++) {
215 if (!ElementAt(i
).Equals(aOther
.ElementAt(i
))) {
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
) {
237 bool HasClauses() const {
238 for (const TextRange
& range
: *this) {
239 if (range
.IsClause()) {
246 uint32_t GetCaretPosition() const {
247 for (const TextRange
& range
: *this) {
248 if (range
.mRangeType
== TextRangeType::eCaret
) {
249 return range
.mStartOffset
;
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
) {
263 MOZ_ASSERT(!HasClauses());
268 } // namespace mozilla
270 #endif // mozilla_TextRage_h_