1 /* -*- Mode: C++; tab-width: 40; 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/. */
10 #include "ContentData.h"
11 #include "gfxFontUtils.h"
12 #include "TextEvents.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/ToString.h"
16 #include "mozilla/WritingModes.h"
18 #include "nsPrintfCString.h"
23 template PrintStringDetail::PrintStringDetail(
24 const Maybe
<nsString
>& aMaybeString
, uint32_t aMaxLength
);
26 template <typename StringType
>
27 PrintStringDetail::PrintStringDetail(const Maybe
<StringType
>& aMaybeString
,
28 uint32_t aMaxLength
/* = UINT32_MAX */)
29 : PrintStringDetail(aMaybeString
.refOr(EmptyString()), aMaxLength
) {
30 if (aMaybeString
.isNothing()) {
31 AssignASCII(ToString(aMaybeString
).c_str());
35 PrintStringDetail::PrintStringDetail(const nsAString
& aString
,
36 uint32_t aMaxLength
/* = UINT32_MAX */) {
38 const uint32_t kFirstHalf
=
39 aString
.Length() <= aMaxLength
? UINT32_MAX
: (aMaxLength
+ 1) / 2;
40 const uint32_t kSecondHalf
=
41 aString
.Length() <= aMaxLength
? 0 : aMaxLength
/ 2;
42 for (uint32_t i
= 0; i
< aString
.Length(); i
++) {
46 char32_t ch
= aString
.CharAt(i
);
47 if (NS_IS_HIGH_SURROGATE(ch
) && i
+ 1 < aString
.Length() &&
48 NS_IS_LOW_SURROGATE(aString
.CharAt(i
+ 1))) {
49 ch
= SURROGATE_TO_UCS4(ch
, aString
.CharAt(i
+ 1));
51 Append(PrintCharData(ch
));
52 if (i
+ 1 == kFirstHalf
) {
53 AppendLiteral(" ...");
54 i
= aString
.Length() - kSecondHalf
- 1;
55 if (NS_IS_LOW_SURROGATE(aString
.CharAt(i
)) &&
56 NS_IS_HIGH_SURROGATE(aString
.CharAt(i
- 1))) {
57 if (i
- 1 <= kFirstHalf
) {
63 } else if (!IS_IN_BMP(ch
)) {
67 AppendLiteral("\" (Length()=");
68 AppendInt(static_cast<uint32_t>(aString
.Length()));
73 nsCString
PrintStringDetail::PrintCharData(char32_t aChar
) {
76 return "NULL (0x0000)"_ns
;
78 return "BACKSPACE (0x0008)"_ns
;
80 return "CHARACTER TABULATION (0x0009)"_ns
;
82 return "LINE FEED (0x000A)"_ns
;
84 return "LINE TABULATION (0x000B)"_ns
;
86 return "FORM FEED (0x000C)"_ns
;
88 return "CARRIAGE RETURN (0x000D)"_ns
;
90 return "CANCEL (0x0018)"_ns
;
92 return "ESCAPE (0x001B)"_ns
;
94 return "SPACE (0x0020)"_ns
;
96 return "DELETE (0x007F)"_ns
;
98 return "NO-BREAK SPACE (0x00A0)"_ns
;
100 return "SOFT HYPHEN (0x00AD)"_ns
;
102 return "EN QUAD (0x2000)"_ns
;
104 return "EM QUAD (0x2001)"_ns
;
106 return "EN SPACE (0x2002)"_ns
;
108 return "EM SPACE (0x2003)"_ns
;
110 return "THREE-PER-EM SPACE (0x2004)"_ns
;
112 return "FOUR-PER-EM SPACE (0x2005)"_ns
;
114 return "SIX-PER-EM SPACE (0x2006)"_ns
;
116 return "FIGURE SPACE (0x2007)"_ns
;
118 return "PUNCTUATION SPACE (0x2008)"_ns
;
120 return "THIN SPACE (0x2009)"_ns
;
122 return "HAIR SPACE (0x200A)"_ns
;
124 return "ZERO WIDTH SPACE (0x200B)"_ns
;
126 return "ZERO WIDTH NON-JOINER (0x200C)"_ns
;
128 return "ZERO WIDTH JOINER (0x200D)"_ns
;
130 return "LEFT-TO-RIGHT MARK (0x200E)"_ns
;
132 return "RIGHT-TO-LEFT MARK (0x200F)"_ns
;
134 return "PARAGRAPH SEPARATOR (0x2029)"_ns
;
136 return "LEFT-TO-RIGHT EMBEDDING (0x202A)"_ns
;
138 return "RIGHT-TO-LEFT EMBEDDING (0x202B)"_ns
;
140 return "LEFT-TO-RIGHT OVERRIDE (0x202D)"_ns
;
142 return "RIGHT-TO-LEFT OVERRIDE (0x202E)"_ns
;
144 return "NARROW NO-BREAK SPACE (0x202F)"_ns
;
146 return "MEDIUM MATHEMATICAL SPACE (0x205F)"_ns
;
148 return "WORD JOINER (0x2060)"_ns
;
150 return "LEFT-TO-RIGHT ISOLATE (0x2066)"_ns
;
152 return "RIGHT-TO-LEFT ISOLATE (0x2067)"_ns
;
154 return "IDEOGRAPHIC SPACE (0x3000)"_ns
;
156 return "ZERO WIDTH NO-BREAK SPACE (0xFEFF)"_ns
;
158 if (aChar
< ' ' || (aChar
>= 0x80 && aChar
< 0xA0)) {
159 return nsPrintfCString("Control (0x%04X)", aChar
);
161 if (NS_IS_HIGH_SURROGATE(aChar
)) {
162 return nsPrintfCString("High Surrogate (0x%04X)", aChar
);
164 if (NS_IS_LOW_SURROGATE(aChar
)) {
165 return nsPrintfCString("Low Surrogate (0x%04X)", aChar
);
167 if (gfxFontUtils::IsVarSelector(aChar
)) {
168 return IS_IN_BMP(aChar
)
169 ? nsPrintfCString("Variant Selector (0x%04X)", aChar
)
170 : nsPrintfCString("Variant Selector (0x%08X)", aChar
);
172 nsAutoString utf16Str
;
173 AppendUCS4ToUTF16(aChar
, utf16Str
);
174 return IS_IN_BMP(aChar
)
175 ? nsPrintfCString("'%s' (0x%04X)",
176 NS_ConvertUTF16toUTF8(utf16Str
).get(), aChar
)
177 : nsPrintfCString("'%s' (0x%08X)",
178 NS_ConvertUTF16toUTF8(utf16Str
).get(),
186 std::ostream
& operator<<(std::ostream
& aStream
, const IMEEnabled
& aEnabled
) {
188 case IMEEnabled::Disabled
:
189 return aStream
<< "DISABLED";
190 case IMEEnabled::Enabled
:
191 return aStream
<< "ENABLED";
192 case IMEEnabled::Password
:
193 return aStream
<< "PASSWORD";
194 case IMEEnabled::Unknown
:
195 return aStream
<< "illegal value";
197 MOZ_ASSERT_UNREACHABLE("Add a case to handle your new IMEEnabled value");
201 std::ostream
& operator<<(std::ostream
& aStream
, const IMEState::Open
& aOpen
) {
203 case IMEState::DONT_CHANGE_OPEN_STATE
:
204 aStream
<< "DONT_CHANGE_OPEN_STATE";
209 case IMEState::CLOSED
:
213 aStream
<< "illegal value";
219 std::ostream
& operator<<(std::ostream
& aStream
, const IMEState
& aState
) {
220 aStream
<< "{ mEnabled=" << aState
.mEnabled
<< ", mOpen=" << aState
.mOpen
225 std::ostream
& operator<<(std::ostream
& aStream
,
226 const InputContext::Origin
& aOrigin
) {
228 case InputContext::ORIGIN_MAIN
:
229 aStream
<< "ORIGIN_MAIN";
231 case InputContext::ORIGIN_CONTENT
:
232 aStream
<< "ORIGIN_CONTENT";
235 aStream
<< "illegal value";
241 std::ostream
& operator<<(std::ostream
& aStream
, const InputContext
& aContext
) {
242 aStream
<< "{ mIMEState=" << aContext
.mIMEState
243 << ", mOrigin=" << aContext
.mOrigin
<< ", mHTMLInputType=\""
244 << aContext
.mHTMLInputType
<< "\", mHTMLInputMode=\""
245 << aContext
.mHTMLInputMode
<< "\", mActionHint=\""
246 << aContext
.mActionHint
<< "\", mAutocapitalize=\""
247 << aContext
.mAutocapitalize
<< "\", mIsPrivateBrowsing="
248 << (aContext
.mInPrivateBrowsing
? "true" : "false") << " }";
252 std::ostream
& operator<<(std::ostream
& aStream
,
253 const InputContextAction::Cause
& aCause
) {
255 case InputContextAction::CAUSE_UNKNOWN
:
256 aStream
<< "CAUSE_UNKNOWN";
258 case InputContextAction::CAUSE_UNKNOWN_CHROME
:
259 aStream
<< "CAUSE_UNKNOWN_CHROME";
261 case InputContextAction::CAUSE_KEY
:
262 aStream
<< "CAUSE_KEY";
264 case InputContextAction::CAUSE_MOUSE
:
265 aStream
<< "CAUSE_MOUSE";
267 case InputContextAction::CAUSE_TOUCH
:
268 aStream
<< "CAUSE_TOUCH";
270 case InputContextAction::CAUSE_LONGPRESS
:
271 aStream
<< "CAUSE_LONGPRESS";
273 case InputContextAction::CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT
:
274 aStream
<< "CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT";
276 case InputContextAction::CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT
:
277 aStream
<< "CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT";
280 aStream
<< "illegal value";
286 std::ostream
& operator<<(std::ostream
& aStream
,
287 const InputContextAction::FocusChange
& aFocusChange
) {
288 switch (aFocusChange
) {
289 case InputContextAction::FOCUS_NOT_CHANGED
:
290 aStream
<< "FOCUS_NOT_CHANGED";
292 case InputContextAction::GOT_FOCUS
:
293 aStream
<< "GOT_FOCUS";
295 case InputContextAction::LOST_FOCUS
:
296 aStream
<< "LOST_FOCUS";
298 case InputContextAction::MENU_GOT_PSEUDO_FOCUS
:
299 aStream
<< "MENU_GOT_PSEUDO_FOCUS";
301 case InputContextAction::MENU_LOST_PSEUDO_FOCUS
:
302 aStream
<< "MENU_LOST_PSEUDO_FOCUS";
304 case InputContextAction::WIDGET_CREATED
:
305 aStream
<< "WIDGET_CREATED";
308 aStream
<< "illegal value";
314 std::ostream
& operator<<(
315 std::ostream
& aStream
,
316 const IMENotification::SelectionChangeDataBase
& aData
) {
317 if (!aData
.IsInitialized()) {
318 aStream
<< "{ IsInitialized()=false }";
321 if (!aData
.HasRange()) {
322 aStream
<< "{ HasRange()=false }";
325 aStream
<< "{ mOffset=" << aData
.mOffset
;
326 if (aData
.mString
->Length() > 20) {
327 aStream
<< ", mString.Length()=" << aData
.mString
->Length();
329 aStream
<< ", mString=\"" << NS_ConvertUTF16toUTF8(*aData
.mString
)
330 << "\" (Length()=" << aData
.mString
->Length() << ")";
333 aStream
<< ", GetWritingMode()=" << aData
.GetWritingMode()
334 << ", mReversed=" << (aData
.mReversed
? "true" : "false")
335 << ", mCausedByComposition="
336 << (aData
.mCausedByComposition
? "true" : "false")
337 << ", mCausedBySelectionEvent="
338 << (aData
.mCausedBySelectionEvent
? "true" : "false")
339 << ", mOccurredDuringComposition="
340 << (aData
.mOccurredDuringComposition
? "true" : "false") << " }";
344 std::ostream
& operator<<(std::ostream
& aStream
,
345 const IMENotification::TextChangeDataBase
& aData
) {
346 if (!aData
.IsValid()) {
347 aStream
<< "{ IsValid()=false }";
350 aStream
<< "{ mStartOffset=" << aData
.mStartOffset
351 << ", mRemoveEndOffset=" << aData
.mRemovedEndOffset
352 << ", mAddedEndOffset=" << aData
.mAddedEndOffset
353 << ", mCausedOnlyByComposition="
354 << (aData
.mCausedOnlyByComposition
? "true" : "false")
355 << ", mIncludingChangesDuringComposition="
356 << (aData
.mIncludingChangesDuringComposition
? "true" : "false")
357 << ", mIncludingChangesWithoutComposition="
358 << (aData
.mIncludingChangesWithoutComposition
? "true" : "false")
363 /******************************************************************************
364 * IMENotification::SelectionChangeDataBase
365 ******************************************************************************/
367 void IMENotification::SelectionChangeDataBase::Assign(
368 const WidgetQueryContentEvent
& aQuerySelectedTextEvent
) {
369 MOZ_ASSERT(aQuerySelectedTextEvent
.mMessage
== eQuerySelectedText
);
370 MOZ_ASSERT(aQuerySelectedTextEvent
.Succeeded());
372 if (!(mIsInitialized
= aQuerySelectedTextEvent
.Succeeded())) {
373 ClearSelectionData();
376 if ((mHasRange
= aQuerySelectedTextEvent
.FoundSelection())) {
377 mOffset
= aQuerySelectedTextEvent
.mReply
->StartOffset();
378 *mString
= aQuerySelectedTextEvent
.mReply
->DataRef();
379 mReversed
= aQuerySelectedTextEvent
.mReply
->mReversed
;
380 SetWritingMode(aQuerySelectedTextEvent
.mReply
->WritingModeRef());
382 mOffset
= UINT32_MAX
;
385 // Let's keep the writing mode for avoiding temporarily changing the
386 // writing mode at no selection range.
390 void IMENotification::SelectionChangeDataBase::SetWritingMode(
391 const WritingMode
& aWritingMode
) {
392 mWritingModeBits
= aWritingMode
.GetBits();
395 WritingMode
IMENotification::SelectionChangeDataBase::GetWritingMode() const {
396 return WritingMode(mWritingModeBits
);
399 bool IMENotification::SelectionChangeDataBase::EqualsRange(
400 const ContentSelection
& aContentSelection
) const {
401 if (aContentSelection
.HasRange() != HasRange()) {
407 return mOffset
== aContentSelection
.OffsetAndDataRef().StartOffset() &&
408 *mString
== aContentSelection
.OffsetAndDataRef().DataRef();
411 bool IMENotification::SelectionChangeDataBase::EqualsRangeAndWritingMode(
412 const ContentSelection
& aContentSelection
) const {
413 return EqualsRange(aContentSelection
) &&
414 mWritingModeBits
== aContentSelection
.WritingModeRef().GetBits();
417 } // namespace widget
418 } // namespace mozilla