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

Quelle  mozInlineSpellWordUtil.h   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; 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/. */


#ifndef mozInlineSpellWordUtil_h
#define mozInlineSpellWordUtil_h

#include <utility>

#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/RangeBoundary.h"
#include "mozilla/Result.h"
#include "mozilla/dom/Document.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"

// #define DEBUG_SPELLCHECK

class nsRange;
class nsINode;

namespace mozilla {
class EditorBase;

namespace dom {
class Document;
}
}  // namespace mozilla

struct NodeOffset {
  nsCOMPtr<nsINode> mNode;
  int32_t mOffset;

  NodeOffset() : mOffset(0) {}
  NodeOffset(nsINode* aNode, int32_t aOffset)
      : mNode(aNode), mOffset(aOffset) {}

  bool operator==(const NodeOffset& aOther) const {
    return mNode == aOther.mNode && mOffset == aOther.mOffset;
  }

  bool operator==(const mozilla::RangeBoundary& aRangeBoundary) const;

  bool operator!=(const NodeOffset& aOther) const { return !(*this == aOther); }

  nsINode* Node() const { return mNode.get(); }
  int32_t Offset() const { return mOffset; }
};

class NodeOffsetRange {
 private:
  NodeOffset mBegin;
  NodeOffset mEnd;

 public:
  NodeOffsetRange() {}
  NodeOffsetRange(NodeOffset b, NodeOffset e)
      : mBegin(std::move(b)), mEnd(std::move(e)) {}

  bool operator==(const nsRange& aRange) const;

  const NodeOffset& Begin() const { return mBegin; }

  const NodeOffset& End() const { return mEnd; }
};

/**
 *    This class extracts text from the DOM and builds it into a single string.
 *    The string includes whitespace breaks whereever non-inline elements begin
 *    and end. This string is broken into "real words", following somewhat
 *    complex rules; for example substrings that look like URLs or
 *    email addresses are treated as single words, but otherwise many kinds of
 *    punctuation are treated as word separators. GetNextWord provides a way
 *    to iterate over these "real words".
 *
 *    The basic operation is:
 *
 *    1. Call Init with the editor that you're using.
 *    2. Call SetPositionAndEnd to to initialize the current position inside the
 *       previously given range and set where you want to stop spellchecking.
 *       We'll stop at the word boundary after that. If SetEnd is not called,
 *       we'll stop at the end of the root element.
 *    3. Call GetNextWord over and over until it returns false.
 */


class MOZ_STACK_CLASS mozInlineSpellWordUtil {
 public:
  static mozilla::Maybe<mozInlineSpellWordUtil> Create(
      const mozilla::EditorBase& aEditorBase);

  // sets the current position, this should be inside the range. If we are in
  // the middle of a word, we'll move to its start.
  nsresult SetPositionAndEnd(nsINode* aPositionNode, int32_t aPositionOffset,
                             nsINode* aEndNode, int32_t aEndOffset);

  // Given a point inside or immediately following a word, this returns the
  // DOM range that exactly encloses that word's characters. The current
  // position will be at the end of the word. This will find the previous
  // word if the current position is space, so if you care that the point is
  // inside the word, you should check the range.
  //
  // THIS CHANGES THE CURRENT POSITION AND RANGE. It is designed to be called
  // before you actually generate the range you are interested in and iterate
  // the words in it.
  nsresult GetRangeForWord(nsINode* aWordNode, int32_t aWordOffset,
                           nsRange** aRange);

  // Convenience functions, object must be initialized
  nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd,
                     nsRange** aRange) const;
  static already_AddRefed<nsRange> MakeRange(const NodeOffsetRange& aRange);

  struct Word {
    nsAutoString mText;
    NodeOffsetRange mNodeOffsetRange;
    bool mSkipChecking = false;
  };

  // Moves to the the next word in the range, and retrieves it's text and range.
  // `false` is returned when we are done checking.
  // mSkipChecking will be set if the word is "special" and shouldn't be
  // checked (e.g., an email address).
  bool GetNextWord(Word& aWord);

  // Call to normalize some punctuation. This function takes an autostring
  // so we can access characters directly.
  static void NormalizeWord(nsAString& aWord);

  mozilla::dom::Document* GetDocument() const { return mDocument; }
  const nsINode* GetRootNode() const { return mRootNode; }

 private:
  // A list of where we extracted text from, ordered by mSoftTextOffset. A given
  // DOM node appears at most once in this list.
  struct DOMTextMapping {
    NodeOffset mNodeOffset;
    int32_t mSoftTextOffset;
    int32_t mLength;

    DOMTextMapping(NodeOffset aNodeOffset, int32_t aSoftTextOffset,
                   int32_t aLength)
        : mNodeOffset(std::move(aNodeOffset)),
          mSoftTextOffset(aSoftTextOffset),
          mLength(aLength) {}
  };

  struct SoftText {
    void AdjustBeginAndBuildText(NodeOffset aBegin, NodeOffset aEnd,
                                 const nsINode* aRootNode);

    void Invalidate() { mIsValid = false; }

    const NodeOffset& GetBegin() const { return mBegin; }
    const NodeOffset& GetEnd() const { return mEnd; }

    const nsTArray<DOMTextMapping>& GetDOMMapping() const {
      return mDOMMapping;
    }

    const nsString& GetValue() const { return mValue; }

    bool mIsValid = false;

   private:
    NodeOffset mBegin = NodeOffset(nullptr, 0);
    NodeOffset mEnd = NodeOffset(nullptr, 0);

    nsTArray<DOMTextMapping> mDOMMapping;

    // DOM text covering the soft range, with newlines added at block boundaries
    nsString mValue;
  };

  SoftText mSoftText;

  mozInlineSpellWordUtil(mozilla::dom::Document& aDocument,
                         bool aIsContentEditableOrDesignMode, nsINode& aRootNode

                         )
      : mDocument(&aDocument),
        mIsContentEditableOrDesignMode(aIsContentEditableOrDesignMode),
        mRootNode(&aRootNode),
        mNextWordIndex(-1) {}

  // cached stuff for the editor
  const RefPtr<mozilla::dom::Document> mDocument;
  const bool mIsContentEditableOrDesignMode;

  // range to check, see SetPosition and SetEnd
  const nsINode* mRootNode;

  // A list of the "real words" in mSoftText.mValue, ordered by mSoftTextOffset
  struct RealWord {
    int32_t mSoftTextOffset;
    uint32_t mLength : 31;
    uint32_t mCheckableWord : 1;

    RealWord(int32_t aOffset, uint32_t aLength, bool aCheckable)
        : mSoftTextOffset(aOffset),
          mLength(aLength),
          mCheckableWord(aCheckable) {
      static_assert(sizeof(RealWord) == 8,
                    "RealWord should be limited to 8 bytes");
      MOZ_ASSERT(aLength < INT32_MAX,
                 "Word length is too large to fit in the bitfield");
    }

    int32_t EndOffset() const { return mSoftTextOffset + mLength; }
  };
  using RealWords = nsTArray<RealWord>;
  RealWords mRealWords;
  int32_t mNextWordIndex;

  nsresult EnsureWords(NodeOffset aSoftBegin, NodeOffset aSoftEnd);

  int32_t MapDOMPositionToSoftTextOffset(const NodeOffset& aNodeOffset) const;
  // Map an offset into mSoftText.mValue to a DOM position. Note that two DOM
  // positions can map to the same mSoftText.mValue offset, e.g. given nodes
  // A=aaaa and B=bbbb forming aaaabbbb, (A,4) and (B,0) give the same string
  // offset. So, aHintBefore controls which position we return ... if aHint is
  // eEnd then the position indicates the END of a range so we return (A,4).
  // Otherwise the position indicates the START of a range so we return (B,0).
  enum DOMMapHint { HINT_BEGIN, HINT_END };
  NodeOffset MapSoftTextOffsetToDOMPosition(int32_t aSoftTextOffset,
                                            DOMMapHint aHint) const;

  static void ToString(DOMMapHint aHint, nsACString& aResult);

  // Finds the index of the real word containing aSoftTextOffset, or -1 if none.
  //
  // If it's exactly between two words, then if aHint is HINT_BEGIN, return the
  // later word (favouring the assumption that it's the BEGINning of a word),
  // otherwise return the earlier word (assuming it's the END of a word).
  // If aSearchForward is true, then if we don't find a word at the given
  // position, search forward until we do find a word and return that (if
  // found).
  int32_t FindRealWordContaining(int32_t aSoftTextOffset, DOMMapHint aHint,
                                 bool aSearchForward) const;

  mozilla::Result<RealWords, nsresult> BuildRealWords() const;

  nsresult SplitDOMWordAndAppendTo(int32_t aStart, int32_t aEnd,
                                   nsTArray<RealWord>& aRealWords) const;

  nsresult MakeRangeForWord(const RealWord& aWord, nsRange** aRange) const;
  void MakeNodeOffsetRangeForWord(const RealWord& aWord,
                                  NodeOffsetRange* aNodeOffsetRange);
};

#endif

Messung V0.5
C=93 H=99 G=95

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© 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 und die Messung sind noch experimentell.