mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 00:35:44 +00:00
b8fd63d7b5
Fortunately, despite of becoming public method, HTMLEditor::CreateElementWithDefaults() can be used by internal methods too since it does not touch undo transactions nor the DOM tree, and does not refer mRules nor GetSelection(). So, we can make it public and make any C++ callers use it.
1672 lines
47 KiB
C++
1672 lines
47 KiB
C++
/* -*- 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 "mozilla/EditorBase.h" // for EditorBase
|
|
#include "mozilla/ErrorResult.h"
|
|
#include "mozilla/HTMLEditor.h" // for HTMLEditor
|
|
#include "mozilla/HTMLEditorCommands.h"
|
|
#include "mozilla/dom/Element.h"
|
|
#include "nsAString.h"
|
|
#include "nsCommandParams.h" // for nsCommandParams, etc
|
|
#include "nsCOMPtr.h" // for nsCOMPtr, do_QueryInterface, etc
|
|
#include "nsComponentManagerUtils.h" // for do_CreateInstance
|
|
#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 "nsAtom.h" // for nsAtom, etc
|
|
#include "nsIClipboard.h" // for nsIClipboard, etc
|
|
#include "nsID.h"
|
|
#include "nsIEditor.h" // for nsIEditor
|
|
#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 nsString
|
|
|
|
class nsISupports;
|
|
|
|
namespace mozilla {
|
|
using dom::Element;
|
|
|
|
//prototype
|
|
static nsresult
|
|
GetListState(HTMLEditor* aHTMLEditor, bool* aMixed, nsAString& aLocalName);
|
|
|
|
//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"
|
|
|
|
|
|
HTMLEditorCommandBase::HTMLEditorCommandBase()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(HTMLEditorCommandBase, nsIControllerCommand)
|
|
|
|
|
|
StateUpdatingCommandBase::StateUpdatingCommandBase(nsAtom* aTagName)
|
|
: HTMLEditorCommandBase()
|
|
, mTagName(aTagName)
|
|
{
|
|
MOZ_ASSERT(mTagName);
|
|
}
|
|
|
|
StateUpdatingCommandBase::~StateUpdatingCommandBase()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
StateUpdatingCommandBase::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
StateUpdatingCommandBase::DoCommand(const char* aCommandName,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return ToggleState(htmlEditor);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
StateUpdatingCommandBase::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
StateUpdatingCommandBase::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return GetCurrentState(htmlEditor, aParams);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
PasteNoFormattingCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
|
*outCmdEnabled = false;
|
|
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// This command is only implemented by nsIHTMLEditor, since
|
|
// pasting in a plaintext editor automatically only supplies
|
|
// "unformatted" text
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return htmlEditor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
PasteNoFormattingCommand::DoCommand(const char* aCommandName,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return htmlEditor->PasteNoFormatting(nsIClipboard::kGlobalClipboard);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
PasteNoFormattingCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
PasteNoFormattingCommand::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->AsCommandParams()->SetBool(STATE_ENABLED, enabled);
|
|
}
|
|
|
|
StyleUpdatingCommand::StyleUpdatingCommand(nsAtom* aTagName)
|
|
: StateUpdatingCommandBase(aTagName)
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
StyleUpdatingCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams *aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
bool firstOfSelectionHasProp = false;
|
|
bool anyOfSelectionHasProp = false;
|
|
bool allOfSelectionHasProp = false;
|
|
|
|
nsresult rv = aHTMLEditor->GetInlineProperty(mTagName, nullptr,
|
|
EmptyString(),
|
|
&firstOfSelectionHasProp,
|
|
&anyOfSelectionHasProp,
|
|
&allOfSelectionHasProp);
|
|
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_ENABLED, NS_SUCCEEDED(rv));
|
|
params->SetBool(STATE_ALL, allOfSelectionHasProp);
|
|
params->SetBool(STATE_ANY, anyOfSelectionHasProp);
|
|
params->SetBool(STATE_MIXED, anyOfSelectionHasProp && !allOfSelectionHasProp);
|
|
params->SetBool(STATE_BEGIN, firstOfSelectionHasProp);
|
|
params->SetBool(STATE_END, allOfSelectionHasProp); //not completely accurate
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
StyleUpdatingCommand::ToggleState(HTMLEditor* aHTMLEditor)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
RefPtr<nsCommandParams> params = new nsCommandParams();
|
|
|
|
// 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
|
|
nsresult rv = GetCurrentState(aHTMLEditor, params);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
ErrorResult error;
|
|
doTagRemoval = params->GetBool(STATE_ALL, error);
|
|
if (NS_WARN_IF(error.Failed())) {
|
|
return error.StealNSResult();
|
|
}
|
|
}
|
|
|
|
if (doTagRemoval) {
|
|
// Also remove equivalent properties (bug 317093)
|
|
// XXX Why don't we make the following two transactions as an atomic
|
|
// transaction? If the element is <b>, <i> or <strike>, user
|
|
// needs to undo twice.
|
|
if (mTagName == nsGkAtoms::b) {
|
|
nsresult rv =
|
|
aHTMLEditor->RemoveInlineProperty(nsGkAtoms::strong, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
} else if (mTagName == nsGkAtoms::i) {
|
|
nsresult rv =
|
|
aHTMLEditor->RemoveInlineProperty(nsGkAtoms::em, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
} else if (mTagName == nsGkAtoms::strike) {
|
|
nsresult rv =
|
|
aHTMLEditor->RemoveInlineProperty(nsGkAtoms::s, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
nsresult rv = aHTMLEditor->RemoveInlineProperty(mTagName, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// Superscript and Subscript styles are mutually exclusive.
|
|
AutoTransactionBatch bundleAllTransactions(*aHTMLEditor);
|
|
|
|
if (mTagName == nsGkAtoms::sub || mTagName == nsGkAtoms::sup) {
|
|
nsresult rv = aHTMLEditor->RemoveInlineProperty(mTagName, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
nsresult rv =
|
|
aHTMLEditor->SetInlineProperty(*mTagName, nullptr, EmptyString());
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
ListCommand::ListCommand(nsAtom* aTagName)
|
|
: StateUpdatingCommandBase(aTagName)
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
ListCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
bool bMixed;
|
|
nsAutoString localName;
|
|
nsresult rv = GetListState(aHTMLEditor, &bMixed, localName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool inList = mTagName->Equals(localName);
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_ALL, !bMixed && inList);
|
|
params->SetBool(STATE_MIXED, bMixed);
|
|
params->SetBool(STATE_ENABLED, true);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
ListCommand::ToggleState(HTMLEditor* aHTMLEditor)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
nsresult rv;
|
|
RefPtr<nsCommandParams> params = new nsCommandParams();
|
|
rv = GetCurrentState(aHTMLEditor, params);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
ErrorResult error;
|
|
bool inList = params->GetBool(STATE_ALL, error);
|
|
if (NS_WARN_IF(error.Failed())) {
|
|
return error.StealNSResult();
|
|
}
|
|
|
|
nsDependentAtomString listType(mTagName);
|
|
if (inList) {
|
|
rv = aHTMLEditor->RemoveList(listType);
|
|
} else {
|
|
rv = aHTMLEditor->MakeOrChangeList(listType, false, EmptyString());
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
ListItemCommand::ListItemCommand(nsAtom* aTagName)
|
|
: StateUpdatingCommandBase(aTagName)
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
ListItemCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams *aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
bool bMixed, bLI, bDT, bDD;
|
|
nsresult rv = aHTMLEditor->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;
|
|
}
|
|
}
|
|
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_ALL, !bMixed && inList);
|
|
params->SetBool(STATE_MIXED, bMixed);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
ListItemCommand::ToggleState(HTMLEditor* aHTMLEditor)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
// Need to use mTagName????
|
|
RefPtr<nsCommandParams> params = new nsCommandParams();
|
|
GetCurrentState(aHTMLEditor, params);
|
|
ErrorResult error;
|
|
bool inList = params->GetBool(STATE_ALL, error);
|
|
if (NS_WARN_IF(error.Failed())) {
|
|
return error.StealNSResult();
|
|
}
|
|
|
|
if (inList) {
|
|
// To remove a list, first get what kind of list we're in
|
|
bool bMixed;
|
|
nsAutoString localName;
|
|
nsresult rv = GetListState(aHTMLEditor, &bMixed, localName);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
if (localName.IsEmpty() || bMixed) {
|
|
return NS_OK;
|
|
}
|
|
return aHTMLEditor->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 aHTMLEditor->SetParagraphFormat(nsDependentAtomString(mTagName));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
RemoveListCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
*outCmdEnabled = false;
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
|
|
if (!editorBase->IsSelectionEditable()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// It is enabled if we are in any list type
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
bool bMixed;
|
|
nsAutoString localName;
|
|
nsresult rv = GetListState(htmlEditor, &bMixed, localName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
*outCmdEnabled = bMixed || !localName.IsEmpty();
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
RemoveListCommand::DoCommand(const char* aCommandName, nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (!htmlEditor) {
|
|
return NS_OK;
|
|
}
|
|
// This removes any list type
|
|
return htmlEditor->RemoveList(EmptyString());
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
RemoveListCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
RemoveListCommand::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
bool outCmdEnabled = false;
|
|
IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
|
|
return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IndentCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon, bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IndentCommand::DoCommand(const char* aCommandName, nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (!htmlEditor) {
|
|
return NS_OK;
|
|
}
|
|
nsresult rv = htmlEditor->IndentAsAction();
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IndentCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IndentCommand::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
bool outCmdEnabled = false;
|
|
IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
|
|
return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
|
|
//OUTDENT
|
|
|
|
NS_IMETHODIMP
|
|
OutdentCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
OutdentCommand::DoCommand(const char* aCommandName, nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (!htmlEditor) {
|
|
return NS_OK;
|
|
}
|
|
nsresult rv = htmlEditor->OutdentAsAction();
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
OutdentCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
OutdentCommand::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
bool outCmdEnabled = false;
|
|
IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
|
|
return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
MultiStateCommandBase::MultiStateCommandBase()
|
|
: HTMLEditorCommandBase()
|
|
{
|
|
}
|
|
|
|
MultiStateCommandBase::~MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MultiStateCommandBase::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool *outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
// should be disabled sometimes, like if the current selection is an image
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MultiStateCommandBase::DoCommand(const char* aCommandName, nsISupports* refCon)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("who is calling MultiStateCommandBase::DoCommand \
|
|
(no implementation)? %s\n", aCommandName);
|
|
#endif
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MultiStateCommandBase::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsAutoString attribute;
|
|
if (aParams) {
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
nsAutoCString asciiAttribute;
|
|
nsresult rv = params->GetCString(STATE_ATTRIBUTE, asciiAttribute);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
CopyASCIItoUTF16(asciiAttribute, attribute);
|
|
} else {
|
|
params->GetString(STATE_ATTRIBUTE, attribute);
|
|
}
|
|
}
|
|
return SetState(htmlEditor, attribute);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MultiStateCommandBase::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return GetCurrentState(htmlEditor, aParams);
|
|
}
|
|
|
|
ParagraphStateCommand::ParagraphStateCommand()
|
|
: MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
ParagraphStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
bool outMixed;
|
|
nsAutoString outStateString;
|
|
nsresult rv = aHTMLEditor->GetParagraphState(&outMixed, outStateString);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsAutoCString tOutStateString;
|
|
LossyCopyUTF16toASCII(outStateString, tOutStateString);
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_MIXED, outMixed);
|
|
params->SetCString(STATE_ATTRIBUTE, tOutStateString);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
ParagraphStateCommand::SetState(HTMLEditor* aHTMLEditor,
|
|
const nsString& newState)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
return aHTMLEditor->SetParagraphFormat(newState);
|
|
}
|
|
|
|
FontFaceStateCommand::FontFaceStateCommand()
|
|
: MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
FontFaceStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
nsAutoString outStateString;
|
|
bool outMixed;
|
|
nsresult rv = aHTMLEditor->GetFontFaceState(&outMixed, outStateString);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_MIXED, outMixed);
|
|
params->SetCString(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString));
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
FontFaceStateCommand::SetState(HTMLEditor* aHTMLEditor,
|
|
const nsString& newState)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
if (newState.EqualsLiteral("tt")) {
|
|
// The old "teletype" attribute
|
|
nsresult rv = aHTMLEditor->SetInlineProperty(*nsGkAtoms::tt, nullptr,
|
|
EmptyString());
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
// Clear existing font face
|
|
rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::font, nsGkAtoms::face);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// Remove any existing TT nodes
|
|
nsresult rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::tt, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
|
|
rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::font, nsGkAtoms::face);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
rv = aHTMLEditor->SetInlineProperty(*nsGkAtoms::font,
|
|
nsGkAtoms::face,
|
|
newState);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
FontSizeStateCommand::FontSizeStateCommand()
|
|
: MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
FontSizeStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
nsAutoString outStateString;
|
|
bool firstHas, anyHas, allHas;
|
|
nsresult rv = aHTMLEditor->GetInlinePropertyWithAttrValue(
|
|
nsGkAtoms::font,
|
|
nsGkAtoms::size,
|
|
EmptyString(),
|
|
&firstHas, &anyHas, &allHas,
|
|
outStateString);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString tOutStateString;
|
|
LossyCopyUTF16toASCII(outStateString, tOutStateString);
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_MIXED, anyHas && !allHas);
|
|
params->SetCString(STATE_ATTRIBUTE, tOutStateString);
|
|
params->SetBool(STATE_ENABLED, true);
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
// acceptable values for "newState" are:
|
|
// -2
|
|
// -1
|
|
// 0
|
|
// +1
|
|
// +2
|
|
// +3
|
|
// medium
|
|
// normal
|
|
nsresult
|
|
FontSizeStateCommand::SetState(HTMLEditor* aHTMLEditor,
|
|
const nsString& newState)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
if (!newState.IsEmpty() &&
|
|
!newState.EqualsLiteral("normal") &&
|
|
!newState.EqualsLiteral("medium")) {
|
|
nsresult rv = aHTMLEditor->SetInlineProperty(*nsGkAtoms::font,
|
|
nsGkAtoms::size,
|
|
newState);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// remove any existing font size, big or small
|
|
nsresult rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::font,
|
|
nsGkAtoms::size);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::big, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::small, nullptr);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
FontColorStateCommand::FontColorStateCommand()
|
|
: MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
FontColorStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
bool outMixed;
|
|
nsAutoString outStateString;
|
|
nsresult rv = aHTMLEditor->GetFontColorState(&outMixed, outStateString);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString tOutStateString;
|
|
LossyCopyUTF16toASCII(outStateString, tOutStateString);
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_MIXED, outMixed);
|
|
params->SetCString(STATE_ATTRIBUTE, tOutStateString);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
FontColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
|
|
const nsString& newState)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
|
|
nsresult rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::font,
|
|
nsGkAtoms::color);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult rv = aHTMLEditor->SetInlineProperty(*nsGkAtoms::font,
|
|
nsGkAtoms::color,
|
|
newState);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
HighlightColorStateCommand::HighlightColorStateCommand()
|
|
: MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
HighlightColorStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
bool outMixed;
|
|
nsAutoString outStateString;
|
|
nsresult rv = aHTMLEditor->GetHighlightColorState(&outMixed, outStateString);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString tOutStateString;
|
|
LossyCopyUTF16toASCII(outStateString, tOutStateString);
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_MIXED, outMixed);
|
|
params->SetCString(STATE_ATTRIBUTE, tOutStateString);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
HighlightColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
|
|
const nsString& newState)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
|
|
nsresult rv = aHTMLEditor->RemoveInlineProperty(nsGkAtoms::font,
|
|
nsGkAtoms::bgcolor);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult rv = aHTMLEditor->SetInlineProperty(*nsGkAtoms::font,
|
|
nsGkAtoms::bgcolor,
|
|
newState);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HighlightColorStateCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
BackgroundColorStateCommand::BackgroundColorStateCommand()
|
|
: MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
BackgroundColorStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
bool outMixed;
|
|
nsAutoString outStateString;
|
|
nsresult rv = aHTMLEditor->GetBackgroundColorState(&outMixed, outStateString);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString tOutStateString;
|
|
LossyCopyUTF16toASCII(outStateString, tOutStateString);
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_MIXED, outMixed);
|
|
params->SetCString(STATE_ATTRIBUTE, tOutStateString);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
BackgroundColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
|
|
const nsString& newState)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
return aHTMLEditor->SetBackgroundColor(newState);
|
|
}
|
|
|
|
AlignCommand::AlignCommand()
|
|
: MultiStateCommandBase()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
AlignCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
nsIHTMLEditor::EAlignment firstAlign;
|
|
bool outMixed;
|
|
nsresult rv = aHTMLEditor->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;
|
|
LossyCopyUTF16toASCII(outStateString, tOutStateString);
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
params->SetBool(STATE_MIXED, outMixed);
|
|
params->SetCString(STATE_ATTRIBUTE, tOutStateString);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
AlignCommand::SetState(HTMLEditor* aHTMLEditor,
|
|
const nsString& newState)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
return aHTMLEditor->Align(newState);
|
|
}
|
|
|
|
AbsolutePositioningCommand::AbsolutePositioningCommand()
|
|
: StateUpdatingCommandBase(nsGkAtoms::_empty)
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AbsolutePositioningCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* aCommandRefCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
*outCmdEnabled = false;
|
|
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (!htmlEditor) {
|
|
return NS_OK;
|
|
}
|
|
if (!htmlEditor->IsSelectionEditable()) {
|
|
return NS_OK;
|
|
}
|
|
*outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
AbsolutePositioningCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
|
|
nsICommandParams* aParams)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
nsCommandParams* params = aParams->AsCommandParams();
|
|
bool isEnabled = aHTMLEditor->AbsolutePositioningEnabled();
|
|
if (!isEnabled) {
|
|
params->SetBool(STATE_MIXED, false);
|
|
params->SetCString(STATE_ATTRIBUTE, EmptyCString());
|
|
return NS_OK;
|
|
}
|
|
|
|
RefPtr<Element> container =
|
|
aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
|
|
params->SetBool(STATE_MIXED, false);
|
|
params->SetCString(STATE_ATTRIBUTE,
|
|
container ? NS_LITERAL_CSTRING("absolute") :
|
|
EmptyCString());
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
AbsolutePositioningCommand::ToggleState(HTMLEditor* aHTMLEditor)
|
|
{
|
|
if (NS_WARN_IF(!aHTMLEditor)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
RefPtr<Element> container =
|
|
aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
|
|
return aHTMLEditor->SetSelectionToAbsoluteOrStatic(!container);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
*outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
|
|
if (!(*outCmdEnabled))
|
|
return NS_OK;
|
|
|
|
RefPtr<Element> positionedElement = htmlEditor->GetPositionedElement();
|
|
*outCmdEnabled = false;
|
|
if (!positionedElement) {
|
|
return NS_OK;
|
|
}
|
|
|
|
int32_t z = htmlEditor->GetZIndex(*positionedElement);
|
|
*outCmdEnabled = (z > 0);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseZIndexCommand::DoCommand(const char* aCommandName,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return htmlEditor->AddZIndex(-1);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseZIndexCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseZIndexCommand::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->AsCommandParams()->SetBool(STATE_ENABLED, enabled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
*outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
|
|
if (!(*outCmdEnabled))
|
|
return NS_OK;
|
|
|
|
Element* positionedElement = htmlEditor->GetPositionedElement();
|
|
*outCmdEnabled = (nullptr != positionedElement);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseZIndexCommand::DoCommand(const char* aCommandName,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return htmlEditor->AddZIndex(1);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseZIndexCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseZIndexCommand::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->AsCommandParams()->SetBool(STATE_ENABLED, enabled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
RemoveStylesCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
// test if we have any styles?
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
RemoveStylesCommand::DoCommand(const char* aCommandName,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (!htmlEditor) {
|
|
return NS_OK;
|
|
}
|
|
return htmlEditor->RemoveAllInlineProperties();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
RemoveStylesCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
RemoveStylesCommand::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
bool outCmdEnabled = false;
|
|
IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
|
|
return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
// test if we are at max size?
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseFontSizeCommand::DoCommand(const char* aCommandName,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (!htmlEditor) {
|
|
return NS_OK;
|
|
}
|
|
return htmlEditor->IncreaseFontSize();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseFontSizeCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IncreaseFontSizeCommand::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
bool outCmdEnabled = false;
|
|
IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
|
|
return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
// test if we are at min size?
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseFontSizeCommand::DoCommand(const char* aCommandName,
|
|
nsISupports* refCon)
|
|
{
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
return NS_OK;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (!htmlEditor) {
|
|
return NS_OK;
|
|
}
|
|
return htmlEditor->DecreaseFontSize();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseFontSizeCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
return DoCommand(aCommandName, refCon);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecreaseFontSizeCommand::GetCommandStateParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
bool outCmdEnabled = false;
|
|
IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
|
|
return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
InsertHTMLCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
InsertHTMLCommand::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<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
nsAutoString html;
|
|
return htmlEditor->InsertHTML(html);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
InsertHTMLCommand::DoCommandParams(const char* aCommandName,
|
|
nsICommandParams* aParams,
|
|
nsISupports* refCon)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aParams);
|
|
NS_ENSURE_ARG_POINTER(refCon);
|
|
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// Get HTML source string to insert from command params
|
|
nsAutoString html;
|
|
nsresult rv = aParams->AsCommandParams()->GetString(STATE_DATA, html);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return htmlEditor->InsertHTML(html);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
InsertHTMLCommand::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->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
InsertTagCommand::InsertTagCommand(nsAtom* aTagName)
|
|
: HTMLEditorCommandBase()
|
|
, mTagName(aTagName)
|
|
{
|
|
MOZ_ASSERT(mTagName);
|
|
}
|
|
|
|
InsertTagCommand::~InsertTagCommand()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
InsertTagCommand::IsCommandEnabled(const char* aCommandName,
|
|
nsISupports* refCon,
|
|
bool* outCmdEnabled)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (!editor) {
|
|
*outCmdEnabled = false;
|
|
return NS_OK;
|
|
}
|
|
mozilla::EditorBase* editorBase = editor->AsEditorBase();
|
|
MOZ_ASSERT(editorBase);
|
|
*outCmdEnabled = editorBase->IsSelectionEditable();
|
|
return NS_OK;
|
|
}
|
|
|
|
// corresponding STATE_ATTRIBUTE is: src (img) and href (a)
|
|
NS_IMETHODIMP
|
|
InsertTagCommand::DoCommand(const char* aCmdName, nsISupports* refCon)
|
|
{
|
|
NS_ENSURE_TRUE(mTagName == nsGkAtoms::hr, NS_ERROR_NOT_IMPLEMENTED);
|
|
|
|
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
RefPtr<Element> newElement =
|
|
htmlEditor->CreateElementWithDefaults(*mTagName);
|
|
if (NS_WARN_IF(!newElement)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
nsresult rv = htmlEditor->InsertElementAtSelection(newElement, true);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
InsertTagCommand::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<nsIEditor> editor = do_QueryInterface(refCon);
|
|
if (NS_WARN_IF(!editor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
|
|
if (NS_WARN_IF(!htmlEditor)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// do we have an href to use for creating link?
|
|
nsAutoCString asciiAttribute;
|
|
nsresult rv =
|
|
aParams->AsCommandParams()->GetCString(STATE_ATTRIBUTE, asciiAttribute);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
nsAutoString attribute;
|
|
CopyASCIItoUTF16(asciiAttribute, attribute);
|
|
|
|
if (attribute.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;
|
|
}
|
|
|
|
RefPtr<Element> newElement =
|
|
htmlEditor->CreateElementWithDefaults(*mTagName);
|
|
if (NS_WARN_IF(!newElement)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
ErrorResult err;
|
|
newElement->SetAttribute(attributeType, attribute, err);
|
|
if (NS_WARN_IF(err.Failed())) {
|
|
return err.StealNSResult();
|
|
}
|
|
|
|
// do actual insertion
|
|
if (mTagName == nsGkAtoms::a) {
|
|
rv = htmlEditor->InsertLinkAroundSelection(newElement);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
rv = htmlEditor->InsertElementAtSelection(newElement, true);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
InsertTagCommand::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->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
|
|
}
|
|
|
|
|
|
/****************************/
|
|
//HELPER METHODS
|
|
/****************************/
|
|
|
|
static nsresult
|
|
GetListState(HTMLEditor* aHTMLEditor, bool* aMixed, nsAString& aLocalName)
|
|
{
|
|
MOZ_ASSERT(aHTMLEditor);
|
|
MOZ_ASSERT(aMixed);
|
|
|
|
*aMixed = false;
|
|
aLocalName.Truncate();
|
|
|
|
bool bOL, bUL, bDL;
|
|
nsresult rv = aHTMLEditor->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;
|
|
}
|
|
|
|
} // namespace mozilla
|