michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc michael@0: #include "nsCOMPtr.h" // for nsCOMPtr, do_QueryInterface, etc michael@0: #include "nsCRT.h" // for nsCRT michael@0: #include "nsComposerCommands.h" // for nsSetDocumentOptionsCommand, etc michael@0: #include "nsDebug.h" // for NS_ENSURE_ARG_POINTER, etc michael@0: #include "nsError.h" // for NS_ERROR_INVALID_ARG, etc michael@0: #include "nsICommandParams.h" // for nsICommandParams michael@0: #include "nsIDOMDocument.h" // for nsIDOMDocument michael@0: #include "nsIDocShell.h" // for nsIDocShell michael@0: #include "nsIDocument.h" // for nsIDocument michael@0: #include "nsIEditingSession.h" // for nsIEditingSession, etc michael@0: #include "nsIEditor.h" // for nsIEditor michael@0: #include "nsIHTMLEditor.h" // for nsIHTMLEditor michael@0: #include "nsIHTMLInlineTableEditor.h" // for nsIHTMLInlineTableEditor michael@0: #include "nsIHTMLObjectResizer.h" // for nsIHTMLObjectResizer michael@0: #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc michael@0: #include "nsIPresShell.h" // for nsIPresShell michael@0: #include "nsISelectionController.h" // for nsISelectionController michael@0: #include "nsISupportsImpl.h" // for nsPresContext::Release michael@0: #include "nsISupportsUtils.h" // for NS_IF_ADDREF michael@0: #include "nsIURI.h" // for nsIURI michael@0: #include "nsPresContext.h" // for nsPresContext michael@0: #include "nscore.h" // for NS_IMETHODIMP, nsresult, etc michael@0: michael@0: class nsISupports; michael@0: michael@0: //defines michael@0: #define STATE_ENABLED "state_enabled" michael@0: #define STATE_ALL "state_all" michael@0: #define STATE_ATTRIBUTE "state_attribute" michael@0: #define STATE_DATA "state_data" michael@0: michael@0: static michael@0: nsresult michael@0: GetPresContextFromEditor(nsIEditor *aEditor, nsPresContext **aResult) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aResult); michael@0: *aResult = nullptr; michael@0: NS_ENSURE_ARG_POINTER(aEditor); michael@0: michael@0: nsCOMPtr selCon; michael@0: nsresult rv = aEditor->GetSelectionController(getter_AddRefs(selCon)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE); michael@0: michael@0: nsCOMPtr presShell = do_QueryInterface(selCon); michael@0: NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); michael@0: michael@0: NS_IF_ADDREF(*aResult = presShell->GetPresContext()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentOptionsCommand::IsCommandEnabled(const char * aCommandName, michael@0: nsISupports *refCon, michael@0: bool *outCmdEnabled) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(outCmdEnabled); michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: if (editor) michael@0: return editor->GetIsSelectionEditable(outCmdEnabled); michael@0: michael@0: *outCmdEnabled = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentOptionsCommand::DoCommand(const char *aCommandName, michael@0: nsISupports *refCon) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentOptionsCommand::DoCommandParams(const char *aCommandName, michael@0: nsICommandParams *aParams, michael@0: nsISupports *refCon) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG); michael@0: michael@0: nsRefPtr presContext; michael@0: nsresult rv = GetPresContextFromEditor(editor, getter_AddRefs(presContext)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE); michael@0: michael@0: int32_t animationMode; michael@0: rv = aParams->GetLongValue("imageAnimation", &animationMode); michael@0: if (NS_SUCCEEDED(rv)) michael@0: { michael@0: // for possible values of animation mode, see: michael@0: // http://lxr.mozilla.org/seamonkey/source/image/public/imgIContainer.idl michael@0: presContext->SetImageAnimationMode(animationMode); michael@0: } michael@0: michael@0: bool allowPlugins; michael@0: rv = aParams->GetBooleanValue("plugins", &allowPlugins); michael@0: if (NS_SUCCEEDED(rv)) michael@0: { michael@0: nsCOMPtr docShell(presContext->GetDocShell()); michael@0: NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); michael@0: michael@0: rv = docShell->SetAllowPlugins(allowPlugins); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentOptionsCommand::GetCommandStateParams(const char *aCommandName, michael@0: nsICommandParams *aParams, michael@0: nsISupports *refCon) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: NS_ENSURE_ARG_POINTER(refCon); michael@0: michael@0: // The base editor owns most state info michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG); michael@0: michael@0: // Always get the enabled state michael@0: bool outCmdEnabled = false; michael@0: IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); michael@0: nsresult rv = aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // get pres context michael@0: nsRefPtr presContext; michael@0: rv = GetPresContextFromEditor(editor, getter_AddRefs(presContext)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE); michael@0: michael@0: int32_t animationMode; michael@0: rv = aParams->GetLongValue("imageAnimation", &animationMode); michael@0: if (NS_SUCCEEDED(rv)) michael@0: { michael@0: // for possible values of animation mode, see michael@0: // http://lxr.mozilla.org/seamonkey/source/image/public/imgIContainer.idl michael@0: rv = aParams->SetLongValue("imageAnimation", michael@0: presContext->ImageAnimationMode()); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: bool allowPlugins = false; michael@0: rv = aParams->GetBooleanValue("plugins", &allowPlugins); michael@0: if (NS_SUCCEEDED(rv)) michael@0: { michael@0: nsCOMPtr docShell(presContext->GetDocShell()); michael@0: NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); michael@0: michael@0: allowPlugins = docShell->PluginsAllowedInCurrentDoc(); michael@0: michael@0: rv = aParams->SetBooleanValue("plugins", allowPlugins); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Commands for document state that may be changed via doCommandParams michael@0: * As of 11/11/02, this is just "cmd_setDocumentModified" michael@0: * Note that you can use the same command class, nsSetDocumentStateCommand, michael@0: * for more than one of this type of command michael@0: * We check the input command param for different behavior michael@0: */ michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentStateCommand::IsCommandEnabled(const char * aCommandName, michael@0: nsISupports *refCon, michael@0: bool *outCmdEnabled) michael@0: { michael@0: // These commands are always enabled michael@0: NS_ENSURE_ARG_POINTER(outCmdEnabled); michael@0: *outCmdEnabled = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentStateCommand::DoCommand(const char *aCommandName, michael@0: nsISupports *refCon) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentStateCommand::DoCommandParams(const char *aCommandName, michael@0: nsICommandParams *aParams, michael@0: nsISupports *refCon) michael@0: { michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG); michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: michael@0: bool modified; michael@0: nsresult rv = aParams->GetBooleanValue(STATE_ATTRIBUTE, &modified); michael@0: michael@0: // Should we fail if this param wasn't set? michael@0: // I'm not sure we should be that strict michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: if (modified) michael@0: return editor->IncrementModificationCount(1); michael@0: michael@0: return editor->ResetModificationCount(); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: bool isReadOnly; michael@0: nsresult rvRO = aParams->GetBooleanValue(STATE_ATTRIBUTE, &isReadOnly); michael@0: NS_ENSURE_SUCCESS(rvRO, rvRO); michael@0: michael@0: uint32_t flags; michael@0: editor->GetFlags(&flags); michael@0: if (isReadOnly) michael@0: flags |= nsIPlaintextEditor::eEditorReadonlyMask; michael@0: else michael@0: flags &= ~(nsIPlaintextEditor::eEditorReadonlyMask); michael@0: michael@0: return editor->SetFlags(flags); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr htmleditor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool desireCSS; michael@0: nsresult rvCSS = aParams->GetBooleanValue(STATE_ATTRIBUTE, &desireCSS); michael@0: NS_ENSURE_SUCCESS(rvCSS, rvCSS); michael@0: michael@0: return htmleditor->SetIsCSSEnabled(desireCSS); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr htmleditor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool insertBrOnReturn; michael@0: nsresult rvBR = aParams->GetBooleanValue(STATE_ATTRIBUTE, michael@0: &insertBrOnReturn); michael@0: NS_ENSURE_SUCCESS(rvBR, rvBR); michael@0: michael@0: return htmleditor->SetReturnInParagraphCreatesNewParagraph(!insertBrOnReturn); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr resizer = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(resizer, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool enabled; michael@0: nsresult rvOR = aParams->GetBooleanValue(STATE_ATTRIBUTE, &enabled); michael@0: NS_ENSURE_SUCCESS(rvOR, rvOR); michael@0: michael@0: return resizer->SetObjectResizingEnabled(enabled); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool enabled; michael@0: nsresult rvOR = aParams->GetBooleanValue(STATE_ATTRIBUTE, &enabled); michael@0: NS_ENSURE_SUCCESS(rvOR, rvOR); michael@0: michael@0: return editor->SetInlineTableEditingEnabled(enabled); michael@0: } michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSetDocumentStateCommand::GetCommandStateParams(const char *aCommandName, michael@0: nsICommandParams *aParams, michael@0: nsISupports *refCon) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: NS_ENSURE_ARG_POINTER(refCon); michael@0: michael@0: // The base editor owns most state info michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG); michael@0: michael@0: // Always get the enabled state michael@0: bool outCmdEnabled = false; michael@0: IsCommandEnabled(aCommandName, refCon, &outCmdEnabled); michael@0: nsresult rv = aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) michael@0: { michael@0: bool modified; michael@0: rv = editor->GetDocumentModified(&modified); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return aParams->SetBooleanValue(STATE_ATTRIBUTE, modified); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: michael@0: uint32_t flags; michael@0: editor->GetFlags(&flags); michael@0: bool isReadOnly = flags & nsIPlaintextEditor::eEditorReadonlyMask; michael@0: return aParams->SetBooleanValue(STATE_ATTRIBUTE, isReadOnly); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr htmleditor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool isCSS; michael@0: htmleditor->GetIsCSSEnabled(&isCSS); michael@0: return aParams->SetBooleanValue(STATE_ALL, isCSS); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr htmleditor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool createPOnReturn; michael@0: htmleditor->GetReturnInParagraphCreatesNewParagraph(&createPOnReturn); michael@0: return aParams->SetBooleanValue(STATE_ATTRIBUTE, !createPOnReturn); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr resizer = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(resizer, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool enabled; michael@0: resizer->GetObjectResizingEnabled(&enabled); michael@0: return aParams->SetBooleanValue(STATE_ATTRIBUTE, enabled); michael@0: } michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG); michael@0: michael@0: bool enabled; michael@0: editor->GetInlineTableEditingEnabled(&enabled); michael@0: return aParams->SetBooleanValue(STATE_ATTRIBUTE, enabled); michael@0: } michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: /** michael@0: * Commands just for state notification michael@0: * As of 11/21/02, possible commands are: michael@0: * "obs_documentCreated" michael@0: * "obs_documentWillBeDestroyed" michael@0: * "obs_documentLocationChanged" michael@0: * Note that you can use the same command class, nsDocumentStateCommand michael@0: * for these or future observer commands. michael@0: * We check the input command param for different behavior michael@0: * michael@0: * How to use: michael@0: * 1. Get the nsICommandManager for the current editor michael@0: * 2. Implement an nsIObserve object, e.g: michael@0: * michael@0: * void Observe( michael@0: * in nsISupports aSubject, // The nsICommandManager calling this Observer michael@0: * in string aTopic, // command name, e.g.:"obs_documentCreated" michael@0: * // or "obs_documentWillBeDestroyed" michael@0: in wstring aData ); // ignored (set to "command_status_changed") michael@0: * michael@0: * 3. Add the observer by: michael@0: * commandManager.addObserver(observeobject, obs_documentCreated); michael@0: * 4. In the appropriate location in editorSession, editor, or commands code, michael@0: * trigger the notification of this observer by something like: michael@0: * michael@0: * nsCOMPtr commandManager = do_GetInterface(mDocShell); michael@0: * nsCOMPtr commandUpdater = do_QueryInterface(commandManager); michael@0: * NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE); michael@0: * commandUpdater->CommandStatusChanged(obs_documentCreated); michael@0: * michael@0: * 5. Use GetCommandStateParams() to obtain state information michael@0: * e.g., any creation state codes when creating an editor are michael@0: * supplied for "obs_documentCreated" command in the michael@0: * "state_data" param's value michael@0: * michael@0: */ michael@0: michael@0: NS_IMETHODIMP michael@0: nsDocumentStateCommand::IsCommandEnabled(const char* aCommandName, michael@0: nsISupports *refCon, michael@0: bool *outCmdEnabled) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(outCmdEnabled); michael@0: // Always return false to discourage callers from using DoCommand() michael@0: *outCmdEnabled = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsDocumentStateCommand::DoCommand(const char *aCommandName, michael@0: nsISupports *refCon) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsDocumentStateCommand::DoCommandParams(const char *aCommandName, michael@0: nsICommandParams *aParams, michael@0: nsISupports *refCon) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsDocumentStateCommand::GetCommandStateParams(const char *aCommandName, michael@0: nsICommandParams *aParams, michael@0: nsISupports *refCon) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aParams); michael@0: NS_ENSURE_ARG_POINTER(aCommandName); michael@0: nsresult rv; michael@0: michael@0: if (!nsCRT::strcmp(aCommandName, "obs_documentCreated")) michael@0: { michael@0: uint32_t editorStatus = nsIEditingSession::eEditorErrorUnknown; michael@0: michael@0: nsCOMPtr editingSession = do_QueryInterface(refCon); michael@0: if (editingSession) michael@0: { michael@0: // refCon is initially set to nsIEditingSession until editor michael@0: // is successfully created and source doc is loaded michael@0: // Embedder gets error status if this fails michael@0: // If called before startup is finished, michael@0: // status = eEditorCreationInProgress michael@0: rv = editingSession->GetEditorStatus(&editorStatus); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: else michael@0: { michael@0: // If refCon is an editor, then everything started up OK! michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: if (editor) michael@0: editorStatus = nsIEditingSession::eEditorOK; michael@0: } michael@0: michael@0: // Note that if refCon is not-null, but is neither michael@0: // an nsIEditingSession or nsIEditor, we return "eEditorErrorUnknown" michael@0: aParams->SetLongValue(STATE_DATA, editorStatus); michael@0: return NS_OK; michael@0: } michael@0: else if (!nsCRT::strcmp(aCommandName, "obs_documentLocationChanged")) michael@0: { michael@0: nsCOMPtr editor = do_QueryInterface(refCon); michael@0: if (editor) michael@0: { michael@0: nsCOMPtr domDoc; michael@0: editor->GetDocument(getter_AddRefs(domDoc)); michael@0: nsCOMPtr doc = do_QueryInterface(domDoc); michael@0: NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); michael@0: michael@0: nsIURI *uri = doc->GetDocumentURI(); michael@0: NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); michael@0: michael@0: return aParams->SetISupportsValue(STATE_DATA, (nsISupports*)uri); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: }