Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor/./../../../editor/libeditor/ChangeStyleTransaction.cpp
Warning:line 104, column 9
Value stored to 'end' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_editor_libeditor0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/editor/libeditor -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/html -I /root/firefox-clang/extensions/spellcheck/src -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/style -I /root/firefox-clang/layout/tables -I /root/firefox-clang/layout/xul -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_editor_libeditor0.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "ChangeStyleTransaction.h"
6
7#include "EditorDOMAPIWrapper.h"
8#include "HTMLEditor.h"
9#include "HTMLEditUtils.h"
10#include "mozilla/Logging.h"
11#include "mozilla/ToString.h"
12#include "mozilla/dom/Element.h" // for Element
13#include "nsAString.h" // for nsAString::Append, etc.
14#include "nsCRT.h" // for nsCRT::IsAsciiSpace
15#include "nsDebug.h" // for NS_WARNING, etc.
16#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc.
17#include "nsGkAtoms.h" // for nsGkAtoms, etc.
18#include "nsICSSDeclaration.h" // for nsICSSDeclaration.
19#include "nsLiteralString.h" // for NS_LITERAL_STRING, etc.
20#include "nsReadableUtils.h" // for ToNewUnicode
21#include "nsString.h" // for nsAutoString, nsString, etc.
22#include "nsStyledElement.h" // for nsStyledElement.
23#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator
24
25namespace mozilla {
26
27using namespace dom;
28
29// static
30already_AddRefed<ChangeStyleTransaction> ChangeStyleTransaction::Create(
31 HTMLEditor& aHTMLEditor, nsStyledElement& aStyledElement, nsAtom& aProperty,
32 const nsAString& aValue) {
33 RefPtr<ChangeStyleTransaction> transaction = new ChangeStyleTransaction(
34 aHTMLEditor, aStyledElement, aProperty, aValue, false);
35 return transaction.forget();
36}
37
38// static
39already_AddRefed<ChangeStyleTransaction> ChangeStyleTransaction::CreateToRemove(
40 HTMLEditor& aHTMLEditor, nsStyledElement& aStyledElement, nsAtom& aProperty,
41 const nsAString& aValue) {
42 RefPtr<ChangeStyleTransaction> transaction = new ChangeStyleTransaction(
43 aHTMLEditor, aStyledElement, aProperty, aValue, true);
44 return transaction.forget();
45}
46
47ChangeStyleTransaction::ChangeStyleTransaction(HTMLEditor& aHTMLEditor,
48 nsStyledElement& aStyledElement,
49 nsAtom& aProperty,
50 const nsAString& aValue,
51 bool aRemove)
52 : EditTransactionBase(),
53 mHTMLEditor(&aHTMLEditor),
54 mStyledElement(&aStyledElement),
55 mProperty(&aProperty),
56 mRemoveProperty(aRemove),
57 mUndoAttributeWasSet(false),
58 mRedoAttributeWasSet(false) {
59 CopyUTF16toUTF8(aValue, mValue);
60}
61
62std::ostream& operator<<(std::ostream& aStream,
63 const ChangeStyleTransaction& aTransaction) {
64 aStream << "{ mStyledElement=" << aTransaction.mStyledElement.get();
65 if (aTransaction.mStyledElement) {
66 aStream << " (" << *aTransaction.mStyledElement << ")";
67 }
68 aStream << ", mProperty=" << nsAtomCString(aTransaction.mProperty).get()
69 << ", mValue=\"" << aTransaction.mValue.get() << "\", mUndoValue=\""
70 << aTransaction.mUndoValue.get()
71 << "\", mRedoValue=" << aTransaction.mRedoValue.get()
72 << ", mRemoveProperty="
73 << (aTransaction.mRemoveProperty ? "true" : "false")
74 << ", mUndoAttributeWasSet="
75 << (aTransaction.mUndoAttributeWasSet ? "true" : "false")
76 << ", mRedoAttributeWasSet="
77 << (aTransaction.mRedoAttributeWasSet ? "true" : "false")
78 << ", mHTMLEditor=" << aTransaction.mHTMLEditor.get() << " }";
79 return aStream;
80}
81
82#define kNullCh('\0') ('\0')
83
84NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeStyleTransaction, EditTransactionBase,ChangeStyleTransaction::cycleCollection ChangeStyleTransaction
::_cycleCollectorGlobal; void ChangeStyleTransaction::cycleCollection
::Unlink(void* p) { ChangeStyleTransaction* tmp = DowncastCCParticipant
<ChangeStyleTransaction>(p); nsISupports* s = static_cast
<nsISupports*>(p); EditTransactionBase::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mHTMLEditor); ImplCycleCollectionUnlink
(tmp->mStyledElement); (void)tmp; } nsresult ChangeStyleTransaction
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { ChangeStyleTransaction* tmp = DowncastCCParticipant
<ChangeStyleTransaction>(p); nsISupports* s = static_cast
<nsISupports*>(p); if (EditTransactionBase::cycleCollection
::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mHTMLEditor, "mHTMLEditor", 0); ImplCycleCollectionTraverse
(cb, tmp->mStyledElement, "mStyledElement", 0); (void)tmp;
return NS_OK; }
85 mHTMLEditor, mStyledElement)ChangeStyleTransaction::cycleCollection ChangeStyleTransaction
::_cycleCollectorGlobal; void ChangeStyleTransaction::cycleCollection
::Unlink(void* p) { ChangeStyleTransaction* tmp = DowncastCCParticipant
<ChangeStyleTransaction>(p); nsISupports* s = static_cast
<nsISupports*>(p); EditTransactionBase::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mHTMLEditor); ImplCycleCollectionUnlink
(tmp->mStyledElement); (void)tmp; } nsresult ChangeStyleTransaction
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { ChangeStyleTransaction* tmp = DowncastCCParticipant
<ChangeStyleTransaction>(p); nsISupports* s = static_cast
<nsISupports*>(p); if (EditTransactionBase::cycleCollection
::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mHTMLEditor, "mHTMLEditor", 0); ImplCycleCollectionTraverse
(cb, tmp->mStyledElement, "mStyledElement", 0); (void)tmp;
return NS_OK; }
86
87NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeStyleTransaction)nsresult ChangeStyleTransaction::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 87); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::kIID), (nsCycleCollectionISupports::kIID)) && (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID)) || LowWordEquals
(aIID, (nsCycleCollectionISupports::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID))) { *aInstancePtr
= ChangeStyleTransaction::cycleCollection::GetParticipant();
return NS_OK; } if (LowWordEquals(aIID, (nsCycleCollectionISupports
::kIID))) { *aInstancePtr = ChangeStyleTransaction::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
88NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)foundInterface = 0; nsresult status; if (!foundInterface) status
= EditTransactionBase::QueryInterface(aIID, (void**)&foundInterface
); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr
= foundInterface; return status; }
89
90NS_IMPL_ADDREF_INHERITED(ChangeStyleTransaction, EditTransactionBase)MozExternalRefCountType ChangeStyleTransaction::AddRef(void) {
static_assert(!std::is_destructible_v<ChangeStyleTransaction
>, "Reference-counted class " "ChangeStyleTransaction" " should not have a public destructor. "
"Make this class's destructor non-public"); nsrefcnt r = EditTransactionBase
::AddRef(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt
<ChangeStyleTransaction>) { NS_LogAddRef((this), (r), (
"ChangeStyleTransaction"), (uint32_t)(sizeof(*this))); } return
r; }
91NS_IMPL_RELEASE_INHERITED(ChangeStyleTransaction, EditTransactionBase)MozExternalRefCountType ChangeStyleTransaction::Release(void)
{ nsrefcnt r = EditTransactionBase::Release(); if constexpr (
::mozilla::detail::ShouldLogInheritedRefcnt<ChangeStyleTransaction
>) { NS_LogRelease((this), (r), ("ChangeStyleTransaction")
); } return r; }
92
93// Answers true if aValue is in the string list of white-space separated values
94// aValueList.
95bool ChangeStyleTransaction::ValueIncludes(const nsACString& aValueList,
96 const nsACString& aValue) {
97 nsAutoCString valueList(aValueList);
98 bool result = false;
99
100 // put an extra null at the end
101 valueList.Append(kNullCh('\0'));
102
103 char* start = valueList.BeginWriting();
104 char* end = start;
Value stored to 'end' during its initialization is never read
105
106 while (kNullCh('\0') != *start) {
107 while (kNullCh('\0') != *start && nsCRT::IsAsciiSpace(*start)) {
108 // skip leading space
109 start++;
110 }
111 end = start;
112
113 while (kNullCh('\0') != *end && !nsCRT::IsAsciiSpace(*end)) {
114 // look for space or end
115 end++;
116 }
117 // end string here
118 *end = kNullCh('\0');
119
120 if (start < end) {
121 if (aValue.Equals(nsDependentCString(start),
122 nsCaseInsensitiveCStringComparator)) {
123 result = true;
124 break;
125 }
126 }
127 start = ++end;
128 }
129 return result;
130}
131
132NS_IMETHODIMPnsresult ChangeStyleTransaction::DoTransaction() {
133 MOZ_LOG(GetLogModule(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
134 ("%p ChangeStyleTransaction::%s this=%s", this, __FUNCTION__,do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
135 ToString(*this).c_str()))do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
;
136
137 MOZ_ASSERT(mHTMLEditor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mHTMLEditor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mHTMLEditor))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mHTMLEditor", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mHTMLEditor"
")"); do { MOZ_CrashSequence(__null, 137); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
138 if (NS_WARN_IF(!mStyledElement)NS_warn_if_impl(!mStyledElement, "!mStyledElement", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 138)
) {
139 return NS_ERROR_NOT_AVAILABLE;
140 }
141
142 const OwningNonNull<HTMLEditor> htmlEditor = *mHTMLEditor;
143 const OwningNonNull<nsStyledElement> styledElement = *mStyledElement;
144 const nsCOMPtr<nsDOMCSSDeclaration> cssDecl = styledElement->Style();
145
146 // FIXME(bug 1606994): Using atoms forces a string copy here which is not
147 // great.
148 nsAutoCString propertyNameString;
149 mProperty->ToUTF8String(propertyNameString);
150
151 mUndoAttributeWasSet = mStyledElement->HasAttr(nsGkAtoms::style);
152
153 nsAutoCString values;
154 cssDecl->GetPropertyValue(propertyNameString, values);
155 mUndoValue.Assign(values);
156
157 if (mRemoveProperty) {
158 if (mProperty == nsGkAtoms::text_decoration) {
159 BuildTextDecorationValueToRemove(values, mValue, values);
160 if (values.IsEmpty()) {
161 nsresult rv =
162 AutoCSSDeclarationAPIWrapper(htmlEditor, styledElement, cssDecl)
163 .RemoveProperty(propertyNameString);
164 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
165 NS_WARNING("AutoCSSDeclarationAPIWrapper::RemoveProperty() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoCSSDeclarationAPIWrapper::RemoveProperty() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 165)
;
166 return rv;
167 }
168 } else {
169 nsAutoCString priority;
170 cssDecl->GetPropertyPriority(propertyNameString, priority);
171 nsresult rv =
172 AutoCSSDeclarationAPIWrapper(htmlEditor, styledElement, cssDecl)
173 .SetProperty(propertyNameString, values, priority);
174 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
175 NS_WARNING("AutoCSSDeclarationAPIWrapper::SetProperty() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoCSSDeclarationAPIWrapper::SetProperty() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 175)
;
176 return rv;
177 }
178 }
179 } else {
180 nsresult rv =
181 AutoCSSDeclarationAPIWrapper(htmlEditor, styledElement, cssDecl)
182 .RemoveProperty(propertyNameString);
183 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
184 NS_WARNING("AutoCSSDeclarationAPIWrapper::RemoveProperty() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoCSSDeclarationAPIWrapper::RemoveProperty() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 184)
;
185 return rv;
186 }
187 }
188 } else {
189 nsAutoCString priority;
190 cssDecl->GetPropertyPriority(propertyNameString, priority);
191 if (mProperty == nsGkAtoms::text_decoration) {
192 BuildTextDecorationValueToSet(values, mValue, values);
193 } else {
194 values.Assign(mValue);
195 }
196 nsresult rv =
197 AutoCSSDeclarationAPIWrapper(htmlEditor, styledElement, cssDecl)
198 .SetProperty(propertyNameString, values, priority);
199 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
200 NS_WARNING("AutoCSSDeclarationAPIWrapper::SetProperty() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoCSSDeclarationAPIWrapper::SetProperty() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 200)
;
201 return rv;
202 }
203 }
204
205 // Let's be sure we don't keep an empty style attribute
206 uint32_t length = cssDecl->Length();
207 if (!length) {
208 AutoElementAttrAPIWrapper elementWrapper(htmlEditor, styledElement);
209 nsresult rv = elementWrapper.UnsetAttr(nsGkAtoms::style, true);
210 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
211 NS_WARNING("AutoElementAttrAPIWrapper::UnsetAttr() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoElementAttrAPIWrapper::UnsetAttr() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 211)
;
212 return rv;
213 }
214 NS_WARNING_ASSERTION(do { if (!(elementWrapper.IsExpectedResult(EmptyString()))) {
NS_DebugBreak(NS_DEBUG_WARNING, "Removing style attribute caused other mutations, but ignored"
, "elementWrapper.IsExpectedResult(EmptyString())", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 216); } } while (false)
215 elementWrapper.IsExpectedResult(EmptyString()),do { if (!(elementWrapper.IsExpectedResult(EmptyString()))) {
NS_DebugBreak(NS_DEBUG_WARNING, "Removing style attribute caused other mutations, but ignored"
, "elementWrapper.IsExpectedResult(EmptyString())", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 216); } } while (false)
216 "Removing style attribute caused other mutations, but ignored")do { if (!(elementWrapper.IsExpectedResult(EmptyString()))) {
NS_DebugBreak(NS_DEBUG_WARNING, "Removing style attribute caused other mutations, but ignored"
, "elementWrapper.IsExpectedResult(EmptyString())", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 216); } } while (false)
;
217 } else {
218 mRedoAttributeWasSet = true;
219 }
220
221 cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
222 return NS_OK;
223}
224
225nsresult ChangeStyleTransaction::SetStyle(bool aAttributeWasSet,
226 nsACString& aValue) {
227 if (NS_WARN_IF(!mHTMLEditor)NS_warn_if_impl(!mHTMLEditor, "!mHTMLEditor", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 227)
|| NS_WARN_IF(!mStyledElement)NS_warn_if_impl(!mStyledElement, "!mStyledElement", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 227)
) {
228 return NS_ERROR_NOT_AVAILABLE;
229 }
230 const OwningNonNull<HTMLEditor> htmlEditor = *mHTMLEditor;
231 const OwningNonNull<nsStyledElement> styledElement = *mStyledElement;
232 if (aAttributeWasSet) {
233 // The style attribute was not empty, let's recreate the declaration
234 nsAutoCString propertyNameString;
235 mProperty->ToUTF8String(propertyNameString);
236
237 const nsCOMPtr<nsDOMCSSDeclaration> cssDecl = styledElement->Style();
238
239 ErrorResult error;
240 if (aValue.IsEmpty()) {
241 // An empty value means we have to remove the property
242 nsresult rv =
243 AutoCSSDeclarationAPIWrapper(htmlEditor, styledElement, cssDecl)
244 .RemoveProperty(propertyNameString);
245 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
246 NS_WARNING("AutoCSSDeclarationAPIWrapper::RemoveProperty() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoCSSDeclarationAPIWrapper::RemoveProperty() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 246)
;
247 return rv;
248 }
249 }
250 // Let's recreate the declaration as it was
251 nsAutoCString priority;
252 cssDecl->GetPropertyPriority(propertyNameString, priority);
253 nsresult rv =
254 AutoCSSDeclarationAPIWrapper(htmlEditor, styledElement, cssDecl)
255 .SetProperty(propertyNameString, aValue, priority);
256 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
257 NS_WARNING("AutoCSSDeclarationAPIWrapper::SetProperty() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoCSSDeclarationAPIWrapper::SetProperty() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 257)
;
258 return rv;
259 }
260 return NS_OK;
261 }
262
263 AutoElementAttrAPIWrapper elementWrapper(htmlEditor, styledElement);
264 nsresult rv = elementWrapper.UnsetAttr(nsGkAtoms::style, true);
265 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
266 NS_WARNING("AutoElementAttrAPIWrapper::UnsetAttr() failed")NS_DebugBreak(NS_DEBUG_WARNING, "AutoElementAttrAPIWrapper::UnsetAttr() failed"
, nullptr, "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 266)
;
267 return rv;
268 }
269 NS_WARNING_ASSERTION(do { if (!(elementWrapper.IsExpectedResult(EmptyString()))) {
NS_DebugBreak(NS_DEBUG_WARNING, "Removing style attribute caused other mutations, but ignored"
, "elementWrapper.IsExpectedResult(EmptyString())", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 271); } } while (false)
270 elementWrapper.IsExpectedResult(EmptyString()),do { if (!(elementWrapper.IsExpectedResult(EmptyString()))) {
NS_DebugBreak(NS_DEBUG_WARNING, "Removing style attribute caused other mutations, but ignored"
, "elementWrapper.IsExpectedResult(EmptyString())", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 271); } } while (false)
271 "Removing style attribute caused other mutations, but ignored")do { if (!(elementWrapper.IsExpectedResult(EmptyString()))) {
NS_DebugBreak(NS_DEBUG_WARNING, "Removing style attribute caused other mutations, but ignored"
, "elementWrapper.IsExpectedResult(EmptyString())", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 271); } } while (false)
;
272 return NS_OK;
273}
274
275NS_IMETHODIMPnsresult ChangeStyleTransaction::UndoTransaction() {
276 MOZ_LOG(GetLogModule(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
277 ("%p ChangeStyleTransaction::%s this=%s", this, __FUNCTION__,do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
278 ToString(*this).c_str()))do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
;
279
280 nsresult rv = SetStyle(mUndoAttributeWasSet, mUndoValue);
281 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "ChangeStyleTransaction::SetStyle() failed"
, "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 282); } } while (false)
282 "ChangeStyleTransaction::SetStyle() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "ChangeStyleTransaction::SetStyle() failed"
, "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 282); } } while (false)
;
283 return rv;
284}
285
286NS_IMETHODIMPnsresult ChangeStyleTransaction::RedoTransaction() {
287 MOZ_LOG(GetLogModule(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
288 ("%p ChangeStyleTransaction::%s this=%s", this, __FUNCTION__,do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
289 ToString(*this).c_str()))do { const ::mozilla::LogModule* moz_real_module = GetLogModule
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "%p ChangeStyleTransaction::%s this=%s", this
, __FUNCTION__, ToString(*this).c_str()); } } while (0)
;
290
291 nsresult rv = SetStyle(mRedoAttributeWasSet, mRedoValue);
292 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "ChangeStyleTransaction::SetStyle() failed"
, "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 293); } } while (false)
293 "ChangeStyleTransaction::SetStyle() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "ChangeStyleTransaction::SetStyle() failed"
, "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/ChangeStyleTransaction.cpp"
, 293); } } while (false)
;
294 return rv;
295}
296
297// static
298void ChangeStyleTransaction::BuildTextDecorationValueToSet(
299 const nsACString& aCurrentValues, const nsACString& aAddingValues,
300 nsACString& aOutValues) {
301 const bool underline = ValueIncludes(aCurrentValues, "underline"_ns) ||
302 ValueIncludes(aAddingValues, "underline"_ns);
303 const bool overline = ValueIncludes(aCurrentValues, "overline"_ns) ||
304 ValueIncludes(aAddingValues, "overline"_ns);
305 const bool lineThrough = ValueIncludes(aCurrentValues, "line-through"_ns) ||
306 ValueIncludes(aAddingValues, "line-through"_ns);
307 // FYI: Don't refer aCurrentValues which may refer same instance as
308 // aOutValues.
309 BuildTextDecorationValue(underline, overline, lineThrough, aOutValues);
310}
311
312// static
313void ChangeStyleTransaction::BuildTextDecorationValueToRemove(
314 const nsACString& aCurrentValues, const nsACString& aRemovingValues,
315 nsACString& aOutValues) {
316 const bool underline = ValueIncludes(aCurrentValues, "underline"_ns) &&
317 !ValueIncludes(aRemovingValues, "underline"_ns);
318 const bool overline = ValueIncludes(aCurrentValues, "overline"_ns) &&
319 !ValueIncludes(aRemovingValues, "overline"_ns);
320 const bool lineThrough = ValueIncludes(aCurrentValues, "line-through"_ns) &&
321 !ValueIncludes(aRemovingValues, "line-through"_ns);
322 // FYI: Don't refer aCurrentValues which may refer same instance as
323 // aOutValues.
324 BuildTextDecorationValue(underline, overline, lineThrough, aOutValues);
325}
326
327void ChangeStyleTransaction::BuildTextDecorationValue(bool aUnderline,
328 bool aOverline,
329 bool aLineThrough,
330 nsACString& aOutValues) {
331 // We should build text-decoration(-line) value as same as Blink for
332 // compatibility. Blink sets text-decoration-line to the values in the
333 // following order. Blink drops `blink` and other styles like color and
334 // style. For keeping the code simple, let's use the lossy behavior.
335 aOutValues.Truncate();
336 if (aUnderline) {
337 aOutValues.AssignLiteral("underline");
338 }
339 if (aOverline) {
340 if (!aOutValues.IsEmpty()) {
341 aOutValues.Append(HTMLEditUtils::kSpace);
342 }
343 aOutValues.AppendLiteral("overline");
344 }
345 if (aLineThrough) {
346 if (!aOutValues.IsEmpty()) {
347 aOutValues.Append(HTMLEditUtils::kSpace);
348 }
349 aOutValues.AppendLiteral("line-through");
350 }
351}
352
353} // namespace mozilla