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 #include "EditorCommands.h"
7 
8 #include "mozilla/ArrayUtils.h"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/FlushType.h"
11 #include "mozilla/TextEditor.h"
12 #include "mozilla/dom/Selection.h"
13 #include "nsCOMPtr.h"
14 #include "nsCRT.h"
15 #include "nsDebug.h"
16 #include "nsError.h"
17 #include "nsIClipboard.h"
18 #include "nsICommandParams.h"
19 #include "nsID.h"
20 #include "nsIDOMDocument.h"
21 #include "nsIDocument.h"
22 #include "nsIEditor.h"
23 #include "nsIEditorMailSupport.h"
24 #include "nsIPlaintextEditor.h"
25 #include "nsISelectionController.h"
26 #include "nsITransferable.h"
27 #include "nsString.h"
28 #include "nsAString.h"
29 
30 class nsISupports;
31 
32 #define STATE_ENABLED "state_enabled"
33 #define STATE_DATA "state_data"
34 
35 namespace mozilla {
36 
37 /******************************************************************************
38  * mozilla::EditorCommandBase
39  ******************************************************************************/
40 
EditorCommandBase()41 EditorCommandBase::EditorCommandBase() {}
42 
NS_IMPL_ISUPPORTS(EditorCommandBase,nsIControllerCommand)43 NS_IMPL_ISUPPORTS(EditorCommandBase, nsIControllerCommand)
44 
45 /******************************************************************************
46  * mozilla::UndoCommand
47  ******************************************************************************/
48 
49 NS_IMETHODIMP
50 UndoCommand::IsCommandEnabled(const char* aCommandName,
51                               nsISupports* aCommandRefCon, bool* aIsEnabled) {
52   if (NS_WARN_IF(!aIsEnabled)) {
53     return NS_ERROR_INVALID_ARG;
54   }
55 
56   *aIsEnabled = false;
57 
58   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
59   if (!editor) {
60     return NS_OK;
61   }
62   TextEditor* textEditor = editor->AsTextEditor();
63   MOZ_ASSERT(textEditor);
64   if (!textEditor->IsSelectionEditable()) {
65     return NS_OK;
66   }
67   bool isEnabled = false;
68   return editor->CanUndo(&isEnabled, aIsEnabled);
69 }
70 
71 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)72 UndoCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
73   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
74   if (!editor) {
75     return NS_ERROR_FAILURE;
76   }
77   TextEditor* textEditor = editor->AsTextEditor();
78   MOZ_ASSERT(textEditor);
79   return textEditor->Undo(1);
80 }
81 
82 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)83 UndoCommand::DoCommandParams(const char* aCommandName,
84                              nsICommandParams* aParams,
85                              nsISupports* aCommandRefCon) {
86   return DoCommand(aCommandName, aCommandRefCon);
87 }
88 
89 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)90 UndoCommand::GetCommandStateParams(const char* aCommandName,
91                                    nsICommandParams* aParams,
92                                    nsISupports* aCommandRefCon) {
93   bool canUndo;
94   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
95   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
96 }
97 
98 /******************************************************************************
99  * mozilla::RedoCommand
100  ******************************************************************************/
101 
102 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)103 RedoCommand::IsCommandEnabled(const char* aCommandName,
104                               nsISupports* aCommandRefCon, bool* aIsEnabled) {
105   if (NS_WARN_IF(!aIsEnabled)) {
106     return NS_ERROR_INVALID_ARG;
107   }
108 
109   *aIsEnabled = false;
110 
111   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
112   if (!editor) {
113     return NS_OK;
114   }
115   TextEditor* textEditor = editor->AsTextEditor();
116   MOZ_ASSERT(textEditor);
117   if (!textEditor->IsSelectionEditable()) {
118     return NS_OK;
119   }
120   bool isEnabled = false;
121   return editor->CanRedo(&isEnabled, aIsEnabled);
122 }
123 
124 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)125 RedoCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
126   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
127   if (!editor) {
128     return NS_ERROR_FAILURE;
129   }
130   TextEditor* textEditor = editor->AsTextEditor();
131   MOZ_ASSERT(textEditor);
132   return textEditor->Redo(1);
133 }
134 
135 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)136 RedoCommand::DoCommandParams(const char* aCommandName,
137                              nsICommandParams* aParams,
138                              nsISupports* aCommandRefCon) {
139   return DoCommand(aCommandName, aCommandRefCon);
140 }
141 
142 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)143 RedoCommand::GetCommandStateParams(const char* aCommandName,
144                                    nsICommandParams* aParams,
145                                    nsISupports* aCommandRefCon) {
146   bool canUndo;
147   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
148   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
149 }
150 
151 /******************************************************************************
152  * mozilla::ClearUndoCommand
153  ******************************************************************************/
154 
155 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)156 ClearUndoCommand::IsCommandEnabled(const char* aCommandName,
157                                    nsISupports* aCommandRefCon,
158                                    bool* aIsEnabled) {
159   if (NS_WARN_IF(!aIsEnabled)) {
160     return NS_ERROR_INVALID_ARG;
161   }
162   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
163   if (!editor) {
164     *aIsEnabled = false;
165     return NS_OK;
166   }
167   TextEditor* textEditor = editor->AsTextEditor();
168   MOZ_ASSERT(textEditor);
169   *aIsEnabled = textEditor->IsSelectionEditable();
170   return NS_OK;
171 }
172 
173 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)174 ClearUndoCommand::DoCommand(const char* aCommandName,
175                             nsISupports* aCommandRefCon) {
176   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
177   if (!editor) {
178     return NS_ERROR_FAILURE;
179   }
180   TextEditor* textEditor = editor->AsTextEditor();
181   MOZ_ASSERT(textEditor);
182   textEditor->EnableUndo(false);  // Turning off undo clears undo/redo stacks.
183   textEditor->EnableUndo(true);   // This re-enables undo/redo.
184   return NS_OK;
185 }
186 
187 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)188 ClearUndoCommand::DoCommandParams(const char* aCommandName,
189                                   nsICommandParams* aParams,
190                                   nsISupports* aCommandRefCon) {
191   return DoCommand(aCommandName, aCommandRefCon);
192 }
193 
194 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)195 ClearUndoCommand::GetCommandStateParams(const char* aCommandName,
196                                         nsICommandParams* aParams,
197                                         nsISupports* aCommandRefCon) {
198   NS_ENSURE_ARG_POINTER(aParams);
199 
200   bool enabled;
201   nsresult rv = IsCommandEnabled(aCommandName, aCommandRefCon, &enabled);
202   NS_ENSURE_SUCCESS(rv, rv);
203 
204   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
205 }
206 
207 /******************************************************************************
208  * mozilla::CutCommand
209  ******************************************************************************/
210 
211 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)212 CutCommand::IsCommandEnabled(const char* aCommandName,
213                              nsISupports* aCommandRefCon, bool* aIsEnabled) {
214   if (NS_WARN_IF(!aIsEnabled)) {
215     return NS_ERROR_INVALID_ARG;
216   }
217 
218   *aIsEnabled = false;
219 
220   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
221   if (!editor) {
222     return NS_OK;
223   }
224   TextEditor* textEditor = editor->AsTextEditor();
225   MOZ_ASSERT(textEditor);
226   if (!textEditor->IsSelectionEditable()) {
227     return NS_OK;
228   }
229   return editor->CanCut(aIsEnabled);
230 }
231 
232 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)233 CutCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
234   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
235   if (!editor) {
236     return NS_ERROR_FAILURE;
237   }
238   TextEditor* textEditor = editor->AsTextEditor();
239   MOZ_ASSERT(textEditor);
240   return textEditor->Cut();
241 }
242 
243 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)244 CutCommand::DoCommandParams(const char* aCommandName, nsICommandParams* aParams,
245                             nsISupports* aCommandRefCon) {
246   return DoCommand(aCommandName, aCommandRefCon);
247 }
248 
249 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)250 CutCommand::GetCommandStateParams(const char* aCommandName,
251                                   nsICommandParams* aParams,
252                                   nsISupports* aCommandRefCon) {
253   bool canUndo;
254   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
255   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
256 }
257 
258 /******************************************************************************
259  * mozilla::CutOrDeleteCommand
260  ******************************************************************************/
261 
262 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)263 CutOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
264                                      nsISupports* aCommandRefCon,
265                                      bool* aIsEnabled) {
266   if (NS_WARN_IF(!aIsEnabled)) {
267     return NS_ERROR_INVALID_ARG;
268   }
269   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
270   if (!editor) {
271     *aIsEnabled = false;
272     return NS_OK;
273   }
274   TextEditor* textEditor = editor->AsTextEditor();
275   MOZ_ASSERT(textEditor);
276   *aIsEnabled = textEditor->IsSelectionEditable();
277   return NS_OK;
278 }
279 
280 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)281 CutOrDeleteCommand::DoCommand(const char* aCommandName,
282                               nsISupports* aCommandRefCon) {
283   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
284   if (!editor) {
285     return NS_ERROR_FAILURE;
286   }
287   TextEditor* textEditor = editor->AsTextEditor();
288   MOZ_ASSERT(textEditor);
289   dom::Selection* selection = textEditor->GetSelection();
290   if (selection && selection->Collapsed()) {
291     return textEditor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
292   }
293   return textEditor->Cut();
294 }
295 
296 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)297 CutOrDeleteCommand::DoCommandParams(const char* aCommandName,
298                                     nsICommandParams* aParams,
299                                     nsISupports* aCommandRefCon) {
300   return DoCommand(aCommandName, aCommandRefCon);
301 }
302 
303 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)304 CutOrDeleteCommand::GetCommandStateParams(const char* aCommandName,
305                                           nsICommandParams* aParams,
306                                           nsISupports* aCommandRefCon) {
307   bool canUndo;
308   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
309   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
310 }
311 
312 /******************************************************************************
313  * mozilla::CopyCommand
314  ******************************************************************************/
315 
316 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)317 CopyCommand::IsCommandEnabled(const char* aCommandName,
318                               nsISupports* aCommandRefCon, bool* aIsEnabled) {
319   if (NS_WARN_IF(!aIsEnabled)) {
320     return NS_ERROR_INVALID_ARG;
321   }
322   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
323   if (!editor) {
324     *aIsEnabled = false;
325     return NS_OK;
326   }
327   TextEditor* textEditor = editor->AsTextEditor();
328   MOZ_ASSERT(textEditor);
329   return textEditor->CanCopy(aIsEnabled);
330 }
331 
332 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)333 CopyCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
334   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
335   if (!editor) {
336     return NS_ERROR_FAILURE;
337   }
338   TextEditor* textEditor = editor->AsTextEditor();
339   MOZ_ASSERT(textEditor);
340   return textEditor->Copy();
341 }
342 
343 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)344 CopyCommand::DoCommandParams(const char* aCommandName,
345                              nsICommandParams* aParams,
346                              nsISupports* aCommandRefCon) {
347   return DoCommand(aCommandName, aCommandRefCon);
348 }
349 
350 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)351 CopyCommand::GetCommandStateParams(const char* aCommandName,
352                                    nsICommandParams* aParams,
353                                    nsISupports* aCommandRefCon) {
354   bool canUndo;
355   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
356   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
357 }
358 
359 /******************************************************************************
360  * mozilla::CopyOrDeleteCommand
361  ******************************************************************************/
362 
363 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)364 CopyOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
365                                       nsISupports* aCommandRefCon,
366                                       bool* aIsEnabled) {
367   if (NS_WARN_IF(!aIsEnabled)) {
368     return NS_ERROR_INVALID_ARG;
369   }
370 
371   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
372   if (!editor) {
373     *aIsEnabled = false;
374     return NS_OK;
375   }
376   TextEditor* textEditor = editor->AsTextEditor();
377   MOZ_ASSERT(textEditor);
378   *aIsEnabled = textEditor->IsSelectionEditable();
379   return NS_OK;
380 }
381 
382 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)383 CopyOrDeleteCommand::DoCommand(const char* aCommandName,
384                                nsISupports* aCommandRefCon) {
385   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
386   if (!editor) {
387     return NS_ERROR_FAILURE;
388   }
389   TextEditor* textEditor = editor->AsTextEditor();
390   MOZ_ASSERT(textEditor);
391   dom::Selection* selection = textEditor->GetSelection();
392   if (selection && selection->Collapsed()) {
393     return textEditor->DeleteSelection(nsIEditor::eNextWord, nsIEditor::eStrip);
394   }
395   return textEditor->Copy();
396 }
397 
398 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)399 CopyOrDeleteCommand::DoCommandParams(const char* aCommandName,
400                                      nsICommandParams* aParams,
401                                      nsISupports* aCommandRefCon) {
402   return DoCommand(aCommandName, aCommandRefCon);
403 }
404 
405 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)406 CopyOrDeleteCommand::GetCommandStateParams(const char* aCommandName,
407                                            nsICommandParams* aParams,
408                                            nsISupports* aCommandRefCon) {
409   bool canUndo;
410   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
411   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
412 }
413 
414 /******************************************************************************
415  * mozilla::CopyAndCollapseToEndCommand
416  ******************************************************************************/
417 
418 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)419 CopyAndCollapseToEndCommand::IsCommandEnabled(const char* aCommandName,
420                                               nsISupports* aCommandRefCon,
421                                               bool* aIsEnabled) {
422   if (NS_WARN_IF(!aIsEnabled)) {
423     return NS_ERROR_INVALID_ARG;
424   }
425   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
426   if (!editor) {
427     *aIsEnabled = false;
428     return NS_OK;
429   }
430   TextEditor* textEditor = editor->AsTextEditor();
431   MOZ_ASSERT(textEditor);
432   return textEditor->CanCopy(aIsEnabled);
433 }
434 
435 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)436 CopyAndCollapseToEndCommand::DoCommand(const char* aCommandName,
437                                        nsISupports* aCommandRefCon) {
438   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
439   if (!editor) {
440     return NS_ERROR_FAILURE;
441   }
442   TextEditor* textEditor = editor->AsTextEditor();
443   MOZ_ASSERT(textEditor);
444   nsresult rv = textEditor->Copy();
445   if (NS_FAILED(rv)) {
446     return rv;
447   }
448   RefPtr<dom::Selection> selection = textEditor->GetSelection();
449   if (selection) {
450     selection->CollapseToEnd();
451   }
452   return NS_OK;
453 }
454 
455 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)456 CopyAndCollapseToEndCommand::DoCommandParams(const char* aCommandName,
457                                              nsICommandParams* aParams,
458                                              nsISupports* aCommandRefCon) {
459   return DoCommand(aCommandName, aCommandRefCon);
460 }
461 
462 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)463 CopyAndCollapseToEndCommand::GetCommandStateParams(
464     const char* aCommandName, nsICommandParams* aParams,
465     nsISupports* aCommandRefCon) {
466   bool canUndo;
467   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
468   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
469 }
470 
471 /******************************************************************************
472  * mozilla::PasteCommand
473  ******************************************************************************/
474 
475 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)476 PasteCommand::IsCommandEnabled(const char* aCommandName,
477                                nsISupports* aCommandRefCon, bool* aIsEnabled) {
478   if (NS_WARN_IF(!aIsEnabled)) {
479     return NS_ERROR_INVALID_ARG;
480   }
481 
482   *aIsEnabled = false;
483 
484   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
485   if (!editor) {
486     return NS_OK;
487   }
488   TextEditor* textEditor = editor->AsTextEditor();
489   MOZ_ASSERT(textEditor);
490   if (!textEditor->IsSelectionEditable()) {
491     return NS_OK;
492   }
493   return textEditor->CanPaste(nsIClipboard::kGlobalClipboard, aIsEnabled);
494 }
495 
496 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)497 PasteCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
498   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
499   if (NS_WARN_IF(!editor)) {
500     return NS_ERROR_FAILURE;
501   }
502   TextEditor* textEditor = editor->AsTextEditor();
503   MOZ_ASSERT(textEditor);
504   return textEditor->Paste(nsIClipboard::kGlobalClipboard);
505 }
506 
507 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)508 PasteCommand::DoCommandParams(const char* aCommandName,
509                               nsICommandParams* aParams,
510                               nsISupports* aCommandRefCon) {
511   return DoCommand(aCommandName, aCommandRefCon);
512 }
513 
514 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)515 PasteCommand::GetCommandStateParams(const char* aCommandName,
516                                     nsICommandParams* aParams,
517                                     nsISupports* aCommandRefCon) {
518   bool canUndo;
519   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
520   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
521 }
522 
523 /******************************************************************************
524  * mozilla::PasteTransferableCommand
525  ******************************************************************************/
526 
527 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)528 PasteTransferableCommand::IsCommandEnabled(const char* aCommandName,
529                                            nsISupports* aCommandRefCon,
530                                            bool* aIsEnabled) {
531   if (NS_WARN_IF(!aIsEnabled)) {
532     return NS_ERROR_INVALID_ARG;
533   }
534 
535   *aIsEnabled = false;
536 
537   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
538   if (!editor) {
539     return NS_OK;
540   }
541   TextEditor* textEditor = editor->AsTextEditor();
542   MOZ_ASSERT(textEditor);
543   if (!textEditor->IsSelectionEditable()) {
544     return NS_OK;
545   }
546   return textEditor->CanPasteTransferable(nullptr, aIsEnabled);
547 }
548 
549 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)550 PasteTransferableCommand::DoCommand(const char* aCommandName,
551                                     nsISupports* aCommandRefCon) {
552   return NS_ERROR_FAILURE;
553 }
554 
555 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)556 PasteTransferableCommand::DoCommandParams(const char* aCommandName,
557                                           nsICommandParams* aParams,
558                                           nsISupports* aCommandRefCon) {
559   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
560   if (NS_WARN_IF(!editor)) {
561     return NS_ERROR_FAILURE;
562   }
563 
564   nsCOMPtr<nsISupports> supports;
565   aParams->GetISupportsValue("transferable", getter_AddRefs(supports));
566   if (NS_WARN_IF(!supports)) {
567     return NS_ERROR_FAILURE;
568   }
569 
570   nsCOMPtr<nsITransferable> trans = do_QueryInterface(supports);
571   if (NS_WARN_IF(!trans)) {
572     return NS_ERROR_FAILURE;
573   }
574 
575   TextEditor* textEditor = editor->AsTextEditor();
576   MOZ_ASSERT(textEditor);
577   return textEditor->PasteTransferable(trans);
578 }
579 
580 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)581 PasteTransferableCommand::GetCommandStateParams(const char* aCommandName,
582                                                 nsICommandParams* aParams,
583                                                 nsISupports* aCommandRefCon) {
584   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
585   if (NS_WARN_IF(!editor)) {
586     return NS_ERROR_FAILURE;
587   }
588 
589   nsCOMPtr<nsISupports> supports;
590   aParams->GetISupportsValue("transferable", getter_AddRefs(supports));
591   if (NS_WARN_IF(!supports)) {
592     return NS_ERROR_FAILURE;
593   }
594 
595   nsCOMPtr<nsITransferable> trans;
596   trans = do_QueryInterface(supports);
597   if (NS_WARN_IF(!trans)) {
598     return NS_ERROR_FAILURE;
599   }
600 
601   TextEditor* textEditor = editor->AsTextEditor();
602   MOZ_ASSERT(textEditor);
603 
604   bool canPaste;
605   nsresult rv = textEditor->CanPasteTransferable(trans, &canPaste);
606   if (NS_WARN_IF(NS_FAILED(rv))) {
607     return rv;
608   }
609 
610   return aParams->SetBooleanValue(STATE_ENABLED, canPaste);
611 }
612 
613 /******************************************************************************
614  * mozilla::SwitchTextDirectionCommand
615  ******************************************************************************/
616 
617 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)618 SwitchTextDirectionCommand::IsCommandEnabled(const char* aCommandName,
619                                              nsISupports* aCommandRefCon,
620                                              bool* aIsEnabled) {
621   if (NS_WARN_IF(!aIsEnabled)) {
622     return NS_ERROR_INVALID_ARG;
623   }
624   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
625   if (!editor) {
626     *aIsEnabled = false;
627     return NS_OK;
628   }
629   TextEditor* textEditor = editor->AsTextEditor();
630   MOZ_ASSERT(textEditor);
631   *aIsEnabled = textEditor->IsSelectionEditable();
632   return NS_OK;
633 }
634 
635 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)636 SwitchTextDirectionCommand::DoCommand(const char* aCommandName,
637                                       nsISupports* aCommandRefCon) {
638   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
639   if (NS_WARN_IF(!editor)) {
640     return NS_ERROR_FAILURE;
641   }
642   TextEditor* textEditor = editor->AsTextEditor();
643   MOZ_ASSERT(textEditor);
644   return textEditor->SwitchTextDirection();
645 }
646 
647 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)648 SwitchTextDirectionCommand::DoCommandParams(const char* aCommandName,
649                                             nsICommandParams* aParams,
650                                             nsISupports* aCommandRefCon) {
651   return DoCommand(aCommandName, aCommandRefCon);
652 }
653 
654 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)655 SwitchTextDirectionCommand::GetCommandStateParams(const char* aCommandName,
656                                                   nsICommandParams* aParams,
657                                                   nsISupports* aCommandRefCon) {
658   bool canSwitchTextDirection = true;
659   IsCommandEnabled(aCommandName, aCommandRefCon, &canSwitchTextDirection);
660   return aParams->SetBooleanValue(STATE_ENABLED, canSwitchTextDirection);
661 }
662 
663 /******************************************************************************
664  * mozilla::DeleteCommand
665  ******************************************************************************/
666 
667 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)668 DeleteCommand::IsCommandEnabled(const char* aCommandName,
669                                 nsISupports* aCommandRefCon, bool* aIsEnabled) {
670   if (NS_WARN_IF(!aIsEnabled)) {
671     return NS_ERROR_INVALID_ARG;
672   }
673 
674   *aIsEnabled = false;
675 
676   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
677   if (!editor) {
678     return NS_OK;
679   }
680 
681   TextEditor* textEditor = editor->AsTextEditor();
682   MOZ_ASSERT(textEditor);
683 
684   // We can generally delete whenever the selection is editable.  However,
685   // cmd_delete doesn't make sense if the selection is collapsed because it's
686   // directionless, which is the same condition under which we can't cut.
687   *aIsEnabled = textEditor->IsSelectionEditable();
688 
689   if (!nsCRT::strcmp("cmd_delete", aCommandName) && *aIsEnabled) {
690     nsresult rv = textEditor->CanDelete(aIsEnabled);
691     if (NS_WARN_IF(NS_FAILED(rv))) {
692       return rv;
693     }
694   }
695   return NS_OK;
696 }
697 
698 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)699 DeleteCommand::DoCommand(const char* aCommandName,
700                          nsISupports* aCommandRefCon) {
701   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
702   if (NS_WARN_IF(!editor)) {
703     return NS_ERROR_FAILURE;
704   }
705 
706   nsIEditor::EDirection deleteDir = nsIEditor::eNone;
707 
708   if (!nsCRT::strcmp("cmd_delete", aCommandName)) {
709     // Really this should probably be eNone, but it only makes a difference if
710     // the selection is collapsed, and then this command is disabled.  So let's
711     // keep it as it always was to avoid breaking things.
712     deleteDir = nsIEditor::ePrevious;
713   } else if (!nsCRT::strcmp("cmd_deleteCharForward", aCommandName)) {
714     deleteDir = nsIEditor::eNext;
715   } else if (!nsCRT::strcmp("cmd_deleteCharBackward", aCommandName)) {
716     deleteDir = nsIEditor::ePrevious;
717   } else if (!nsCRT::strcmp("cmd_deleteWordBackward", aCommandName)) {
718     deleteDir = nsIEditor::ePreviousWord;
719   } else if (!nsCRT::strcmp("cmd_deleteWordForward", aCommandName)) {
720     deleteDir = nsIEditor::eNextWord;
721   } else if (!nsCRT::strcmp("cmd_deleteToBeginningOfLine", aCommandName)) {
722     deleteDir = nsIEditor::eToBeginningOfLine;
723   } else if (!nsCRT::strcmp("cmd_deleteToEndOfLine", aCommandName)) {
724     deleteDir = nsIEditor::eToEndOfLine;
725   } else {
726     MOZ_CRASH("Unrecognized nsDeleteCommand");
727   }
728 
729   TextEditor* textEditor = editor->AsTextEditor();
730   MOZ_ASSERT(textEditor);
731   return textEditor->DeleteSelection(deleteDir, nsIEditor::eStrip);
732 }
733 
734 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)735 DeleteCommand::DoCommandParams(const char* aCommandName,
736                                nsICommandParams* aParams,
737                                nsISupports* aCommandRefCon) {
738   return DoCommand(aCommandName, aCommandRefCon);
739 }
740 
741 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)742 DeleteCommand::GetCommandStateParams(const char* aCommandName,
743                                      nsICommandParams* aParams,
744                                      nsISupports* aCommandRefCon) {
745   bool canUndo;
746   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
747   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
748 }
749 
750 /******************************************************************************
751  * mozilla::SelectAllCommand
752  ******************************************************************************/
753 
754 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)755 SelectAllCommand::IsCommandEnabled(const char* aCommandName,
756                                    nsISupports* aCommandRefCon,
757                                    bool* aIsEnabled) {
758   NS_ENSURE_ARG_POINTER(aIsEnabled);
759 
760   nsresult rv = NS_OK;
761   // You can always select all, unless the selection is editable,
762   // and the editable region is empty!
763   *aIsEnabled = true;
764   bool docIsEmpty;
765 
766   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
767   if (!editor) {
768     return NS_OK;
769   }
770 
771   // You can select all if there is an editor which is non-empty
772   TextEditor* textEditor = editor->AsTextEditor();
773   MOZ_ASSERT(textEditor);
774   rv = textEditor->GetDocumentIsEmpty(&docIsEmpty);
775   if (NS_WARN_IF(NS_FAILED(rv))) {
776     return rv;
777   }
778   *aIsEnabled = !docIsEmpty;
779   return NS_OK;
780 }
781 
782 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)783 SelectAllCommand::DoCommand(const char* aCommandName,
784                             nsISupports* aCommandRefCon) {
785   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
786   if (!editor) {
787     return NS_ERROR_FAILURE;
788   }
789   TextEditor* textEditor = editor->AsTextEditor();
790   MOZ_ASSERT(textEditor);
791   return textEditor->SelectAll();
792 }
793 
794 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)795 SelectAllCommand::DoCommandParams(const char* aCommandName,
796                                   nsICommandParams* aParams,
797                                   nsISupports* aCommandRefCon) {
798   return DoCommand(aCommandName, aCommandRefCon);
799 }
800 
801 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)802 SelectAllCommand::GetCommandStateParams(const char* aCommandName,
803                                         nsICommandParams* aParams,
804                                         nsISupports* aCommandRefCon) {
805   bool canUndo;
806   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
807   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
808 }
809 
810 /******************************************************************************
811  * mozilla::SelectionMoveCommands
812  ******************************************************************************/
813 
814 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)815 SelectionMoveCommands::IsCommandEnabled(const char* aCommandName,
816                                         nsISupports* aCommandRefCon,
817                                         bool* aIsEnabled) {
818   NS_ENSURE_ARG_POINTER(aIsEnabled);
819   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
820   if (!editor) {
821     *aIsEnabled = false;
822     return NS_OK;
823   }
824   TextEditor* textEditor = editor->AsTextEditor();
825   MOZ_ASSERT(textEditor);
826   *aIsEnabled = textEditor->IsSelectionEditable();
827   return NS_OK;
828 }
829 
830 static const struct ScrollCommand {
831   const char* reverseScroll;
832   const char* forwardScroll;
833   nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
834 } scrollCommands[] = {{"cmd_scrollTop", "cmd_scrollBottom",
835                        &nsISelectionController::CompleteScroll},
836                       {"cmd_scrollPageUp", "cmd_scrollPageDown",
837                        &nsISelectionController::ScrollPage},
838                       {"cmd_scrollLineUp", "cmd_scrollLineDown",
839                        &nsISelectionController::ScrollLine}};
840 
841 static const struct MoveCommand {
842   const char* reverseMove;
843   const char* forwardMove;
844   const char* reverseSelect;
845   const char* forwardSelect;
846   nsresult (NS_STDCALL nsISelectionController::*move)(bool, bool);
847 } moveCommands[] = {
848     {"cmd_charPrevious", "cmd_charNext", "cmd_selectCharPrevious",
849      "cmd_selectCharNext", &nsISelectionController::CharacterMove},
850     {"cmd_linePrevious", "cmd_lineNext", "cmd_selectLinePrevious",
851      "cmd_selectLineNext", &nsISelectionController::LineMove},
852     {"cmd_wordPrevious", "cmd_wordNext", "cmd_selectWordPrevious",
853      "cmd_selectWordNext", &nsISelectionController::WordMove},
854     {"cmd_beginLine", "cmd_endLine", "cmd_selectBeginLine", "cmd_selectEndLine",
855      &nsISelectionController::IntraLineMove},
856     {"cmd_movePageUp", "cmd_movePageDown", "cmd_selectPageUp",
857      "cmd_selectPageDown", &nsISelectionController::PageMove},
858     {"cmd_moveTop", "cmd_moveBottom", "cmd_selectTop", "cmd_selectBottom",
859      &nsISelectionController::CompleteMove}};
860 
861 static const struct PhysicalCommand {
862   const char* move;
863   const char* select;
864   int16_t direction;
865   int16_t amount;
866 } physicalCommands[] = {
867     {"cmd_moveLeft", "cmd_selectLeft", nsISelectionController::MOVE_LEFT, 0},
868     {"cmd_moveRight", "cmd_selectRight", nsISelectionController::MOVE_RIGHT, 0},
869     {"cmd_moveUp", "cmd_selectUp", nsISelectionController::MOVE_UP, 0},
870     {"cmd_moveDown", "cmd_selectDown", nsISelectionController::MOVE_DOWN, 0},
871     {"cmd_moveLeft2", "cmd_selectLeft2", nsISelectionController::MOVE_LEFT, 1},
872     {"cmd_moveRight2", "cmd_selectRight2", nsISelectionController::MOVE_RIGHT,
873      1},
874     {"cmd_moveUp2", "cmd_selectUp2", nsISelectionController::MOVE_UP, 1},
875     {"cmd_moveDown2", "cmd_selectDown2", nsISelectionController::MOVE_DOWN, 1}};
876 
877 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)878 SelectionMoveCommands::DoCommand(const char* aCommandName,
879                                  nsISupports* aCommandRefCon) {
880   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
881   if (NS_WARN_IF(!editor)) {
882     return NS_ERROR_FAILURE;
883   }
884 
885   TextEditor* textEditor = editor->AsTextEditor();
886   MOZ_ASSERT(textEditor);
887   nsCOMPtr<nsIDocument> doc = textEditor->GetDocument();
888   if (doc) {
889     // Most of the commands below (possibly all of them) need layout to
890     // be up to date.
891     doc->FlushPendingNotifications(FlushType::Layout);
892   }
893 
894   nsCOMPtr<nsISelectionController> selectionController =
895       textEditor->GetSelectionController();
896   if (NS_WARN_IF(!selectionController)) {
897     return NS_ERROR_FAILURE;
898   }
899 
900   // scroll commands
901   for (size_t i = 0; i < mozilla::ArrayLength(scrollCommands); i++) {
902     const ScrollCommand& cmd = scrollCommands[i];
903     if (!nsCRT::strcmp(aCommandName, cmd.reverseScroll)) {
904       return (selectionController->*(cmd.scroll))(false);
905     } else if (!nsCRT::strcmp(aCommandName, cmd.forwardScroll)) {
906       return (selectionController->*(cmd.scroll))(true);
907     }
908   }
909 
910   // caret movement/selection commands
911   for (size_t i = 0; i < mozilla::ArrayLength(moveCommands); i++) {
912     const MoveCommand& cmd = moveCommands[i];
913     if (!nsCRT::strcmp(aCommandName, cmd.reverseMove)) {
914       return (selectionController->*(cmd.move))(false, false);
915     } else if (!nsCRT::strcmp(aCommandName, cmd.forwardMove)) {
916       return (selectionController->*(cmd.move))(true, false);
917     } else if (!nsCRT::strcmp(aCommandName, cmd.reverseSelect)) {
918       return (selectionController->*(cmd.move))(false, true);
919     } else if (!nsCRT::strcmp(aCommandName, cmd.forwardSelect)) {
920       return (selectionController->*(cmd.move))(true, true);
921     }
922   }
923 
924   // physical-direction movement/selection
925   for (size_t i = 0; i < mozilla::ArrayLength(physicalCommands); i++) {
926     const PhysicalCommand& cmd = physicalCommands[i];
927     if (!nsCRT::strcmp(aCommandName, cmd.move)) {
928       return selectionController->PhysicalMove(cmd.direction, cmd.amount,
929                                                false);
930     } else if (!nsCRT::strcmp(aCommandName, cmd.select)) {
931       return selectionController->PhysicalMove(cmd.direction, cmd.amount, true);
932     }
933   }
934 
935   return NS_ERROR_FAILURE;
936 }
937 
938 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)939 SelectionMoveCommands::DoCommandParams(const char* aCommandName,
940                                        nsICommandParams* aParams,
941                                        nsISupports* aCommandRefCon) {
942   return DoCommand(aCommandName, aCommandRefCon);
943 }
944 
945 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)946 SelectionMoveCommands::GetCommandStateParams(const char* aCommandName,
947                                              nsICommandParams* aParams,
948                                              nsISupports* aCommandRefCon) {
949   bool canUndo;
950   IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
951   return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
952 }
953 
954 /******************************************************************************
955  * mozilla::InsertPlaintextCommand
956  ******************************************************************************/
957 
958 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)959 InsertPlaintextCommand::IsCommandEnabled(const char* aCommandName,
960                                          nsISupports* aCommandRefCon,
961                                          bool* aIsEnabled) {
962   if (NS_WARN_IF(!aIsEnabled)) {
963     return NS_ERROR_INVALID_ARG;
964   }
965   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
966   if (NS_WARN_IF(!editor)) {
967     *aIsEnabled = false;
968     return NS_ERROR_FAILURE;
969   }
970   TextEditor* textEditor = editor->AsTextEditor();
971   MOZ_ASSERT(textEditor);
972   *aIsEnabled = textEditor->IsSelectionEditable();
973   return NS_OK;
974 }
975 
976 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)977 InsertPlaintextCommand::DoCommand(const char* aCommandName,
978                                   nsISupports* aCommandRefCon) {
979   // No value is equivalent to empty string
980   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
981   if (NS_WARN_IF(!editor)) {
982     return NS_ERROR_FAILURE;
983   }
984   TextEditor* textEditor = editor->AsTextEditor();
985   MOZ_ASSERT(textEditor);
986   return textEditor->InsertText(EmptyString());
987 }
988 
989 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)990 InsertPlaintextCommand::DoCommandParams(const char* aCommandName,
991                                         nsICommandParams* aParams,
992                                         nsISupports* aCommandRefCon) {
993   if (NS_WARN_IF(!aParams)) {
994     return NS_ERROR_INVALID_ARG;
995   }
996 
997   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
998   if (NS_WARN_IF(!editor)) {
999     return NS_ERROR_FAILURE;
1000   }
1001 
1002   // Get text to insert from command params
1003   nsAutoString text;
1004   nsresult rv = aParams->GetStringValue(STATE_DATA, text);
1005   if (NS_WARN_IF(NS_FAILED(rv))) {
1006     return rv;
1007   }
1008 
1009   TextEditor* textEditor = editor->AsTextEditor();
1010   MOZ_ASSERT(textEditor);
1011   return textEditor->InsertText(text);
1012 }
1013 
1014 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)1015 InsertPlaintextCommand::GetCommandStateParams(const char* aCommandName,
1016                                               nsICommandParams* aParams,
1017                                               nsISupports* aCommandRefCon) {
1018   if (NS_WARN_IF(!aParams)) {
1019     return NS_ERROR_INVALID_ARG;
1020   }
1021 
1022   bool aIsEnabled = false;
1023   IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
1024   return aParams->SetBooleanValue(STATE_ENABLED, aIsEnabled);
1025 }
1026 
1027 /******************************************************************************
1028  * mozilla::InsertParagraphCommand
1029  ******************************************************************************/
1030 
1031 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)1032 InsertParagraphCommand::IsCommandEnabled(const char* aCommandName,
1033                                          nsISupports* aCommandRefCon,
1034                                          bool* aIsEnabled) {
1035   if (NS_WARN_IF(!aIsEnabled)) {
1036     return NS_ERROR_INVALID_ARG;
1037   }
1038   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1039   if (NS_WARN_IF(!editor)) {
1040     *aIsEnabled = false;
1041     return NS_ERROR_FAILURE;
1042   }
1043 
1044   TextEditor* textEditor = editor->AsTextEditor();
1045   MOZ_ASSERT(textEditor);
1046   *aIsEnabled = textEditor->IsSelectionEditable();
1047   return NS_OK;
1048 }
1049 
1050 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)1051 InsertParagraphCommand::DoCommand(const char* aCommandName,
1052                                   nsISupports* aCommandRefCon) {
1053   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1054   if (NS_WARN_IF(!editor)) {
1055     return NS_ERROR_FAILURE;
1056   }
1057 
1058   TextEditor* textEditor = editor->AsTextEditor();
1059   MOZ_ASSERT(textEditor);
1060   return textEditor->TypedText(EmptyString(), TextEditor::eTypedBreak);
1061 }
1062 
1063 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)1064 InsertParagraphCommand::DoCommandParams(const char* aCommandName,
1065                                         nsICommandParams* aParams,
1066                                         nsISupports* aCommandRefCon) {
1067   return DoCommand(aCommandName, aCommandRefCon);
1068 }
1069 
1070 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)1071 InsertParagraphCommand::GetCommandStateParams(const char* aCommandName,
1072                                               nsICommandParams* aParams,
1073                                               nsISupports* aCommandRefCon) {
1074   if (NS_WARN_IF(!aParams)) {
1075     return NS_ERROR_INVALID_ARG;
1076   }
1077 
1078   bool aIsEnabled = false;
1079   IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
1080   return aParams->SetBooleanValue(STATE_ENABLED, aIsEnabled);
1081 }
1082 
1083 /******************************************************************************
1084  * mozilla::InsertLineBreakCommand
1085  ******************************************************************************/
1086 
1087 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)1088 InsertLineBreakCommand::IsCommandEnabled(const char* aCommandName,
1089                                          nsISupports* aCommandRefCon,
1090                                          bool* aIsEnabled) {
1091   if (NS_WARN_IF(!aIsEnabled)) {
1092     return NS_ERROR_INVALID_ARG;
1093   }
1094   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1095   if (NS_WARN_IF(!editor)) {
1096     *aIsEnabled = false;
1097     return NS_ERROR_FAILURE;
1098   }
1099 
1100   TextEditor* textEditor = editor->AsTextEditor();
1101   MOZ_ASSERT(textEditor);
1102   *aIsEnabled = textEditor->IsSelectionEditable();
1103   return NS_OK;
1104 }
1105 
1106 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)1107 InsertLineBreakCommand::DoCommand(const char* aCommandName,
1108                                   nsISupports* aCommandRefCon) {
1109   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1110   if (NS_WARN_IF(!editor)) {
1111     return NS_ERROR_FAILURE;
1112   }
1113 
1114   TextEditor* textEditor = editor->AsTextEditor();
1115   MOZ_ASSERT(textEditor);
1116   return textEditor->TypedText(EmptyString(), TextEditor::eTypedBR);
1117 }
1118 
1119 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)1120 InsertLineBreakCommand::DoCommandParams(const char* aCommandName,
1121                                         nsICommandParams* aParams,
1122                                         nsISupports* aCommandRefCon) {
1123   return DoCommand(aCommandName, aCommandRefCon);
1124 }
1125 
1126 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)1127 InsertLineBreakCommand::GetCommandStateParams(const char* aCommandName,
1128                                               nsICommandParams* aParams,
1129                                               nsISupports* aCommandRefCon) {
1130   if (NS_WARN_IF(!aParams)) {
1131     return NS_ERROR_INVALID_ARG;
1132   }
1133 
1134   bool aIsEnabled = false;
1135   IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
1136   return aParams->SetBooleanValue(STATE_ENABLED, aIsEnabled);
1137 }
1138 
1139 /******************************************************************************
1140  * mozilla::PasteQuotationCommand
1141  ******************************************************************************/
1142 
1143 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * aIsEnabled)1144 PasteQuotationCommand::IsCommandEnabled(const char* aCommandName,
1145                                         nsISupports* aCommandRefCon,
1146                                         bool* aIsEnabled) {
1147   if (NS_WARN_IF(!aIsEnabled)) {
1148     return NS_ERROR_INVALID_ARG;
1149   }
1150 
1151   *aIsEnabled = false;
1152 
1153   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1154   if (!editor) {
1155     return NS_OK;
1156   }
1157   TextEditor* textEditor = editor->AsTextEditor();
1158   MOZ_ASSERT(textEditor);
1159   if (textEditor->IsSingleLineEditor()) {
1160     return NS_OK;
1161   }
1162   return textEditor->CanPaste(nsIClipboard::kGlobalClipboard, aIsEnabled);
1163 }
1164 
1165 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * aCommandRefCon)1166 PasteQuotationCommand::DoCommand(const char* aCommandName,
1167                                  nsISupports* aCommandRefCon) {
1168   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1169   if (NS_WARN_IF(!editor)) {
1170     return NS_ERROR_FAILURE;
1171   }
1172   TextEditor* textEditor = editor->AsTextEditor();
1173   MOZ_ASSERT(textEditor);
1174   return textEditor->PasteAsQuotation(nsIClipboard::kGlobalClipboard);
1175 }
1176 
1177 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)1178 PasteQuotationCommand::DoCommandParams(const char* aCommandName,
1179                                        nsICommandParams* aParams,
1180                                        nsISupports* aCommandRefCon) {
1181   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1182   if (!editor) {
1183     return NS_ERROR_FAILURE;
1184   }
1185   TextEditor* textEditor = editor->AsTextEditor();
1186   MOZ_ASSERT(textEditor);
1187   return textEditor->PasteAsQuotation(nsIClipboard::kGlobalClipboard);
1188 }
1189 
1190 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * aCommandRefCon)1191 PasteQuotationCommand::GetCommandStateParams(const char* aCommandName,
1192                                              nsICommandParams* aParams,
1193                                              nsISupports* aCommandRefCon) {
1194   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
1195   if (!editor) {
1196     return NS_OK;
1197   }
1198   TextEditor* textEditor = editor->AsTextEditor();
1199   MOZ_ASSERT(textEditor);
1200   bool enabled = false;
1201   textEditor->CanPaste(nsIClipboard::kGlobalClipboard, &enabled);
1202   aParams->SetBooleanValue(STATE_ENABLED, enabled);
1203   return NS_OK;
1204 }
1205 
1206 }  // namespace mozilla
1207