extensions/spellcheck/src/mozInlineSpellChecker.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/extensions/spellcheck/src/mozInlineSpellChecker.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,274 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef __mozinlinespellchecker_h__
    1.10 +#define __mozinlinespellchecker_h__
    1.11 +
    1.12 +#include "nsAutoPtr.h"
    1.13 +#include "nsRange.h"
    1.14 +#include "nsIEditorSpellCheck.h"
    1.15 +#include "nsIEditActionListener.h"
    1.16 +#include "nsIInlineSpellChecker.h"
    1.17 +#include "nsIDOMTreeWalker.h"
    1.18 +#include "nsWeakReference.h"
    1.19 +#include "nsEditor.h"
    1.20 +#include "nsIDOMEventListener.h"
    1.21 +#include "nsWeakReference.h"
    1.22 +#include "mozISpellI18NUtil.h"
    1.23 +#include "nsCycleCollectionParticipant.h"
    1.24 +
    1.25 +// X.h defines KeyPress
    1.26 +#ifdef KeyPress
    1.27 +#undef KeyPress
    1.28 +#endif
    1.29 +
    1.30 +class nsIDOMMouseEventListener;
    1.31 +class mozInlineSpellWordUtil;
    1.32 +class mozInlineSpellChecker;
    1.33 +class mozInlineSpellResume;
    1.34 +class InitEditorSpellCheckCallback;
    1.35 +class UpdateCurrentDictionaryCallback;
    1.36 +class mozInlineSpellResume;
    1.37 +
    1.38 +class mozInlineSpellStatus
    1.39 +{
    1.40 +public:
    1.41 +  mozInlineSpellStatus(mozInlineSpellChecker* aSpellChecker);
    1.42 +
    1.43 +  nsresult InitForEditorChange(EditAction aAction,
    1.44 +                               nsIDOMNode* aAnchorNode, int32_t aAnchorOffset,
    1.45 +                               nsIDOMNode* aPreviousNode, int32_t aPreviousOffset,
    1.46 +                               nsIDOMNode* aStartNode, int32_t aStartOffset,
    1.47 +                               nsIDOMNode* aEndNode, int32_t aEndOffset);
    1.48 +  nsresult InitForNavigation(bool aForceCheck, int32_t aNewPositionOffset,
    1.49 +                             nsIDOMNode* aOldAnchorNode, int32_t aOldAnchorOffset,
    1.50 +                             nsIDOMNode* aNewAnchorNode, int32_t aNewAnchorOffset,
    1.51 +                             bool* aContinue);
    1.52 +  nsresult InitForSelection();
    1.53 +  nsresult InitForRange(nsRange* aRange);
    1.54 +
    1.55 +  nsresult FinishInitOnEvent(mozInlineSpellWordUtil& aWordUtil);
    1.56 +
    1.57 +  // Return true if we plan to spell-check everything
    1.58 +  bool IsFullSpellCheck() const {
    1.59 +    return mOp == eOpChange && !mRange;
    1.60 +  }
    1.61 +
    1.62 +  nsRefPtr<mozInlineSpellChecker> mSpellChecker;
    1.63 +
    1.64 +  // The total number of words checked in this sequence, using this tally tells
    1.65 +  // us when to stop. This count is preserved as we continue checking in new
    1.66 +  // messages.
    1.67 +  int32_t mWordCount;
    1.68 +
    1.69 +  // what happened?
    1.70 +  enum Operation { eOpChange,       // for SpellCheckAfterChange except deleteSelection
    1.71 +                   eOpChangeDelete, // for SpellCheckAfterChange deleteSelection
    1.72 +                   eOpNavigation,   // for HandleNavigationEvent
    1.73 +                   eOpSelection,    // re-check all misspelled words
    1.74 +                   eOpResume };     // for resuming a previously started check
    1.75 +  Operation mOp;
    1.76 +
    1.77 +  // Used for events where we have already computed the range to use. It can
    1.78 +  // also be nullptr in these cases where we need to check the entire range.
    1.79 +  nsRefPtr<nsRange> mRange;
    1.80 +
    1.81 +  // If we happen to know something was inserted, this is that range.
    1.82 +  // Can be nullptr (this only allows an optimization, so not setting doesn't hurt)
    1.83 +  nsCOMPtr<nsIDOMRange> mCreatedRange;
    1.84 +
    1.85 +  // Contains the range computed for the current word. Can be nullptr.
    1.86 +  nsRefPtr<nsRange> mNoCheckRange;
    1.87 +
    1.88 +  // Indicates the position of the cursor for the event (so we can compute
    1.89 +  // mNoCheckRange). It can be nullptr if we don't care about the cursor position
    1.90 +  // (such as for the intial check of everything).
    1.91 +  //
    1.92 +  // For mOp == eOpNavigation, this is the NEW position of the cursor
    1.93 +  nsCOMPtr<nsIDOMRange> mAnchorRange;
    1.94 +
    1.95 +  // -----
    1.96 +  // The following members are only for navigation events and are only
    1.97 +  // stored for FinishNavigationEvent to initialize the other members.
    1.98 +  // -----
    1.99 +
   1.100 +  // this is the OLD position of the cursor
   1.101 +  nsCOMPtr<nsIDOMRange> mOldNavigationAnchorRange;
   1.102 +
   1.103 +  // Set when we should force checking the current word. See
   1.104 +  // mozInlineSpellChecker::HandleNavigationEvent for a description of why we
   1.105 +  // have this.
   1.106 +  bool mForceNavigationWordCheck;
   1.107 +
   1.108 +  // Contains the offset passed in to HandleNavigationEvent
   1.109 +  int32_t mNewNavigationPositionOffset;
   1.110 +
   1.111 +protected:
   1.112 +  nsresult FinishNavigationEvent(mozInlineSpellWordUtil& aWordUtil);
   1.113 +
   1.114 +  nsresult FillNoCheckRangeFromAnchor(mozInlineSpellWordUtil& aWordUtil);
   1.115 +
   1.116 +  nsresult GetDocument(nsIDOMDocument** aDocument);
   1.117 +  nsresult PositionToCollapsedRange(nsIDOMDocument* aDocument,
   1.118 +                                    nsIDOMNode* aNode, int32_t aOffset,
   1.119 +                                    nsIDOMRange** aRange);
   1.120 +};
   1.121 +
   1.122 +class mozInlineSpellChecker : public nsIInlineSpellChecker,
   1.123 +                              public nsIEditActionListener,
   1.124 +                              public nsIDOMEventListener,
   1.125 +                              public nsSupportsWeakReference
   1.126 +{
   1.127 +private:
   1.128 +  friend class mozInlineSpellStatus;
   1.129 +  friend class InitEditorSpellCheckCallback;
   1.130 +  friend class UpdateCurrentDictionaryCallback;
   1.131 +  friend class AutoChangeNumPendingSpellChecks;
   1.132 +  friend class mozInlineSpellResume;
   1.133 +
   1.134 +  // Access with CanEnableInlineSpellChecking
   1.135 +  enum SpellCheckingState { SpellCheck_Uninitialized = -1,
   1.136 +                            SpellCheck_NotAvailable = 0,
   1.137 +                            SpellCheck_Available = 1};
   1.138 +  static SpellCheckingState gCanEnableSpellChecking;
   1.139 +
   1.140 +  nsWeakPtr mEditor; 
   1.141 +  nsCOMPtr<nsIEditorSpellCheck> mSpellCheck;
   1.142 +  nsCOMPtr<nsIEditorSpellCheck> mPendingSpellCheck;
   1.143 +  nsCOMPtr<nsIDOMTreeWalker> mTreeWalker;
   1.144 +  nsCOMPtr<mozISpellI18NUtil> mConverter;
   1.145 +
   1.146 +  int32_t mNumWordsInSpellSelection;
   1.147 +  int32_t mMaxNumWordsInSpellSelection;
   1.148 +
   1.149 +  // How many misspellings we can add at once. This is often less than the max
   1.150 +  // total number of misspellings. When you have a large textarea prepopulated
   1.151 +  // with text with many misspellings, we can hit this limit. By making it
   1.152 +  // lower than the total number of misspelled words, new text typed by the
   1.153 +  // user can also have spellchecking in it.
   1.154 +  int32_t mMaxMisspellingsPerCheck;
   1.155 +
   1.156 +  // we need to keep track of the current text position in the document
   1.157 +  // so we can spell check the old word when the user clicks around the document.
   1.158 +  nsCOMPtr<nsIDOMNode> mCurrentSelectionAnchorNode;
   1.159 +  int32_t              mCurrentSelectionOffset;
   1.160 +
   1.161 +  // Tracks the number of pending spell checks *and* async operations that may
   1.162 +  // lead to spell checks, like updating the current dictionary.  This is
   1.163 +  // necessary so that observers can know when to wait for spell check to
   1.164 +  // complete.
   1.165 +  int32_t mNumPendingSpellChecks;
   1.166 +
   1.167 +  // The number of calls to UpdateCurrentDictionary that haven't finished yet.
   1.168 +  int32_t mNumPendingUpdateCurrentDictionary;
   1.169 +
   1.170 +  // This number is incremented each time the spell checker is disabled so that
   1.171 +  // pending scheduled spell checks and UpdateCurrentDictionary calls can be
   1.172 +  // ignored when they finish.
   1.173 +  uint32_t mDisabledAsyncToken;
   1.174 +
   1.175 +  // When mPendingSpellCheck is non-null, this is the callback passed when
   1.176 +  // it was initialized.
   1.177 +  nsRefPtr<InitEditorSpellCheckCallback> mPendingInitEditorSpellCheckCallback;
   1.178 +
   1.179 +  // Set when we have spellchecked after the last edit operation. See the
   1.180 +  // commment at the top of the .cpp file for more info.
   1.181 +  bool mNeedsCheckAfterNavigation;
   1.182 +
   1.183 +  // Set when we have a pending mozInlineSpellResume which will check
   1.184 +  // the whole document.
   1.185 +  bool mFullSpellCheckScheduled;
   1.186 +
   1.187 +  // Maintains state during the asynchronous UpdateCurrentDictionary call.
   1.188 +  nsString mPreviousDictionary;
   1.189 +
   1.190 +public:
   1.191 +
   1.192 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   1.193 +  NS_DECL_NSIEDITACTIONLISTENER
   1.194 +  NS_DECL_NSIINLINESPELLCHECKER
   1.195 +  NS_DECL_NSIDOMEVENTLISTENER
   1.196 +  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozInlineSpellChecker, nsIDOMEventListener)
   1.197 +
   1.198 +  // returns true if there are any spell checking dictionaries available
   1.199 +  static bool CanEnableInlineSpellChecking();
   1.200 +  // update the cached value whenever the list of available dictionaries changes
   1.201 +  static void UpdateCanEnableInlineSpellChecking();
   1.202 +
   1.203 +  nsresult Blur(nsIDOMEvent* aEvent);
   1.204 +  nsresult MouseClick(nsIDOMEvent* aMouseEvent);
   1.205 +  nsresult KeyPress(nsIDOMEvent* aKeyEvent);
   1.206 +
   1.207 +  mozInlineSpellChecker();
   1.208 +  virtual ~mozInlineSpellChecker();
   1.209 +
   1.210 +  // spell checks all of the words between two nodes
   1.211 +  nsresult SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
   1.212 +                                  int32_t aStartOffset,
   1.213 +                                  nsIDOMNode *aEndNode,
   1.214 +                                  int32_t aEndOffset);
   1.215 +
   1.216 +  // examines the dom node in question and returns true if the inline spell
   1.217 +  // checker should skip the node (i.e. the text is inside of a block quote
   1.218 +  // or an e-mail signature...)
   1.219 +  nsresult SkipSpellCheckForNode(nsIEditor* aEditor,
   1.220 +                                 nsIDOMNode *aNode, bool * aCheckSpelling);
   1.221 +
   1.222 +  nsresult SpellCheckAfterChange(nsIDOMNode* aCursorNode, int32_t aCursorOffset,
   1.223 +                                 nsIDOMNode* aPreviousNode, int32_t aPreviousOffset,
   1.224 +                                 nsISelection* aSpellCheckSelection);
   1.225 +
   1.226 +  // spell check the text contained within aRange, potentially scheduling
   1.227 +  // another check in the future if the time threshold is reached
   1.228 +  nsresult ScheduleSpellCheck(const mozInlineSpellStatus& aStatus);
   1.229 +
   1.230 +  nsresult DoSpellCheckSelection(mozInlineSpellWordUtil& aWordUtil,
   1.231 +                                 nsISelection* aSpellCheckSelection,
   1.232 +                                 mozInlineSpellStatus* aStatus);
   1.233 +  nsresult DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
   1.234 +                        nsISelection *aSpellCheckSelection,
   1.235 +                        mozInlineSpellStatus* aStatus,
   1.236 +                        bool* aDoneChecking);
   1.237 +
   1.238 +  // helper routine to determine if a point is inside of the passed in selection.
   1.239 +  nsresult IsPointInSelection(nsISelection *aSelection,
   1.240 +                              nsIDOMNode *aNode,
   1.241 +                              int32_t aOffset,
   1.242 +                              nsIDOMRange **aRange);
   1.243 +
   1.244 +  nsresult CleanupRangesInSelection(nsISelection *aSelection);
   1.245 +
   1.246 +  nsresult RemoveRange(nsISelection *aSpellCheckSelection, nsIDOMRange * aRange);
   1.247 +  nsresult AddRange(nsISelection *aSpellCheckSelection, nsIDOMRange * aRange);
   1.248 +  bool     SpellCheckSelectionIsFull() { return mNumWordsInSpellSelection >= mMaxNumWordsInSpellSelection; }
   1.249 +
   1.250 +  nsresult MakeSpellCheckRange(nsIDOMNode* aStartNode, int32_t aStartOffset,
   1.251 +                               nsIDOMNode* aEndNode, int32_t aEndOffset,
   1.252 +                               nsRange** aRange);
   1.253 +
   1.254 +  // DOM and editor event registration helper routines
   1.255 +  nsresult RegisterEventListeners();
   1.256 +  nsresult UnregisterEventListeners();
   1.257 +  nsresult HandleNavigationEvent(bool aForceWordSpellCheck, int32_t aNewPositionOffset = 0);
   1.258 +
   1.259 +  nsresult GetSpellCheckSelection(nsISelection ** aSpellCheckSelection);
   1.260 +  nsresult SaveCurrentSelectionPosition();
   1.261 +
   1.262 +  nsresult ResumeCheck(mozInlineSpellStatus* aStatus);
   1.263 +
   1.264 +protected:
   1.265 +
   1.266 +  // called when async nsIEditorSpellCheck methods complete
   1.267 +  nsresult EditorSpellCheckInited();
   1.268 +  nsresult CurrentDictionaryUpdated();
   1.269 +
   1.270 +  // track the number of pending spell checks and async operations that may lead
   1.271 +  // to spell checks, notifying observers accordingly
   1.272 +  void ChangeNumPendingSpellChecks(int32_t aDelta,
   1.273 +                                   nsIEditor* aEditor = nullptr);
   1.274 +  void NotifyObservers(const char* aTopic, nsIEditor* aEditor);
   1.275 +};
   1.276 +
   1.277 +#endif /* __mozinlinespellchecker_h__ */

mercurial