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 15 kB image not shown  

Quelle  EditorUtils.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 "EditorUtils.h"

#include "EditorDOMPoint.h"   // for EditorDOMPoint, EditorDOMRange, etc
#include "HTMLEditHelpers.h"  // for MoveNodeResult
#include "HTMLEditUtils.h"    // for HTMLEditUtils
#include "TextEditor.h"       // for TextEditor

#include "mozilla/ComputedStyle.h"  // for ComputedStyle
#include "mozilla/IntegerRange.h"   // for IntegerRange
#include "mozilla/dom/Document.h"   // for dom::Document
#include "mozilla/dom/Selection.h"  // for dom::Selection
#include "mozilla/dom/Text.h"       // for dom::Text

#include "nsComponentManagerUtils.h"  // for do_CreateInstance
#include "nsContentUtils.h"           // for nsContentUtils
#include "nsComputedDOMStyle.h"       // for nsComputedDOMStyle
#include "nsError.h"                  // for NS_SUCCESS_* and NS_ERROR_*
#include "nsFrameSelection.h"         // for nsFrameSelection
#include "nsIContent.h"               // for nsIContent
#include "nsINode.h"                  // for nsINode
#include "nsITransferable.h"          // for nsITransferable
#include "nsRange.h"                  // for nsRange
#include "nsStyleConsts.h"            // for StyleWhiteSpace
#include "nsStyleStruct.h"            // for nsStyleText, etc

namespace mozilla {

using namespace dom;

/******************************************************************************
 * some general purpose editor utils
 *****************************************************************************/


bool EditorUtils::IsDescendantOf(const nsINode& aNode, const nsINode& aParent,
                                 EditorRawDOMPoint* aOutPoint /* = nullptr */) {
  if (aOutPoint) {
    aOutPoint->Clear();
  }

  if (&aNode == &aParent) {
    return false;
  }

  for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
    if (node->GetParentNode() == &aParent) {
      if (aOutPoint) {
        MOZ_ASSERT(node->IsContent());
        aOutPoint->Set(node->AsContent());
      }
      return true;
    }
  }

  return false;
}

bool EditorUtils::IsDescendantOf(const nsINode& aNode, const nsINode& aParent,
                                 EditorDOMPoint* aOutPoint) {
  MOZ_ASSERT(aOutPoint);
  aOutPoint->Clear();
  if (&aNode == &aParent) {
    return false;
  }

  for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
    if (node->GetParentNode() == &aParent) {
      MOZ_ASSERT(node->IsContent());
      aOutPoint->Set(node->AsContent());
      return true;
    }
  }

  return false;
}

// static
Maybe<std::pair<StyleWhiteSpaceCollapse, StyleTextWrapMode>>
EditorUtils::GetComputedWhiteSpaceStyles(const nsIContent& aContent) {
  if (MOZ_UNLIKELY(!aContent.IsElement() && !aContent.GetParentElement())) {
    return Nothing();
  }
  RefPtr<const ComputedStyle> elementStyle =
      nsComputedDOMStyle::GetComputedStyleNoFlush(
          aContent.IsElement() ? aContent.AsElement()
                               : aContent.GetParentElement());
  if (NS_WARN_IF(!elementStyle)) {
    return Nothing();
  }
  const auto* styleText = elementStyle->StyleText();
  return Some(
      std::pair(styleText->mWhiteSpaceCollapse, styleText->mTextWrapMode));
}

// static
bool EditorUtils::IsWhiteSpacePreformatted(const nsIContent& aContent) {
  // Look at the node (and its parent if it's not an element), and grab its
  // ComputedStyle.
  Element* element = aContent.GetAsElementOrParentElement();
  if (!element) {
    return false;
  }

  RefPtr<const ComputedStyle> elementStyle =
      nsComputedDOMStyle::GetComputedStyleNoFlush(element);
  if (!elementStyle) {
    // Consider nodes without a ComputedStyle to be NOT preformatted:
    // For instance, this is true of JS tags inside the body (which show
    // up as #text nodes but have no ComputedStyle).
    return false;
  }

  return elementStyle->StyleText()->WhiteSpaceIsSignificant();
}

// static
bool EditorUtils::IsNewLinePreformatted(const nsIContent& aContent) {
  // Look at the node (and its parent if it's not an element), and grab its
  // ComputedStyle.
  Element* element = aContent.GetAsElementOrParentElement();
  if (!element) {
    return false;
  }

  RefPtr<const ComputedStyle> elementStyle =
      nsComputedDOMStyle::GetComputedStyleNoFlush(element);
  if (!elementStyle) {
    // Consider nodes without a ComputedStyle to be NOT preformatted:
    // For instance, this is true of JS tags inside the body (which show
    // up as #text nodes but have no ComputedStyle).
    return false;
  }

  return elementStyle->StyleText()->NewlineIsSignificantStyle();
}

// static
bool EditorUtils::IsOnlyNewLinePreformatted(const nsIContent& aContent) {
  // Look at the node (and its parent if it's not an element), and grab its
  // ComputedStyle.
  Element* element = aContent.GetAsElementOrParentElement();
  if (!element) {
    return false;
  }

  RefPtr<const ComputedStyle> elementStyle =
      nsComputedDOMStyle::GetComputedStyleNoFlush(element);
  if (!elementStyle) {
    // Consider nodes without a ComputedStyle to be NOT preformatted:
    // For instance, this is true of JS tags inside the body (which show
    // up as #text nodes but have no ComputedStyle).
    return false;
  }

  return elementStyle->StyleText()->mWhiteSpaceCollapse ==
         StyleWhiteSpaceCollapse::PreserveBreaks;
}

// static
Result<nsCOMPtr<nsITransferable>, nsresult>
EditorUtils::CreateTransferableForPlainText(const Document& aDocument) {
  // Create generic Transferable for getting the data
  nsresult rv;
  nsCOMPtr<nsITransferable> transferable =
      do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
  if (NS_FAILED(rv)) {
    NS_WARNING("do_CreateInstance() failed to create nsITransferable instance");
    return Err(rv);
  }

  if (!transferable) {
    NS_WARNING("do_CreateInstance() returned nullptr, but ignored");
    return nsCOMPtr<nsITransferable>();
  }

  DebugOnly<nsresult> rvIgnored =
      transferable->Init(aDocument.GetLoadContext());
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
                       "nsITransferable::Init() failed, but ignored");

  rvIgnored = transferable->AddDataFlavor(kTextMime);
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rvIgnored),
      "nsITransferable::AddDataFlavor(kTextMime) failed, but ignored");
  rvIgnored = transferable->AddDataFlavor(kMozTextInternal);
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rvIgnored),
      "nsITransferable::AddDataFlavor(kMozTextInternal) failed, but ignored");
  return transferable;
}

/******************************************************************************
 * mozilla::EditorDOMPointBase
 *****************************************************************************/


NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool, IsCharCollapsibleASCIISpace);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsCharCollapsibleASCIISpace() const {
  if (IsCharNewLine()) {
    return !EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
  }
  return IsCharASCIISpace() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool, IsCharCollapsibleNBSP);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsCharCollapsibleNBSP() const {
  // TODO: Perhaps, we should return false if neither previous char nor
  //       next char is collapsible white-space or NBSP.
  return IsCharNBSP() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool,
                                             IsCharCollapsibleASCIISpaceOrNBSP);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsCharCollapsibleASCIISpaceOrNBSP() const {
  if (IsCharNewLine()) {
    return !EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
  }
  return IsCharASCIISpaceOrNBSP() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(
    bool, IsPreviousCharCollapsibleASCIISpace);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsPreviousCharCollapsibleASCIISpace() const {
  if (IsPreviousCharNewLine()) {
    return !EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
  }
  return IsPreviousCharASCIISpace() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool,
                                             IsPreviousCharCollapsibleNBSP);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsPreviousCharCollapsibleNBSP() const {
  return IsPreviousCharNBSP() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(
    bool, IsPreviousCharCollapsibleASCIISpaceOrNBSP);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsPreviousCharCollapsibleASCIISpaceOrNBSP()
    const {
  if (IsPreviousCharNewLine()) {
    return !EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
  }
  return IsPreviousCharASCIISpaceOrNBSP() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool,
                                             IsNextCharCollapsibleASCIISpace);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsNextCharCollapsibleASCIISpace() const {
  if (IsNextCharNewLine()) {
    return !EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
  }
  return IsNextCharASCIISpace() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool, IsNextCharCollapsibleNBSP);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsNextCharCollapsibleNBSP() const {
  return IsNextCharNBSP() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(
    bool, IsNextCharCollapsibleASCIISpaceOrNBSP);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsNextCharCollapsibleASCIISpaceOrNBSP() const {
  if (IsNextCharNewLine()) {
    return !EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
  }
  return IsNextCharASCIISpaceOrNBSP() &&
         !EditorUtils::IsWhiteSpacePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool, IsCharPreformattedNewLine);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsCharPreformattedNewLine() const {
  return IsCharNewLine() &&
         EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(
    bool, IsCharPreformattedNewLineCollapsedWithWhiteSpaces);

template <typename PT, typename CT>
bool EditorDOMPointBase<
    PT, CT>::IsCharPreformattedNewLineCollapsedWithWhiteSpaces() const {
  return IsCharNewLine() &&
         EditorUtils::IsOnlyNewLinePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool,
                                             IsPreviousCharPreformattedNewLine);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsPreviousCharPreformattedNewLine() const {
  return IsPreviousCharNewLine() &&
         EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(
    bool, IsPreviousCharPreformattedNewLineCollapsedWithWhiteSpaces);

template <typename PT, typename CT>
bool EditorDOMPointBase<
    PT, CT>::IsPreviousCharPreformattedNewLineCollapsedWithWhiteSpaces() const {
  return IsPreviousCharNewLine() &&
         EditorUtils::IsOnlyNewLinePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(bool,
                                             IsNextCharPreformattedNewLine);

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsNextCharPreformattedNewLine() const {
  return IsNextCharNewLine() &&
         EditorUtils::IsNewLinePreformatted(*ContainerAs<Text>());
}

NS_INSTANTIATE_EDITOR_DOM_POINT_CONST_METHOD(
    bool, IsNextCharPreformattedNewLineCollapsedWithWhiteSpaces);

template <typename PT, typename CT>
bool EditorDOMPointBase<
    PT, CT>::IsNextCharPreformattedNewLineCollapsedWithWhiteSpaces() const {
  return IsNextCharNewLine() &&
         EditorUtils::IsOnlyNewLinePreformatted(*ContainerAs<Text>());
}

template <typename PT, typename CT>
bool EditorDOMPointBase<PT, CT>::IsContainerEditableRoot() const {
  if (MOZ_UNLIKELY(!mParent) || MOZ_UNLIKELY(!mParent->IsEditable()) ||
      NS_WARN_IF(mParent->IsInNativeAnonymousSubtree())) {
    return false;
  }
  return HTMLEditUtils::ElementIsEditableRoot(*mParent);
}

/******************************************************************************
 * mozilla::EditorDOMRangeBase
 *****************************************************************************/


NS_INSTANTIATE_EDITOR_DOM_RANGE_CONST_METHOD(nsINode*,
                                             GetClosestCommonInclusiveAncestor);

template <typename EditorDOMPointType>
nsINode* EditorDOMRangeBase<
    EditorDOMPointType>::GetClosestCommonInclusiveAncestor() const {
  if (NS_WARN_IF(!IsPositioned())) {
    return nullptr;
  }
  return nsContentUtils::GetClosestCommonInclusiveAncestor(
      mStart.GetContainer(), mEnd.GetContainer());
}

/******************************************************************************
 * mozilla::CaretPoint
 *****************************************************************************/


nsresult CaretPoint::SuggestCaretPointTo(
    EditorBase& aEditorBase, const SuggestCaretOptions& aOptions) const {
  mHandledCaretPoint = true;
  if (!mCaretPoint.IsSet()) {
    if (aOptions.contains(SuggestCaret::OnlyIfHasSuggestion)) {
      return NS_OK;
    }
    NS_WARNING("There was no suggestion to put caret");
    return NS_ERROR_FAILURE;
  }
  if (aOptions.contains(SuggestCaret::OnlyIfTransactionsAllowedToDoIt) &&
      !aEditorBase.AllowsTransactionsToChangeSelection()) {
    return NS_OK;
  }
  nsresult rv = aEditorBase.CollapseSelectionTo(mCaretPoint);
  if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
    NS_WARNING(
        "EditorBase::CollapseSelectionTo() caused destroying the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  return aOptions.contains(SuggestCaret::AndIgnoreTrivialError) && NS_FAILED(rv)
             ? NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR
             : rv;
}

bool CaretPoint::CopyCaretPointTo(EditorDOMPoint& aPointToPutCaret,
                                  const EditorBase& aEditorBase,
                                  const SuggestCaretOptions& aOptions) const {
  MOZ_ASSERT(!aOptions.contains(SuggestCaret::AndIgnoreTrivialError));
  mHandledCaretPoint = true;
  if (aOptions.contains(SuggestCaret::OnlyIfHasSuggestion) &&
      !mCaretPoint.IsSet()) {
    return false;
  }
  if (aOptions.contains(SuggestCaret::OnlyIfTransactionsAllowedToDoIt) &&
      !aEditorBase.AllowsTransactionsToChangeSelection()) {
    return false;
  }
  aPointToPutCaret = mCaretPoint;
  return true;
}

bool CaretPoint::MoveCaretPointTo(EditorDOMPoint& aPointToPutCaret,
                                  const EditorBase& aEditorBase,
                                  const SuggestCaretOptions& aOptions) {
  MOZ_ASSERT(!aOptions.contains(SuggestCaret::AndIgnoreTrivialError));
  mHandledCaretPoint = true;
  if (aOptions.contains(SuggestCaret::OnlyIfHasSuggestion) &&
      !mCaretPoint.IsSet()) {
    return false;
  }
  if (aOptions.contains(SuggestCaret::OnlyIfTransactionsAllowedToDoIt) &&
      !aEditorBase.AllowsTransactionsToChangeSelection()) {
    return false;
  }
  aPointToPutCaret = UnwrapCaretPoint();
  return true;
}

}  // namespace mozilla

99%


¤ Dauer der Verarbeitung: 0.17 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.