# HG changeset patch # Parent 37dedb70a68adaf8d74fb2c2e58377ffb89e0449 # User Fabien Cazenave Bug 676401 - The queryCommandEnabled API doesn't take the active editing host into account * adding an `isSelectionEditable' readonly attribute in ; * modified all ::IsCommandEnabled methods in editor/ to take it into account: ./libeditor/base/nsEditorCommands.cpp (15 commands) nsUndoCommand 'undo' nsRedoCommand 'redo' nsClearUndoCommand 'clearUndo' nsCutCommand 'cut' nsCutOrDeleteCommand ? nsCopyCommand 'copy' nsCopyOrDeleteCommand ? nsPasteCommand 'paste' nsPasteTransferableCommand ? nsSwitchTextDirectionCommand ? nsDeleteCommand 'delete' nsSelectAllCommand 'selectAll' nsSelectionMoveCommands ? nsInsertPlaintextCommand ? nsPasteQuotationCommand ? ./composer/src/nsComposerCommands.cpp (15 commands) nsBaseStateUpdatingCommand ? nsPasteNoFormattingCommand ? nsRemoveListCommand ? nsIndentCommand 'indent' nsOutdentCommand 'outdent' nsMultiStateCommand ? nsHighlightColorStateCommand 'hiliteColor' nsAbsolutePositioningCommand ? nsDecreaseZIndexCommand ? nsIncreaseZIndexCommand ? nsRemoveStylesCommand 'removeFormat' nsIncreaseFontSizeCommand 'increaseFontSize' nsDecreaseFontSizeCommand 'decreaseFontSize' nsInsertHTMLCommand 'insertHTML' nsInsertTagCommand ? ./composer/src/nsComposerDocumentCommands.cpp (3 commands) nsSetDocumentOptionsCommand ? nsSetDocumentStateCommand ? nsDocumentStateCommand n/a (unpatched) diff --git a/editor/composer/src/nsComposerCommands.cpp b/editor/composer/src/nsComposerCommands.cpp --- a/editor/composer/src/nsComposerCommands.cpp +++ b/editor/composer/src/nsComposerCommands.cpp @@ -99,17 +99,20 @@ nsBaseStateUpdatingCommand::~nsBaseState NS_IMPL_ISUPPORTS_INHERITED0(nsBaseStateUpdatingCommand, nsBaseComposerCommand) NS_IMETHODIMP nsBaseStateUpdatingCommand::IsCommandEnabled(const char *aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { nsCOMPtr editor = do_QueryInterface(refCon); - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsBaseStateUpdatingCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { @@ -422,29 +425,34 @@ nsListItemCommand::ToggleState(nsIEditor NS_IMETHODIMP nsRemoveListCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { nsCOMPtr editor = do_QueryInterface(refCon); if (editor) { - // It is enabled if we are in any list type - PRBool bMixed; - PRUnichar *tagStr; - nsresult rv = GetListState(editor, &bMixed, &tagStr); - NS_ENSURE_SUCCESS(rv, rv); + PRBool isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + { + // It is enabled if we are in any list type + PRBool bMixed; + PRUnichar *tagStr; + nsresult rv = GetListState(editor, &bMixed, &tagStr); + NS_ENSURE_SUCCESS(rv, rv); - *outCmdEnabled = bMixed ? PR_TRUE : (tagStr && *tagStr); - - if (tagStr) NS_Free(tagStr); + *outCmdEnabled = bMixed ? PR_TRUE : (tagStr && *tagStr); + + if (tagStr) NS_Free(tagStr); + return NS_OK; + } } - else - *outCmdEnabled = PR_FALSE; + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsRemoveListCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { nsCOMPtr editor = do_QueryInterface(refCon); @@ -476,18 +484,21 @@ nsRemoveListCommand::GetCommandStatePara IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled); } NS_IMETHODIMP nsIndentCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { - nsCOMPtr editor = do_QueryInterface(refCon); - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + nsCOMPtr editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { nsCOMPtr editor = do_QueryInterface(refCon); @@ -522,26 +533,27 @@ nsIndentCommand::GetCommandStateParams(c //OUTDENT NS_IMETHODIMP nsOutdentCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { + nsCOMPtr editor = do_QueryInterface(refCon); nsCOMPtr htmlEditor = do_QueryInterface(refCon); - if (htmlEditor) + if (editor && htmlEditor) { - PRBool canIndent, canOutdent; - htmlEditor->GetIndentState(&canIndent, &canOutdent); - *outCmdEnabled = canOutdent; + PRBool canIndent, isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return htmlEditor->GetIndentState(&canIndent, outCmdEnabled); } - else - *outCmdEnabled = PR_FALSE; + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { nsCOMPtr htmlEditor = do_QueryInterface(refCon); @@ -582,17 +594,20 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsMultiStat NS_IMETHODIMP nsMultiStateCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { nsCOMPtr editor = do_QueryInterface(refCon); // should be disabled sometimes, like if the current selection is an image - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsMultiStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { #ifdef DEBUG @@ -912,18 +927,21 @@ nsHighlightColorStateCommand::SetState(n return rv; } NS_IMETHODIMP nsHighlightColorStateCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { - nsCOMPtr htmlEditor = do_QueryInterface(refCon); - *outCmdEnabled = htmlEditor ? PR_TRUE : PR_FALSE; + nsCOMPtr editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } nsBackgroundColorStateCommand::nsBackgroundColorStateCommand() : nsMultiStateCommand() { } @@ -1021,24 +1039,29 @@ nsAlignCommand::SetState(nsIEditor *aEdi nsAbsolutePositioningCommand::nsAbsolutePositioningCommand() : nsBaseStateUpdatingCommand("") { } NS_IMETHODIMP nsAbsolutePositioningCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, - PRBool *_retval) + PRBool *outCmdEnabled) { - NS_ASSERTION(aCommandRefCon, "Need an editor here"); - + nsCOMPtr editor = do_QueryInterface(aCommandRefCon); nsCOMPtr htmlEditor = do_QueryInterface(aCommandRefCon); - NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE); + if (htmlEditor) + { + PRBool isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled); + } - htmlEditor->GetAbsolutePositioningEnabled(_retval); + *outCmdEnabled = PR_FALSE; return NS_OK; } nsresult nsAbsolutePositioningCommand::GetCurrentState(nsIEditor *aEditor, const char* aTagName, nsICommandParams *aParams) { NS_ASSERTION(aEditor, "Need an editor here"); @@ -1199,17 +1222,20 @@ nsIncreaseZIndexCommand::GetCommandState NS_IMETHODIMP nsRemoveStylesCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { nsCOMPtr editor = do_QueryInterface(refCon); // test if we have any styles? - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsRemoveStylesCommand::DoCommand(const char *aCommandName, nsISupports *refCon) @@ -1244,18 +1270,21 @@ nsRemoveStylesCommand::GetCommandStatePa } NS_IMETHODIMP nsIncreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { nsCOMPtr editor = do_QueryInterface(refCon); - // test if we have any styles? - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + // test if we are at max size? + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsIncreaseFontSizeCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { @@ -1290,17 +1319,20 @@ nsIncreaseFontSizeCommand::GetCommandSta NS_IMETHODIMP nsDecreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { nsCOMPtr editor = do_QueryInterface(refCon); // test if we are at min size? - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsDecreaseFontSizeCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { @@ -1334,18 +1366,21 @@ nsDecreaseFontSizeCommand::GetCommandSta } NS_IMETHODIMP nsInsertHTMLCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); - nsCOMPtr editor = do_QueryInterface(refCon); - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + nsCOMPtr editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsInsertHTMLCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { return NS_ERROR_NOT_IMPLEMENTED; @@ -1399,18 +1434,21 @@ nsInsertTagCommand::~nsInsertTagCommand( } NS_IMETHODIMP nsInsertTagCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); - nsCOMPtr editor = do_QueryInterface(refCon); - *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; + nsCOMPtr editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } // corresponding STATE_ATTRIBUTE is: src (img) and href (a) NS_IMETHODIMP nsInsertTagCommand::DoCommand(const char *aCmdName, nsISupports *refCon) { diff --git a/editor/composer/src/nsComposerDocumentCommands.cpp b/editor/composer/src/nsComposerDocumentCommands.cpp --- a/editor/composer/src/nsComposerDocumentCommands.cpp +++ b/editor/composer/src/nsComposerDocumentCommands.cpp @@ -87,18 +87,21 @@ GetPresContextFromEditor(nsIEditor *aEdi } NS_IMETHODIMP nsSetDocumentOptionsCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); - nsCOMPtr editor = do_QueryInterface(refCon); - *outCmdEnabled = (editor != nsnull); + nsCOMPtr editor = do_QueryInterface(refCon); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsSetDocumentOptionsCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { return NS_ERROR_NOT_IMPLEMENTED; @@ -213,17 +216,20 @@ nsSetDocumentOptionsCommand::GetCommandS NS_IMETHODIMP nsSetDocumentStateCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(refCon); - *outCmdEnabled = (editor != nsnull); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsSetDocumentStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { return NS_ERROR_NOT_IMPLEMENTED; diff --git a/editor/idl/nsIEditor.idl b/editor/idl/nsIEditor.idl --- a/editor/idl/nsIEditor.idl +++ b/editor/idl/nsIEditor.idl @@ -50,17 +50,17 @@ interface nsIDocumentStateListener; interface nsIOutputStream; interface nsITransactionManager; interface nsITransaction; interface nsIEditorObserver; interface nsIEditActionListener; interface nsIInlineSpellChecker; interface nsITransferable; -[scriptable, uuid(bd5d93f0-6451-11e0-ae3e-0800200c9a66)] +[scriptable, uuid(20ee0b70-c528-11e0-9572-0800200c9a66)] interface nsIEditor : nsISupports { %{C++ typedef short EDirection; %} const short eNone = 0; const short eNext = 1; @@ -117,16 +117,19 @@ interface nsIEditor : nsISupports /** * the MimeType of the document */ attribute string contentsMIMEType; /** Returns true if we have a document that is not marked read-only */ readonly attribute boolean isDocumentEditable; + /** Returns true if the current selection anchor is editable */ + readonly attribute boolean isSelectionEditable; + /** * the DOM Document this editor is associated with, refcounted. */ readonly attribute nsIDOMDocument document; /** the body element, i.e. the root of the editable document. */ readonly attribute nsIDOMElement rootElement; diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -481,16 +481,36 @@ nsEditor::SetFlags(PRUint32 aFlags) nsIMEStateManager::UpdateIMEState(newState, focusedContent); } } return NS_OK; } NS_IMETHODIMP +nsEditor::GetIsSelectionEditable(PRBool *aIsSelectionEditable) +{ + NS_ENSURE_ARG_POINTER(aIsSelectionEditable); + + // get current selection + nsCOMPtr selection; + nsresult res = GetSelection(getter_AddRefs(selection)); + NS_ENSURE_SUCCESS(res, res); + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); + + // XXX we just check that the anchor node is editable at the moment + // we should check that all nodes in the selection are editable + nsCOMPtr anchorNode; + selection->GetAnchorNode(getter_AddRefs(anchorNode)); + *aIsSelectionEditable = anchorNode && IsEditable(anchorNode); + + return NS_OK; +} + +NS_IMETHODIMP nsEditor::GetIsDocumentEditable(PRBool *aIsDocumentEditable) { NS_ENSURE_ARG_POINTER(aIsDocumentEditable); nsCOMPtr doc; GetDocument(getter_AddRefs(doc)); *aIsDocumentEditable = doc ? PR_TRUE : PR_FALSE; return NS_OK; diff --git a/editor/libeditor/base/nsEditorCommands.cpp b/editor/libeditor/base/nsEditorCommands.cpp --- a/editor/libeditor/base/nsEditorCommands.cpp +++ b/editor/libeditor/base/nsEditorCommands.cpp @@ -65,18 +65,20 @@ NS_IMETHODIMP nsUndoCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); if (editor) { - PRBool isEnabled; - return editor->CanUndo(&isEnabled, outCmdEnabled); + PRBool isEnabled, isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return editor->CanUndo(&isEnabled, outCmdEnabled); } *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP @@ -111,18 +113,20 @@ NS_IMETHODIMP nsRedoCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); if (editor) { - PRBool isEnabled; - return editor->CanRedo(&isEnabled, outCmdEnabled); + PRBool isEnabled, isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return editor->CanRedo(&isEnabled, outCmdEnabled); } *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP @@ -153,19 +157,21 @@ nsRedoCommand::GetCommandStateParams(con return aParams->SetBooleanValue(STATE_ENABLED,canUndo); } NS_IMETHODIMP nsClearUndoCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); - nsCOMPtr editor = do_QueryInterface(refCon); - *outCmdEnabled = (editor != nsnull); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsClearUndoCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { nsCOMPtr editor = do_QueryInterface(refCon); @@ -202,17 +208,22 @@ nsClearUndoCommand::GetCommandStateParam NS_IMETHODIMP nsCutCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); if (editor) - return editor->CanCut(outCmdEnabled); + { + PRBool isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return editor->CanCut(outCmdEnabled); + } *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsCutCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) @@ -245,17 +256,20 @@ nsCutCommand::GetCommandStateParams(cons NS_IMETHODIMP nsCutOrDeleteCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); - *outCmdEnabled = (editor != nsnull); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsCutOrDeleteCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) { @@ -298,17 +312,22 @@ nsCutOrDeleteCommand::GetCommandStatePar NS_IMETHODIMP nsCopyCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); if (editor) - return editor->CanCopy(outCmdEnabled); + { + PRBool isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return editor->CanCopy(outCmdEnabled); + } *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsCopyCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) @@ -340,17 +359,20 @@ nsCopyCommand::GetCommandStateParams(con NS_IMETHODIMP nsCopyOrDeleteCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); - *outCmdEnabled = (editor != nsnull); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsCopyOrDeleteCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) { @@ -393,17 +415,22 @@ nsCopyOrDeleteCommand::GetCommandStatePa NS_IMETHODIMP nsPasteCommand::IsCommandEnabled(const char *aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); if (editor) - return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled); + { + PRBool isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled); + } *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsPasteCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) @@ -435,17 +462,22 @@ nsPasteCommand::GetCommandStateParams(co NS_IMETHODIMP nsPasteTransferableCommand::IsCommandEnabled(const char *aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); if (editor) - return editor->CanPasteTransferable(nsnull, outCmdEnabled); + { + PRBool isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + if (isEditable) + return editor->CanPasteTransferable(nsnull, outCmdEnabled); + } *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsPasteTransferableCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) { @@ -496,18 +528,20 @@ nsPasteTransferableCommand::GetCommandSt NS_IMETHODIMP nsSwitchTextDirectionCommand::IsCommandEnabled(const char *aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); - *outCmdEnabled = (editor != nsnull); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsSwitchTextDirectionCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) { nsCOMPtr editor = do_QueryInterface(aCommandRefCon); NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE); @@ -536,20 +570,26 @@ nsSwitchTextDirectionCommand::GetCommand NS_IMETHODIMP nsDeleteCommand::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); *outCmdEnabled = PR_FALSE; + // we can delete when we can cut NS_ENSURE_TRUE(editor, NS_OK); - if (!nsCRT::strcmp(aCommandName,"cmd_delete")) + PRBool isEditable = PR_FALSE; + NS_SUCCEEDED(editor->GetIsSelectionEditable(&isEditable)); + + if (!isEditable) + return NS_OK; + else if (!nsCRT::strcmp(aCommandName,"cmd_delete")) return editor->CanCut(outCmdEnabled); else if (!nsCRT::strcmp(aCommandName,"cmd_deleteCharBackward")) *outCmdEnabled = PR_TRUE; else if (!nsCRT::strcmp(aCommandName,"cmd_deleteCharForward")) *outCmdEnabled = PR_TRUE; else if (!nsCRT::strcmp(aCommandName,"cmd_deleteWordBackward")) *outCmdEnabled = PR_TRUE; else if (!nsCRT::strcmp(aCommandName,"cmd_deleteWordForward")) @@ -612,18 +652,20 @@ nsSelectAllCommand::IsCommandEnabled(con nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); // you can select all if there is an editor (and potentially no contents) // some day we may want to change this nsCOMPtr editor = do_QueryInterface(aCommandRefCon); - *outCmdEnabled = (editor != nsnull); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsSelectAllCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) { @@ -655,19 +697,20 @@ nsSelectAllCommand::GetCommandStateParam NS_IMETHODIMP nsSelectionMoveCommands::IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(aCommandRefCon); - *outCmdEnabled = (editor != nsnull); - NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE); + if (editor) + return editor->GetIsSelectionEditable(outCmdEnabled); + *outCmdEnabled = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsSelectionMoveCommands::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon) { nsCOMPtr editor = do_QueryInterface(aCommandRefCon); @@ -790,17 +833,17 @@ nsSelectionMoveCommands::GetCommandState NS_IMETHODIMP nsInsertPlaintextCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { NS_ENSURE_ARG_POINTER(outCmdEnabled); nsCOMPtr editor = do_QueryInterface(refCon); if (editor) - return editor->GetIsDocumentEditable(outCmdEnabled); + return editor->GetIsSelectionEditable(outCmdEnabled); *outCmdEnabled = PR_FALSE; return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP nsInsertPlaintextCommand::DoCommand(const char *aCommandName, diff --git a/editor/libeditor/html/tests/Makefile.in b/editor/libeditor/html/tests/Makefile.in --- a/editor/libeditor/html/tests/Makefile.in +++ b/editor/libeditor/html/tests/Makefile.in @@ -80,16 +80,17 @@ _TEST_FILES = \ test_bug611182.html \ test_bug612447.html \ test_bug620906.html \ test_bug622371.html \ test_bug629845.html \ test_bug640321.html \ test_bug668599.html \ test_bug674861.html \ + test_bug676401.html \ test_CF_HTML_clipboard.html \ test_contenteditable_focus.html \ test_htmleditor_keyevent_handling.html \ test_select_all_without_body.html \ file_select_all_without_body.html \ test_root_element_replacement.html \ $(NULL) diff --git a/editor/libeditor/html/tests/browserscope/test_richtext2.html b/editor/libeditor/html/tests/browserscope/test_richtext2.html --- a/editor/libeditor/html/tests/browserscope/test_richtext2.html +++ b/editor/libeditor/html/tests/browserscope/test_richtext2.html @@ -49,16 +49,32 @@ http://code.google.com/p/browserscope/so - + diff --git a/editor/libeditor/html/tests/test_bug676401.html b/editor/libeditor/html/tests/test_bug676401.html new file mode 100644 --- /dev/null +++ b/editor/libeditor/html/tests/test_bug676401.html @@ -0,0 +1,111 @@ + + + + + Test for Bug 676401 + + + + + + +Mozilla Bug 676401 +

+
+ +
+
not editable
+
+
+
editable
+
+
+ +
+
+
+ +