Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/editor/libeditor/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 18 kB image not shown  

Quelle  HTMLEditorDocumentCommands.cpp   Sprache: 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 "EditorCommands.h"

#include "EditorBase.h"  // for EditorBase
#include "ErrorList.h"
#include "HTMLEditor.h"  // for HTMLEditor

#include "mozilla/BasePrincipal.h"  // for nsIPrincipal::IsSystemPrincipal()
#include "mozilla/dom/Element.h"    // for Element
#include "mozilla/dom/Document.h"   // for Document
#include "mozilla/dom/HTMLInputElement.h"     // for HTMLInputElement
#include "mozilla/dom/HTMLTextAreaElement.h"  // for HTMLTextAreaElement

#include "nsCommandParams.h"    // for nsCommandParams
#include "nsIEditingSession.h"  // for nsIEditingSession, etc
#include "nsIPrincipal.h"       // for nsIPrincipal
#include "nsISupportsImpl.h"    // for nsPresContext::Release
#include "nsISupportsUtils.h"   // for NS_IF_ADDREF
#include "nsIURI.h"             // for nsIURI
#include "nsPresContext.h"      // for nsPresContext

// defines
#define STATE_ENABLED "state_enabled"
#define STATE_ALL "state_all"
#define STATE_ATTRIBUTE "state_attribute"
#define STATE_DATA "state_data"

namespace mozilla {

using namespace dom;

/*****************************************************************************
 * mozilla::SetDocumentStateCommand
 *
 *  Commands for document state that may be changed via doCommandParams
 *  As of 11/11/02, this is just "cmd_setDocumentModified"
 *  Note that you can use the same command class, SetDocumentStateCommand,
 *    for more than one of this type of command
 *    We check the input command param for different behavior
 *****************************************************************************/


StaticRefPtr<SetDocumentStateCommand> SetDocumentStateCommand::sInstance;

bool SetDocumentStateCommand::IsCommandEnabled(Command aCommand,
                                               EditorBase* aEditorBase) const {
  switch (aCommand) {
    case Command::SetDocumentReadOnly:
      return !!aEditorBase;
    default:
      // The other commands are always enabled if given editor is an HTMLEditor.
      return aEditorBase && aEditorBase->IsHTMLEditor();
  }
}

nsresult SetDocumentStateCommand::DoCommand(Command aCommand,
                                            EditorBase& aEditorBase,
                                            nsIPrincipal* aPrincipal) const {
  return NS_ERROR_NOT_IMPLEMENTED;
}

nsresult SetDocumentStateCommand::DoCommandParam(
    Command aCommand, const Maybe<bool>& aBoolParam, EditorBase& aEditorBase,
    nsIPrincipal* aPrincipal) const {
  if (NS_WARN_IF(aBoolParam.isNothing())) {
    return NS_ERROR_INVALID_ARG;
  }

  if (aCommand != Command::SetDocumentReadOnly &&
      NS_WARN_IF(!aEditorBase.IsHTMLEditor())) {
    return NS_ERROR_FAILURE;
  }

  switch (aCommand) {
    case Command::SetDocumentModified: {
      if (aBoolParam.value()) {
        nsresult rv = aEditorBase.IncrementModificationCount(1);
        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                             "EditorBase::IncrementModificationCount() failed");
        return rv;
      }
      nsresult rv = aEditorBase.ResetModificationCount();
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "EditorBase::ResetModificationCount() failed");
      return rv;
    }
    case Command::SetDocumentReadOnly: {
      if (aEditorBase.IsTextEditor()) {
        Element* inputOrTextArea = aEditorBase.GetExposedRoot();
        if (NS_WARN_IF(!inputOrTextArea)) {
          return NS_ERROR_FAILURE;
        }
        // Perhaps, this legacy command shouldn't work with
        // `<input type="file">` and `<input type="number">.
        if (inputOrTextArea->IsInNativeAnonymousSubtree()) {
          return NS_ERROR_FAILURE;
        }
        if (RefPtr<HTMLInputElement> inputElement =
                HTMLInputElement::FromNode(inputOrTextArea)) {
          if (inputElement->ReadOnly() == aBoolParam.value()) {
            return NS_SUCCESS_DOM_NO_OPERATION;
          }
          ErrorResult error;
          inputElement->SetReadOnly(aBoolParam.value(), error);
          return error.StealNSResult();
        }
        if (RefPtr<HTMLTextAreaElement> textAreaElement =
                HTMLTextAreaElement::FromNode(inputOrTextArea)) {
          if (textAreaElement->ReadOnly() == aBoolParam.value()) {
            return NS_SUCCESS_DOM_NO_OPERATION;
          }
          ErrorResult error;
          textAreaElement->SetReadOnly(aBoolParam.value(), error);
          return error.StealNSResult();
        }
        NS_ASSERTION(
            false,
            "Unexpected exposed root element, fallthrough to directly make the "
            "editor readonly");
      }
      ErrorResult error;
      if (aBoolParam.value()) {
        nsresult rv = aEditorBase.AddFlags(nsIEditor::eEditorReadonlyMask);
        NS_WARNING_ASSERTION(
            NS_SUCCEEDED(rv),
            "EditorBase::AddFlags(nsIEditor::eEditorReadonlyMask) failed");
        return rv;
      }
      nsresult rv = aEditorBase.RemoveFlags(nsIEditor::eEditorReadonlyMask);
      NS_WARNING_ASSERTION(
          NS_SUCCEEDED(rv),
          "EditorBase::RemoveFlags(nsIEditor::eEditorReadonlyMask) failed");
      return rv;
    }
    case Command::SetDocumentUseCSS: {
      nsresult rv = MOZ_KnownLive(aEditorBase.AsHTMLEditor())
                        ->SetIsCSSEnabled(aBoolParam.value());
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "HTMLEditor::SetIsCSSEnabled() failed");
      return rv;
    }
    case Command::SetDocumentInsertBROnEnterKeyPress: {
      nsresult rv =
          aEditorBase.AsHTMLEditor()->SetReturnInParagraphCreatesNewParagraph(
              !aBoolParam.value());
      NS_WARNING_ASSERTION(
          NS_SUCCEEDED(rv),
          "HTMLEditor::SetReturnInParagraphCreatesNewParagraph() failed");
      return rv;
    }
    case Command::ToggleObjectResizers: {
      MOZ_KnownLive(aEditorBase.AsHTMLEditor())
          ->EnableObjectResizer(aBoolParam.value());
      return NS_OK;
    }
    case Command::ToggleInlineTableEditor: {
      MOZ_KnownLive(aEditorBase.AsHTMLEditor())
          ->EnableInlineTableEditor(aBoolParam.value());
      return NS_OK;
    }
    case Command::ToggleAbsolutePositionEditor: {
      MOZ_KnownLive(aEditorBase.AsHTMLEditor())
          ->EnableAbsolutePositionEditor(aBoolParam.value());
      return NS_OK;
    }
    case Command::EnableCompatibleJoinSplitNodeDirection:
      // Now we don't support the legacy join/split node direction anymore, but
      // this result may be used for the feature detection whether Gecko
      // supports the new direction mode.  Therefore, even though we do nothing,
      // but we should return NS_OK to return `true` from
      // `Document.execCommand()`.
      return NS_OK;
    default:
      return NS_ERROR_NOT_IMPLEMENTED;
  }
}

nsresult SetDocumentStateCommand::DoCommandParam(
    Command aCommand, const nsACString& aCStringParam, EditorBase& aEditorBase,
    nsIPrincipal* aPrincipal) const {
  if (NS_WARN_IF(aCStringParam.IsVoid())) {
    return NS_ERROR_INVALID_ARG;
  }

  if (NS_WARN_IF(!aEditorBase.IsHTMLEditor())) {
    return NS_ERROR_FAILURE;
  }

  switch (aCommand) {
    case Command::SetDocumentDefaultParagraphSeparator: {
      if (aCStringParam.LowerCaseEqualsLiteral("div")) {
        aEditorBase.AsHTMLEditor()->SetDefaultParagraphSeparator(
            ParagraphSeparator::div);
        return NS_OK;
      }
      if (aCStringParam.LowerCaseEqualsLiteral("p")) {
        aEditorBase.AsHTMLEditor()->SetDefaultParagraphSeparator(
            ParagraphSeparator::p);
        return NS_OK;
      }
      if (aCStringParam.LowerCaseEqualsLiteral("br")) {
        // Mozilla extension for backwards compatibility
        aEditorBase.AsHTMLEditor()->SetDefaultParagraphSeparator(
            ParagraphSeparator::br);
        return NS_OK;
      }

      // This should not be reachable from nsHTMLDocument::ExecCommand
      // XXX Shouldn't return error in this case because Chrome does not throw
      //     exception in this case.
      NS_WARNING("Invalid default paragraph separator");
      return NS_ERROR_UNEXPECTED;
    }
    default:
      return NS_ERROR_NOT_IMPLEMENTED;
  }
}

nsresult SetDocumentStateCommand::GetCommandStateParams(
    Command aCommand, nsCommandParams& aParams, EditorBase* aEditorBase,
    nsIEditingSession* aEditingSession) const {
  // If the result is set to STATE_ATTRIBUTE as CString value,
  // queryCommandValue() returns the string value.
  // Otherwise, ignored.

  // The base editor owns most state info
  if (NS_WARN_IF(!aEditorBase)) {
    return NS_ERROR_INVALID_ARG;
  }

  if (NS_WARN_IF(!aEditorBase->IsHTMLEditor())) {
    return NS_ERROR_FAILURE;
  }

  // Always get the enabled state
  nsresult rv =
      aParams.SetBool(STATE_ENABLED, IsCommandEnabled(aCommand, aEditorBase));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  switch (aCommand) {
    case Command::SetDocumentModified: {
      bool modified;
      rv = aEditorBase->GetDocumentModified(&modified);
      if (NS_FAILED(rv)) {
        NS_WARNING("EditorBase::GetDocumentModified() failed");
        return rv;
      }
      // XXX Nobody refers this result due to wrong type.
      rv = aParams.SetBool(STATE_ATTRIBUTE, modified);
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "nsCommandParams::SetBool(STATE_ATTRIBUTE) failed");
      return rv;
    }
    case Command::SetDocumentReadOnly: {
      // XXX Nobody refers this result due to wrong type.
      rv = aParams.SetBool(STATE_ATTRIBUTE, aEditorBase->IsReadonly());
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "nsCommandParams::SetBool(STATE_ATTRIBUTE) failed");
      return rv;
    }
    case Command::SetDocumentUseCSS: {
      HTMLEditor* htmlEditor = aEditorBase->GetAsHTMLEditor();
      if (NS_WARN_IF(!htmlEditor)) {
        return NS_ERROR_INVALID_ARG;
      }
      rv = aParams.SetBool(STATE_ALL, htmlEditor->IsCSSEnabled());
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "nsCommandParams::SetBool(STATE_ALL) failed");
      return rv;
    }
    case Command::SetDocumentInsertBROnEnterKeyPress: {
      HTMLEditor* htmlEditor = aEditorBase->GetAsHTMLEditor();
      if (NS_WARN_IF(!htmlEditor)) {
        return NS_ERROR_INVALID_ARG;
      }
      bool createPOnReturn;
      DebugOnly<nsresult> rvIgnored =
          htmlEditor->GetReturnInParagraphCreatesNewParagraph(&createPOnReturn);
      NS_WARNING_ASSERTION(
          NS_SUCCEEDED(rvIgnored),
          "HTMLEditor::GetReturnInParagraphCreatesNewParagraph() failed");
      // XXX Nobody refers this result due to wrong type.
      rv = aParams.SetBool(STATE_ATTRIBUTE, !createPOnReturn);
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "nsCommandParams::SetBool(STATE_ATTRIBUTE) failed");
      return rv;
    }
    case Command::SetDocumentDefaultParagraphSeparator: {
      HTMLEditor* htmlEditor = aEditorBase->GetAsHTMLEditor();
      if (NS_WARN_IF(!htmlEditor)) {
        return NS_ERROR_INVALID_ARG;
      }

      switch (htmlEditor->GetDefaultParagraphSeparator()) {
        case ParagraphSeparator::div: {
          DebugOnly<nsresult> rv =
              aParams.SetCString(STATE_ATTRIBUTE, "div"_ns);
          NS_WARNING_ASSERTION(
              NS_SUCCEEDED(rv),
              "Failed to set command params to return \"div\"");
          return NS_OK;
        }
        case ParagraphSeparator::p: {
          DebugOnly<nsresult> rv = aParams.SetCString(STATE_ATTRIBUTE, "p"_ns);
          NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                               "Failed to set command params to return \"p\"");
          return NS_OK;
        }
        case ParagraphSeparator::br: {
          DebugOnly<nsresult> rv = aParams.SetCString(STATE_ATTRIBUTE, "br"_ns);
          NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                               "Failed to set command params to return \"br\"");
          return NS_OK;
        }
        default:
          MOZ_ASSERT_UNREACHABLE("Invalid paragraph separator value");
          return NS_ERROR_UNEXPECTED;
      }
    }
    case Command::ToggleObjectResizers: {
      HTMLEditor* htmlEditor = aEditorBase->GetAsHTMLEditor();
      if (NS_WARN_IF(!htmlEditor)) {
        return NS_ERROR_INVALID_ARG;
      }
      // We returned the result as STATE_ATTRIBUTE with bool value 60 or
      // earlier. So, the result was ignored by both
      // nsHTMLDocument::QueryCommandValue() and
      // nsHTMLDocument::QueryCommandState().
      rv = aParams.SetBool(STATE_ALL, htmlEditor->IsObjectResizerEnabled());
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "nsCommandParams::SetBool(STATE_ALL) failed");
      return rv;
    }
    case Command::ToggleInlineTableEditor: {
      HTMLEditor* htmlEditor = aEditorBase->GetAsHTMLEditor();
      if (NS_WARN_IF(!htmlEditor)) {
        return NS_ERROR_INVALID_ARG;
      }
      // We returned the result as STATE_ATTRIBUTE with bool value 60 or
      // earlier. So, the result was ignored by both
      // nsHTMLDocument::QueryCommandValue() and
      // nsHTMLDocument::QueryCommandState().
      rv = aParams.SetBool(STATE_ALL, htmlEditor->IsInlineTableEditorEnabled());
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "nsCommandParams::SetBool(STATE_ALL) failed");
      return rv;
    }
    case Command::ToggleAbsolutePositionEditor: {
      HTMLEditor* htmlEditor = aEditorBase->GetAsHTMLEditor();
      if (NS_WARN_IF(!htmlEditor)) {
        return NS_ERROR_INVALID_ARG;
      }
      return aParams.SetBool(STATE_ALL,
                             htmlEditor->IsAbsolutePositionEditorEnabled());
    }
    case Command::EnableCompatibleJoinSplitNodeDirection: {
      HTMLEditor* htmlEditor = aEditorBase->GetAsHTMLEditor();
      if (NS_WARN_IF(!htmlEditor)) {
        return NS_ERROR_INVALID_ARG;
      }
      // Now we don't support the legacy join/split node direction anymore, but
      // this result may be used for the feature detection whether Gecko
      // supports the new direction mode.  Therefore, we should return `true`
      // even though executing the command does nothing.
      return aParams.SetBool(STATE_ALL, true);
    }
    default:
      return NS_ERROR_NOT_IMPLEMENTED;
  }
}

/*****************************************************************************
 * mozilla::DocumentStateCommand
 *
 * Commands just for state notification
 *  As of 11/21/02, possible commands are:
 *    "obs_documentCreated"
 *    "obs_documentWillBeDestroyed"
 *    "obs_documentLocationChanged"
 *  Note that you can use the same command class, DocumentStateCommand
 *    for these or future observer commands.
 *    We check the input command param for different behavior
 *
 *  How to use:
 *  1. Get the nsCommandManager for the current editor
 *  2. Implement an nsIObserve object, e.g:
 *
 *    void Observe(
 *        in nsISupports aSubject, // The nsCommandManager calling this
 *                                 // Observer
 *        in string      aTopic,   // command name, e.g.:"obs_documentCreated"
 *                                 //    or "obs_documentWillBeDestroyed"
          in wstring     aData );  // ignored (set to "command_status_changed")
 *
 *  3. Add the observer by:
 *       commandManager.addObserver(observeobject, obs_documentCreated);
 *  4. In the appropriate location in editorSession, editor, or commands code,
 *     trigger the notification of this observer by something like:
 *
 *  RefPtr<nsCommandManager> commandManager = mDocShell->GetCommandManager();
 *  commandManager->CommandStatusChanged(obs_documentCreated);
 *
 *  5. Use GetCommandStateParams() to obtain state information
 *     e.g., any creation state codes when creating an editor are
 *     supplied for "obs_documentCreated" command in the
 *     "state_data" param's value
 *****************************************************************************/


StaticRefPtr<DocumentStateCommand> DocumentStateCommand::sInstance;

bool DocumentStateCommand::IsCommandEnabled(Command aCommand,
                                            EditorBase* aEditorBase) const {
  // Always return false to discourage callers from using DoCommand()
  return false;
}

nsresult DocumentStateCommand::DoCommand(Command aCommand,
                                         EditorBase& aEditorBase,
                                         nsIPrincipal* aPrincipal) const {
  return NS_ERROR_NOT_IMPLEMENTED;
}

nsresult DocumentStateCommand::GetCommandStateParams(
    Command aCommand, nsCommandParams& aParams, EditorBase* aEditorBase,
    nsIEditingSession* aEditingSession) const {
  switch (aCommand) {
    case Command::EditorObserverDocumentCreated: {
      uint32_t editorStatus = nsIEditingSession::eEditorErrorUnknown;
      if (aEditingSession) {
        // Current context is initially set to nsIEditingSession until editor is
        // successfully created and source doc is loaded.  Embedder gets error
        // status if this fails.  If called before startup is finished,
        // status will be eEditorCreationInProgress.
        nsresult rv = aEditingSession->GetEditorStatus(&editorStatus);
        if (NS_FAILED(rv)) {
          NS_WARNING("nsIEditingSession::GetEditorStatus() failed");
          return rv;
        }
      } else if (aEditorBase) {
        // If current context is an editor, then everything started up OK!
        editorStatus = nsIEditingSession::eEditorOK;
      }

      // Note that if refCon is not-null, but is neither
      // an nsIEditingSession or nsIEditor, we return "eEditorErrorUnknown"
      DebugOnly<nsresult> rvIgnored = aParams.SetInt(STATE_DATA, editorStatus);
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
                           "Failed to set editor status");
      return NS_OK;
    }
    case Command::EditorObserverDocumentLocationChanged: {
      if (!aEditorBase) {
        return NS_OK;
      }
      Document* document = aEditorBase->GetDocument();
      if (NS_WARN_IF(!document)) {
        return NS_ERROR_FAILURE;
      }
      nsIURI* uri = document->GetDocumentURI();
      if (NS_WARN_IF(!uri)) {
        return NS_ERROR_FAILURE;
      }
      nsresult rv = aParams.SetISupports(STATE_DATA, uri);
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                           "nsCOmmandParms::SetISupports(STATE_DATA) failed");
      return rv;
    }
    default:
      return NS_ERROR_NOT_IMPLEMENTED;
  }
}

}  // namespace mozilla

100%


¤ Dauer der Verarbeitung: 0.34 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.