Bug 1247796. Use keyboardFocusIndicatorColor for ActiveBorder system color keyword...
[gecko.git] / editor / libeditor / nsEditorCommands.cpp
blobdd7f87af18182636b6145f9ab706c6a19c403310
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/. */
6 #include "nsEditorCommands.h"
8 #include "mozFlushType.h"
9 #include "mozilla/ArrayUtils.h"
10 #include "mozilla/Assertions.h"
11 #include "nsCOMPtr.h"
12 #include "nsCRT.h"
13 #include "nsDebug.h"
14 #include "nsError.h"
15 #include "nsIClipboard.h"
16 #include "nsICommandParams.h"
17 #include "nsID.h"
18 #include "nsIDOMDocument.h"
19 #include "nsIDocument.h"
20 #include "nsIEditor.h"
21 #include "nsIEditorMailSupport.h"
22 #include "nsIPlaintextEditor.h"
23 #include "nsISelection.h"
24 #include "nsISelectionController.h"
25 #include "nsITransferable.h"
26 #include "nsString.h"
27 #include "nsAString.h"
29 class nsISupports;
31 #define STATE_ENABLED "state_enabled"
32 #define STATE_DATA "state_data"
34 nsBaseEditorCommand::nsBaseEditorCommand() {}
36 NS_IMPL_ISUPPORTS(nsBaseEditorCommand, nsIControllerCommand)
38 NS_IMETHODIMP
39 nsUndoCommand::IsCommandEnabled(const char *aCommandName,
40 nsISupports *aCommandRefCon,
41 bool *outCmdEnabled)
43 NS_ENSURE_ARG_POINTER(outCmdEnabled);
44 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
45 if (editor) {
46 bool isEnabled, isEditable = false;
47 nsresult rv = editor->GetIsSelectionEditable(&isEditable);
48 NS_ENSURE_SUCCESS(rv, rv);
49 if (isEditable)
50 return editor->CanUndo(&isEnabled, outCmdEnabled);
53 *outCmdEnabled = false;
54 return NS_OK;
57 NS_IMETHODIMP
58 nsUndoCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon)
60 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
61 if (editor)
62 return editor->Undo(1);
64 return NS_ERROR_FAILURE;
67 NS_IMETHODIMP
68 nsUndoCommand::DoCommandParams(const char *aCommandName,
69 nsICommandParams *aParams,
70 nsISupports *aCommandRefCon)
72 return DoCommand(aCommandName, aCommandRefCon);
75 NS_IMETHODIMP
76 nsUndoCommand::GetCommandStateParams(const char *aCommandName,
77 nsICommandParams *aParams,
78 nsISupports *aCommandRefCon)
80 bool canUndo;
81 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
82 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
85 NS_IMETHODIMP
86 nsRedoCommand::IsCommandEnabled(const char *aCommandName,
87 nsISupports *aCommandRefCon,
88 bool *outCmdEnabled)
90 NS_ENSURE_ARG_POINTER(outCmdEnabled);
91 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
92 if (editor) {
93 bool isEnabled, isEditable = false;
94 nsresult rv = editor->GetIsSelectionEditable(&isEditable);
95 NS_ENSURE_SUCCESS(rv, rv);
96 if (isEditable)
97 return editor->CanRedo(&isEnabled, outCmdEnabled);
100 *outCmdEnabled = false;
101 return NS_OK;
104 NS_IMETHODIMP
105 nsRedoCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon)
107 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
108 if (editor)
109 return editor->Redo(1);
111 return NS_ERROR_FAILURE;
114 NS_IMETHODIMP
115 nsRedoCommand::DoCommandParams(const char *aCommandName,
116 nsICommandParams *aParams,
117 nsISupports *aCommandRefCon)
119 return DoCommand(aCommandName, aCommandRefCon);
122 NS_IMETHODIMP
123 nsRedoCommand::GetCommandStateParams(const char *aCommandName,
124 nsICommandParams *aParams,
125 nsISupports *aCommandRefCon)
127 bool canUndo;
128 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
129 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
132 NS_IMETHODIMP
133 nsClearUndoCommand::IsCommandEnabled(const char *aCommandName,
134 nsISupports *refCon, bool *outCmdEnabled)
136 NS_ENSURE_ARG_POINTER(outCmdEnabled);
137 nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
138 if (editor)
139 return editor->GetIsSelectionEditable(outCmdEnabled);
141 *outCmdEnabled = false;
142 return NS_OK;
145 NS_IMETHODIMP
146 nsClearUndoCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
148 nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
149 NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
151 editor->EnableUndo(false); // Turning off undo clears undo/redo stacks.
152 editor->EnableUndo(true); // This re-enables undo/redo.
154 return NS_OK;
157 NS_IMETHODIMP
158 nsClearUndoCommand::DoCommandParams(const char *aCommandName,
159 nsICommandParams *aParams,
160 nsISupports *refCon)
162 return DoCommand(aCommandName, refCon);
165 NS_IMETHODIMP
166 nsClearUndoCommand::GetCommandStateParams(const char *aCommandName,
167 nsICommandParams *aParams,
168 nsISupports *refCon)
170 NS_ENSURE_ARG_POINTER(aParams);
172 bool enabled;
173 nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
174 NS_ENSURE_SUCCESS(rv, rv);
176 return aParams->SetBooleanValue(STATE_ENABLED, enabled);
179 NS_IMETHODIMP
180 nsCutCommand::IsCommandEnabled(const char *aCommandName,
181 nsISupports *aCommandRefCon, bool *outCmdEnabled)
183 NS_ENSURE_ARG_POINTER(outCmdEnabled);
184 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
185 if (editor) {
186 bool isEditable = false;
187 nsresult rv = editor->GetIsSelectionEditable(&isEditable);
188 NS_ENSURE_SUCCESS(rv, rv);
189 if (isEditable)
190 return editor->CanCut(outCmdEnabled);
193 *outCmdEnabled = false;
194 return NS_OK;
197 NS_IMETHODIMP
198 nsCutCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon)
200 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
201 if (editor)
202 return editor->Cut();
204 return NS_ERROR_FAILURE;
207 NS_IMETHODIMP
208 nsCutCommand::DoCommandParams(const char *aCommandName,
209 nsICommandParams *aParams,
210 nsISupports *aCommandRefCon)
212 return DoCommand(aCommandName, aCommandRefCon);
215 NS_IMETHODIMP
216 nsCutCommand::GetCommandStateParams(const char *aCommandName,
217 nsICommandParams *aParams,
218 nsISupports *aCommandRefCon)
220 bool canUndo;
221 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
222 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
225 NS_IMETHODIMP
226 nsCutOrDeleteCommand::IsCommandEnabled(const char *aCommandName,
227 nsISupports *aCommandRefCon,
228 bool *outCmdEnabled)
230 NS_ENSURE_ARG_POINTER(outCmdEnabled);
231 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
232 if (editor)
233 return editor->GetIsSelectionEditable(outCmdEnabled);
235 *outCmdEnabled = false;
236 return NS_OK;
239 NS_IMETHODIMP
240 nsCutOrDeleteCommand::DoCommand(const char *aCommandName,
241 nsISupports *aCommandRefCon)
243 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
244 if (editor) {
245 nsCOMPtr<nsISelection> selection;
246 nsresult rv = editor->GetSelection(getter_AddRefs(selection));
247 if (NS_SUCCEEDED(rv) && selection && selection->Collapsed()) {
248 return editor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
250 return editor->Cut();
253 return NS_ERROR_FAILURE;
256 NS_IMETHODIMP
257 nsCutOrDeleteCommand::DoCommandParams(const char *aCommandName,
258 nsICommandParams *aParams,
259 nsISupports *aCommandRefCon)
261 return DoCommand(aCommandName, aCommandRefCon);
264 NS_IMETHODIMP
265 nsCutOrDeleteCommand::GetCommandStateParams(const char *aCommandName,
266 nsICommandParams *aParams,
267 nsISupports *aCommandRefCon)
269 bool canUndo;
270 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
271 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
274 NS_IMETHODIMP
275 nsCopyCommand::IsCommandEnabled(const char *aCommandName,
276 nsISupports *aCommandRefCon,
277 bool *outCmdEnabled)
279 NS_ENSURE_ARG_POINTER(outCmdEnabled);
280 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
281 if (editor)
282 return editor->CanCopy(outCmdEnabled);
284 *outCmdEnabled = false;
285 return NS_OK;
288 NS_IMETHODIMP
289 nsCopyCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon)
291 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
292 if (editor)
293 return editor->Copy();
295 return NS_ERROR_FAILURE;
298 NS_IMETHODIMP
299 nsCopyCommand::DoCommandParams(const char *aCommandName,
300 nsICommandParams *aParams,
301 nsISupports *aCommandRefCon)
303 return DoCommand(aCommandName, aCommandRefCon);
306 NS_IMETHODIMP
307 nsCopyCommand::GetCommandStateParams(const char *aCommandName,
308 nsICommandParams *aParams,
309 nsISupports *aCommandRefCon)
311 bool canUndo;
312 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
313 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
316 NS_IMETHODIMP
317 nsCopyOrDeleteCommand::IsCommandEnabled(const char *aCommandName,
318 nsISupports *aCommandRefCon,
319 bool *outCmdEnabled)
321 NS_ENSURE_ARG_POINTER(outCmdEnabled);
322 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
323 if (editor)
324 return editor->GetIsSelectionEditable(outCmdEnabled);
326 *outCmdEnabled = false;
327 return NS_OK;
330 NS_IMETHODIMP
331 nsCopyOrDeleteCommand::DoCommand(const char *aCommandName,
332 nsISupports *aCommandRefCon)
334 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
335 if (editor) {
336 nsCOMPtr<nsISelection> selection;
337 nsresult rv = editor->GetSelection(getter_AddRefs(selection));
338 if (NS_SUCCEEDED(rv) && selection && selection->Collapsed()) {
339 return editor->DeleteSelection(nsIEditor::eNextWord, nsIEditor::eStrip);
341 return editor->Copy();
344 return NS_ERROR_FAILURE;
347 NS_IMETHODIMP
348 nsCopyOrDeleteCommand::DoCommandParams(const char *aCommandName,
349 nsICommandParams *aParams,
350 nsISupports *aCommandRefCon)
352 return DoCommand(aCommandName, aCommandRefCon);
355 NS_IMETHODIMP
356 nsCopyOrDeleteCommand::GetCommandStateParams(const char *aCommandName,
357 nsICommandParams *aParams,
358 nsISupports *aCommandRefCon)
360 bool canUndo;
361 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
362 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
365 NS_IMETHODIMP
366 nsCopyAndCollapseToEndCommand::IsCommandEnabled(const char *aCommandName,
367 nsISupports *aCommandRefCon,
368 bool *outCmdEnabled)
370 NS_ENSURE_ARG_POINTER(outCmdEnabled);
371 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
372 if (editor)
373 return editor->CanCopy(outCmdEnabled);
375 *outCmdEnabled = false;
376 return NS_OK;
379 NS_IMETHODIMP
380 nsCopyAndCollapseToEndCommand::DoCommand(const char *aCommandName,
381 nsISupports *aCommandRefCon)
383 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
384 if (editor) {
385 nsresult rv = editor->Copy();
386 if (NS_FAILED(rv)) {
387 return rv;
390 nsCOMPtr<nsISelection> selection;
391 rv = editor->GetSelection(getter_AddRefs(selection));
392 if (NS_SUCCEEDED(rv) && selection) {
393 selection->CollapseToEnd();
395 return rv;
398 return NS_ERROR_FAILURE;
401 NS_IMETHODIMP
402 nsCopyAndCollapseToEndCommand::DoCommandParams(const char *aCommandName,
403 nsICommandParams *aParams,
404 nsISupports *aCommandRefCon)
406 return DoCommand(aCommandName, aCommandRefCon);
409 NS_IMETHODIMP
410 nsCopyAndCollapseToEndCommand::GetCommandStateParams(
411 const char *aCommandName, nsICommandParams *aParams,
412 nsISupports *aCommandRefCon)
414 bool canUndo;
415 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
416 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
419 NS_IMETHODIMP
420 nsPasteCommand::IsCommandEnabled(const char *aCommandName,
421 nsISupports *aCommandRefCon,
422 bool *outCmdEnabled)
424 NS_ENSURE_ARG_POINTER(outCmdEnabled);
425 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
426 if (editor) {
427 bool isEditable = false;
428 nsresult rv = editor->GetIsSelectionEditable(&isEditable);
429 NS_ENSURE_SUCCESS(rv, rv);
430 if (isEditable)
431 return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled);
434 *outCmdEnabled = false;
435 return NS_OK;
438 NS_IMETHODIMP
439 nsPasteCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon)
441 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
442 NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
444 return editor->Paste(nsIClipboard::kGlobalClipboard);
447 NS_IMETHODIMP
448 nsPasteCommand::DoCommandParams(const char *aCommandName,
449 nsICommandParams *aParams,
450 nsISupports *aCommandRefCon)
452 return DoCommand(aCommandName, aCommandRefCon);
455 NS_IMETHODIMP
456 nsPasteCommand::GetCommandStateParams(const char *aCommandName,
457 nsICommandParams *aParams,
458 nsISupports *aCommandRefCon)
460 bool canUndo;
461 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
462 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
465 NS_IMETHODIMP
466 nsPasteTransferableCommand::IsCommandEnabled(const char *aCommandName,
467 nsISupports *aCommandRefCon,
468 bool *outCmdEnabled)
470 NS_ENSURE_ARG_POINTER(outCmdEnabled);
471 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
472 if (editor) {
473 bool isEditable = false;
474 nsresult rv = editor->GetIsSelectionEditable(&isEditable);
475 NS_ENSURE_SUCCESS(rv, rv);
476 if (isEditable)
477 return editor->CanPasteTransferable(nullptr, outCmdEnabled);
480 *outCmdEnabled = false;
481 return NS_OK;
484 NS_IMETHODIMP
485 nsPasteTransferableCommand::DoCommand(const char *aCommandName,
486 nsISupports *aCommandRefCon)
488 return NS_ERROR_FAILURE;
491 NS_IMETHODIMP
492 nsPasteTransferableCommand::DoCommandParams(const char *aCommandName,
493 nsICommandParams *aParams,
494 nsISupports *aCommandRefCon)
496 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
497 NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
499 nsCOMPtr<nsISupports> supports;
500 aParams->GetISupportsValue("transferable", getter_AddRefs(supports));
501 NS_ENSURE_TRUE(supports, NS_ERROR_FAILURE);
503 nsCOMPtr<nsITransferable> trans = do_QueryInterface(supports);
504 NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
506 return editor->PasteTransferable(trans);
509 NS_IMETHODIMP
510 nsPasteTransferableCommand::GetCommandStateParams(const char *aCommandName,
511 nsICommandParams *aParams,
512 nsISupports *aCommandRefCon)
514 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
515 NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
517 nsCOMPtr<nsITransferable> trans;
519 nsCOMPtr<nsISupports> supports;
520 aParams->GetISupportsValue("transferable", getter_AddRefs(supports));
521 if (supports) {
522 trans = do_QueryInterface(supports);
523 NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
526 bool canPaste;
527 nsresult rv = editor->CanPasteTransferable(trans, &canPaste);
528 NS_ENSURE_SUCCESS(rv, rv);
530 return aParams->SetBooleanValue(STATE_ENABLED, canPaste);
533 NS_IMETHODIMP
534 nsSwitchTextDirectionCommand::IsCommandEnabled(const char *aCommandName,
535 nsISupports *aCommandRefCon,
536 bool *outCmdEnabled)
538 NS_ENSURE_ARG_POINTER(outCmdEnabled);
539 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
540 if (editor)
541 return editor->GetIsSelectionEditable(outCmdEnabled);
543 *outCmdEnabled = false;
544 return NS_OK;
547 NS_IMETHODIMP
548 nsSwitchTextDirectionCommand::DoCommand(const char *aCommandName,
549 nsISupports *aCommandRefCon)
551 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
552 NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
554 return editor->SwitchTextDirection();
557 NS_IMETHODIMP
558 nsSwitchTextDirectionCommand::DoCommandParams(const char *aCommandName,
559 nsICommandParams *aParams,
560 nsISupports *aCommandRefCon)
562 return DoCommand(aCommandName, aCommandRefCon);
565 NS_IMETHODIMP
566 nsSwitchTextDirectionCommand::GetCommandStateParams(const char *aCommandName,
567 nsICommandParams *aParams,
568 nsISupports *aCommandRefCon)
570 bool canSwitchTextDirection = true;
571 IsCommandEnabled(aCommandName, aCommandRefCon, &canSwitchTextDirection);
572 return aParams->SetBooleanValue(STATE_ENABLED, canSwitchTextDirection);
575 NS_IMETHODIMP
576 nsDeleteCommand::IsCommandEnabled(const char *aCommandName,
577 nsISupports *aCommandRefCon,
578 bool *outCmdEnabled)
580 NS_ENSURE_ARG_POINTER(outCmdEnabled);
581 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
582 *outCmdEnabled = false;
584 NS_ENSURE_TRUE(editor, NS_OK);
586 // We can generally delete whenever the selection is editable. However,
587 // cmd_delete doesn't make sense if the selection is collapsed because it's
588 // directionless, which is the same condition under which we can't cut.
589 nsresult rv = editor->GetIsSelectionEditable(outCmdEnabled);
590 NS_ENSURE_SUCCESS(rv, rv);
592 if (!nsCRT::strcmp("cmd_delete", aCommandName) && *outCmdEnabled) {
593 rv = editor->CanDelete(outCmdEnabled);
594 NS_ENSURE_SUCCESS(rv, rv);
597 return NS_OK;
600 NS_IMETHODIMP
601 nsDeleteCommand::DoCommand(const char *aCommandName,
602 nsISupports *aCommandRefCon)
604 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
605 NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
607 nsIEditor::EDirection deleteDir = nsIEditor::eNone;
609 if (!nsCRT::strcmp("cmd_delete", aCommandName)) {
610 // Really this should probably be eNone, but it only makes a difference if
611 // the selection is collapsed, and then this command is disabled. So let's
612 // keep it as it always was to avoid breaking things.
613 deleteDir = nsIEditor::ePrevious;
614 } else if (!nsCRT::strcmp("cmd_deleteCharForward", aCommandName)) {
615 deleteDir = nsIEditor::eNext;
616 } else if (!nsCRT::strcmp("cmd_deleteCharBackward", aCommandName)) {
617 deleteDir = nsIEditor::ePrevious;
618 } else if (!nsCRT::strcmp("cmd_deleteWordBackward", aCommandName)) {
619 deleteDir = nsIEditor::ePreviousWord;
620 } else if (!nsCRT::strcmp("cmd_deleteWordForward", aCommandName)) {
621 deleteDir = nsIEditor::eNextWord;
622 } else if (!nsCRT::strcmp("cmd_deleteToBeginningOfLine", aCommandName)) {
623 deleteDir = nsIEditor::eToBeginningOfLine;
624 } else if (!nsCRT::strcmp("cmd_deleteToEndOfLine", aCommandName)) {
625 deleteDir = nsIEditor::eToEndOfLine;
626 } else {
627 MOZ_CRASH("Unrecognized nsDeleteCommand");
630 return editor->DeleteSelection(deleteDir, nsIEditor::eStrip);
633 NS_IMETHODIMP
634 nsDeleteCommand::DoCommandParams(const char *aCommandName,
635 nsICommandParams *aParams,
636 nsISupports *aCommandRefCon)
638 return DoCommand(aCommandName, aCommandRefCon);
641 NS_IMETHODIMP
642 nsDeleteCommand::GetCommandStateParams(const char *aCommandName,
643 nsICommandParams *aParams,
644 nsISupports *aCommandRefCon)
646 bool canUndo;
647 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
648 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
651 NS_IMETHODIMP
652 nsSelectAllCommand::IsCommandEnabled(const char *aCommandName,
653 nsISupports *aCommandRefCon,
654 bool *outCmdEnabled)
656 NS_ENSURE_ARG_POINTER(outCmdEnabled);
658 nsresult rv = NS_OK;
659 // You can always select all, unless the selection is editable,
660 // and the editable region is empty!
661 *outCmdEnabled = true;
662 bool docIsEmpty;
664 // you can select all if there is an editor which is non-empty
665 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
666 if (editor) {
667 rv = editor->GetDocumentIsEmpty(&docIsEmpty);
668 NS_ENSURE_SUCCESS(rv, rv);
669 *outCmdEnabled = !docIsEmpty;
672 return rv;
675 NS_IMETHODIMP
676 nsSelectAllCommand::DoCommand(const char *aCommandName,
677 nsISupports *aCommandRefCon)
679 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
680 if (editor)
681 return editor->SelectAll();
683 return NS_ERROR_FAILURE;
686 NS_IMETHODIMP
687 nsSelectAllCommand::DoCommandParams(const char *aCommandName,
688 nsICommandParams *aParams,
689 nsISupports *aCommandRefCon)
691 return DoCommand(aCommandName, aCommandRefCon);
694 NS_IMETHODIMP
695 nsSelectAllCommand::GetCommandStateParams(const char *aCommandName,
696 nsICommandParams *aParams,
697 nsISupports *aCommandRefCon)
699 bool canUndo;
700 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
701 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
704 NS_IMETHODIMP
705 nsSelectionMoveCommands::IsCommandEnabled(const char *aCommandName,
706 nsISupports *aCommandRefCon,
707 bool *outCmdEnabled)
709 NS_ENSURE_ARG_POINTER(outCmdEnabled);
710 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
711 if (editor)
712 return editor->GetIsSelectionEditable(outCmdEnabled);
714 *outCmdEnabled = false;
715 return NS_OK;
718 static const struct ScrollCommand {
719 const char *reverseScroll;
720 const char *forwardScroll;
721 nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
722 } scrollCommands[] = {
723 { "cmd_scrollTop", "cmd_scrollBottom",
724 &nsISelectionController::CompleteScroll },
725 { "cmd_scrollPageUp", "cmd_scrollPageDown",
726 &nsISelectionController::ScrollPage },
727 { "cmd_scrollLineUp", "cmd_scrollLineDown",
728 &nsISelectionController::ScrollLine }
731 static const struct MoveCommand {
732 const char *reverseMove;
733 const char *forwardMove;
734 const char *reverseSelect;
735 const char *forwardSelect;
736 nsresult (NS_STDCALL nsISelectionController::*move)(bool, bool);
737 } moveCommands[] = {
738 { "cmd_charPrevious", "cmd_charNext",
739 "cmd_selectCharPrevious", "cmd_selectCharNext",
740 &nsISelectionController::CharacterMove },
741 { "cmd_linePrevious", "cmd_lineNext",
742 "cmd_selectLinePrevious", "cmd_selectLineNext",
743 &nsISelectionController::LineMove },
744 { "cmd_wordPrevious", "cmd_wordNext",
745 "cmd_selectWordPrevious", "cmd_selectWordNext",
746 &nsISelectionController::WordMove },
747 { "cmd_beginLine", "cmd_endLine",
748 "cmd_selectBeginLine", "cmd_selectEndLine",
749 &nsISelectionController::IntraLineMove },
750 { "cmd_movePageUp", "cmd_movePageDown",
751 "cmd_selectPageUp", "cmd_selectPageDown",
752 &nsISelectionController::PageMove },
753 { "cmd_moveTop", "cmd_moveBottom",
754 "cmd_selectTop", "cmd_selectBottom",
755 &nsISelectionController::CompleteMove }
758 static const struct PhysicalCommand {
759 const char *move;
760 const char *select;
761 int16_t direction;
762 int16_t amount;
763 } physicalCommands[] = {
764 { "cmd_moveLeft", "cmd_selectLeft",
765 nsISelectionController::MOVE_LEFT, 0 },
766 { "cmd_moveRight", "cmd_selectRight",
767 nsISelectionController::MOVE_RIGHT, 0 },
768 { "cmd_moveUp", "cmd_selectUp",
769 nsISelectionController::MOVE_UP, 0 },
770 { "cmd_moveDown", "cmd_selectDown",
771 nsISelectionController::MOVE_DOWN, 0 },
772 { "cmd_moveLeft2", "cmd_selectLeft2",
773 nsISelectionController::MOVE_LEFT, 1 },
774 { "cmd_moveRight2", "cmd_selectRight2",
775 nsISelectionController::MOVE_RIGHT, 1 },
776 { "cmd_moveUp2", "cmd_selectUp2",
777 nsISelectionController::MOVE_UP, 1 },
778 { "cmd_moveDown2", "cmd_selectDown2",
779 nsISelectionController::MOVE_DOWN, 1 }
782 NS_IMETHODIMP
783 nsSelectionMoveCommands::DoCommand(const char *aCommandName,
784 nsISupports *aCommandRefCon)
786 nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
787 NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
789 nsCOMPtr<nsIDOMDocument> domDoc;
790 editor->GetDocument(getter_AddRefs(domDoc));
791 nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
792 if (doc) {
793 // Most of the commands below (possibly all of them) need layout to
794 // be up to date.
795 doc->FlushPendingNotifications(Flush_Layout);
798 nsCOMPtr<nsISelectionController> selCont;
799 nsresult rv = editor->GetSelectionController(getter_AddRefs(selCont));
800 NS_ENSURE_SUCCESS(rv, rv);
801 NS_ENSURE_TRUE(selCont, NS_ERROR_FAILURE);
803 // scroll commands
804 for (size_t i = 0; i < mozilla::ArrayLength(scrollCommands); i++) {
805 const ScrollCommand &cmd = scrollCommands[i];
806 if (!nsCRT::strcmp(aCommandName, cmd.reverseScroll)) {
807 return (selCont->*(cmd.scroll))(false);
808 } else if (!nsCRT::strcmp(aCommandName, cmd.forwardScroll)) {
809 return (selCont->*(cmd.scroll))(true);
813 // caret movement/selection commands
814 for (size_t i = 0; i < mozilla::ArrayLength(moveCommands); i++) {
815 const MoveCommand &cmd = moveCommands[i];
816 if (!nsCRT::strcmp(aCommandName, cmd.reverseMove)) {
817 return (selCont->*(cmd.move))(false, false);
818 } else if (!nsCRT::strcmp(aCommandName, cmd.forwardMove)) {
819 return (selCont->*(cmd.move))(true, false);
820 } else if (!nsCRT::strcmp(aCommandName, cmd.reverseSelect)) {
821 return (selCont->*(cmd.move))(false, true);
822 } else if (!nsCRT::strcmp(aCommandName, cmd.forwardSelect)) {
823 return (selCont->*(cmd.move))(true, true);
827 // physical-direction movement/selection
828 for (size_t i = 0; i < mozilla::ArrayLength(physicalCommands); i++) {
829 const PhysicalCommand &cmd = physicalCommands[i];
830 if (!nsCRT::strcmp(aCommandName, cmd.move)) {
831 return selCont->PhysicalMove(cmd.direction, cmd.amount, false);
832 } else if (!nsCRT::strcmp(aCommandName, cmd.select)) {
833 return selCont->PhysicalMove(cmd.direction, cmd.amount, true);
837 return NS_ERROR_FAILURE;
840 NS_IMETHODIMP
841 nsSelectionMoveCommands::DoCommandParams(const char *aCommandName,
842 nsICommandParams *aParams,
843 nsISupports *aCommandRefCon)
845 return DoCommand(aCommandName, aCommandRefCon);
848 NS_IMETHODIMP
849 nsSelectionMoveCommands::GetCommandStateParams(const char *aCommandName,
850 nsICommandParams *aParams,
851 nsISupports *aCommandRefCon)
853 bool canUndo;
854 IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
855 return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
858 NS_IMETHODIMP
859 nsInsertPlaintextCommand::IsCommandEnabled(const char *aCommandName,
860 nsISupports *refCon,
861 bool *outCmdEnabled)
863 NS_ENSURE_ARG_POINTER(outCmdEnabled);
864 nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
865 if (editor)
866 return editor->GetIsSelectionEditable(outCmdEnabled);
868 *outCmdEnabled = false;
869 return NS_ERROR_NOT_IMPLEMENTED;
872 NS_IMETHODIMP
873 nsInsertPlaintextCommand::DoCommand(const char *aCommandName,
874 nsISupports *refCon)
876 return NS_ERROR_NOT_IMPLEMENTED;
879 NS_IMETHODIMP
880 nsInsertPlaintextCommand::DoCommandParams(const char *aCommandName,
881 nsICommandParams *aParams,
882 nsISupports *refCon)
884 NS_ENSURE_ARG_POINTER(aParams);
886 nsCOMPtr<nsIPlaintextEditor> editor = do_QueryInterface(refCon);
887 NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
889 // Get text to insert from command params
890 nsAutoString text;
891 nsresult rv = aParams->GetStringValue(STATE_DATA, text);
892 NS_ENSURE_SUCCESS(rv, rv);
894 if (!text.IsEmpty())
895 return editor->InsertText(text);
897 return NS_OK;
900 NS_IMETHODIMP
901 nsInsertPlaintextCommand::GetCommandStateParams(const char *aCommandName,
902 nsICommandParams *aParams,
903 nsISupports *refCon)
905 NS_ENSURE_ARG_POINTER(aParams);
907 bool outCmdEnabled = false;
908 IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
909 return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
912 NS_IMETHODIMP
913 nsPasteQuotationCommand::IsCommandEnabled(const char *aCommandName,
914 nsISupports *refCon,
915 bool *outCmdEnabled)
917 NS_ENSURE_ARG_POINTER(outCmdEnabled);
919 nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
920 nsCOMPtr<nsIEditorMailSupport> mailEditor = do_QueryInterface(refCon);
921 if (editor && mailEditor) {
922 uint32_t flags;
923 editor->GetFlags(&flags);
924 if (!(flags & nsIPlaintextEditor::eEditorSingleLineMask))
925 return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled);
928 *outCmdEnabled = false;
929 return NS_OK;
932 NS_IMETHODIMP
933 nsPasteQuotationCommand::DoCommand(const char *aCommandName,
934 nsISupports *refCon)
936 nsCOMPtr<nsIEditorMailSupport> mailEditor = do_QueryInterface(refCon);
937 if (mailEditor)
938 return mailEditor->PasteAsQuotation(nsIClipboard::kGlobalClipboard);
940 return NS_ERROR_NOT_IMPLEMENTED;
943 NS_IMETHODIMP
944 nsPasteQuotationCommand::DoCommandParams(const char *aCommandName,
945 nsICommandParams *aParams,
946 nsISupports *refCon)
948 nsCOMPtr<nsIEditorMailSupport> mailEditor = do_QueryInterface(refCon);
949 if (mailEditor)
950 return mailEditor->PasteAsQuotation(nsIClipboard::kGlobalClipboard);
952 return NS_ERROR_NOT_IMPLEMENTED;
955 NS_IMETHODIMP
956 nsPasteQuotationCommand::GetCommandStateParams(const char *aCommandName,
957 nsICommandParams *aParams,
958 nsISupports *refCon)
960 nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
961 if (editor) {
962 bool enabled = false;
963 editor->CanPaste(nsIClipboard::kGlobalClipboard, &enabled);
964 aParams->SetBooleanValue(STATE_ENABLED, enabled);
967 return NS_OK;