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
248 << "\", mAutocorrect=" << (aContext
.mAutocorrect
? "true" : "false")
249 << ", mIsPrivateBrowsing="
250 << (aContext
.mInPrivateBrowsing
? "true" : "false") << " }";
254 std::ostream
& operator<<(std::ostream
& aStream
,
255 const InputContextAction::Cause
& aCause
) {
257 case InputContextAction::CAUSE_UNKNOWN
:
258 aStream
<< "CAUSE_UNKNOWN";
260 case InputContextAction::CAUSE_UNKNOWN_CHROME
:
261 aStream
<< "CAUSE_UNKNOWN_CHROME";
263 case InputContextAction::CAUSE_KEY
:
264 aStream
<< "CAUSE_KEY";
266 case InputContextAction::CAUSE_MOUSE
:
267 aStream
<< "CAUSE_MOUSE";
269 case InputContextAction::CAUSE_TOUCH
:
270 aStream
<< "CAUSE_TOUCH";
272 case InputContextAction::CAUSE_LONGPRESS
:
273 aStream
<< "CAUSE_LONGPRESS";
275 case InputContextAction::CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT
:
276 aStream
<< "CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT";
278 case InputContextAction::CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT
:
279 aStream
<< "CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT";
282 aStream
<< "illegal value";
288 std::ostream
& operator<<(std::ostream
& aStream
,
289 const InputContextAction::FocusChange
& aFocusChange
) {
290 switch (aFocusChange
) {
291 case InputContextAction::FOCUS_NOT_CHANGED
:
292 aStream
<< "FOCUS_NOT_CHANGED";
294 case InputContextAction::GOT_FOCUS
:
295 aStream
<< "GOT_FOCUS";
297 case InputContextAction::LOST_FOCUS
:
298 aStream
<< "LOST_FOCUS";
300 case InputContextAction::MENU_GOT_PSEUDO_FOCUS
:
301 aStream
<< "MENU_GOT_PSEUDO_FOCUS";
303 case InputContextAction::MENU_LOST_PSEUDO_FOCUS
:
304 aStream
<< "MENU_LOST_PSEUDO_FOCUS";
306 case InputContextAction::WIDGET_CREATED
:
307 aStream
<< "WIDGET_CREATED";
310 aStream
<< "illegal value";
316 std::ostream
& operator<<(
317 std::ostream
& aStream
,
318 const IMENotification::SelectionChangeDataBase
& aData
) {
319 if (!aData
.IsInitialized()) {
320 aStream
<< "{ IsInitialized()=false }";
323 if (!aData
.HasRange()) {
324 aStream
<< "{ HasRange()=false }";
327 aStream
<< "{ mOffset=" << aData
.mOffset
;
328 if (aData
.mString
->Length() > 20) {
329 aStream
<< ", mString.Length()=" << aData
.mString
->Length();
331 aStream
<< ", mString=\"" << NS_ConvertUTF16toUTF8(*aData
.mString
)
332 << "\" (Length()=" << aData
.mString
->Length() << ")";
335 aStream
<< ", GetWritingMode()=" << aData
.GetWritingMode()
336 << ", mReversed=" << (aData
.mReversed
? "true" : "false")
337 << ", mCausedByComposition="
338 << (aData
.mCausedByComposition
? "true" : "false")
339 << ", mCausedBySelectionEvent="
340 << (aData
.mCausedBySelectionEvent
? "true" : "false")
341 << ", mOccurredDuringComposition="
342 << (aData
.mOccurredDuringComposition
? "true" : "false") << " }";
346 std::ostream
& operator<<(std::ostream
& aStream
,
347 const IMENotification::TextChangeDataBase
& aData
) {
348 if (!aData
.IsValid()) {
349 aStream
<< "{ IsValid()=false }";
352 aStream
<< "{ mStartOffset=" << aData
.mStartOffset
353 << ", mRemoveEndOffset=" << aData
.mRemovedEndOffset
354 << ", mAddedEndOffset=" << aData
.mAddedEndOffset
355 << ", mCausedOnlyByComposition="
356 << (aData
.mCausedOnlyByComposition
? "true" : "false")
357 << ", mIncludingChangesDuringComposition="
358 << (aData
.mIncludingChangesDuringComposition
? "true" : "false")
359 << ", mIncludingChangesWithoutComposition="
360 << (aData
.mIncludingChangesWithoutComposition
? "true" : "false")
365 /******************************************************************************
366 * IMENotification::SelectionChangeDataBase
367 ******************************************************************************/
369 void IMENotification::SelectionChangeDataBase::Assign(
370 const WidgetQueryContentEvent
& aQuerySelectedTextEvent
) {
371 MOZ_ASSERT(aQuerySelectedTextEvent
.mMessage
== eQuerySelectedText
);
372 MOZ_ASSERT(aQuerySelectedTextEvent
.Succeeded());
374 if (!(mIsInitialized
= aQuerySelectedTextEvent
.Succeeded())) {
375 ClearSelectionData();
378 if ((mHasRange
= aQuerySelectedTextEvent
.FoundSelection())) {
379 mOffset
= aQuerySelectedTextEvent
.mReply
->StartOffset();
380 *mString
= aQuerySelectedTextEvent
.mReply
->DataRef();
381 mReversed
= aQuerySelectedTextEvent
.mReply
->mReversed
;
382 SetWritingMode(aQuerySelectedTextEvent
.mReply
->WritingModeRef());
384 mOffset
= UINT32_MAX
;
387 // Let's keep the writing mode for avoiding temporarily changing the
388 // writing mode at no selection range.
392 void IMENotification::SelectionChangeDataBase::SetWritingMode(
393 const WritingMode
& aWritingMode
) {
394 mWritingModeBits
= aWritingMode
.GetBits();
397 WritingMode
IMENotification::SelectionChangeDataBase::GetWritingMode() const {
398 return WritingMode(mWritingModeBits
);
401 bool IMENotification::SelectionChangeDataBase::EqualsRange(
402 const ContentSelection
& aContentSelection
) const {
403 if (aContentSelection
.HasRange() != HasRange()) {
409 return mOffset
== aContentSelection
.OffsetAndDataRef().StartOffset() &&
410 *mString
== aContentSelection
.OffsetAndDataRef().DataRef();
413 bool IMENotification::SelectionChangeDataBase::EqualsRangeAndWritingMode(
414 const ContentSelection
& aContentSelection
) const {
415 return EqualsRange(aContentSelection
) &&
416 mWritingModeBits
== aContentSelection
.WritingModeRef().GetBits();
419 } // namespace widget
420 } // namespace mozilla