diff options
Diffstat (limited to 'editor/composer/nsComposerCommands.cpp')
-rw-r--r-- | editor/composer/nsComposerCommands.cpp | 1525 |
1 files changed, 1525 insertions, 0 deletions
diff --git a/editor/composer/nsComposerCommands.cpp b/editor/composer/nsComposerCommands.cpp new file mode 100644 index 000000000..3853604e4 --- /dev/null +++ b/editor/composer/nsComposerCommands.cpp @@ -0,0 +1,1525 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#include <stdio.h> // for printf + +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "nsAString.h" +#include "nsCOMPtr.h" // for nsCOMPtr, do_QueryInterface, etc +#include "nsComponentManagerUtils.h" // for do_CreateInstance +#include "nsComposerCommands.h" +#include "nsDebug.h" // for NS_ENSURE_TRUE, etc +#include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc +#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::font, etc +#include "nsIAtom.h" // for nsIAtom, etc +#include "nsIClipboard.h" // for nsIClipboard, etc +#include "nsICommandParams.h" // for nsICommandParams, etc +#include "nsID.h" +#include "nsIDOMElement.h" // for nsIDOMElement +#include "nsIEditor.h" // for nsIEditor +#include "nsIHTMLAbsPosEditor.h" // for nsIHTMLAbsPosEditor +#include "nsIHTMLEditor.h" // for nsIHTMLEditor, etc +#include "nsLiteralString.h" // for NS_LITERAL_STRING +#include "nsReadableUtils.h" // for EmptyString +#include "nsString.h" // for nsAutoString, nsString, etc +#include "nsStringFwd.h" // for nsAFlatString + +class nsISupports; + +//prototype +nsresult GetListState(nsIHTMLEditor* aEditor, bool* aMixed, + nsAString& aLocalName); +nsresult RemoveOneProperty(nsIHTMLEditor* aEditor, const nsAString& aProp); +nsresult RemoveTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp); +nsresult SetTextProperty(nsIHTMLEditor *aEditor, const nsAString& aProp); + + +//defines +#define STATE_ENABLED "state_enabled" +#define STATE_ALL "state_all" +#define STATE_ANY "state_any" +#define STATE_MIXED "state_mixed" +#define STATE_BEGIN "state_begin" +#define STATE_END "state_end" +#define STATE_ATTRIBUTE "state_attribute" +#define STATE_DATA "state_data" + + +nsBaseComposerCommand::nsBaseComposerCommand() +{ +} + +NS_IMPL_ISUPPORTS(nsBaseComposerCommand, nsIControllerCommand) + + +nsBaseStateUpdatingCommand::nsBaseStateUpdatingCommand(nsIAtom* aTagName) +: nsBaseComposerCommand() +, mTagName(aTagName) +{ + MOZ_ASSERT(mTagName); +} + +nsBaseStateUpdatingCommand::~nsBaseStateUpdatingCommand() +{ +} + +NS_IMPL_ISUPPORTS_INHERITED0(nsBaseStateUpdatingCommand, nsBaseComposerCommand) + +NS_IMETHODIMP +nsBaseStateUpdatingCommand::IsCommandEnabled(const char *aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +NS_IMETHODIMP +nsBaseStateUpdatingCommand::DoCommand(const char *aCommandName, + nsISupports *refCon) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(editor, NS_ERROR_NOT_INITIALIZED); + + return ToggleState(editor); +} + +NS_IMETHODIMP +nsBaseStateUpdatingCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsBaseStateUpdatingCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + if (editor) + return GetCurrentState(editor, aParams); + + return NS_OK; +} + +NS_IMETHODIMP +nsPasteNoFormattingCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + NS_ENSURE_ARG_POINTER(outCmdEnabled); + *outCmdEnabled = false; + + // This command is only implemented by nsIHTMLEditor, since + // pasting in a plaintext editor automatically only supplies + // "unformatted" text + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED); + + nsCOMPtr<nsIEditor> editor = do_QueryInterface(htmlEditor); + NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG); + + return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled); +} + + +NS_IMETHODIMP +nsPasteNoFormattingCommand::DoCommand(const char *aCommandName, + nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED); + + return htmlEditor->PasteNoFormatting(nsIClipboard::kGlobalClipboard); +} + +NS_IMETHODIMP +nsPasteNoFormattingCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsPasteNoFormattingCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + NS_ENSURE_ARG_POINTER(aParams); + + bool enabled = false; + nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled); + NS_ENSURE_SUCCESS(rv, rv); + + return aParams->SetBooleanValue(STATE_ENABLED, enabled); +} + +nsStyleUpdatingCommand::nsStyleUpdatingCommand(nsIAtom* aTagName) +: nsBaseStateUpdatingCommand(aTagName) +{ +} + +nsresult +nsStyleUpdatingCommand::GetCurrentState(nsIEditor *aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_INITIALIZED); + + bool firstOfSelectionHasProp = false; + bool anyOfSelectionHasProp = false; + bool allOfSelectionHasProp = false; + + nsresult rv = htmlEditor->GetInlineProperty(mTagName, EmptyString(), + EmptyString(), + &firstOfSelectionHasProp, + &anyOfSelectionHasProp, + &allOfSelectionHasProp); + + aParams->SetBooleanValue(STATE_ENABLED, NS_SUCCEEDED(rv)); + aParams->SetBooleanValue(STATE_ALL, allOfSelectionHasProp); + aParams->SetBooleanValue(STATE_ANY, anyOfSelectionHasProp); + aParams->SetBooleanValue(STATE_MIXED, anyOfSelectionHasProp + && !allOfSelectionHasProp); + aParams->SetBooleanValue(STATE_BEGIN, firstOfSelectionHasProp); + aParams->SetBooleanValue(STATE_END, allOfSelectionHasProp);//not completely accurate + return NS_OK; +} + +nsresult +nsStyleUpdatingCommand::ToggleState(nsIEditor *aEditor) +{ + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE); + + //create some params now... + nsresult rv; + nsCOMPtr<nsICommandParams> params = + do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv); + if (NS_FAILED(rv) || !params) + return rv; + + // tags "href" and "name" are special cases in the core editor + // they are used to remove named anchor/link and shouldn't be used for insertion + bool doTagRemoval; + if (mTagName == nsGkAtoms::href || mTagName == nsGkAtoms::name) { + doTagRemoval = true; + } else { + // check current selection; set doTagRemoval if formatting should be removed + rv = GetCurrentState(aEditor, params); + NS_ENSURE_SUCCESS(rv, rv); + rv = params->GetBooleanValue(STATE_ALL, &doTagRemoval); + NS_ENSURE_SUCCESS(rv, rv); + } + + if (doTagRemoval) { + // Also remove equivalent properties (bug 317093) + if (mTagName == nsGkAtoms::b) { + rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("strong")); + NS_ENSURE_SUCCESS(rv, rv); + } else if (mTagName == nsGkAtoms::i) { + rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("em")); + NS_ENSURE_SUCCESS(rv, rv); + } else if (mTagName == nsGkAtoms::strike) { + rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("s")); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = RemoveTextProperty(htmlEditor, nsDependentAtomString(mTagName)); + } else { + // Superscript and Subscript styles are mutually exclusive + aEditor->BeginTransaction(); + + nsDependentAtomString tagName(mTagName); + if (mTagName == nsGkAtoms::sub || mTagName == nsGkAtoms::sup) { + rv = RemoveTextProperty(htmlEditor, tagName); + } + if (NS_SUCCEEDED(rv)) + rv = SetTextProperty(htmlEditor, tagName); + + aEditor->EndTransaction(); + } + + return rv; +} + +nsListCommand::nsListCommand(nsIAtom* aTagName) +: nsBaseStateUpdatingCommand(aTagName) +{ +} + +nsresult +nsListCommand::GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams) +{ + NS_ASSERTION(aEditor, "Need editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE); + + bool bMixed; + nsAutoString localName; + nsresult rv = GetListState(htmlEditor, &bMixed, localName); + NS_ENSURE_SUCCESS(rv, rv); + + bool inList = mTagName->Equals(localName); + aParams->SetBooleanValue(STATE_ALL, !bMixed && inList); + aParams->SetBooleanValue(STATE_MIXED, bMixed); + aParams->SetBooleanValue(STATE_ENABLED, true); + return NS_OK; +} + +nsresult +nsListCommand::ToggleState(nsIEditor *aEditor) +{ + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(editor, NS_NOINTERFACE); + + nsresult rv; + nsCOMPtr<nsICommandParams> params = + do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv); + if (NS_FAILED(rv) || !params) + return rv; + + rv = GetCurrentState(aEditor, params); + NS_ENSURE_SUCCESS(rv, rv); + + bool inList; + rv = params->GetBooleanValue(STATE_ALL,&inList); + NS_ENSURE_SUCCESS(rv, rv); + + nsDependentAtomString listType(mTagName); + if (inList) { + rv = editor->RemoveList(listType); + } else { + rv = editor->MakeOrChangeList(listType, false, EmptyString()); + } + + return rv; +} + +nsListItemCommand::nsListItemCommand(nsIAtom* aTagName) +: nsBaseStateUpdatingCommand(aTagName) +{ +} + +nsresult +nsListItemCommand::GetCurrentState(nsIEditor* aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need editor here"); + // 39584 + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_NOINTERFACE); + + bool bMixed, bLI, bDT, bDD; + nsresult rv = htmlEditor->GetListItemState(&bMixed, &bLI, &bDT, &bDD); + NS_ENSURE_SUCCESS(rv, rv); + + bool inList = false; + if (!bMixed) { + if (bLI) { + inList = mTagName == nsGkAtoms::li; + } else if (bDT) { + inList = mTagName == nsGkAtoms::dt; + } else if (bDD) { + inList = mTagName == nsGkAtoms::dd; + } + } + + aParams->SetBooleanValue(STATE_ALL, !bMixed && inList); + aParams->SetBooleanValue(STATE_MIXED, bMixed); + + return NS_OK; +} + +nsresult +nsListItemCommand::ToggleState(nsIEditor *aEditor) +{ + NS_ASSERTION(aEditor, "Need editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_INITIALIZED); + + bool inList; + // Need to use mTagName???? + nsresult rv; + nsCOMPtr<nsICommandParams> params = + do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv); + if (NS_FAILED(rv) || !params) + return rv; + rv = GetCurrentState(aEditor, params); + rv = params->GetBooleanValue(STATE_ALL,&inList); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_SUCCESS(rv, rv); + + if (inList) { + // To remove a list, first get what kind of list we're in + bool bMixed; + nsAutoString localName; + rv = GetListState(htmlEditor, &bMixed, localName); + NS_ENSURE_SUCCESS(rv, rv); + if (localName.IsEmpty() || bMixed) { + return rv; + } + return htmlEditor->RemoveList(localName); + } + + // Set to the requested paragraph type + //XXX Note: This actually doesn't work for "LI", + // but we currently don't use this for non DL lists anyway. + // Problem: won't this replace any current block paragraph style? + return htmlEditor->SetParagraphFormat(nsDependentAtomString(mTagName)); +} + +NS_IMETHODIMP +nsRemoveListCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + *outCmdEnabled = false; + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(editor, NS_OK); + + bool isEditable = false; + nsresult rv = editor->GetIsSelectionEditable(&isEditable); + NS_ENSURE_SUCCESS(rv, rv); + if (!isEditable) { + return NS_OK; + } + + // It is enabled if we are in any list type + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE); + + bool bMixed; + nsAutoString localName; + rv = GetListState(htmlEditor, &bMixed, localName); + NS_ENSURE_SUCCESS(rv, rv); + + *outCmdEnabled = bMixed || !localName.IsEmpty(); + return NS_OK; +} + + +NS_IMETHODIMP +nsRemoveListCommand::DoCommand(const char *aCommandName, nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + + nsresult rv = NS_OK; + if (editor) { + // This removes any list type + rv = editor->RemoveList(EmptyString()); + } + + return rv; +} + +NS_IMETHODIMP +nsRemoveListCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsRemoveListCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled); +} + +NS_IMETHODIMP +nsIndentCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +NS_IMETHODIMP +nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + + nsresult rv = NS_OK; + if (editor) { + rv = editor->Indent(NS_LITERAL_STRING("indent")); + } + + return rv; +} + +NS_IMETHODIMP +nsIndentCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsIndentCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled); +} + + +//OUTDENT + +NS_IMETHODIMP +nsOutdentCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + *outCmdEnabled = false; + + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + if (editor) { + nsresult rv = editor->GetIsSelectionEditable(outCmdEnabled); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + + +NS_IMETHODIMP +nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon); + if (htmlEditor) + return htmlEditor->Indent(NS_LITERAL_STRING("outdent")); + + return NS_OK; +} + +NS_IMETHODIMP +nsOutdentCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsOutdentCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled); +} + +nsMultiStateCommand::nsMultiStateCommand() +: nsBaseComposerCommand() +{ +} + +nsMultiStateCommand::~nsMultiStateCommand() +{ +} + +NS_IMPL_ISUPPORTS_INHERITED0(nsMultiStateCommand, nsBaseComposerCommand) + +NS_IMETHODIMP +nsMultiStateCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + // should be disabled sometimes, like if the current selection is an image + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +NS_IMETHODIMP +nsMultiStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon) +{ +#ifdef DEBUG + printf("who is calling nsMultiStateCommand::DoCommand \ + (no implementation)? %s\n", aCommandName); +#endif + + return NS_OK; +} + +NS_IMETHODIMP +nsMultiStateCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + + nsresult rv = NS_OK; + if (editor) { + nsAutoString tString; + + if (aParams) { + nsXPIDLCString s; + rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s)); + if (NS_SUCCEEDED(rv)) + tString.AssignWithConversion(s); + else + rv = aParams->GetStringValue(STATE_ATTRIBUTE, tString); + } + + rv = SetState(editor, tString); + } + + return rv; +} + +NS_IMETHODIMP +nsMultiStateCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + nsresult rv = NS_OK; + if (editor) { + rv = GetCurrentState(editor, aParams); + } + return rv; +} + +nsParagraphStateCommand::nsParagraphStateCommand() +: nsMultiStateCommand() +{ +} + +nsresult +nsParagraphStateCommand::GetCurrentState(nsIEditor *aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + bool outMixed; + nsAutoString outStateString; + nsresult rv = htmlEditor->GetParagraphState(&outMixed, outStateString); + if (NS_SUCCEEDED(rv)) { + nsAutoCString tOutStateString; + tOutStateString.AssignWithConversion(outStateString); + aParams->SetBooleanValue(STATE_MIXED,outMixed); + aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get()); + } + return rv; +} + + +nsresult +nsParagraphStateCommand::SetState(nsIEditor *aEditor, nsString& newState) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + return htmlEditor->SetParagraphFormat(newState); +} + +nsFontFaceStateCommand::nsFontFaceStateCommand() +: nsMultiStateCommand() +{ +} + +nsresult +nsFontFaceStateCommand::GetCurrentState(nsIEditor *aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + nsAutoString outStateString; + bool outMixed; + nsresult rv = htmlEditor->GetFontFaceState(&outMixed, outStateString); + if (NS_SUCCEEDED(rv)) { + aParams->SetBooleanValue(STATE_MIXED,outMixed); + aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get()); + } + return rv; +} + + +nsresult +nsFontFaceStateCommand::SetState(nsIEditor *aEditor, nsString& newState) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + if (newState.EqualsLiteral("tt")) { + // The old "teletype" attribute + nsresult rv = htmlEditor->SetInlineProperty(nsGkAtoms::tt, EmptyString(), + EmptyString()); + NS_ENSURE_SUCCESS(rv, rv); + // Clear existing font face + return htmlEditor->RemoveInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("face")); + } + + // Remove any existing TT nodes + nsresult rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::tt, EmptyString()); + NS_ENSURE_SUCCESS(rv, rv); + + if (newState.IsEmpty() || newState.EqualsLiteral("normal")) { + return htmlEditor->RemoveInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("face")); + } + + return htmlEditor->SetInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("face"), newState); +} + +nsFontSizeStateCommand::nsFontSizeStateCommand() + : nsMultiStateCommand() +{ +} + +// nsAutoCString tOutStateString; +// tOutStateString.AssignWithConversion(outStateString); +nsresult +nsFontSizeStateCommand::GetCurrentState(nsIEditor *aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_INVALID_ARG); + + nsAutoString outStateString; + nsCOMPtr<nsIAtom> fontAtom = NS_Atomize("font"); + bool firstHas, anyHas, allHas; + nsresult rv = htmlEditor->GetInlinePropertyWithAttrValue(fontAtom, + NS_LITERAL_STRING("size"), + EmptyString(), + &firstHas, &anyHas, &allHas, + outStateString); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString tOutStateString; + tOutStateString.AssignWithConversion(outStateString); + aParams->SetBooleanValue(STATE_MIXED, anyHas && !allHas); + aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get()); + aParams->SetBooleanValue(STATE_ENABLED, true); + + return rv; +} + + +// acceptable values for "newState" are: +// -2 +// -1 +// 0 +// +1 +// +2 +// +3 +// medium +// normal +nsresult +nsFontSizeStateCommand::SetState(nsIEditor *aEditor, nsString& newState) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_INVALID_ARG); + + if (!newState.IsEmpty() && + !newState.EqualsLiteral("normal") && + !newState.EqualsLiteral("medium")) { + return htmlEditor->SetInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("size"), newState); + } + + // remove any existing font size, big or small + nsresult rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("size")); + NS_ENSURE_SUCCESS(rv, rv); + + rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::big, EmptyString()); + NS_ENSURE_SUCCESS(rv, rv); + + return htmlEditor->RemoveInlineProperty(nsGkAtoms::small, EmptyString()); +} + +nsFontColorStateCommand::nsFontColorStateCommand() +: nsMultiStateCommand() +{ +} + +nsresult +nsFontColorStateCommand::GetCurrentState(nsIEditor *aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + bool outMixed; + nsAutoString outStateString; + nsresult rv = htmlEditor->GetFontColorState(&outMixed, outStateString); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString tOutStateString; + tOutStateString.AssignWithConversion(outStateString); + aParams->SetBooleanValue(STATE_MIXED, outMixed); + aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get()); + return NS_OK; +} + +nsresult +nsFontColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + if (newState.IsEmpty() || newState.EqualsLiteral("normal")) { + return htmlEditor->RemoveInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("color")); + } + + return htmlEditor->SetInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("color"), newState); +} + +nsHighlightColorStateCommand::nsHighlightColorStateCommand() +: nsMultiStateCommand() +{ +} + +nsresult +nsHighlightColorStateCommand::GetCurrentState(nsIEditor *aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + bool outMixed; + nsAutoString outStateString; + nsresult rv = htmlEditor->GetHighlightColorState(&outMixed, outStateString); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString tOutStateString; + tOutStateString.AssignWithConversion(outStateString); + aParams->SetBooleanValue(STATE_MIXED, outMixed); + aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get()); + return NS_OK; +} + +nsresult +nsHighlightColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + if (newState.IsEmpty() || newState.EqualsLiteral("normal")) { + return htmlEditor->RemoveInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("bgcolor")); + } + + return htmlEditor->SetInlineProperty(nsGkAtoms::font, + NS_LITERAL_STRING("bgcolor"), + newState); +} + +NS_IMETHODIMP +nsHighlightColorStateCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +nsBackgroundColorStateCommand::nsBackgroundColorStateCommand() +: nsMultiStateCommand() +{ +} + +nsresult +nsBackgroundColorStateCommand::GetCurrentState(nsIEditor *aEditor, + nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + bool outMixed; + nsAutoString outStateString; + nsresult rv = htmlEditor->GetBackgroundColorState(&outMixed, outStateString); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString tOutStateString; + tOutStateString.AssignWithConversion(outStateString); + aParams->SetBooleanValue(STATE_MIXED, outMixed); + aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get()); + return NS_OK; +} + +nsresult +nsBackgroundColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + return htmlEditor->SetBackgroundColor(newState); +} + +nsAlignCommand::nsAlignCommand() +: nsMultiStateCommand() +{ +} + +nsresult +nsAlignCommand::GetCurrentState(nsIEditor *aEditor, nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + nsIHTMLEditor::EAlignment firstAlign; + bool outMixed; + nsresult rv = htmlEditor->GetAlignment(&outMixed, &firstAlign); + + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString outStateString; + switch (firstAlign) { + default: + case nsIHTMLEditor::eLeft: + outStateString.AssignLiteral("left"); + break; + + case nsIHTMLEditor::eCenter: + outStateString.AssignLiteral("center"); + break; + + case nsIHTMLEditor::eRight: + outStateString.AssignLiteral("right"); + break; + + case nsIHTMLEditor::eJustify: + outStateString.AssignLiteral("justify"); + break; + } + nsAutoCString tOutStateString; + tOutStateString.AssignWithConversion(outStateString); + aParams->SetBooleanValue(STATE_MIXED,outMixed); + aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get()); + return NS_OK; +} + +nsresult +nsAlignCommand::SetState(nsIEditor *aEditor, nsString& newState) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + return htmlEditor->Align(newState); +} + +nsAbsolutePositioningCommand::nsAbsolutePositioningCommand() +: nsBaseStateUpdatingCommand(nsGkAtoms::_empty) +{ +} + +NS_IMETHODIMP +nsAbsolutePositioningCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *aCommandRefCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon); + nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aCommandRefCon); + if (htmlEditor) { + bool isEditable = false; + nsresult rv = editor->GetIsSelectionEditable(&isEditable); + NS_ENSURE_SUCCESS(rv, rv); + if (isEditable) + return htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled); + } + + *outCmdEnabled = false; + return NS_OK; +} + +nsresult +nsAbsolutePositioningCommand::GetCurrentState(nsIEditor *aEditor, nsICommandParams *aParams) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + bool isEnabled; + htmlEditor->GetAbsolutePositioningEnabled(&isEnabled); + if (!isEnabled) { + aParams->SetBooleanValue(STATE_MIXED,false); + aParams->SetCStringValue(STATE_ATTRIBUTE, ""); + return NS_OK; + } + + nsCOMPtr<nsIDOMElement> elt; + nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString outStateString; + if (elt) + outStateString.AssignLiteral("absolute"); + + aParams->SetBooleanValue(STATE_MIXED,false); + aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get()); + return NS_OK; +} + +nsresult +nsAbsolutePositioningCommand::ToggleState(nsIEditor *aEditor) +{ + NS_ASSERTION(aEditor, "Need an editor here"); + + nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDOMElement> elt; + nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt)); + NS_ENSURE_SUCCESS(rv, rv); + + return htmlEditor->AbsolutePositionSelection(!elt); +} + + +NS_IMETHODIMP +nsDecreaseZIndexCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled); + if (!(*outCmdEnabled)) + return NS_OK; + + nsCOMPtr<nsIDOMElement> positionedElement; + htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement)); + *outCmdEnabled = false; + if (positionedElement) { + int32_t z; + nsresult rv = htmlEditor->GetElementZIndex(positionedElement, &z); + NS_ENSURE_SUCCESS(rv, rv); + *outCmdEnabled = (z > 0); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDecreaseZIndexCommand::DoCommand(const char *aCommandName, + nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED); + + return htmlEditor->RelativeChangeZIndex(-1); +} + +NS_IMETHODIMP +nsDecreaseZIndexCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsDecreaseZIndexCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + NS_ENSURE_ARG_POINTER(aParams); + + bool enabled = false; + nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled); + NS_ENSURE_SUCCESS(rv, rv); + + return aParams->SetBooleanValue(STATE_ENABLED, enabled); +} + +NS_IMETHODIMP +nsIncreaseZIndexCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + + htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled); + if (!(*outCmdEnabled)) + return NS_OK; + + nsCOMPtr<nsIDOMElement> positionedElement; + htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement)); + *outCmdEnabled = (nullptr != positionedElement); + return NS_OK; +} + +NS_IMETHODIMP +nsIncreaseZIndexCommand::DoCommand(const char *aCommandName, + nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED); + + return htmlEditor->RelativeChangeZIndex(1); +} + +NS_IMETHODIMP +nsIncreaseZIndexCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsIncreaseZIndexCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + NS_ENSURE_ARG_POINTER(aParams); + + bool enabled = false; + nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled); + NS_ENSURE_SUCCESS(rv, rv); + + return aParams->SetBooleanValue(STATE_ENABLED, enabled); +} + + +NS_IMETHODIMP +nsRemoveStylesCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + // test if we have any styles? + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + + +NS_IMETHODIMP +nsRemoveStylesCommand::DoCommand(const char *aCommandName, + nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + + nsresult rv = NS_OK; + if (editor) { + rv = editor->RemoveAllInlineProperties(); + } + + return rv; +} + +NS_IMETHODIMP +nsRemoveStylesCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsRemoveStylesCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled); +} + +NS_IMETHODIMP +nsIncreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + // test if we are at max size? + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +NS_IMETHODIMP +nsIncreaseFontSizeCommand::DoCommand(const char *aCommandName, + nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + + nsresult rv = NS_OK; + if (editor) { + rv = editor->IncreaseFontSize(); + } + + return rv; +} + +NS_IMETHODIMP +nsIncreaseFontSizeCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsIncreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled); +} + +NS_IMETHODIMP +nsDecreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + // test if we are at min size? + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +NS_IMETHODIMP +nsDecreaseFontSizeCommand::DoCommand(const char *aCommandName, + nsISupports *refCon) +{ + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + + nsresult rv = NS_OK; + if (editor) { + rv = editor->DecreaseFontSize(); + } + + return rv; +} + +NS_IMETHODIMP +nsDecreaseFontSizeCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + return DoCommand(aCommandName, refCon); +} + +NS_IMETHODIMP +nsDecreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled); +} + +NS_IMETHODIMP +nsInsertHTMLCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + NS_ENSURE_ARG_POINTER(outCmdEnabled); + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +NS_IMETHODIMP +nsInsertHTMLCommand::DoCommand(const char *aCommandName, nsISupports *refCon) +{ + // If nsInsertHTMLCommand is called with no parameters, it was probably called with + // an empty string parameter ''. In this case, it should act the same as the delete command + NS_ENSURE_ARG_POINTER(refCon); + + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED); + + nsString html = EmptyString(); + return editor->InsertHTML(html); +} + +NS_IMETHODIMP +nsInsertHTMLCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + NS_ENSURE_ARG_POINTER(aParams); + NS_ENSURE_ARG_POINTER(refCon); + + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED); + + // Get HTML source string to insert from command params + nsAutoString html; + nsresult rv = aParams->GetStringValue(STATE_DATA, html); + NS_ENSURE_SUCCESS(rv, rv); + + return editor->InsertHTML(html); +} + +NS_IMETHODIMP +nsInsertHTMLCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + NS_ENSURE_ARG_POINTER(aParams); + NS_ENSURE_ARG_POINTER(refCon); + + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled); +} + +NS_IMPL_ISUPPORTS_INHERITED0(nsInsertTagCommand, nsBaseComposerCommand) + +nsInsertTagCommand::nsInsertTagCommand(nsIAtom* aTagName) +: nsBaseComposerCommand() +, mTagName(aTagName) +{ + MOZ_ASSERT(mTagName); +} + +nsInsertTagCommand::~nsInsertTagCommand() +{ +} + +NS_IMETHODIMP +nsInsertTagCommand::IsCommandEnabled(const char * aCommandName, + nsISupports *refCon, + bool *outCmdEnabled) +{ + NS_ENSURE_ARG_POINTER(outCmdEnabled); + nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = false; + return NS_OK; +} + + +// corresponding STATE_ATTRIBUTE is: src (img) and href (a) +NS_IMETHODIMP +nsInsertTagCommand::DoCommand(const char *aCmdName, nsISupports *refCon) +{ + NS_ENSURE_TRUE(mTagName == nsGkAtoms::hr, NS_ERROR_NOT_IMPLEMENTED); + + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED); + + nsCOMPtr<nsIDOMElement> domElem; + nsresult rv = editor->CreateElementWithDefaults( + nsDependentAtomString(mTagName), getter_AddRefs(domElem)); + NS_ENSURE_SUCCESS(rv, rv); + + return editor->InsertElementAtSelection(domElem, true); +} + +NS_IMETHODIMP +nsInsertTagCommand::DoCommandParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + NS_ENSURE_ARG_POINTER(refCon); + + // inserting an hr shouldn't have an parameters, just call DoCommand for that + if (mTagName == nsGkAtoms::hr) { + return DoCommand(aCommandName, refCon); + } + + NS_ENSURE_ARG_POINTER(aParams); + + nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon); + NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED); + + // do we have an href to use for creating link? + nsXPIDLCString s; + nsresult rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s)); + NS_ENSURE_SUCCESS(rv, rv); + nsAutoString attrib; attrib.AssignWithConversion(s); + + if (attrib.IsEmpty()) + return NS_ERROR_INVALID_ARG; + + // filter out tags we don't know how to insert + nsAutoString attributeType; + if (mTagName == nsGkAtoms::a) { + attributeType.AssignLiteral("href"); + } else if (mTagName == nsGkAtoms::img) { + attributeType.AssignLiteral("src"); + } else { + return NS_ERROR_NOT_IMPLEMENTED; + } + + nsCOMPtr<nsIDOMElement> domElem; + rv = editor->CreateElementWithDefaults(nsDependentAtomString(mTagName), + getter_AddRefs(domElem)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = domElem->SetAttribute(attributeType, attrib); + NS_ENSURE_SUCCESS(rv, rv); + + // do actual insertion + if (mTagName == nsGkAtoms::a) + return editor->InsertLinkAroundSelection(domElem); + + return editor->InsertElementAtSelection(domElem, true); +} + +NS_IMETHODIMP +nsInsertTagCommand::GetCommandStateParams(const char *aCommandName, + nsICommandParams *aParams, + nsISupports *refCon) +{ + NS_ENSURE_ARG_POINTER(aParams); + NS_ENSURE_ARG_POINTER(refCon); + + bool outCmdEnabled = false; + IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); + return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled); +} + + +/****************************/ +//HELPER METHODS +/****************************/ + +nsresult +GetListState(nsIHTMLEditor* aEditor, bool* aMixed, nsAString& aLocalName) +{ + MOZ_ASSERT(aEditor); + MOZ_ASSERT(aMixed); + + *aMixed = false; + aLocalName.Truncate(); + + bool bOL, bUL, bDL; + nsresult rv = aEditor->GetListState(aMixed, &bOL, &bUL, &bDL); + NS_ENSURE_SUCCESS(rv, rv); + + if (*aMixed) { + return NS_OK; + } + + if (bOL) { + aLocalName.AssignLiteral("ol"); + } else if (bUL) { + aLocalName.AssignLiteral("ul"); + } else if (bDL) { + aLocalName.AssignLiteral("dl"); + } + return NS_OK; +} + +nsresult +RemoveOneProperty(nsIHTMLEditor* aEditor, const nsAString& aProp) +{ + MOZ_ASSERT(aEditor); + + /// XXX Hack alert! Look in nsIEditProperty.h for this + nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp); + NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY); + + return aEditor->RemoveInlineProperty(styleAtom, EmptyString()); +} + + +// the name of the attribute here should be the contents of the appropriate +// tag, e.g. 'b' for bold, 'i' for italics. +nsresult +RemoveTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp) +{ + MOZ_ASSERT(aEditor); + + if (aProp.LowerCaseEqualsLiteral("all")) { + return aEditor->RemoveAllInlineProperties(); + } + + return RemoveOneProperty(aEditor, aProp); +} + +// the name of the attribute here should be the contents of the appropriate +// tag, e.g. 'b' for bold, 'i' for italics. +nsresult +SetTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp) +{ + MOZ_ASSERT(aEditor); + + /// XXX Hack alert! Look in nsIEditProperty.h for this + nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp); + NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY); + + return aEditor->SetInlineProperty(styleAtom, EmptyString(), EmptyString()); +} |