|
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 nsTextEditRules_h__ |
|
7 #define nsTextEditRules_h__ |
|
8 |
|
9 #include "nsCOMPtr.h" |
|
10 #include "nsCycleCollectionParticipant.h" |
|
11 #include "nsEditRules.h" |
|
12 #include "nsEditor.h" |
|
13 #include "nsIEditor.h" |
|
14 #include "nsISupportsImpl.h" |
|
15 #include "nsITimer.h" |
|
16 #include "nsPlaintextEditor.h" |
|
17 #include "nsString.h" |
|
18 #include "nscore.h" |
|
19 |
|
20 class nsIDOMElement; |
|
21 class nsIDOMNode; |
|
22 class nsISelection; |
|
23 namespace mozilla { |
|
24 namespace dom { |
|
25 class Selection; |
|
26 } // namespace dom |
|
27 } // namespace mozilla |
|
28 |
|
29 /** Object that encapsulates HTML text-specific editing rules. |
|
30 * |
|
31 * To be a good citizen, edit rules must live by these restrictions: |
|
32 * 1. All data manipulation is through the editor. |
|
33 * Content nodes in the document tree must <B>not</B> be manipulated directly. |
|
34 * Content nodes in document fragments that are not part of the document itself |
|
35 * may be manipulated at will. Operations on document fragments must <B>not</B> |
|
36 * go through the editor. |
|
37 * 2. Selection must not be explicitly set by the rule method. |
|
38 * Any manipulation of Selection must be done by the editor. |
|
39 */ |
|
40 class nsTextEditRules : public nsIEditRules, public nsITimerCallback |
|
41 { |
|
42 public: |
|
43 NS_DECL_NSITIMERCALLBACK |
|
44 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
45 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTextEditRules, nsIEditRules) |
|
46 |
|
47 nsTextEditRules(); |
|
48 virtual ~nsTextEditRules(); |
|
49 |
|
50 // nsIEditRules methods |
|
51 NS_IMETHOD Init(nsPlaintextEditor *aEditor); |
|
52 NS_IMETHOD SetInitialValue(const nsAString& aValue); |
|
53 NS_IMETHOD DetachEditor(); |
|
54 NS_IMETHOD BeforeEdit(EditAction action, |
|
55 nsIEditor::EDirection aDirection); |
|
56 NS_IMETHOD AfterEdit(EditAction action, |
|
57 nsIEditor::EDirection aDirection); |
|
58 NS_IMETHOD WillDoAction(mozilla::dom::Selection* aSelection, |
|
59 nsRulesInfo* aInfo, bool* aCancel, bool* aHandled); |
|
60 NS_IMETHOD DidDoAction(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); |
|
61 NS_IMETHOD DocumentIsEmpty(bool *aDocumentIsEmpty); |
|
62 NS_IMETHOD DocumentModified(); |
|
63 |
|
64 public: |
|
65 void ResetIMETextPWBuf(); |
|
66 |
|
67 /** |
|
68 * Handles the newline characters either according to aNewLineHandling |
|
69 * or to the default system prefs if aNewLineHandling is negative. |
|
70 * |
|
71 * @param aString the string to be modified in place. |
|
72 * @param aNewLineHandling determine the desired type of newline handling: |
|
73 * * negative values: |
|
74 * handle newlines according to platform defaults. |
|
75 * * nsIPlaintextEditor::eNewlinesReplaceWithSpaces: |
|
76 * replace newlines with spaces. |
|
77 * * nsIPlaintextEditor::eNewlinesStrip: |
|
78 * remove newlines from the string. |
|
79 * * nsIPlaintextEditor::eNewlinesReplaceWithCommas: |
|
80 * replace newlines with commas. |
|
81 * * nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace: |
|
82 * collapse newlines and surrounding whitespace characters and |
|
83 * remove them from the string. |
|
84 * * nsIPlaintextEditor::eNewlinesPasteIntact: |
|
85 * only remove the leading and trailing newlines. |
|
86 * * nsIPlaintextEditor::eNewlinesPasteToFirst or any other value: |
|
87 * remove the first newline and all characters following it. |
|
88 */ |
|
89 static void HandleNewLines(nsString &aString, int32_t aNewLineHandling); |
|
90 |
|
91 /** |
|
92 * Prepare a string buffer for being displayed as the contents of a password |
|
93 * field. This function uses the platform-specific character for representing |
|
94 * characters entered into password fields. |
|
95 * |
|
96 * @param aOutString the output string. When this function returns, |
|
97 * aOutString will contain aLength password characters. |
|
98 * @param aLength the number of password characters that aOutString should |
|
99 * contain. |
|
100 */ |
|
101 static void FillBufWithPWChars(nsAString *aOutString, int32_t aLength); |
|
102 |
|
103 protected: |
|
104 |
|
105 void InitFields(); |
|
106 |
|
107 // nsTextEditRules implementation methods |
|
108 nsresult WillInsertText( EditAction aAction, |
|
109 mozilla::dom::Selection* aSelection, |
|
110 bool *aCancel, |
|
111 bool *aHandled, |
|
112 const nsAString *inString, |
|
113 nsAString *outString, |
|
114 int32_t aMaxLength); |
|
115 nsresult DidInsertText(nsISelection *aSelection, nsresult aResult); |
|
116 nsresult GetTopEnclosingPre(nsIDOMNode *aNode, nsIDOMNode** aOutPreNode); |
|
117 |
|
118 nsresult WillInsertBreak(mozilla::dom::Selection* aSelection, bool* aCancel, |
|
119 bool *aHandled, int32_t aMaxLength); |
|
120 nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult); |
|
121 |
|
122 nsresult WillInsert(nsISelection *aSelection, bool *aCancel); |
|
123 nsresult DidInsert(nsISelection *aSelection, nsresult aResult); |
|
124 |
|
125 nsresult WillDeleteSelection(mozilla::dom::Selection* aSelection, |
|
126 nsIEditor::EDirection aCollapsedAction, |
|
127 bool *aCancel, |
|
128 bool *aHandled); |
|
129 nsresult DidDeleteSelection(nsISelection *aSelection, |
|
130 nsIEditor::EDirection aCollapsedAction, |
|
131 nsresult aResult); |
|
132 |
|
133 nsresult WillSetTextProperty(nsISelection *aSelection, bool *aCancel, bool *aHandled); |
|
134 nsresult DidSetTextProperty(nsISelection *aSelection, nsresult aResult); |
|
135 |
|
136 nsresult WillRemoveTextProperty(nsISelection *aSelection, bool *aCancel, bool *aHandled); |
|
137 nsresult DidRemoveTextProperty(nsISelection *aSelection, nsresult aResult); |
|
138 |
|
139 nsresult WillUndo(nsISelection *aSelection, bool *aCancel, bool *aHandled); |
|
140 nsresult DidUndo(nsISelection *aSelection, nsresult aResult); |
|
141 |
|
142 nsresult WillRedo(nsISelection *aSelection, bool *aCancel, bool *aHandled); |
|
143 nsresult DidRedo(nsISelection *aSelection, nsresult aResult); |
|
144 |
|
145 /** called prior to nsIEditor::OutputToString |
|
146 * @param aSelection |
|
147 * @param aInFormat the format requested for the output, a MIME type |
|
148 * @param aOutText the string to use for output, if aCancel is set to true |
|
149 * @param aOutCancel if set to true, the caller should cancel the operation |
|
150 * and use aOutText as the result. |
|
151 */ |
|
152 nsresult WillOutputText(nsISelection *aSelection, |
|
153 const nsAString *aInFormat, |
|
154 nsAString *aOutText, |
|
155 bool *aOutCancel, |
|
156 bool *aHandled); |
|
157 |
|
158 nsresult DidOutputText(nsISelection *aSelection, nsresult aResult); |
|
159 |
|
160 |
|
161 // helper functions |
|
162 |
|
163 /** check for and replace a redundant trailing break */ |
|
164 nsresult RemoveRedundantTrailingBR(); |
|
165 |
|
166 /** creates a trailing break in the text doc if there is not one already */ |
|
167 nsresult CreateTrailingBRIfNeeded(); |
|
168 |
|
169 /** creates a bogus text node if the document has no editable content */ |
|
170 nsresult CreateBogusNodeIfNeeded(nsISelection *aSelection); |
|
171 |
|
172 /** returns a truncated insertion string if insertion would place us |
|
173 over aMaxLength */ |
|
174 nsresult TruncateInsertionIfNeeded(mozilla::dom::Selection* aSelection, |
|
175 const nsAString *aInString, |
|
176 nsAString *aOutString, |
|
177 int32_t aMaxLength, |
|
178 bool *aTruncated); |
|
179 |
|
180 /** Remove IME composition text from password buffer */ |
|
181 void RemoveIMETextFromPWBuf(int32_t &aStart, nsAString *aIMEString); |
|
182 |
|
183 nsresult CreateMozBR(nsIDOMNode* inParent, int32_t inOffset, |
|
184 nsIDOMNode** outBRNode = nullptr); |
|
185 |
|
186 nsresult CheckBidiLevelForDeletion(nsISelection *aSelection, |
|
187 nsIDOMNode *aSelNode, |
|
188 int32_t aSelOffset, |
|
189 nsIEditor::EDirection aAction, |
|
190 bool *aCancel); |
|
191 |
|
192 nsresult HideLastPWInput(); |
|
193 |
|
194 nsresult CollapseSelectionToTrailingBRIfNeeded(nsISelection *aSelection); |
|
195 |
|
196 bool IsPasswordEditor() const |
|
197 { |
|
198 return mEditor ? mEditor->IsPasswordEditor() : false; |
|
199 } |
|
200 bool IsSingleLineEditor() const |
|
201 { |
|
202 return mEditor ? mEditor->IsSingleLineEditor() : false; |
|
203 } |
|
204 bool IsPlaintextEditor() const |
|
205 { |
|
206 return mEditor ? mEditor->IsPlaintextEditor() : false; |
|
207 } |
|
208 bool IsReadonly() const |
|
209 { |
|
210 return mEditor ? mEditor->IsReadonly() : false; |
|
211 } |
|
212 bool IsDisabled() const |
|
213 { |
|
214 return mEditor ? mEditor->IsDisabled() : false; |
|
215 } |
|
216 bool IsMailEditor() const |
|
217 { |
|
218 return mEditor ? mEditor->IsMailEditor() : false; |
|
219 } |
|
220 bool DontEchoPassword() const |
|
221 { |
|
222 return mEditor ? mEditor->DontEchoPassword() : false; |
|
223 } |
|
224 |
|
225 // data members |
|
226 nsPlaintextEditor *mEditor; // note that we do not refcount the editor |
|
227 nsString mPasswordText; // a buffer we use to store the real value of password editors |
|
228 nsString mPasswordIMEText; // a buffer we use to track the IME composition string |
|
229 uint32_t mPasswordIMEIndex; |
|
230 nsCOMPtr<nsIDOMNode> mBogusNode; // magic node acts as placeholder in empty doc |
|
231 nsCOMPtr<nsIDOMNode> mCachedSelectionNode; // cached selected node |
|
232 int32_t mCachedSelectionOffset; // cached selected offset |
|
233 uint32_t mActionNesting; |
|
234 bool mLockRulesSniffing; |
|
235 bool mDidExplicitlySetInterline; |
|
236 bool mDeleteBidiImmediately; // in bidirectional text, delete |
|
237 // characters not visually |
|
238 // adjacent to the caret without |
|
239 // moving the caret first. |
|
240 EditAction mTheAction; // the top level editor action |
|
241 nsCOMPtr<nsITimer> mTimer; |
|
242 uint32_t mLastStart, mLastLength; |
|
243 |
|
244 // friends |
|
245 friend class nsAutoLockRulesSniffing; |
|
246 |
|
247 }; |
|
248 |
|
249 |
|
250 |
|
251 class nsTextRulesInfo : public nsRulesInfo |
|
252 { |
|
253 public: |
|
254 |
|
255 nsTextRulesInfo(EditAction aAction) : |
|
256 nsRulesInfo(aAction), |
|
257 inString(0), |
|
258 outString(0), |
|
259 outputFormat(0), |
|
260 maxLength(-1), |
|
261 collapsedAction(nsIEditor::eNext), |
|
262 stripWrappers(nsIEditor::eStrip), |
|
263 bOrdered(false), |
|
264 entireList(false), |
|
265 bulletType(0), |
|
266 alignType(0), |
|
267 blockType(0), |
|
268 insertElement(0) |
|
269 {} |
|
270 |
|
271 virtual ~nsTextRulesInfo() {} |
|
272 |
|
273 // kInsertText |
|
274 const nsAString *inString; |
|
275 nsAString *outString; |
|
276 const nsAString *outputFormat; |
|
277 int32_t maxLength; |
|
278 |
|
279 // kDeleteSelection |
|
280 nsIEditor::EDirection collapsedAction; |
|
281 nsIEditor::EStripWrappers stripWrappers; |
|
282 |
|
283 // kMakeList |
|
284 bool bOrdered; |
|
285 bool entireList; |
|
286 const nsAString *bulletType; |
|
287 |
|
288 // kAlign |
|
289 const nsAString *alignType; |
|
290 |
|
291 // kMakeBasicBlock |
|
292 const nsAString *blockType; |
|
293 |
|
294 // kInsertElement |
|
295 const nsIDOMElement* insertElement; |
|
296 }; |
|
297 |
|
298 |
|
299 /*************************************************************************** |
|
300 * stack based helper class for StartOperation()/EndOperation() sandwich. |
|
301 * this class sets a bool letting us know to ignore any rules sniffing |
|
302 * that tries to occur reentrantly. |
|
303 */ |
|
304 class nsAutoLockRulesSniffing |
|
305 { |
|
306 public: |
|
307 |
|
308 nsAutoLockRulesSniffing(nsTextEditRules *rules) : mRules(rules) |
|
309 {if (mRules) mRules->mLockRulesSniffing = true;} |
|
310 ~nsAutoLockRulesSniffing() |
|
311 {if (mRules) mRules->mLockRulesSniffing = false;} |
|
312 |
|
313 protected: |
|
314 nsTextEditRules *mRules; |
|
315 }; |
|
316 |
|
317 |
|
318 |
|
319 /*************************************************************************** |
|
320 * stack based helper class for turning on/off the edit listener. |
|
321 */ |
|
322 class nsAutoLockListener |
|
323 { |
|
324 public: |
|
325 |
|
326 nsAutoLockListener(bool *enabled) : mEnabled(enabled) |
|
327 {if (mEnabled) { mOldState=*mEnabled; *mEnabled = false;}} |
|
328 ~nsAutoLockListener() |
|
329 {if (mEnabled) *mEnabled = mOldState;} |
|
330 |
|
331 protected: |
|
332 bool *mEnabled; |
|
333 bool mOldState; |
|
334 }; |
|
335 |
|
336 #endif //nsTextEditRules_h__ |