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 #include "mozilla/EditorCommands.h"
8 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
9 #include "mozilla/EditorBase.h" // for EditorBase
10 #include "mozilla/ErrorResult.h"
11 #include "mozilla/HTMLEditor.h" // for HTMLEditor
12 #include "mozilla/dom/Element.h"
13 #include "nsAString.h"
14 #include "nsAtom.h" // for nsAtom, nsStaticAtom, etc
15 #include "nsCommandParams.h" // for nsCommandParams, etc
16 #include "nsComponentManagerUtils.h" // for do_CreateInstance
17 #include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::font, etc
18 #include "nsIClipboard.h" // for nsIClipboard, etc
19 #include "nsIEditingSession.h"
20 #include "nsIPrincipal.h" // for nsIPrincipal
21 #include "nsLiteralString.h" // for NS_LITERAL_STRING
22 #include "nsReadableUtils.h" // for EmptyString
23 #include "nsString.h" // for nsAutoString, nsString, etc
24 #include "nsStringFwd.h" // for nsString
32 static nsresult
GetListState(HTMLEditor
* aHTMLEditor
, bool* aMixed
,
33 nsAString
& aLocalName
);
36 #define STATE_ENABLED "state_enabled"
37 #define STATE_ALL "state_all"
38 #define STATE_ANY "state_any"
39 #define STATE_MIXED "state_mixed"
40 #define STATE_BEGIN "state_begin"
41 #define STATE_END "state_end"
42 #define STATE_ATTRIBUTE "state_attribute"
43 #define STATE_DATA "state_data"
45 /*****************************************************************************
46 * mozilla::StateUpdatingCommandBase
47 *****************************************************************************/
49 bool StateUpdatingCommandBase::IsCommandEnabled(Command aCommand
,
50 EditorBase
* aEditorBase
) const {
51 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
55 if (!htmlEditor
->IsModifiable() || !htmlEditor
->IsSelectionEditable()) {
58 if (aCommand
== Command::FormatAbsolutePosition
) {
59 return htmlEditor
->IsAbsolutePositionEditorEnabled();
64 nsresult
StateUpdatingCommandBase::DoCommand(Command aCommand
,
65 EditorBase
& aEditorBase
,
66 nsIPrincipal
* aPrincipal
) const {
67 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
68 if (NS_WARN_IF(!htmlEditor
)) {
69 return NS_ERROR_FAILURE
;
71 nsStaticAtom
* tagName
= GetTagName(aCommand
);
72 if (NS_WARN_IF(!tagName
)) {
73 return NS_ERROR_UNEXPECTED
;
75 nsresult rv
= ToggleState(MOZ_KnownLive(*tagName
), MOZ_KnownLive(*htmlEditor
),
77 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
78 "StateUpdatingCommandBase::ToggleState() failed");
82 nsresult
StateUpdatingCommandBase::GetCommandStateParams(
83 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
84 nsIEditingSession
* aEditingSession
) const {
88 HTMLEditor
* htmlEditor
= aEditorBase
->GetAsHTMLEditor();
89 if (NS_WARN_IF(!htmlEditor
)) {
90 return NS_ERROR_FAILURE
;
92 nsStaticAtom
* tagName
= GetTagName(aCommand
);
93 if (NS_WARN_IF(!tagName
)) {
94 return NS_ERROR_UNEXPECTED
;
96 // MOZ_KnownLive(htmlEditor) because the lifetime of aEditorBase is guaranteed
98 // MOZ_KnownLive(tagName) because nsStaticAtom instances are alive until
100 nsresult rv
= GetCurrentState(MOZ_KnownLive(*tagName
),
101 MOZ_KnownLive(*htmlEditor
), aParams
);
102 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
103 "StateUpdatingCommandBase::GetCurrentState() failed");
107 /*****************************************************************************
108 * mozilla::PasteNoFormattingCommand
109 *****************************************************************************/
111 StaticRefPtr
<PasteNoFormattingCommand
> PasteNoFormattingCommand::sInstance
;
113 bool PasteNoFormattingCommand::IsCommandEnabled(Command aCommand
,
114 EditorBase
* aEditorBase
) const {
115 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
119 return htmlEditor
->CanPaste(nsIClipboard::kGlobalClipboard
);
122 nsresult
PasteNoFormattingCommand::DoCommand(Command aCommand
,
123 EditorBase
& aEditorBase
,
124 nsIPrincipal
* aPrincipal
) const {
125 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
126 if (NS_WARN_IF(!htmlEditor
)) {
127 return NS_ERROR_FAILURE
;
129 // Known live because we hold a ref above in "editor"
131 MOZ_KnownLive(htmlEditor
)
132 ->PasteNoFormattingAsAction(nsIClipboard::kGlobalClipboard
,
133 EditorBase::DispatchPasteEvent::Yes
,
134 nullptr, aPrincipal
);
135 NS_WARNING_ASSERTION(
137 "HTMLEditor::PasteNoFormattingAsAction(DispatchPasteEvent::Yes) failed");
141 nsresult
PasteNoFormattingCommand::GetCommandStateParams(
142 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
143 nsIEditingSession
* aEditingSession
) const {
144 return aParams
.SetBool(STATE_ENABLED
,
145 IsCommandEnabled(aCommand
, aEditorBase
));
148 /*****************************************************************************
149 * mozilla::StyleUpdatingCommand
150 *****************************************************************************/
152 StaticRefPtr
<StyleUpdatingCommand
> StyleUpdatingCommand::sInstance
;
154 nsresult
StyleUpdatingCommand::GetCurrentState(nsStaticAtom
& aTagName
,
155 HTMLEditor
& aHTMLEditor
,
156 nsCommandParams
& aParams
) const {
157 bool firstOfSelectionHasProp
= false;
158 bool anyOfSelectionHasProp
= false;
159 bool allOfSelectionHasProp
= false;
161 nsresult rv
= aHTMLEditor
.GetInlineProperty(
162 aTagName
, nullptr, u
""_ns
, &firstOfSelectionHasProp
,
163 &anyOfSelectionHasProp
, &allOfSelectionHasProp
);
164 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
165 "HTMLEditor::GetInlineProperty() failed");
167 aParams
.SetBool(STATE_ENABLED
, NS_SUCCEEDED(rv
));
168 aParams
.SetBool(STATE_ALL
, allOfSelectionHasProp
);
169 aParams
.SetBool(STATE_ANY
, anyOfSelectionHasProp
);
170 aParams
.SetBool(STATE_MIXED
, anyOfSelectionHasProp
&& !allOfSelectionHasProp
);
171 aParams
.SetBool(STATE_BEGIN
, firstOfSelectionHasProp
);
172 aParams
.SetBool(STATE_END
, allOfSelectionHasProp
); // not completely accurate
176 nsresult
StyleUpdatingCommand::ToggleState(nsStaticAtom
& aTagName
,
177 HTMLEditor
& aHTMLEditor
,
178 nsIPrincipal
* aPrincipal
) const {
179 RefPtr
<nsCommandParams
> params
= new nsCommandParams();
181 // tags "href" and "name" are special cases in the core editor
182 // they are used to remove named anchor/link and shouldn't be used for
185 if (&aTagName
== nsGkAtoms::href
|| &aTagName
== nsGkAtoms::name
) {
188 // check current selection; set doTagRemoval if formatting should be removed
189 nsresult rv
= GetCurrentState(aTagName
, aHTMLEditor
, *params
);
191 NS_WARNING("StyleUpdatingCommand::GetCurrentState() failed");
195 doTagRemoval
= params
->GetBool(STATE_ALL
, error
);
196 if (NS_WARN_IF(error
.Failed())) {
197 return error
.StealNSResult();
203 aHTMLEditor
.RemoveInlinePropertyAsAction(aTagName
, nullptr, aPrincipal
);
204 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
205 "HTMLEditor::RemoveInlinePropertyAsAction() failed");
209 nsresult rv
= aHTMLEditor
.SetInlinePropertyAsAction(aTagName
, nullptr, u
""_ns
,
211 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
212 "HTMLEditor::SetInlinePropertyAsAction() failed");
216 /*****************************************************************************
217 * mozilla::ListCommand
218 *****************************************************************************/
220 StaticRefPtr
<ListCommand
> ListCommand::sInstance
;
222 nsresult
ListCommand::GetCurrentState(nsStaticAtom
& aTagName
,
223 HTMLEditor
& aHTMLEditor
,
224 nsCommandParams
& aParams
) const {
226 nsAutoString localName
;
227 nsresult rv
= GetListState(&aHTMLEditor
, &bMixed
, localName
);
229 NS_WARNING("GetListState() failed");
233 bool inList
= aTagName
.Equals(localName
);
234 aParams
.SetBool(STATE_ALL
, !bMixed
&& inList
);
235 aParams
.SetBool(STATE_MIXED
, bMixed
);
236 aParams
.SetBool(STATE_ENABLED
, true);
240 nsresult
ListCommand::ToggleState(nsStaticAtom
& aTagName
,
241 HTMLEditor
& aHTMLEditor
,
242 nsIPrincipal
* aPrincipal
) const {
243 RefPtr
<nsCommandParams
> params
= new nsCommandParams();
244 nsresult rv
= GetCurrentState(aTagName
, aHTMLEditor
, *params
);
246 NS_WARNING("ListCommand::GetCurrentState() failed");
251 bool inList
= params
->GetBool(STATE_ALL
, error
);
252 if (NS_WARN_IF(error
.Failed())) {
253 return error
.StealNSResult();
256 nsDependentAtomString
listType(&aTagName
);
258 nsresult rv
= aHTMLEditor
.RemoveListAsAction(listType
, aPrincipal
);
259 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
260 "HTMLEditor::RemoveListAsAction() failed");
264 rv
= aHTMLEditor
.MakeOrChangeListAsAction(
265 aTagName
, u
""_ns
, HTMLEditor::SelectAllOfCurrentList::No
, aPrincipal
);
266 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
267 "HTMLEditor::MakeOrChangeListAsAction() failed");
271 /*****************************************************************************
272 * mozilla::ListItemCommand
273 *****************************************************************************/
275 StaticRefPtr
<ListItemCommand
> ListItemCommand::sInstance
;
277 nsresult
ListItemCommand::GetCurrentState(nsStaticAtom
& aTagName
,
278 HTMLEditor
& aHTMLEditor
,
279 nsCommandParams
& aParams
) const {
281 ListItemElementSelectionState
state(aHTMLEditor
, error
);
282 if (error
.Failed()) {
283 NS_WARNING("ListItemElementSelectionState failed");
284 return error
.StealNSResult();
287 if (state
.IsNotOneTypeDefinitionListItemElementSelected()) {
288 aParams
.SetBool(STATE_ALL
, false);
289 aParams
.SetBool(STATE_MIXED
, true);
293 nsStaticAtom
* selectedListItemTagName
= nullptr;
294 if (state
.IsLIElementSelected()) {
295 selectedListItemTagName
= nsGkAtoms::li
;
296 } else if (state
.IsDTElementSelected()) {
297 selectedListItemTagName
= nsGkAtoms::dt
;
298 } else if (state
.IsDDElementSelected()) {
299 selectedListItemTagName
= nsGkAtoms::dd
;
301 aParams
.SetBool(STATE_ALL
, &aTagName
== selectedListItemTagName
);
302 aParams
.SetBool(STATE_MIXED
, false);
306 nsresult
ListItemCommand::ToggleState(nsStaticAtom
& aTagName
,
307 HTMLEditor
& aHTMLEditor
,
308 nsIPrincipal
* aPrincipal
) const {
309 // Need to use aTagName????
310 RefPtr
<nsCommandParams
> params
= new nsCommandParams();
311 GetCurrentState(aTagName
, aHTMLEditor
, *params
);
313 bool inList
= params
->GetBool(STATE_ALL
, error
);
314 if (NS_WARN_IF(error
.Failed())) {
315 return error
.StealNSResult();
319 // To remove a list, first get what kind of list we're in
321 nsAutoString localName
;
322 nsresult rv
= GetListState(&aHTMLEditor
, &bMixed
, localName
);
324 NS_WARNING("GetListState() failed");
327 if (localName
.IsEmpty() || bMixed
) {
330 rv
= aHTMLEditor
.RemoveListAsAction(localName
, aPrincipal
);
331 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
332 "HTMLEditor::RemoveListAsAction() failed");
336 // Set to the requested paragraph type
337 // XXX Note: This actually doesn't work for "LI",
338 // but we currently don't use this for non DL lists anyway.
339 // Problem: won't this replace any current block paragraph style?
340 nsresult rv
= aHTMLEditor
.SetParagraphStateAsAction(
341 nsDependentAtomString(&aTagName
), aPrincipal
);
342 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
343 "HTMLEditor::SetParagraphFormatAsAction() failed");
347 /*****************************************************************************
348 * mozilla::RemoveListCommand
349 *****************************************************************************/
351 StaticRefPtr
<RemoveListCommand
> RemoveListCommand::sInstance
;
353 bool RemoveListCommand::IsCommandEnabled(Command aCommand
,
354 EditorBase
* aEditorBase
) const {
355 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
359 if (!htmlEditor
->IsModifiable() || !htmlEditor
->IsSelectionEditable()) {
363 // It is enabled if we are in any list type
365 nsAutoString localName
;
366 nsresult rv
= GetListState(MOZ_KnownLive(htmlEditor
), &bMixed
, localName
);
367 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "GetListState() failed");
368 return NS_SUCCEEDED(rv
) && (bMixed
|| !localName
.IsEmpty());
371 nsresult
RemoveListCommand::DoCommand(Command aCommand
, EditorBase
& aEditorBase
,
372 nsIPrincipal
* aPrincipal
) const {
373 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
374 if (NS_WARN_IF(!htmlEditor
)) {
377 // This removes any list type
379 MOZ_KnownLive(htmlEditor
)->RemoveListAsAction(u
""_ns
, aPrincipal
);
380 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
381 "HTMLEditor::RemoveListAsAction() failed");
385 nsresult
RemoveListCommand::GetCommandStateParams(
386 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
387 nsIEditingSession
* aEditingSession
) const {
388 return aParams
.SetBool(STATE_ENABLED
,
389 IsCommandEnabled(aCommand
, aEditorBase
));
392 /*****************************************************************************
393 * mozilla::IndentCommand
394 *****************************************************************************/
396 StaticRefPtr
<IndentCommand
> IndentCommand::sInstance
;
398 bool IndentCommand::IsCommandEnabled(Command aCommand
,
399 EditorBase
* aEditorBase
) const {
400 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
404 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
407 nsresult
IndentCommand::DoCommand(Command aCommand
, EditorBase
& aEditorBase
,
408 nsIPrincipal
* aPrincipal
) const {
409 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
410 if (NS_WARN_IF(!htmlEditor
)) {
413 nsresult rv
= MOZ_KnownLive(htmlEditor
)->IndentAsAction(aPrincipal
);
414 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "HTMLEditor::IndentAsAction() failed");
418 nsresult
IndentCommand::GetCommandStateParams(
419 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
420 nsIEditingSession
* aEditingSession
) const {
421 return aParams
.SetBool(STATE_ENABLED
,
422 IsCommandEnabled(aCommand
, aEditorBase
));
425 /*****************************************************************************
426 * mozilla::OutdentCommand
427 *****************************************************************************/
429 StaticRefPtr
<OutdentCommand
> OutdentCommand::sInstance
;
431 bool OutdentCommand::IsCommandEnabled(Command aCommand
,
432 EditorBase
* aEditorBase
) const {
433 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
437 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
440 nsresult
OutdentCommand::DoCommand(Command aCommand
, EditorBase
& aEditorBase
,
441 nsIPrincipal
* aPrincipal
) const {
442 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
443 if (NS_WARN_IF(!htmlEditor
)) {
446 nsresult rv
= MOZ_KnownLive(htmlEditor
)->OutdentAsAction(aPrincipal
);
447 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
448 "HTMLEditor::OutdentAsAction() failed");
452 nsresult
OutdentCommand::GetCommandStateParams(
453 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
454 nsIEditingSession
* aEditingSession
) const {
455 return aParams
.SetBool(STATE_ENABLED
,
456 IsCommandEnabled(aCommand
, aEditorBase
));
459 /*****************************************************************************
460 * mozilla::MultiStateCommandBase
461 *****************************************************************************/
463 bool MultiStateCommandBase::IsCommandEnabled(Command aCommand
,
464 EditorBase
* aEditorBase
) const {
465 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
469 // should be disabled sometimes, like if the current selection is an image
470 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
473 nsresult
MultiStateCommandBase::DoCommand(Command aCommand
,
474 EditorBase
& aEditorBase
,
475 nsIPrincipal
* aPrincipal
) const {
477 "who is calling MultiStateCommandBase::DoCommand (no implementation)?");
481 nsresult
MultiStateCommandBase::DoCommandParam(Command aCommand
,
482 const nsAString
& aStringParam
,
483 EditorBase
& aEditorBase
,
484 nsIPrincipal
* aPrincipal
) const {
485 NS_WARNING_ASSERTION(aCommand
!= Command::FormatJustify
,
486 "Command::FormatJustify should be used only for "
487 "IsCommandEnabled() and GetCommandStateParams()");
488 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
489 if (NS_WARN_IF(!htmlEditor
)) {
490 return NS_ERROR_FAILURE
;
492 nsresult rv
= SetState(MOZ_KnownLive(htmlEditor
), aStringParam
, aPrincipal
);
493 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
494 "MultiStateCommandBase::SetState() failed");
498 nsresult
MultiStateCommandBase::GetCommandStateParams(
499 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
500 nsIEditingSession
* aEditingSession
) const {
504 HTMLEditor
* htmlEditor
= aEditorBase
->GetAsHTMLEditor();
505 if (NS_WARN_IF(!htmlEditor
)) {
506 return NS_ERROR_FAILURE
;
508 nsresult rv
= GetCurrentState(MOZ_KnownLive(htmlEditor
), aParams
);
509 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
510 "MultiStateCommandBase::GetCurrentState() failed");
514 /*****************************************************************************
515 * mozilla::FormatBlockStateCommand
516 *****************************************************************************/
518 StaticRefPtr
<FormatBlockStateCommand
> FormatBlockStateCommand::sInstance
;
520 nsresult
FormatBlockStateCommand::GetCurrentState(
521 HTMLEditor
* aHTMLEditor
, nsCommandParams
& aParams
) const {
522 if (NS_WARN_IF(!aHTMLEditor
)) {
523 return NS_ERROR_INVALID_ARG
;
527 ParagraphStateAtSelection
state(
529 ParagraphStateAtSelection::FormatBlockMode::HTMLFormatBlockCommand
,
531 if (error
.Failed()) {
532 NS_WARNING("ParagraphStateAtSelection failed");
533 return error
.StealNSResult();
535 aParams
.SetBool(STATE_MIXED
, state
.IsMixed());
536 if (NS_WARN_IF(!state
.GetFirstParagraphStateAtSelection())) {
537 aParams
.SetCString(STATE_ATTRIBUTE
, ""_ns
);
539 nsCString paragraphState
; // Don't use `nsAutoCString` for avoiding copy.
540 state
.GetFirstParagraphStateAtSelection()->ToUTF8String(paragraphState
);
541 aParams
.SetCString(STATE_ATTRIBUTE
, paragraphState
);
546 nsresult
FormatBlockStateCommand::SetState(HTMLEditor
* aHTMLEditor
,
547 const nsAString
& aNewState
,
548 nsIPrincipal
* aPrincipal
) const {
549 if (NS_WARN_IF(!aHTMLEditor
) || NS_WARN_IF(aNewState
.IsEmpty())) {
550 return NS_ERROR_INVALID_ARG
;
552 nsresult rv
= aHTMLEditor
->FormatBlockAsAction(aNewState
, aPrincipal
);
553 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
554 "HTMLEditor::FormatBlockAsAction() failed");
558 /*****************************************************************************
559 * mozilla::ParagraphStateCommand
560 *****************************************************************************/
562 StaticRefPtr
<ParagraphStateCommand
> ParagraphStateCommand::sInstance
;
564 nsresult
ParagraphStateCommand::GetCurrentState(
565 HTMLEditor
* aHTMLEditor
, nsCommandParams
& aParams
) const {
566 if (NS_WARN_IF(!aHTMLEditor
)) {
567 return NS_ERROR_INVALID_ARG
;
571 ParagraphStateAtSelection
state(
573 ParagraphStateAtSelection::FormatBlockMode::XULParagraphStateCommand
,
575 if (error
.Failed()) {
576 NS_WARNING("ParagraphStateAtSelection failed");
577 return error
.StealNSResult();
579 aParams
.SetBool(STATE_MIXED
, state
.IsMixed());
580 if (NS_WARN_IF(!state
.GetFirstParagraphStateAtSelection())) {
581 // XXX This is odd behavior, we should fix this later.
582 aParams
.SetCString(STATE_ATTRIBUTE
, "x"_ns
);
584 nsCString paragraphState
; // Don't use `nsAutoCString` for avoiding copy.
585 state
.GetFirstParagraphStateAtSelection()->ToUTF8String(paragraphState
);
586 aParams
.SetCString(STATE_ATTRIBUTE
, paragraphState
);
591 nsresult
ParagraphStateCommand::SetState(HTMLEditor
* aHTMLEditor
,
592 const nsAString
& aNewState
,
593 nsIPrincipal
* aPrincipal
) const {
594 if (NS_WARN_IF(!aHTMLEditor
)) {
595 return NS_ERROR_INVALID_ARG
;
597 nsresult rv
= aHTMLEditor
->SetParagraphStateAsAction(aNewState
, aPrincipal
);
598 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
599 "HTMLEditor::SetParagraphStateAsAction() failed");
603 /*****************************************************************************
604 * mozilla::FontFaceStateCommand
605 *****************************************************************************/
607 StaticRefPtr
<FontFaceStateCommand
> FontFaceStateCommand::sInstance
;
609 nsresult
FontFaceStateCommand::GetCurrentState(HTMLEditor
* aHTMLEditor
,
610 nsCommandParams
& aParams
) const {
611 if (NS_WARN_IF(!aHTMLEditor
)) {
612 return NS_ERROR_INVALID_ARG
;
615 nsAutoString outStateString
;
617 nsresult rv
= aHTMLEditor
->GetFontFaceState(&outMixed
, outStateString
);
619 NS_WARNING("HTMLEditor::GetFontFaceState() failed");
622 aParams
.SetBool(STATE_MIXED
, outMixed
);
623 aParams
.SetCString(STATE_ATTRIBUTE
, NS_ConvertUTF16toUTF8(outStateString
));
627 nsresult
FontFaceStateCommand::SetState(HTMLEditor
* aHTMLEditor
,
628 const nsAString
& aNewState
,
629 nsIPrincipal
* aPrincipal
) const {
630 if (NS_WARN_IF(!aHTMLEditor
)) {
631 return NS_ERROR_INVALID_ARG
;
634 if (aNewState
.IsEmpty() || aNewState
.EqualsLiteral("normal")) {
635 nsresult rv
= aHTMLEditor
->RemoveInlinePropertyAsAction(
636 *nsGkAtoms::font
, nsGkAtoms::face
, aPrincipal
);
637 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
638 "HTMLEditor::RemoveInlinePropertyAsAction(nsGkAtoms::"
639 "font, nsGkAtoms::face) failed");
643 nsresult rv
= aHTMLEditor
->SetInlinePropertyAsAction(
644 *nsGkAtoms::font
, nsGkAtoms::face
, aNewState
, aPrincipal
);
645 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
646 "HTMLEditor::SetInlinePropertyAsAction(nsGkAtoms::font, "
647 "nsGkAtoms::face) failed");
651 /*****************************************************************************
652 * mozilla::FontSizeStateCommand
653 *****************************************************************************/
655 StaticRefPtr
<FontSizeStateCommand
> FontSizeStateCommand::sInstance
;
657 nsresult
FontSizeStateCommand::GetCurrentState(HTMLEditor
* aHTMLEditor
,
658 nsCommandParams
& aParams
) const {
659 if (NS_WARN_IF(!aHTMLEditor
)) {
660 return NS_ERROR_INVALID_ARG
;
663 nsAutoString outStateString
;
664 bool firstHas
, anyHas
, allHas
;
665 nsresult rv
= aHTMLEditor
->GetInlinePropertyWithAttrValue(
666 *nsGkAtoms::font
, nsGkAtoms::size
, u
""_ns
, &firstHas
, &anyHas
, &allHas
,
670 "HTMLEditor::GetInlinePropertyWithAttrValue(nsGkAtoms::font, "
671 "nsGkAtoms::size) failed");
675 nsAutoCString tOutStateString
;
676 LossyCopyUTF16toASCII(outStateString
, tOutStateString
);
677 aParams
.SetBool(STATE_MIXED
, anyHas
&& !allHas
);
678 aParams
.SetCString(STATE_ATTRIBUTE
, tOutStateString
);
679 aParams
.SetBool(STATE_ENABLED
, true);
684 // acceptable values for "aNewState" are:
693 nsresult
FontSizeStateCommand::SetState(HTMLEditor
* aHTMLEditor
,
694 const nsAString
& aNewState
,
695 nsIPrincipal
* aPrincipal
) const {
696 if (NS_WARN_IF(!aHTMLEditor
)) {
697 return NS_ERROR_INVALID_ARG
;
700 if (!aNewState
.IsEmpty() && !aNewState
.EqualsLiteral("normal") &&
701 !aNewState
.EqualsLiteral("medium")) {
702 nsresult rv
= aHTMLEditor
->SetInlinePropertyAsAction(
703 *nsGkAtoms::font
, nsGkAtoms::size
, aNewState
, aPrincipal
);
704 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
705 "HTMLEditor::SetInlinePropertyAsAction(nsGkAtoms::"
706 "font, nsGkAtoms::size) failed");
710 // remove any existing font size, big or small
711 nsresult rv
= aHTMLEditor
->RemoveInlinePropertyAsAction(
712 *nsGkAtoms::font
, nsGkAtoms::size
, aPrincipal
);
713 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
714 "HTMLEditor::RemoveInlinePropertyAsAction(nsGkAtoms::"
715 "font, nsGkAtoms::size) failed");
719 /*****************************************************************************
720 * mozilla::FontColorStateCommand
721 *****************************************************************************/
723 StaticRefPtr
<FontColorStateCommand
> FontColorStateCommand::sInstance
;
725 nsresult
FontColorStateCommand::GetCurrentState(
726 HTMLEditor
* aHTMLEditor
, nsCommandParams
& aParams
) const {
727 if (NS_WARN_IF(!aHTMLEditor
)) {
728 return NS_ERROR_INVALID_ARG
;
732 nsAutoString outStateString
;
733 nsresult rv
= aHTMLEditor
->GetFontColorState(&outMixed
, outStateString
);
735 NS_WARNING("HTMLEditor::GetFontColorState() failed");
739 nsAutoCString tOutStateString
;
740 LossyCopyUTF16toASCII(outStateString
, tOutStateString
);
741 aParams
.SetBool(STATE_MIXED
, outMixed
);
742 aParams
.SetCString(STATE_ATTRIBUTE
, tOutStateString
);
746 nsresult
FontColorStateCommand::SetState(HTMLEditor
* aHTMLEditor
,
747 const nsAString
& aNewState
,
748 nsIPrincipal
* aPrincipal
) const {
749 if (NS_WARN_IF(!aHTMLEditor
)) {
750 return NS_ERROR_INVALID_ARG
;
753 if (aNewState
.IsEmpty() || aNewState
.EqualsLiteral("normal")) {
754 nsresult rv
= aHTMLEditor
->RemoveInlinePropertyAsAction(
755 *nsGkAtoms::font
, nsGkAtoms::color
, aPrincipal
);
756 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
757 "HTMLEditor::RemoveInlinePropertyAsAction(nsGkAtoms::"
758 "font, nsGkAtoms::color) failed");
762 nsresult rv
= aHTMLEditor
->SetInlinePropertyAsAction(
763 *nsGkAtoms::font
, nsGkAtoms::color
, aNewState
, aPrincipal
);
764 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
765 "HTMLEditor::SetInlinePropertyAsAction(nsGkAtoms::font, "
766 "nsGkAtoms::color) failed");
770 /*****************************************************************************
771 * mozilla::HighlightColorStateCommand
772 *****************************************************************************/
774 StaticRefPtr
<HighlightColorStateCommand
> HighlightColorStateCommand::sInstance
;
776 nsresult
HighlightColorStateCommand::GetCurrentState(
777 HTMLEditor
* aHTMLEditor
, nsCommandParams
& aParams
) const {
778 if (NS_WARN_IF(!aHTMLEditor
)) {
779 return NS_ERROR_INVALID_ARG
;
783 nsAutoString outStateString
;
784 nsresult rv
= aHTMLEditor
->GetHighlightColorState(&outMixed
, outStateString
);
786 NS_WARNING("HTMLEditor::GetHighlightColorState() failed");
790 nsAutoCString tOutStateString
;
791 LossyCopyUTF16toASCII(outStateString
, tOutStateString
);
792 aParams
.SetBool(STATE_MIXED
, outMixed
);
793 aParams
.SetCString(STATE_ATTRIBUTE
, tOutStateString
);
797 nsresult
HighlightColorStateCommand::SetState(HTMLEditor
* aHTMLEditor
,
798 const nsAString
& aNewState
,
799 nsIPrincipal
* aPrincipal
) const {
800 if (NS_WARN_IF(!aHTMLEditor
)) {
801 return NS_ERROR_INVALID_ARG
;
804 if (aNewState
.IsEmpty() || aNewState
.EqualsLiteral("normal")) {
805 nsresult rv
= aHTMLEditor
->RemoveInlinePropertyAsAction(
806 *nsGkAtoms::font
, nsGkAtoms::bgcolor
, aPrincipal
);
807 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
808 "HTMLEditor::RemoveInlinePropertyAsAction(nsGkAtoms::"
809 "font, nsGkAtoms::bgcolor) failed");
813 nsresult rv
= aHTMLEditor
->SetInlinePropertyAsAction(
814 *nsGkAtoms::font
, nsGkAtoms::bgcolor
, aNewState
, aPrincipal
);
815 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
816 "HTMLEditor::SetInlinePropertyAsAction(nsGkAtoms::font, "
817 "nsGkAtoms::bgcolor) failed");
821 /*****************************************************************************
822 * mozilla::BackgroundColorStateCommand
823 *****************************************************************************/
825 StaticRefPtr
<BackgroundColorStateCommand
>
826 BackgroundColorStateCommand::sInstance
;
828 nsresult
BackgroundColorStateCommand::GetCurrentState(
829 HTMLEditor
* aHTMLEditor
, nsCommandParams
& aParams
) const {
830 if (NS_WARN_IF(!aHTMLEditor
)) {
831 return NS_ERROR_INVALID_ARG
;
835 nsAutoString outStateString
;
836 nsresult rv
= aHTMLEditor
->GetBackgroundColorState(&outMixed
, outStateString
);
838 NS_WARNING("HTMLEditor::GetBackgroundColorState() failed");
842 nsAutoCString tOutStateString
;
843 LossyCopyUTF16toASCII(outStateString
, tOutStateString
);
844 aParams
.SetBool(STATE_MIXED
, outMixed
);
845 aParams
.SetCString(STATE_ATTRIBUTE
, tOutStateString
);
849 nsresult
BackgroundColorStateCommand::SetState(HTMLEditor
* aHTMLEditor
,
850 const nsAString
& aNewState
,
851 nsIPrincipal
* aPrincipal
) const {
852 if (NS_WARN_IF(!aHTMLEditor
)) {
853 return NS_ERROR_INVALID_ARG
;
855 nsresult rv
= aHTMLEditor
->SetBackgroundColorAsAction(aNewState
, aPrincipal
);
856 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
857 "HTMLEditor::SetBackgroundColorAsAction() failed");
861 /*****************************************************************************
862 * mozilla::AlignCommand
863 *****************************************************************************/
865 StaticRefPtr
<AlignCommand
> AlignCommand::sInstance
;
867 nsresult
AlignCommand::GetCurrentState(HTMLEditor
* aHTMLEditor
,
868 nsCommandParams
& aParams
) const {
869 if (NS_WARN_IF(!aHTMLEditor
)) {
870 return NS_ERROR_INVALID_ARG
;
874 AlignStateAtSelection
state(*aHTMLEditor
, error
);
875 if (error
.Failed()) {
876 if (!state
.IsSelectionRangesFound()) {
877 // If there was no selection ranges, we shouldn't throw exception for
878 // compatibility with the other browsers, but I have no better idea
879 // than returning empty string in this case. Oddly, Blink/WebKit returns
880 // "true" or "false", but it's different from us and the value does not
881 // make sense. Additionally, WPT loves our behavior.
882 error
.SuppressException();
883 aParams
.SetBool(STATE_MIXED
, false);
884 aParams
.SetCString(STATE_ATTRIBUTE
, ""_ns
);
887 NS_WARNING("AlignStateAtSelection failed");
888 return error
.StealNSResult();
890 nsCString alignment
; // Don't use `nsAutoCString` to avoid copying string.
891 switch (state
.AlignmentAtSelectionStart()) {
893 case nsIHTMLEditor::eLeft
:
894 alignment
.AssignLiteral("left");
896 case nsIHTMLEditor::eCenter
:
897 alignment
.AssignLiteral("center");
899 case nsIHTMLEditor::eRight
:
900 alignment
.AssignLiteral("right");
902 case nsIHTMLEditor::eJustify
:
903 alignment
.AssignLiteral("justify");
906 aParams
.SetBool(STATE_MIXED
, false);
907 aParams
.SetCString(STATE_ATTRIBUTE
, alignment
);
911 nsresult
AlignCommand::SetState(HTMLEditor
* aHTMLEditor
,
912 const nsAString
& aNewState
,
913 nsIPrincipal
* aPrincipal
) const {
914 if (NS_WARN_IF(!aHTMLEditor
)) {
915 return NS_ERROR_INVALID_ARG
;
917 nsresult rv
= aHTMLEditor
->AlignAsAction(aNewState
, aPrincipal
);
918 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "HTMLEditor::AlignAsAction() failed");
922 /*****************************************************************************
923 * mozilla::AbsolutePositioningCommand
924 *****************************************************************************/
926 StaticRefPtr
<AbsolutePositioningCommand
> AbsolutePositioningCommand::sInstance
;
928 nsresult
AbsolutePositioningCommand::GetCurrentState(
929 nsStaticAtom
& aTagName
, HTMLEditor
& aHTMLEditor
,
930 nsCommandParams
& aParams
) const {
931 if (!aHTMLEditor
.IsAbsolutePositionEditorEnabled()) {
932 aParams
.SetBool(STATE_MIXED
, false);
933 aParams
.SetCString(STATE_ATTRIBUTE
, ""_ns
);
937 RefPtr
<Element
> container
=
938 aHTMLEditor
.GetAbsolutelyPositionedSelectionContainer();
939 aParams
.SetBool(STATE_MIXED
, false);
940 aParams
.SetCString(STATE_ATTRIBUTE
, container
? "absolute"_ns
: ""_ns
);
944 nsresult
AbsolutePositioningCommand::ToggleState(
945 nsStaticAtom
& aTagName
, HTMLEditor
& aHTMLEditor
,
946 nsIPrincipal
* aPrincipal
) const {
947 RefPtr
<Element
> container
=
948 aHTMLEditor
.GetAbsolutelyPositionedSelectionContainer();
949 nsresult rv
= aHTMLEditor
.SetSelectionToAbsoluteOrStaticAsAction(!container
,
951 NS_WARNING_ASSERTION(
953 "HTMLEditor::SetSelectionToAbsoluteOrStaticAsAction() failed");
957 /*****************************************************************************
958 * mozilla::DecreaseZIndexCommand
959 *****************************************************************************/
961 StaticRefPtr
<DecreaseZIndexCommand
> DecreaseZIndexCommand::sInstance
;
963 bool DecreaseZIndexCommand::IsCommandEnabled(Command aCommand
,
964 EditorBase
* aEditorBase
) const {
965 RefPtr
<HTMLEditor
> htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
969 if (!htmlEditor
->IsAbsolutePositionEditorEnabled()) {
972 RefPtr
<Element
> positionedElement
= htmlEditor
->GetPositionedElement();
973 if (!positionedElement
) {
976 return htmlEditor
->GetZIndex(*positionedElement
) > 0;
979 nsresult
DecreaseZIndexCommand::DoCommand(Command aCommand
,
980 EditorBase
& aEditorBase
,
981 nsIPrincipal
* aPrincipal
) const {
982 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
983 if (NS_WARN_IF(!htmlEditor
)) {
984 return NS_ERROR_FAILURE
;
986 nsresult rv
= MOZ_KnownLive(htmlEditor
)->AddZIndexAsAction(-1, aPrincipal
);
987 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
988 "HTMLEditor::AddZIndexAsAction(-1) failed");
992 nsresult
DecreaseZIndexCommand::GetCommandStateParams(
993 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
994 nsIEditingSession
* aEditingSession
) const {
995 return aParams
.SetBool(STATE_ENABLED
,
996 IsCommandEnabled(aCommand
, aEditorBase
));
999 /*****************************************************************************
1000 * mozilla::IncreaseZIndexCommand
1001 *****************************************************************************/
1003 StaticRefPtr
<IncreaseZIndexCommand
> IncreaseZIndexCommand::sInstance
;
1005 bool IncreaseZIndexCommand::IsCommandEnabled(Command aCommand
,
1006 EditorBase
* aEditorBase
) const {
1007 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
1011 if (!htmlEditor
->IsAbsolutePositionEditorEnabled()) {
1014 return !!htmlEditor
->GetPositionedElement();
1017 nsresult
IncreaseZIndexCommand::DoCommand(Command aCommand
,
1018 EditorBase
& aEditorBase
,
1019 nsIPrincipal
* aPrincipal
) const {
1020 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1021 if (NS_WARN_IF(!htmlEditor
)) {
1022 return NS_ERROR_FAILURE
;
1024 nsresult rv
= MOZ_KnownLive(htmlEditor
)->AddZIndexAsAction(1, aPrincipal
);
1025 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
1026 "HTMLEditor::AddZIndexAsAction(1) failed");
1030 nsresult
IncreaseZIndexCommand::GetCommandStateParams(
1031 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
1032 nsIEditingSession
* aEditingSession
) const {
1033 return aParams
.SetBool(STATE_ENABLED
,
1034 IsCommandEnabled(aCommand
, aEditorBase
));
1037 /*****************************************************************************
1038 * mozilla::RemoveStylesCommand
1039 *****************************************************************************/
1041 StaticRefPtr
<RemoveStylesCommand
> RemoveStylesCommand::sInstance
;
1043 bool RemoveStylesCommand::IsCommandEnabled(Command aCommand
,
1044 EditorBase
* aEditorBase
) const {
1045 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
1049 // test if we have any styles?
1050 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
1053 nsresult
RemoveStylesCommand::DoCommand(Command aCommand
,
1054 EditorBase
& aEditorBase
,
1055 nsIPrincipal
* aPrincipal
) const {
1056 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1057 if (NS_WARN_IF(!htmlEditor
)) {
1061 MOZ_KnownLive(htmlEditor
)->RemoveAllInlinePropertiesAsAction(aPrincipal
);
1062 NS_WARNING_ASSERTION(
1064 "HTMLEditor::RemoveAllInlinePropertiesAsAction() failed");
1068 nsresult
RemoveStylesCommand::GetCommandStateParams(
1069 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
1070 nsIEditingSession
* aEditingSession
) const {
1071 return aParams
.SetBool(STATE_ENABLED
,
1072 IsCommandEnabled(aCommand
, aEditorBase
));
1075 /*****************************************************************************
1076 * mozilla::IncreaseFontSizeCommand
1077 *****************************************************************************/
1079 StaticRefPtr
<IncreaseFontSizeCommand
> IncreaseFontSizeCommand::sInstance
;
1081 bool IncreaseFontSizeCommand::IsCommandEnabled(Command aCommand
,
1082 EditorBase
* aEditorBase
) const {
1083 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
1087 // test if we are at max size?
1088 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
1091 nsresult
IncreaseFontSizeCommand::DoCommand(Command aCommand
,
1092 EditorBase
& aEditorBase
,
1093 nsIPrincipal
* aPrincipal
) const {
1094 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1095 if (NS_WARN_IF(!htmlEditor
)) {
1098 nsresult rv
= MOZ_KnownLive(htmlEditor
)->IncreaseFontSizeAsAction(aPrincipal
);
1099 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
1100 "HTMLEditor::IncreaseFontSizeAsAction() failed");
1104 nsresult
IncreaseFontSizeCommand::GetCommandStateParams(
1105 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
1106 nsIEditingSession
* aEditingSession
) const {
1107 return aParams
.SetBool(STATE_ENABLED
,
1108 IsCommandEnabled(aCommand
, aEditorBase
));
1111 /*****************************************************************************
1112 * mozilla::DecreaseFontSizeCommand
1113 *****************************************************************************/
1115 StaticRefPtr
<DecreaseFontSizeCommand
> DecreaseFontSizeCommand::sInstance
;
1117 bool DecreaseFontSizeCommand::IsCommandEnabled(Command aCommand
,
1118 EditorBase
* aEditorBase
) const {
1119 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
1123 // test if we are at min size?
1124 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
1127 nsresult
DecreaseFontSizeCommand::DoCommand(Command aCommand
,
1128 EditorBase
& aEditorBase
,
1129 nsIPrincipal
* aPrincipal
) const {
1130 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1131 if (NS_WARN_IF(!htmlEditor
)) {
1134 nsresult rv
= MOZ_KnownLive(htmlEditor
)->DecreaseFontSizeAsAction(aPrincipal
);
1135 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
1136 "HTMLEditor::DecreaseFontSizeAsAction() failed");
1140 nsresult
DecreaseFontSizeCommand::GetCommandStateParams(
1141 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
1142 nsIEditingSession
* aEditingSession
) const {
1143 return aParams
.SetBool(STATE_ENABLED
,
1144 IsCommandEnabled(aCommand
, aEditorBase
));
1147 /*****************************************************************************
1148 * mozilla::InsertHTMLCommand
1149 *****************************************************************************/
1151 StaticRefPtr
<InsertHTMLCommand
> InsertHTMLCommand::sInstance
;
1153 bool InsertHTMLCommand::IsCommandEnabled(Command aCommand
,
1154 EditorBase
* aEditorBase
) const {
1155 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
1159 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
1162 nsresult
InsertHTMLCommand::DoCommand(Command aCommand
, EditorBase
& aEditorBase
,
1163 nsIPrincipal
* aPrincipal
) const {
1164 // If InsertHTMLCommand is called with no parameters, it was probably called
1165 // with an empty string parameter ''. In this case, it should act the same as
1166 // the delete command
1167 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1168 if (NS_WARN_IF(!htmlEditor
)) {
1169 return NS_ERROR_FAILURE
;
1172 MOZ_KnownLive(htmlEditor
)->InsertHTMLAsAction(u
""_ns
, aPrincipal
);
1173 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
1174 "HTMLEditor::InsertHTMLAsAction() failed");
1178 nsresult
InsertHTMLCommand::DoCommandParam(Command aCommand
,
1179 const nsAString
& aStringParam
,
1180 EditorBase
& aEditorBase
,
1181 nsIPrincipal
* aPrincipal
) const {
1182 if (NS_WARN_IF(aStringParam
.IsVoid())) {
1183 return NS_ERROR_INVALID_ARG
;
1186 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1187 if (NS_WARN_IF(!htmlEditor
)) {
1188 return NS_ERROR_FAILURE
;
1191 MOZ_KnownLive(htmlEditor
)->InsertHTMLAsAction(aStringParam
, aPrincipal
);
1192 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
1193 "HTMLEditor::InsertHTMLAsAction() failed");
1197 nsresult
InsertHTMLCommand::GetCommandStateParams(
1198 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
1199 nsIEditingSession
* aEditingSession
) const {
1200 return aParams
.SetBool(STATE_ENABLED
,
1201 IsCommandEnabled(aCommand
, aEditorBase
));
1204 /*****************************************************************************
1205 * mozilla::InsertTagCommand
1206 *****************************************************************************/
1208 StaticRefPtr
<InsertTagCommand
> InsertTagCommand::sInstance
;
1210 bool InsertTagCommand::IsCommandEnabled(Command aCommand
,
1211 EditorBase
* aEditorBase
) const {
1212 HTMLEditor
* htmlEditor
= HTMLEditor::GetFrom(aEditorBase
);
1216 return htmlEditor
->IsModifiable() && htmlEditor
->IsSelectionEditable();
1219 // corresponding STATE_ATTRIBUTE is: src (img) and href (a)
1220 nsresult
InsertTagCommand::DoCommand(Command aCommand
, EditorBase
& aEditorBase
,
1221 nsIPrincipal
* aPrincipal
) const {
1222 nsAtom
* tagName
= GetTagName(aCommand
);
1223 if (NS_WARN_IF(tagName
!= nsGkAtoms::hr
)) {
1224 return NS_ERROR_NOT_IMPLEMENTED
;
1227 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1228 if (NS_WARN_IF(!htmlEditor
)) {
1229 return NS_ERROR_FAILURE
;
1232 RefPtr
<Element
> newElement
=
1233 MOZ_KnownLive(htmlEditor
)
1234 ->CreateElementWithDefaults(MOZ_KnownLive(*tagName
));
1235 if (NS_WARN_IF(!newElement
)) {
1236 return NS_ERROR_FAILURE
;
1238 HTMLEditor::InsertElementOptions options
{
1239 HTMLEditor::InsertElementOption::DeleteSelection
};
1240 // We did insert <img> without splitting ancestor inline elements, but the
1241 // other browsers split them. Therefore, let's do it only when the document
1243 if (tagName
== nsGkAtoms::img
&&
1244 htmlEditor
->GetDocument()->IsContentDocument()) {
1245 options
+= HTMLEditor::InsertElementOption::SplitAncestorInlineElements
;
1248 MOZ_KnownLive(htmlEditor
)
1249 ->InsertElementAtSelectionAsAction(newElement
, options
, aPrincipal
);
1250 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
1251 "HTMLEditor::InsertElementAtSelectionAsAction() failed");
1255 nsresult
InsertTagCommand::DoCommandParam(Command aCommand
,
1256 const nsAString
& aStringParam
,
1257 EditorBase
& aEditorBase
,
1258 nsIPrincipal
* aPrincipal
) const {
1259 MOZ_ASSERT(aCommand
!= Command::InsertHorizontalRule
);
1261 if (NS_WARN_IF(aStringParam
.IsEmpty())) {
1262 return NS_ERROR_INVALID_ARG
;
1264 nsAtom
* tagName
= GetTagName(aCommand
);
1265 if (NS_WARN_IF(!tagName
)) {
1266 return NS_ERROR_UNEXPECTED
;
1269 HTMLEditor
* htmlEditor
= aEditorBase
.GetAsHTMLEditor();
1270 if (NS_WARN_IF(!htmlEditor
)) {
1271 return NS_ERROR_FAILURE
;
1274 // filter out tags we don't know how to insert
1275 nsAtom
* attribute
= nullptr;
1276 if (tagName
== nsGkAtoms::a
) {
1277 attribute
= nsGkAtoms::href
;
1278 } else if (tagName
== nsGkAtoms::img
) {
1279 attribute
= nsGkAtoms::src
;
1281 return NS_ERROR_NOT_IMPLEMENTED
;
1284 RefPtr
<Element
> newElement
=
1285 MOZ_KnownLive(htmlEditor
)
1286 ->CreateElementWithDefaults(MOZ_KnownLive(*tagName
));
1288 NS_WARNING("HTMLEditor::CreateElementWithDefaults() failed");
1289 return NS_ERROR_FAILURE
;
1293 newElement
->SetAttr(attribute
, aStringParam
, error
);
1294 if (error
.Failed()) {
1295 NS_WARNING("Element::SetAttr() failed");
1296 return error
.StealNSResult();
1299 // do actual insertion
1300 if (tagName
== nsGkAtoms::a
) {
1302 MOZ_KnownLive(htmlEditor
)
1303 ->InsertLinkAroundSelectionAsAction(newElement
, aPrincipal
);
1304 NS_WARNING_ASSERTION(
1306 "HTMLEditor::InsertLinkAroundSelectionAsAction() failed");
1310 HTMLEditor::InsertElementOptions options
{
1311 HTMLEditor::InsertElementOption::DeleteSelection
};
1312 // We did insert <img> without splitting ancestor inline elements, but the
1313 // other browsers split them. Therefore, let's do it only when the document
1315 if (htmlEditor
->GetDocument()->IsContentDocument()) {
1316 options
+= HTMLEditor::InsertElementOption::SplitAncestorInlineElements
;
1319 MOZ_KnownLive(htmlEditor
)
1320 ->InsertElementAtSelectionAsAction(newElement
, options
, aPrincipal
);
1321 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
1322 "HTMLEditor::InsertElementAtSelectionAsAction() failed");
1326 nsresult
InsertTagCommand::GetCommandStateParams(
1327 Command aCommand
, nsCommandParams
& aParams
, EditorBase
* aEditorBase
,
1328 nsIEditingSession
* aEditingSession
) const {
1329 return aParams
.SetBool(STATE_ENABLED
,
1330 IsCommandEnabled(aCommand
, aEditorBase
));
1333 /*****************************************************************************
1335 *****************************************************************************/
1337 static nsresult
GetListState(HTMLEditor
* aHTMLEditor
, bool* aMixed
,
1338 nsAString
& aLocalName
) {
1339 MOZ_ASSERT(aHTMLEditor
);
1343 aLocalName
.Truncate();
1346 ListElementSelectionState
state(*aHTMLEditor
, error
);
1347 if (error
.Failed()) {
1348 NS_WARNING("ListElementSelectionState failed");
1349 return error
.StealNSResult();
1351 if (state
.IsNotOneTypeListElementSelected()) {
1356 if (state
.IsOLElementSelected()) {
1357 aLocalName
.AssignLiteral("ol");
1358 } else if (state
.IsULElementSelected()) {
1359 aLocalName
.AssignLiteral("ul");
1360 } else if (state
.IsDLElementSelected()) {
1361 aLocalName
.AssignLiteral("dl");
1366 } // namespace mozilla