Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef mozilla_TextEditRules_h
7 : #define mozilla_TextEditRules_h
8 :
9 : #include "mozilla/EditorBase.h"
10 : #include "nsCOMPtr.h"
11 : #include "nsCycleCollectionParticipant.h"
12 : #include "nsIEditRules.h"
13 : #include "nsIEditor.h"
14 : #include "nsISupportsImpl.h"
15 : #include "nsITimer.h"
16 : #include "nsString.h"
17 : #include "nscore.h"
18 :
19 : class nsIDOMNode;
20 :
21 : namespace mozilla {
22 :
23 : class AutoLockRulesSniffing;
24 : class TextEditor;
25 : namespace dom {
26 : class Selection;
27 : } // namespace dom
28 :
29 : /**
30 : * Object that encapsulates HTML text-specific editing rules.
31 : *
32 : * To be a good citizen, edit rules must live by these restrictions:
33 : * 1. All data manipulation is through the editor.
34 : * Content nodes in the document tree must <B>not</B> be manipulated
35 : * directly. Content nodes in document fragments that are not part of the
36 : * document itself may be manipulated at will. Operations on document
37 : * fragments must <B>not</B> go through the editor.
38 : * 2. Selection must not be explicitly set by the rule method.
39 : * Any manipulation of Selection must be done by the editor.
40 : */
41 : class TextEditRules : public nsIEditRules
42 : , public nsITimerCallback
43 : {
44 : public:
45 : typedef dom::Element Element;
46 : typedef dom::Selection Selection;
47 : typedef dom::Text Text;
48 : template<typename T> using OwningNonNull = OwningNonNull<T>;
49 :
50 : NS_DECL_NSITIMERCALLBACK
51 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
52 34 : NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(TextEditRules, nsIEditRules)
53 :
54 : TextEditRules();
55 :
56 : // nsIEditRules methods
57 : NS_IMETHOD Init(TextEditor* aTextEditor) override;
58 : NS_IMETHOD SetInitialValue(const nsAString& aValue) override;
59 : NS_IMETHOD DetachEditor() override;
60 : NS_IMETHOD BeforeEdit(EditAction action,
61 : nsIEditor::EDirection aDirection) override;
62 : NS_IMETHOD AfterEdit(EditAction action,
63 : nsIEditor::EDirection aDirection) override;
64 : NS_IMETHOD WillDoAction(Selection* aSelection, RulesInfo* aInfo,
65 : bool* aCancel, bool* aHandled) override;
66 : NS_IMETHOD DidDoAction(Selection* aSelection, RulesInfo* aInfo,
67 : nsresult aResult) override;
68 : NS_IMETHOD_(bool) DocumentIsEmpty() override;
69 : NS_IMETHOD DocumentModified() override;
70 :
71 : protected:
72 : virtual ~TextEditRules();
73 :
74 : public:
75 : void ResetIMETextPWBuf();
76 :
77 : /**
78 : * Handles the newline characters either according to aNewLineHandling
79 : * or to the default system prefs if aNewLineHandling is negative.
80 : *
81 : * @param aString the string to be modified in place.
82 : * @param aNewLineHandling determine the desired type of newline handling:
83 : * * negative values:
84 : * handle newlines according to platform defaults.
85 : * * nsIPlaintextEditor::eNewlinesReplaceWithSpaces:
86 : * replace newlines with spaces.
87 : * * nsIPlaintextEditor::eNewlinesStrip:
88 : * remove newlines from the string.
89 : * * nsIPlaintextEditor::eNewlinesReplaceWithCommas:
90 : * replace newlines with commas.
91 : * * nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace:
92 : * collapse newlines and surrounding whitespace characters and
93 : * remove them from the string.
94 : * * nsIPlaintextEditor::eNewlinesPasteIntact:
95 : * only remove the leading and trailing newlines.
96 : * * nsIPlaintextEditor::eNewlinesPasteToFirst or any other value:
97 : * remove the first newline and all characters following it.
98 : */
99 : static void HandleNewLines(nsString& aString, int32_t aNewLineHandling);
100 :
101 : /**
102 : * Prepare a string buffer for being displayed as the contents of a password
103 : * field. This function uses the platform-specific character for representing
104 : * characters entered into password fields.
105 : *
106 : * @param aOutString the output string. When this function returns,
107 : * aOutString will contain aLength password characters.
108 : * @param aLength the number of password characters that aOutString should
109 : * contain.
110 : */
111 : static void FillBufWithPWChars(nsAString* aOutString, int32_t aLength);
112 :
113 : protected:
114 :
115 : void InitFields();
116 :
117 : // TextEditRules implementation methods
118 : nsresult WillInsertText(EditAction aAction,
119 : Selection* aSelection,
120 : bool* aCancel,
121 : bool* aHandled,
122 : const nsAString* inString,
123 : nsAString* outString,
124 : int32_t aMaxLength);
125 : nsresult DidInsertText(Selection* aSelection, nsresult aResult);
126 :
127 : nsresult WillInsertBreak(Selection* aSelection, bool* aCancel,
128 : bool* aHandled, int32_t aMaxLength);
129 : nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
130 :
131 : nsresult WillSetText(Selection& aSelection,
132 : bool* aCancel,
133 : bool* aHandled,
134 : const nsAString* inString,
135 : int32_t aMaxLength);
136 : nsresult DidSetText(Selection& aSelection, nsresult aResult);
137 :
138 : void WillInsert(Selection& aSelection, bool* aCancel);
139 : nsresult DidInsert(Selection* aSelection, nsresult aResult);
140 :
141 : nsresult WillDeleteSelection(Selection* aSelection,
142 : nsIEditor::EDirection aCollapsedAction,
143 : bool* aCancel,
144 : bool* aHandled);
145 : nsresult DidDeleteSelection(Selection* aSelection,
146 : nsIEditor::EDirection aCollapsedAction,
147 : nsresult aResult);
148 :
149 : nsresult WillSetTextProperty(Selection* aSelection, bool* aCancel,
150 : bool* aHandled);
151 : nsresult DidSetTextProperty(Selection* aSelection, nsresult aResult);
152 :
153 : nsresult WillRemoveTextProperty(Selection* aSelection, bool* aCancel,
154 : bool* aHandled);
155 : nsresult DidRemoveTextProperty(Selection* aSelection, nsresult aResult);
156 :
157 : nsresult WillUndo(Selection* aSelection, bool* aCancel, bool* aHandled);
158 : nsresult DidUndo(Selection* aSelection, nsresult aResult);
159 :
160 : nsresult WillRedo(Selection* aSelection, bool* aCancel, bool* aHandled);
161 : nsresult DidRedo(Selection* aSelection, nsresult aResult);
162 :
163 : /**
164 : * Called prior to nsIEditor::OutputToString.
165 : * @param aSelection
166 : * @param aInFormat The format requested for the output, a MIME type.
167 : * @param aOutText The string to use for output, if aCancel is set to true.
168 : * @param aOutCancel If set to true, the caller should cancel the operation
169 : * and use aOutText as the result.
170 : */
171 : nsresult WillOutputText(Selection* aSelection,
172 : const nsAString* aInFormat,
173 : nsAString* aOutText,
174 : uint32_t aFlags,
175 : bool* aOutCancel,
176 : bool* aHandled);
177 :
178 : nsresult DidOutputText(Selection* aSelection, nsresult aResult);
179 :
180 : /**
181 : * Check for and replace a redundant trailing break.
182 : */
183 : nsresult RemoveRedundantTrailingBR();
184 :
185 : /**
186 : * Creates a trailing break in the text doc if there is not one already.
187 : */
188 : nsresult CreateTrailingBRIfNeeded();
189 :
190 : /**
191 : * Creates a bogus text node if the document has no editable content.
192 : */
193 : nsresult CreateBogusNodeIfNeeded(Selection* aSelection);
194 :
195 : /**
196 : * Returns a truncated insertion string if insertion would place us over
197 : * aMaxLength
198 : */
199 : nsresult TruncateInsertionIfNeeded(Selection* aSelection,
200 : const nsAString* aInString,
201 : nsAString* aOutString,
202 : int32_t aMaxLength,
203 : bool* aTruncated);
204 :
205 : /**
206 : * Remove IME composition text from password buffer.
207 : */
208 : void RemoveIMETextFromPWBuf(uint32_t& aStart, nsAString* aIMEString);
209 :
210 : nsresult CreateMozBR(nsIDOMNode* inParent, int32_t inOffset,
211 : nsIDOMNode** outBRNode = nullptr);
212 :
213 : void UndefineCaretBidiLevel(Selection* aSelection);
214 :
215 : nsresult CheckBidiLevelForDeletion(Selection* aSelection,
216 : nsIDOMNode* aSelNode,
217 : int32_t aSelOffset,
218 : nsIEditor::EDirection aAction,
219 : bool* aCancel);
220 :
221 : nsresult HideLastPWInput();
222 :
223 : nsresult CollapseSelectionToTrailingBRIfNeeded(Selection* aSelection);
224 :
225 : bool IsPasswordEditor() const;
226 : bool IsSingleLineEditor() const;
227 : bool IsPlaintextEditor() const;
228 : bool IsReadonly() const;
229 : bool IsDisabled() const;
230 : bool IsMailEditor() const;
231 : bool DontEchoPassword() const;
232 :
233 : private:
234 : // Note that we do not refcount the editor.
235 : TextEditor* mTextEditor;
236 :
237 : protected:
238 : // A buffer we use to store the real value of password editors.
239 : nsString mPasswordText;
240 : // A buffer we use to track the IME composition string.
241 : nsString mPasswordIMEText;
242 : uint32_t mPasswordIMEIndex;
243 : // Magic node acts as placeholder in empty doc.
244 : nsCOMPtr<nsIContent> mBogusNode;
245 : // Cached selected node.
246 : nsCOMPtr<nsINode> mCachedSelectionNode;
247 : // Cached selected offset.
248 : int32_t mCachedSelectionOffset;
249 : uint32_t mActionNesting;
250 : bool mLockRulesSniffing;
251 : bool mDidExplicitlySetInterline;
252 : // In bidirectional text, delete characters not visually adjacent to the
253 : // caret without moving the caret first.
254 : bool mDeleteBidiImmediately;
255 : // The top level editor action.
256 : EditAction mTheAction;
257 : nsCOMPtr<nsITimer> mTimer;
258 : uint32_t mLastStart;
259 : uint32_t mLastLength;
260 :
261 : // friends
262 : friend class AutoLockRulesSniffing;
263 : };
264 :
265 : // TODO: This class (almost struct, though) is ugly and its size isn't
266 : // optimized. Should be refined later.
267 5 : class TextRulesInfo final : public RulesInfo
268 : {
269 : public:
270 5 : explicit TextRulesInfo(EditAction aAction)
271 5 : : RulesInfo(aAction)
272 : , inString(nullptr)
273 : , outString(nullptr)
274 : , outputFormat(nullptr)
275 : , maxLength(-1)
276 : , flags(0)
277 : , collapsedAction(nsIEditor::eNext)
278 : , stripWrappers(nsIEditor::eStrip)
279 : , bOrdered(false)
280 : , entireList(false)
281 : , bulletType(nullptr)
282 : , alignType(nullptr)
283 5 : , blockType(nullptr)
284 5 : {}
285 :
286 : // EditAction::insertText / EditAction::insertIMEText
287 : const nsAString* inString;
288 : nsAString* outString;
289 : const nsAString* outputFormat;
290 : int32_t maxLength;
291 :
292 : // EditAction::outputText
293 : uint32_t flags;
294 :
295 : // EditAction::deleteSelection
296 : nsIEditor::EDirection collapsedAction;
297 : nsIEditor::EStripWrappers stripWrappers;
298 :
299 : // EditAction::removeList
300 : bool bOrdered;
301 :
302 : // EditAction::makeList
303 : bool entireList;
304 : const nsAString* bulletType;
305 :
306 : // EditAction::align
307 : const nsAString* alignType;
308 :
309 : // EditAction::makeBasicBlock
310 : const nsAString* blockType;
311 : };
312 :
313 : /**
314 : * Stack based helper class for StartOperation()/EndOperation() sandwich.
315 : * This class sets a bool letting us know to ignore any rules sniffing
316 : * that tries to occur reentrantly.
317 : */
318 : class MOZ_STACK_CLASS AutoLockRulesSniffing final
319 : {
320 : public:
321 6 : explicit AutoLockRulesSniffing(TextEditRules* aRules)
322 6 : : mRules(aRules)
323 : {
324 6 : if (mRules) {
325 6 : mRules->mLockRulesSniffing = true;
326 : }
327 6 : }
328 :
329 6 : ~AutoLockRulesSniffing()
330 6 : {
331 6 : if (mRules) {
332 6 : mRules->mLockRulesSniffing = false;
333 : }
334 6 : }
335 :
336 : protected:
337 : TextEditRules* mRules;
338 : };
339 :
340 : /**
341 : * Stack based helper class for turning on/off the edit listener.
342 : */
343 : class MOZ_STACK_CLASS AutoLockListener final
344 : {
345 : public:
346 0 : explicit AutoLockListener(bool* aEnabled)
347 0 : : mEnabled(aEnabled)
348 0 : , mOldState(false)
349 : {
350 0 : if (mEnabled) {
351 0 : mOldState = *mEnabled;
352 0 : *mEnabled = false;
353 : }
354 0 : }
355 :
356 0 : ~AutoLockListener()
357 0 : {
358 0 : if (mEnabled) {
359 0 : *mEnabled = mOldState;
360 : }
361 0 : }
362 :
363 : protected:
364 : bool* mEnabled;
365 : bool mOldState;
366 : };
367 :
368 : } // namespace mozilla
369 :
370 : #endif // #ifndef mozilla_TextEditRules_h
|