diff --git a/mozilla/content/events/public/nsIEventStateManager.h b/mozilla/content/events/public/nsIEventStateManager.h index ebf74ec9b14..a8c6dcbf5b7 100644 --- a/mozilla/content/events/public/nsIEventStateManager.h +++ b/mozilla/content/events/public/nsIEventStateManager.h @@ -94,6 +94,7 @@ public: NS_IMETHOD EventStatusOK(nsGUIEvent* aEvent, PRBool *aOK) = 0; // This is called when browse with caret changes on the fly + NS_IMETHOD GetBrowseWithCaret(PRBool *aBrowseWithCaret) = 0; NS_IMETHOD ResetBrowseWithCaret(PRBool *aBrowseWithCaret) = 0; // This is called after find text or when a cursor movement key is pressed diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index 3134e502f2a..0da317313a9 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -46,6 +46,7 @@ #include "nsIStyleContext.h" #include "nsIPresContext.h" #include "nsIPresShell.h" +#include "nsIPrefBranchInternal.h" #include "nsDOMEvent.h" #include "nsHTMLAtoms.h" #include "nsIFormControl.h" @@ -82,6 +83,7 @@ #include "nsIServiceManager.h" #include "nsIPref.h" +#include "nsIPrefService.h" #include "nsIScriptSecurityManager.h" #include "nsIChromeEventHandler.h" @@ -218,6 +220,12 @@ nsEventStateManager::Init() mPrefService->GetBoolPref("nglayout.events.dispatchLeftClickOnly", &mLeftClickOnly); if (nsEventStateManager::gGeneralAccesskeyModifier == -1) // magic value of -1 means uninitialized mPrefService->GetIntPref("ui.key.generalAccessKey", &nsEventStateManager::gGeneralAccesskeyModifier); + + nsCOMPtr prefBranch; + mPrefService->GetBranch(nsnull, getter_AddRefs(prefBranch)); + nsCOMPtr prefBranchInt(do_QueryInterface(prefBranch)); + if (prefBranchInt) + prefBranchInt->AddObserver("accessibility.browsewithcaret", this, PR_TRUE); } if (nsEventStateManager::sTextfieldSelectModel == eTextfieldSelect_unset) { @@ -291,6 +299,12 @@ nsEventStateManager::~nsEventStateManager() nsresult nsEventStateManager::Shutdown() { + nsCOMPtr prefBranch; + mPrefService->GetBranch(nsnull, getter_AddRefs(prefBranch)); + nsCOMPtr prefBranchInt(do_QueryInterface(prefBranch)); + if (prefBranchInt) + prefBranchInt->RemoveObserver("accessibility.browsewithcaret", this); + if (mPrefService) { mPrefService = nsnull; } @@ -322,7 +336,13 @@ nsEventStateManager::Observe(nsISupports *aSubject, { if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) Shutdown(); - + else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { + if (someData && nsDependentString(someData).Equals(NS_LITERAL_STRING("accessibility.browsewithcaret"))) { + PRBool browseWithCaret; + ResetBrowseWithCaret(&browseWithCaret); + } + } + return NS_OK; } @@ -1593,8 +1613,6 @@ nsEventStateManager::DoWheelScroll(nsIPresContext* aPresContext, // initialize nativeMsg field otherwise plugin code will crash when trying to access it mouseOutEvent.nativeMsg = nsnull; - nsEventStatus mouseoutStatus = nsEventStatus_eIgnore; - nsCOMPtr presShell; aPresContext->GetShell(getter_AddRefs(presShell)); @@ -4942,6 +4960,15 @@ nsresult nsEventStateManager::SetContentCaretVisible(nsIPresShell* aPresShell, n return NS_OK; } + +NS_IMETHODIMP +nsEventStateManager::GetBrowseWithCaret(PRBool *aBrowseWithCaret) +{ + NS_ENSURE_ARG_POINTER(aBrowseWithCaret); + *aBrowseWithCaret = mBrowseWithCaret; + return NS_OK; +} + NS_IMETHODIMP nsEventStateManager::ResetBrowseWithCaret(PRBool *aBrowseWithCaret) { @@ -4949,7 +4976,8 @@ nsEventStateManager::ResetBrowseWithCaret(PRBool *aBrowseWithCaret) // or when a document gets focused *aBrowseWithCaret = PR_FALSE; - + if (!mPresContext) return NS_ERROR_FAILURE; + nsCOMPtr pcContainer; mPresContext->GetContainer(getter_AddRefs(pcContainer)); PRInt32 itemType; diff --git a/mozilla/content/events/src/nsEventStateManager.h b/mozilla/content/events/src/nsEventStateManager.h index 316ba652bdf..7e7a89193cc 100644 --- a/mozilla/content/events/src/nsEventStateManager.h +++ b/mozilla/content/events/src/nsEventStateManager.h @@ -43,6 +43,7 @@ #include "nsGUIEvent.h" #include "nsIContent.h" #include "nsIPref.h" +#include "nsIPrefBranch.h" #include "nsIObserver.h" #include "nsWeakReference.h" #include "nsHashtable.h" @@ -147,6 +148,7 @@ public: NS_IMETHOD ShiftFocus(PRBool aForward, nsIContent* aStart=nsnull); + NS_IMETHOD GetBrowseWithCaret(PRBool *aBrowseWithCaret); NS_IMETHOD ResetBrowseWithCaret(PRBool *aBrowseWithCaret); NS_IMETHOD MoveFocusToCaret(PRBool aCanFocusDoc, PRBool *aIsSelectionWithFocus); diff --git a/mozilla/docshell/base/Makefile.in b/mozilla/docshell/base/Makefile.in index d482ab294ff..4cd6bbde8f1 100644 --- a/mozilla/docshell/base/Makefile.in +++ b/mozilla/docshell/base/Makefile.in @@ -95,6 +95,7 @@ CPPSRCS = \ nsWebShell.cpp \ nsDocShellLoadInfo.cpp \ nsDocShellEditorData.cpp \ + nsDocShellTransferableHooks.cpp \ nsDocShellEnumerator.cpp \ nsDSURIContentListener.cpp \ nsDefaultURIFixup.cpp \ diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 0b575984e52..7220262c77c 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -425,6 +425,12 @@ NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink) return NS_NOINTERFACE; } + else if (aIID.Equals(NS_GET_IID(nsIClipboardDragDropHookList)) + && NS_SUCCEEDED(EnsureTransferableHookData())) { + *aSink = mTransferableHookData; + NS_ADDREF((nsISupports *)*aSink); + return NS_OK; + } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay))) { nsCOMPtr shell; nsresult rv = GetPresShell(getter_AddRefs(shell)); @@ -2966,6 +2972,8 @@ nsDocShell::Destroy() delete mEditorData; mEditorData = 0; + mTransferableHookData = nsnull; + // Save the state of the current document, before destroying the window. // This is needed to capture the state of a frameset when the new document // causes the frameset to be destroyed... @@ -6562,6 +6570,17 @@ nsDocShell::EnsureEditorData() return mEditorData ? NS_OK : NS_ERROR_FAILURE; } +nsresult +nsDocShell::EnsureTransferableHookData() +{ + if (!mTransferableHookData) { + mTransferableHookData = new nsTransferableHookData(); // owning addref + if (!mTransferableHookData) return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + NS_IMETHODIMP nsDocShell::EnsureFind() { diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index e186e457af8..774e0a389f7 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -79,6 +79,7 @@ #include "nsIURIFixup.h" #include "nsIWebBrowserFind.h" #include "nsIHttpChannel.h" +#include "nsDocShellTransferableHooks.h" #define MAKE_LOAD_TYPE(type, flags) ((type) | ((flags) << 16)) @@ -246,6 +247,7 @@ protected: NS_IMETHOD EnsureContentListener(); NS_IMETHOD EnsureScriptEnvironment(); NS_IMETHOD EnsureEditorData(); + nsresult EnsureTransferableHookData(); NS_IMETHOD EnsureFind(); NS_IMETHOD RefreshURIFromQueue(); NS_IMETHOD DisplayLoadError(nsresult aError, nsIURI *aURI, const PRUnichar *aURL); @@ -356,6 +358,9 @@ protected: // Editor stuff nsDocShellEditorData* mEditorData; // editor data, if any + // Transferable hooks/callbacks + nsCOMPtr mTransferableHookData; + // WEAK REFERENCES BELOW HERE. // Note these are intentionally not addrefd. Doing so will create a cycle. // For that reasons don't use nsCOMPtr. diff --git a/mozilla/docshell/base/nsDocShellTransferableHooks.cpp b/mozilla/docshell/base/nsDocShellTransferableHooks.cpp index b07e4ce527b..e66b7b54c2c 100644 --- a/mozilla/docshell/base/nsDocShellTransferableHooks.cpp +++ b/mozilla/docshell/base/nsDocShellTransferableHooks.cpp @@ -45,6 +45,7 @@ nsTransferableHookData::nsTransferableHookData() { + NS_INIT_ISUPPORTS(); } diff --git a/mozilla/docshell/base/nsDocShellTransferableHooks.h b/mozilla/docshell/base/nsDocShellTransferableHooks.h index 6f352b3ce31..84d0bfd376d 100644 --- a/mozilla/docshell/base/nsDocShellTransferableHooks.h +++ b/mozilla/docshell/base/nsDocShellTransferableHooks.h @@ -59,4 +59,4 @@ protected: nsCOMArray mHookList; }; -#endif // nsDocShellTransferableHooks_h__ +#endif nsDocShellTransferableHooks_h__ diff --git a/mozilla/dom/src/base/Makefile.in b/mozilla/dom/src/base/Makefile.in index 780b103e935..68b84f277bc 100644 --- a/mozilla/dom/src/base/Makefile.in +++ b/mozilla/dom/src/base/Makefile.in @@ -31,6 +31,7 @@ LIBRARY_NAME = jsdombase_s REQUIRES = xpcom \ string \ webbrwsr \ + commandhandler \ js \ widget \ gfx \ @@ -66,6 +67,7 @@ CPPSRCS = \ nsJSEnvironment.cpp \ nsFocusController.cpp \ nsGlobalWindow.cpp \ + nsGlobalWindowCommands.cpp \ nsLocation.cpp \ nsDOMWindowList.cpp \ nsJSUtils.cpp \ diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 110ec3588cf..d78aa68354d 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -129,6 +129,8 @@ #include "nsIJSNativeInitializer.h" #include "nsIFullScreen.h" #include "nsIStringBundle.h" +#include "nsIControllerContext.h" +#include "nsGlobalWindowCommands.h" #include "plbase64.h" @@ -272,12 +274,34 @@ void GlobalWindowImpl::CleanUp() NS_IF_RELEASE(mScrollbars); NS_IF_RELEASE(mLocation); NS_IF_RELEASE(mFrames); + + ClearControllers(); + mOpener = nsnull; // Forces Release - mControllers = nsnull; // Forces Release mContext = nsnull; // Forces Release mChromeEventHandler = nsnull; // Forces Release } +void +GlobalWindowImpl::ClearControllers() +{ + if (mControllers) { + PRUint32 count; + mControllers->GetControllerCount(&count); + + while (count--) { + nsCOMPtr controller; + mControllers->GetControllerAt(count, getter_AddRefs(controller)); + + nsCOMPtr context = do_QueryInterface(controller); + if (context) + context->SetCommandContext(nsnull); + } + + mControllers = nsnull; + } +} + //***************************************************************************** // GlobalWindowImpl::nsISupports //***************************************************************************** @@ -572,10 +596,11 @@ GlobalWindowImpl::SetDocShell(nsIDocShell* aDocShell) } } + ClearControllers(); + mContext->GC(); mContext = nsnull; // force release now - mControllers = nsnull; // force release now mChromeEventHandler = nsnull; // force release now } @@ -1293,17 +1318,22 @@ NS_IMETHODIMP GlobalWindowImpl::GetControllers(nsIControllers** aResult) { if (!mControllers) { - mControllers = do_CreateInstance(kXULControllersCID); - NS_ENSURE_TRUE(mControllers, NS_ERROR_FAILURE); -#ifdef DOM_CONTROLLER + nsresult rv; + mControllers = do_CreateInstance(kXULControllersCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + // Add in the default controller - nsDOMWindowController *domController = new nsDOMWindowController(this); - if (domController) { - nsCOMPtr controller(domController); - mControllers->AppendController(controller); - } -#endif // DOM_CONTROLLER + nsCOMPtr controller = do_CreateInstance( + NS_WINDOWCONTROLLER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + mControllers->InsertControllerAt(0, controller); + nsCOMPtr controllerContext = do_QueryInterface(controller); + if (!controllerContext) return NS_ERROR_FAILURE; + + controllerContext->SetCommandContext(NS_STATIC_CAST(nsIDOMWindow*, this)); } + *aResult = mControllers; NS_ADDREF(*aResult); return NS_OK; @@ -1344,7 +1374,7 @@ GlobalWindowImpl::GetOpener(nsIDOMWindowInternal** aOpener) } } } - } + } NS_IF_ADDREF(*aOpener); return NS_OK; } @@ -2026,7 +2056,7 @@ GlobalWindowImpl::Dump(const nsAString& aStr) char *cstr = ToNewUTF8String(aStr); -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) // have to convert \r to \n so that printing to the console works char *c = cstr, *cEnd = cstr + aStr.Length(); while (c < cEnd) { @@ -2103,7 +2133,7 @@ GlobalWindowImpl::CheckSecurityIsChromeCaller(PRBool *aIsChrome) NS_ENSURE_ARG_POINTER(aIsChrome); *aIsChrome = PR_FALSE; - + // Check if this is a privileged system script NS_ENSURE_TRUE(sSecMan, NS_ERROR_FAILURE); @@ -2145,7 +2175,7 @@ GlobalWindowImpl::MakeScriptDialogTitle(const nsAString &aInTitle, nsAString &aO nsCOMPtr stringBundle; rv = stringBundleService->CreateBundle(kDOMBundleURL, getter_AddRefs(stringBundle)); - + if (stringBundle) { nsAutoString inTitle(aInTitle); nsXPIDLString tempString; @@ -2158,7 +2188,7 @@ GlobalWindowImpl::MakeScriptDialogTitle(const nsAString &aInTitle, nsAString &aO aOutTitle = tempString.get(); } } - + // Just in case if (aOutTitle.IsEmpty()) { NS_WARNING("could not get ScriptDlgTitle string from string bundle"); @@ -2859,7 +2889,7 @@ GlobalWindowImpl::CheckForAbusePoint () if (item) { PRInt32 type = nsIDocShellTreeItem::typeChrome; - + item->GetItemType(&type); if (type != nsIDocShellTreeItem::typeContent) @@ -5869,463 +5899,3 @@ NavigatorImpl::RefreshMIMEArray() return rv; } -#ifdef XP_MAC -#pragma mark - -#endif - -//***************************************************************************** -//*** DOM Controller Stuff -//***************************************************************************** - -#ifdef DOM_CONTROLLER -// nsDOMWindowController -const char * const sCopyString = "cmd_copy"; -const char * const sCutString = "cmd_cut"; -const char * const sPasteString = "cmd_paste"; -const char * const sSelectAllString = "cmd_selectAll"; -const char * const sSelectNoneString = "cmd_selectNone"; -const char * const sCopyLinkString = "cmd_copyLink"; -const char * const sCopyImageLocationString = "cmd_copyImageLocation"; -const char * const sCopyImageContentsString = "cmd_copyImageContents"; - -const char * const sScrollTopString = "cmd_scrollTop"; -const char * const sScrollBottomString = "cmd_scrollBottom"; -const char * const sScrollPageUpString = "cmd_scrollPageUp"; -const char * const sScrollPageDownString = "cmd_scrollPageDown"; -const char * const sMovePageUpString = "cmd_movePageUp"; -const char * const sMovePageDownString = "cmd_movePageDown"; -const char * const sScrollLineUpString = "cmd_scrollLineUp"; -const char * const sScrollLineDownString = "cmd_scrollLineDown"; -const char * const sScrollLeftString = "cmd_scrollLeft"; -const char * const sScrollRightString = "cmd_scrollRight"; -const char * const sBrowserBackString = "cmd_browserBack"; -const char * const sBrowserForwardString = "cmd_browserForward"; - -// These are so the browser can use editor navigation key bindings -// helps with accessibility (boolean pref accessibility.browsewithcaret) - -const char * const sSelectCharPreviousString = "cmd_selectCharPrevious"; -const char * const sSelectCharNextString = "cmd_selectCharNext"; - -const char * const sWordPreviousString = "cmd_wordPrevious"; -const char * const sWordNextString = "cmd_wordNext"; -const char * const sSelectWordPreviousString = "cmd_selectWordPrevious"; -const char * const sSelectWordNextString = "cmd_selectWordNext"; - -const char * const sBeginLineString = "cmd_beginLine"; -const char * const sEndLineString = "cmd_endLine"; -const char * const sSelectBeginLineString = "cmd_selectBeginLine"; -const char * const sSelectEndLineString = "cmd_selectEndLine"; - -const char * const sSelectLinePreviousString = "cmd_selectLinePrevious"; -const char * const sSelectLineNextString = "cmd_selectLineNext"; - -const char * const sSelectPagePreviousString = "cmd_selectPagePrevious"; -const char * const sSelectPageNextString = "cmd_selectPageNext"; - -const char * const sSelectMoveTopString = "cmd_selectMoveTop"; -const char * const sSelectMoveBottomString = "cmd_selectMoveBottom"; - -NS_IMPL_ADDREF(nsDOMWindowController) -NS_IMPL_RELEASE(nsDOMWindowController) - -NS_INTERFACE_MAP_BEGIN(nsDOMWindowController) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIController) - NS_INTERFACE_MAP_ENTRY(nsIController) -NS_INTERFACE_MAP_END - - -nsDOMWindowController::nsDOMWindowController(nsIDOMWindowInternal *aWindow) -{ - NS_INIT_ISUPPORTS(); - mWindow = aWindow; - - // Set mBrowseWithCaret so we don't need to check pref every time - mBrowseWithCaret = PR_FALSE; - nsCOMPtr esm; - if (NS_SUCCEEDED(GetEventStateManager(getter_AddRefs(esm)))) - esm->ResetBrowseWithCaret(&mBrowseWithCaret); - nsCOMPtr prefs(do_GetService(kPrefServiceCID)); - if (prefs) - prefs->RegisterCallback("accessibility.browsewithcaret", (PrefChangedFunc)nsDOMWindowController::BrowseWithCaretPrefCallback, (void*)this); -} - -nsDOMWindowController::~nsDOMWindowController() -{ - nsCOMPtr prefs(do_GetService(kPrefServiceCID)); - if (prefs) - prefs->UnregisterCallback("accessibility.browsewithcaret", (PrefChangedFunc)nsDOMWindowController::BrowseWithCaretPrefCallback, (void*)this); -} - -nsresult -nsDOMWindowController::GetEventStateManager(nsIEventStateManager **aEventStateManager) -{ - *aEventStateManager = nsnull; - // Set browse with caret flag so we don't need to every time - nsCOMPtr presShell; - GetPresShell(getter_AddRefs(presShell)); - - if (presShell) { - nsCOMPtr presContext; - presShell->GetPresContext(getter_AddRefs(presContext)); - if (presContext) { - nsCOMPtr esm; - presContext->GetEventStateManager(getter_AddRefs(esm)); - *aEventStateManager = esm; - if (esm) { - NS_ADDREF(*aEventStateManager); - return NS_OK; - } - } - } - return NS_ERROR_FAILURE; -} - -int PR_CALLBACK -nsDOMWindowController::BrowseWithCaretPrefCallback(const char* aPrefName, void* instance_data) -{ - nsDOMWindowController* domWindowController = (nsDOMWindowController*)instance_data; - NS_ASSERTION(domWindowController, "bad instance data"); - - nsCOMPtr esm; - - if (NS_SUCCEEDED(domWindowController->GetEventStateManager(getter_AddRefs(esm)))) - esm->ResetBrowseWithCaret(&domWindowController->mBrowseWithCaret); - - return 0; // PREF_OK -} - -nsresult -nsDOMWindowController::GetEditInterface(nsIContentViewerEdit **aEditInterface) -{ - nsCOMPtr sgo(do_QueryInterface(mWindow)); - NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE); - - nsCOMPtr docShell; - sgo->GetDocShell(getter_AddRefs(docShell)); - NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); - - nsCOMPtr viewer; - docShell->GetContentViewer(getter_AddRefs(viewer)); - nsCOMPtr edit(do_QueryInterface(viewer)); - NS_ENSURE_TRUE(edit, NS_ERROR_FAILURE); - - *aEditInterface = edit; - NS_ADDREF(*aEditInterface); - return NS_OK; -} - -nsresult -nsDOMWindowController::GetPresShell(nsIPresShell **aPresShell) -{ - nsCOMPtr sgo(do_QueryInterface(mWindow)); - NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE); - - nsCOMPtr docShell; - sgo->GetDocShell(getter_AddRefs(docShell)); - NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); - - NS_ENSURE_SUCCESS(docShell->GetPresShell(aPresShell), NS_ERROR_FAILURE); - return NS_OK; -} - -nsresult -nsDOMWindowController::GetSelectionController(nsISelectionController **aSelCon) -{ - nsCOMPtr presShell; - nsresult result = GetPresShell(getter_AddRefs(presShell)); - if (presShell && NS_SUCCEEDED(result)) { - nsCOMPtr selController = - do_QueryInterface(presShell); - if (selController) { - *aSelCon = selController; - NS_ADDREF(*aSelCon); - return NS_OK; - } - } - return NS_FAILED(result) ? result : NS_ERROR_FAILURE; -} - - - -NS_IMETHODIMP -nsDOMWindowController::IsCommandEnabled(const char* aCommand, - PRBool *aResult) -{ - NS_ENSURE_ARG_POINTER(aResult); - - *aResult = PR_FALSE; - nsresult rv = NS_ERROR_FAILURE; - - nsCOMPtr editInterface; - rv = GetEditInterface(getter_AddRefs(editInterface)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(editInterface, NS_ERROR_NOT_INITIALIZED); - - - if (!nsCRT::strcmp(sCopyString,aCommand)) { - rv = editInterface->GetCopyable(aResult); - } - else if (!nsCRT::strcmp(sCutString,aCommand)) { - rv = editInterface->GetCutable(aResult); - } - else if (!nsCRT::strcmp(sPasteString,aCommand)) { - rv = editInterface->GetPasteable(aResult); - } - else if (!nsCRT::strcmp(sSelectAllString,aCommand)) { - *aResult = PR_TRUE; - rv = NS_OK; - } - else if (!nsCRT::strcmp(sSelectNoneString,aCommand)) { - *aResult = PR_TRUE; - rv = NS_OK; - } - else if (!nsCRT::strcmp(sCopyLinkString,aCommand)) { - rv = editInterface->GetInLink(aResult); - } - else if (!nsCRT::strcmp(sCopyImageLocationString,aCommand)) { - rv = editInterface->GetInImage(aResult); - } - else if (!nsCRT::strcmp(sCopyImageContentsString,aCommand)) { - rv = editInterface->GetInImage(aResult); - } - - return rv; -} - -NS_IMETHODIMP -nsDOMWindowController::SupportsCommand(const char * aCommand, - PRBool *outSupported) -{ - NS_ENSURE_ARG_POINTER(outSupported); - - *outSupported = PR_FALSE; - - if (!nsCRT::strcmp(aCommand,sCopyString) || - !nsCRT::strcmp(aCommand,sSelectAllString) || - !nsCRT::strcmp(aCommand,sSelectNoneString) || - !nsCRT::strcmp(aCommand,sCutString) || - !nsCRT::strcmp(aCommand,sPasteString) || - !nsCRT::strcmp(aCommand,sScrollTopString) || - !nsCRT::strcmp(aCommand,sScrollBottomString) || - !nsCRT::strcmp(aCommand,sCopyLinkString) || - !nsCRT::strcmp(aCommand,sCopyImageLocationString) || - !nsCRT::strcmp(aCommand,sCopyImageContentsString) || - !nsCRT::strcmp(aCommand,sScrollPageUpString) || - !nsCRT::strcmp(aCommand,sScrollPageDownString) || - !nsCRT::strcmp(aCommand,sMovePageUpString) || - !nsCRT::strcmp(aCommand,sMovePageDownString) || - !nsCRT::strcmp(aCommand,sBrowserBackString) || - !nsCRT::strcmp(aCommand,sBrowserForwardString) || - !nsCRT::strcmp(aCommand,sScrollLineUpString) || - !nsCRT::strcmp(aCommand,sScrollLineDownString) || - !nsCRT::strcmp(aCommand,sScrollLeftString) || - !nsCRT::strcmp(aCommand,sScrollRightString) || - !nsCRT::strcmp(aCommand,sSelectCharPreviousString) || - !nsCRT::strcmp(aCommand,sSelectCharNextString) || - !nsCRT::strcmp(aCommand,sWordPreviousString) || - !nsCRT::strcmp(aCommand,sWordNextString) || - !nsCRT::strcmp(aCommand,sSelectWordPreviousString) || - !nsCRT::strcmp(aCommand,sSelectWordNextString) || - !nsCRT::strcmp(aCommand,sBeginLineString) || - !nsCRT::strcmp(aCommand,sEndLineString) || - !nsCRT::strcmp(aCommand,sSelectBeginLineString) || - !nsCRT::strcmp(aCommand,sSelectEndLineString) || - !nsCRT::strcmp(aCommand,sSelectLinePreviousString) || - !nsCRT::strcmp(aCommand,sSelectLineNextString) || - !nsCRT::strcmp(aCommand,sSelectPagePreviousString) || - !nsCRT::strcmp(aCommand,sSelectPageNextString) || - !nsCRT::strcmp(aCommand,sSelectMoveTopString) || - !nsCRT::strcmp(aCommand,sSelectMoveBottomString) - ) - *outSupported = PR_TRUE; - - return NS_OK; -} - -NS_IMETHODIMP -nsDOMWindowController::DoCommand(const char *aCommand) -{ - nsresult rv = NS_ERROR_FAILURE; - - if (!nsCRT::strcmp(aCommand,sCopyString) || - !nsCRT::strcmp(aCommand,sSelectAllString) || - !nsCRT::strcmp(aCommand,sSelectNoneString) || - !nsCRT::strcmp(aCommand,sCutString) || - !nsCRT::strcmp(aCommand,sPasteString) || - !nsCRT::strcmp(aCommand,sCopyLinkString) || - !nsCRT::strcmp(aCommand,sCopyImageLocationString) || - !nsCRT::strcmp(aCommand,sCopyImageContentsString)) { - rv = DoCommandWithEditInterface(aCommand); - } - else if (!nsCRT::strcmp(aCommand,sScrollTopString) || - !nsCRT::strcmp(aCommand,sScrollBottomString) || - !nsCRT::strcmp(aCommand,sScrollPageUpString) || - !nsCRT::strcmp(aCommand,sMovePageDownString) || - !nsCRT::strcmp(aCommand,sMovePageUpString) || - !nsCRT::strcmp(aCommand,sScrollPageDownString) || - !nsCRT::strcmp(aCommand,sScrollLineUpString) || - !nsCRT::strcmp(aCommand,sScrollLineDownString) || - !nsCRT::strcmp(aCommand,sScrollLeftString) || - !nsCRT::strcmp(aCommand,sScrollRightString) || - !nsCRT::strcmp(aCommand,sSelectCharPreviousString) || - !nsCRT::strcmp(aCommand,sSelectCharNextString) || - !nsCRT::strcmp(aCommand,sWordPreviousString) || - !nsCRT::strcmp(aCommand,sWordNextString) || - !nsCRT::strcmp(aCommand,sSelectWordPreviousString) || - !nsCRT::strcmp(aCommand,sSelectWordNextString) || - !nsCRT::strcmp(aCommand,sBeginLineString) || - !nsCRT::strcmp(aCommand,sEndLineString) || - !nsCRT::strcmp(aCommand,sSelectBeginLineString) || - !nsCRT::strcmp(aCommand,sSelectEndLineString) || - !nsCRT::strcmp(aCommand,sSelectLinePreviousString) || - !nsCRT::strcmp(aCommand,sSelectLineNextString) || - !nsCRT::strcmp(aCommand,sSelectMoveTopString) || - !nsCRT::strcmp(aCommand,sSelectMoveBottomString)) { - rv = DoCommandWithSelectionController(aCommand); - // If the user moves the caret in browse with caret mode - // Focus whatever they move onto, if it's focusable - if (mBrowseWithCaret) { - nsCOMPtr esm; - if (NS_SUCCEEDED(GetEventStateManager(getter_AddRefs(esm)))) { - PRBool isSelectionWithFocus; - esm->MoveFocusToCaret(PR_TRUE, &isSelectionWithFocus); - } - } - } - else if (!nsCRT::strcmp(aCommand,sBrowserBackString) || - !nsCRT::strcmp(aCommand,sBrowserForwardString)) { - rv = DoCommandWithWebNavigationInterface(aCommand); - } - - return rv; -} - -nsresult -nsDOMWindowController::DoCommandWithWebNavigationInterface(const char *aCommandName) -{ - nsCOMPtr webNav(do_GetInterface(mWindow)); - - nsresult rv = NS_ERROR_FAILURE; - - if (webNav) { - if (!nsCRT::strcmp(aCommandName, sBrowserBackString)) { - rv = webNav->GoBack(); - } - else if (!nsCRT::strcmp(aCommandName, sBrowserForwardString)) { - rv= webNav->GoForward(); - } - } - return rv; -} - -nsresult -nsDOMWindowController::DoCommandWithEditInterface(const char *aCommandName) -{ - // get edit interface... - nsCOMPtr editInterface; - nsresult rv = GetEditInterface(getter_AddRefs(editInterface)); - // if we can't get an edit interface, that's bad - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(editInterface, NS_ERROR_NOT_INITIALIZED); - - rv = NS_ERROR_FAILURE; - - if (!nsCRT::strcmp(aCommandName,sCopyString)) - rv = editInterface->CopySelection(); - else if (!nsCRT::strcmp(aCommandName,sSelectAllString)) - rv = editInterface->SelectAll(); - else if (!nsCRT::strcmp(aCommandName,sSelectNoneString)) - rv = editInterface->ClearSelection(); - else if (!nsCRT::strcmp(aCommandName,sCutString)) - rv = editInterface->CutSelection(); - else if (!nsCRT::strcmp(aCommandName,sPasteString)) - rv = editInterface->Paste(); - else if (!nsCRT::strcmp(aCommandName,sCopyLinkString)) - rv = editInterface->CopyLinkLocation(); - else if (!nsCRT::strcmp(aCommandName,sCopyImageLocationString)) - rv = editInterface->CopyImageLocation(); - else if (!nsCRT::strcmp(aCommandName,sCopyImageContentsString)) - rv = editInterface->CopyImageContents(); - - return rv; - -} - -nsresult -nsDOMWindowController::DoCommandWithSelectionController(const char *aCommandName) { - - // get selection controller... - nsCOMPtr selCont; - nsresult rv = GetSelectionController(getter_AddRefs(selCont)); - // if we can't get a selection controller, that's bad - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED); - - rv = NS_ERROR_FAILURE; - - if (!nsCRT::strcmp(aCommandName,sScrollTopString)) - rv = (mBrowseWithCaret? selCont->CompleteMove(PR_FALSE, PR_FALSE): selCont->CompleteScroll(PR_FALSE)); - else if (!nsCRT::strcmp(aCommandName,sScrollBottomString)) - rv = (mBrowseWithCaret? selCont->CompleteMove(PR_TRUE, PR_FALSE): selCont->CompleteScroll(PR_TRUE)); - // cmd_ScrollPageUp/Down are used on Mac. They do not move the - // caret in caret browsing mode. - else if (!nsCRT::strcmp(aCommandName,sScrollPageUpString)) - rv = selCont->ScrollPage(PR_FALSE); - else if (!nsCRT::strcmp(aCommandName,sScrollPageDownString)) - rv = selCont->ScrollPage(PR_TRUE); - // cmd_MovePageUp/Down are used on Window/Unix. They move the caret - // in caret browsing mode. - else if (!nsCRT::strcmp(aCommandName,sMovePageUpString)) - rv = (mBrowseWithCaret? selCont->PageMove(PR_FALSE, PR_FALSE): selCont->ScrollPage(PR_FALSE)); - else if (!nsCRT::strcmp(aCommandName,sMovePageDownString)) - rv = (mBrowseWithCaret? selCont->PageMove(PR_TRUE, PR_FALSE): selCont->ScrollPage(PR_TRUE)); - else if (!nsCRT::strcmp(aCommandName,sScrollLineUpString)) - rv = (mBrowseWithCaret? selCont->LineMove(PR_FALSE, PR_FALSE): selCont->ScrollLine(PR_FALSE)); - else if (!nsCRT::strcmp(aCommandName,sScrollLineDownString)) - rv = (mBrowseWithCaret? selCont->LineMove(PR_TRUE, PR_FALSE): selCont->ScrollLine(PR_TRUE)); - else if (!nsCRT::strcmp(aCommandName,sScrollLeftString)) - rv = (mBrowseWithCaret? selCont->CharacterMove(PR_FALSE, PR_FALSE): selCont->ScrollHorizontal(PR_TRUE)); - else if (!nsCRT::strcmp(aCommandName,sScrollRightString)) - rv = (mBrowseWithCaret? selCont->CharacterMove(PR_TRUE, PR_FALSE): selCont->ScrollHorizontal(PR_FALSE)); - // These commands are so the browser can use editor navigation key bindings - - // Helps with accessibility - aaronl@chorus.net - else if (!nsCRT::strcmp(aCommandName,sSelectCharPreviousString)) - rv = selCont->CharacterMove(PR_FALSE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sSelectCharNextString)) - rv = selCont->CharacterMove(PR_TRUE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sWordPreviousString)) - rv = selCont->WordMove(PR_FALSE, PR_FALSE); - else if (!nsCRT::strcmp(aCommandName,sWordNextString)) - rv = selCont->WordMove(PR_TRUE, PR_FALSE); - else if (!nsCRT::strcmp(aCommandName,sSelectWordPreviousString)) - rv = selCont->WordMove(PR_FALSE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sSelectWordNextString)) - rv = selCont->WordMove(PR_TRUE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sBeginLineString)) - rv = selCont->IntraLineMove(PR_FALSE, PR_FALSE); - else if (!nsCRT::strcmp(aCommandName,sEndLineString)) - rv = selCont->IntraLineMove(PR_TRUE, PR_FALSE); - else if (!nsCRT::strcmp(aCommandName,sSelectBeginLineString)) - rv = selCont->IntraLineMove(PR_FALSE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sSelectEndLineString)) - rv = selCont->IntraLineMove(PR_TRUE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sSelectLinePreviousString)) - rv = selCont->LineMove(PR_FALSE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sSelectLineNextString)) - rv = selCont->LineMove(PR_TRUE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sSelectMoveTopString)) - rv = selCont->CompleteMove(PR_FALSE, PR_TRUE); - else if (!nsCRT::strcmp(aCommandName,sSelectMoveBottomString)) - rv = selCont->CompleteMove(PR_TRUE, PR_TRUE); - - return rv; - -} - -NS_IMETHODIMP -nsDOMWindowController::OnEvent(const char * aEventName) -{ - return NS_OK; -} -#endif diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index bc75cc0240e..76dc563fcd7 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -212,6 +212,7 @@ protected: // Object Management virtual ~GlobalWindowImpl(); void CleanUp(); + void ClearControllers(); // Get the parent, returns null if this is a toplevel window void GetParentInternal(nsIDOMWindowInternal **parent); @@ -439,34 +440,4 @@ protected: nsIDocShell *mDocShell; // Weak Reference }; -#define DOM_CONTROLLER -#ifdef DOM_CONTROLLER -class nsIContentViewerEdit; - -class nsISelectionController; - -class nsDOMWindowController : public nsIController -{ -public: - nsDOMWindowController( nsIDOMWindowInternal* aWindow ); - virtual ~nsDOMWindowController(); - NS_DECL_ISUPPORTS - NS_DECL_NSICONTROLLER - -private: - nsresult GetEventStateManager(nsIEventStateManager **esm); - static int PR_CALLBACK BrowseWithCaretPrefCallback(const char* aPrefName, void* instance_data); - nsresult GetPresShell(nsIPresShell **aPresShell); - nsresult GetEditInterface( nsIContentViewerEdit** aEditInterface); - nsresult GetSelectionController(nsISelectionController ** aSelCon); - - nsresult DoCommandWithWebNavigationInterface(const char * aCommandName); - nsresult DoCommandWithEditInterface(const char * aCommandName); - nsresult DoCommandWithSelectionController(const char * aCommandName); - - nsIDOMWindowInternal *mWindow; - PRBool mBrowseWithCaret; -}; -#endif // DOM_CONTROLLER - #endif /* nsGlobalWindow_h___ */ diff --git a/mozilla/dom/src/base/nsGlobalWindowCommands.cpp b/mozilla/dom/src/base/nsGlobalWindowCommands.cpp index 83448382615..0f02d647da1 100644 --- a/mozilla/dom/src/base/nsGlobalWindowCommands.cpp +++ b/mozilla/dom/src/base/nsGlobalWindowCommands.cpp @@ -43,7 +43,6 @@ #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" #include "nsCRT.h" -#include "nsString.h" #include "nsIControllerCommandTable.h" #include "nsICommandParams.h" @@ -112,6 +111,7 @@ const char * const sSelectMoveBottomString = "cmd_selectMoveBottom"; class nsSelectionCommandsBase : public nsIControllerCommand { public: + nsSelectionCommandsBase() { NS_INIT_ISUPPORTS(); } NS_DECL_ISUPPORTS NS_DECL_NSICONTROLLERCOMMAND @@ -395,6 +395,7 @@ nsSelectCommand::DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow class nsClipboardBaseCommand : public nsIControllerCommand { public: + nsClipboardBaseCommand() { NS_INIT_ISUPPORTS(); } NS_DECL_ISUPPORTS NS_DECL_NSICONTROLLERCOMMAND @@ -402,7 +403,7 @@ public: protected: virtual nsresult IsClipboardCommandEnabled(const char * aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled) = 0; - virtual nsresult DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) = 0; + virtual nsresult DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit) = 0; static nsresult GetContentViewerEditFromContext(nsISupports *aContext, nsIContentViewerEdit **aEditInterface); @@ -442,7 +443,7 @@ nsClipboardBaseCommand::DoCommand(const char *aCommandName, GetContentViewerEditFromContext(aCommandContext, getter_AddRefs(contentEdit)); NS_ENSURE_TRUE(contentEdit, NS_ERROR_NOT_INITIALIZED); - return DoClipboardCommand(aCommandName, contentEdit, nsnull); + return DoClipboardCommand(aCommandName, contentEdit); } NS_IMETHODIMP @@ -458,11 +459,7 @@ nsClipboardBaseCommand::DoCommandParams(const char *aCommandName, nsICommandParams *aParams, nsISupports *aCommandContext) { - nsCOMPtr contentEdit; - GetContentViewerEditFromContext(aCommandContext, getter_AddRefs(contentEdit)); - NS_ENSURE_TRUE(contentEdit, NS_ERROR_NOT_INITIALIZED); - - return DoClipboardCommand(aCommandName, contentEdit, aParams); + return DoCommand(aCommandName, aCommandContext); } nsresult @@ -504,7 +501,7 @@ protected: virtual nsresult IsClipboardCommandEnabled(const char* aCommandName, \ nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled); \ virtual nsresult DoClipboardCommand(const char* aCommandName, \ - nsIContentViewerEdit* aEdit, nsICommandParams* aParams); \ + nsIContentViewerEdit* aEdit); \ /* no member variables, please, we're stateless! */ \ }; @@ -514,7 +511,6 @@ NS_DECL_CLIPBOARD_COMMAND(nsClipboardPasteCommand) NS_DECL_CLIPBOARD_COMMAND(nsClipboardCopyLinkCommand) NS_DECL_CLIPBOARD_COMMAND(nsClipboardImageCommands) NS_DECL_CLIPBOARD_COMMAND(nsClipboardSelectAllNoneCommands) -NS_DECL_CLIPBOARD_COMMAND(nsClipboardGetContentsCommand) #if 0 #pragma mark - @@ -528,7 +524,7 @@ nsClipboardCutCommand::IsClipboardCommandEnabled(const char* aCommandName, nsICo } nsresult -nsClipboardCutCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) +nsClipboardCutCommand::DoClipboardCommand(const char* aCommandName, nsIContentViewerEdit* aEdit) { return aEdit->CutSelection(); } @@ -544,7 +540,7 @@ nsClipboardCopyCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIC } nsresult -nsClipboardCopyCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) +nsClipboardCopyCommand::DoClipboardCommand(const char* aCommandName, nsIContentViewerEdit* aEdit) { return aEdit->CopySelection(); } @@ -560,7 +556,7 @@ nsClipboardPasteCommand::IsClipboardCommandEnabled(const char* aCommandName, nsI } nsresult -nsClipboardPasteCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) +nsClipboardPasteCommand::DoClipboardCommand(const char* aCommandName, nsIContentViewerEdit* aEdit) { return aEdit->Paste(); } @@ -577,7 +573,7 @@ nsClipboardCopyLinkCommand::IsClipboardCommandEnabled(const char* aCommandName, } nsresult -nsClipboardCopyLinkCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) +nsClipboardCopyLinkCommand::DoClipboardCommand(const char* aCommandName, nsIContentViewerEdit* aEdit) { return aEdit->CopyLinkLocation(); } @@ -593,7 +589,7 @@ nsClipboardImageCommands::IsClipboardCommandEnabled(const char* aCommandName, ns } nsresult -nsClipboardImageCommands::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) +nsClipboardImageCommands::DoClipboardCommand(const char* aCommandName, nsIContentViewerEdit* aEdit) { if (!nsCRT::strcmp(sCopyImageLocationString, aCommandName)) return aEdit->CopyImageLocation(); @@ -613,7 +609,7 @@ nsClipboardSelectAllNoneCommands::IsClipboardCommandEnabled(const char* aCommand } nsresult -nsClipboardSelectAllNoneCommands::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) +nsClipboardSelectAllNoneCommands::DoClipboardCommand(const char* aCommandName, nsIContentViewerEdit* aEdit) { if (!nsCRT::strcmp(sSelectAllString, aCommandName)) return aEdit->SelectAll(); @@ -622,39 +618,6 @@ nsClipboardSelectAllNoneCommands::DoClipboardCommand(const char *aCommandName, n } -#if 0 -#pragma mark - -#endif - -nsresult -nsClipboardGetContentsCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled) -{ - return aEdit->GetCanGetContents(outCmdEnabled); -} - -nsresult -nsClipboardGetContentsCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) -{ - NS_ENSURE_ARG(aParams); - - nsCAutoString mimeType("text/plain"); - - nsXPIDLCString format; // nsICommandParams needs to use nsACString - if (NS_SUCCEEDED(aParams->GetCStringValue("format", getter_Copies(format)))) - mimeType.Assign(format); - - PRBool selectionOnly = PR_FALSE; - aParams->GetBooleanValue("selection_only", &selectionOnly); - - nsAutoString contents; - nsresult rv = aEdit->GetContents(mimeType.get(), selectionOnly, contents); - if (NS_FAILED(rv)) - return rv; - - return aParams->SetStringValue("result", contents); -} - - #if 0 #pragma mark - #endif @@ -662,6 +625,7 @@ nsClipboardGetContentsCommand::DoClipboardCommand(const char *aCommandName, nsIC class nsWebNavigationBaseCommand : public nsIControllerCommand { public: + nsWebNavigationBaseCommand() { NS_INIT_ISUPPORTS(); } NS_DECL_ISUPPORTS NS_DECL_NSICONTROLLERCOMMAND @@ -792,6 +756,7 @@ nsGoBackCommand::DoWebNavCommand(const char *aCommandName, nsIWebNavigation* aWe class nsClipboardDragDropHookCommand : public nsIControllerCommand { public: + nsClipboardDragDropHookCommand() { NS_INIT_ISUPPORTS(); } NS_DECL_ISUPPORTS NS_DECL_NSICONTROLLERCOMMAND @@ -957,8 +922,6 @@ nsWindowCommandRegistration::RegisterWindowCommands( NS_REGISTER_FIRST_COMMAND(nsClipboardSelectAllNoneCommands, sSelectAllString); NS_REGISTER_LAST_COMMAND(nsClipboardSelectAllNoneCommands, sSelectNoneString); - NS_REGISTER_ONE_COMMAND(nsClipboardGetContentsCommand, "cmd_getContents"); - NS_REGISTER_ONE_COMMAND(nsGoBackCommand, "cmd_browserBack"); NS_REGISTER_ONE_COMMAND(nsGoForwardCommand, "cmd_browserForward"); diff --git a/mozilla/dom/src/build/Makefile.in b/mozilla/dom/src/build/Makefile.in index 7adbdeef798..79cd5c3d075 100644 --- a/mozilla/dom/src/build/Makefile.in +++ b/mozilla/dom/src/build/Makefile.in @@ -39,6 +39,7 @@ REQUIRES = xpcom \ content \ caps \ webbrwsr \ + commandhandler \ xuldoc \ docshell \ sidebar \ diff --git a/mozilla/dom/src/build/nsDOMFactory.cpp b/mozilla/dom/src/build/nsDOMFactory.cpp index 5a27d9706f6..7388969f4ad 100644 --- a/mozilla/dom/src/build/nsDOMFactory.cpp +++ b/mozilla/dom/src/build/nsDOMFactory.cpp @@ -49,9 +49,21 @@ #include "nsIExceptionService.h" #include "nsCRT.h" +#include "nsIController.h" +#include "nsIControllerContext.h" +#include "nsIControllerCommandTable.h" +#include "nsGlobalWindowCommands.h" + #include "nsScriptNameSpaceManager.h" #include "nsDOMException.h" +#define NS_WINDOWCOMMANDTABLE_CID \ + { /* 0DE2FBFA-6B7F-11D7-BBBA-0003938A9D96 */ \ + 0x0DE2FBFA, 0x6B7F, 0x11D7, {0xBB, 0xBA, 0x00, 0x03, 0x93, 0x8A, 0x9D, 0x96} } + +static NS_DEFINE_CID(kWindowCommandTableCID, NS_WINDOWCOMMANDTABLE_CID); + + extern nsresult NS_CreateScriptContext(nsIScriptGlobalObject *aGlobal, nsIScriptContext **aContext); @@ -277,6 +289,47 @@ nsDOMSOFactory::RegisterDOMClassInfo(const char *aName, ////////////////////////////////////////////////////////////////////// +static NS_METHOD +CreateWindowCommandTableConstructor(nsISupports *aOuter, + REFNSIID aIID, void **aResult) +{ + nsresult rv; + nsCOMPtr commandTable = + do_CreateInstance(NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = nsWindowCommandRegistration::RegisterWindowCommands(commandTable); + if (NS_FAILED(rv)) return rv; + + return commandTable->QueryInterface(aIID, aResult); +} + +static NS_METHOD +CreateWindowControllerWithSingletonCommandTable(nsISupports *aOuter, + REFNSIID aIID, void **aResult) +{ + nsresult rv; + nsCOMPtr controller = + do_CreateInstance("@mozilla.org/embedcomp/base-command-controller;1", &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr windowCommandTable = do_GetService(kWindowCommandTableCID, &rv); + if (NS_FAILED(rv)) return rv; + + // this is a singleton; make it immutable + windowCommandTable->MakeImmutable(); + + nsCOMPtr controllerContext = do_QueryInterface(controller, &rv); + if (NS_FAILED(rv)) return rv; + + controllerContext->Init(windowCommandTable); + if (NS_FAILED(rv)) return rv; + + return controller->QueryInterface(aIID, aResult); +} + +////////////////////////////////////////////////////////////////////// + NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSOFactory); NS_GENERIC_FACTORY_CONSTRUCTOR(nsBaseDOMException); @@ -290,7 +343,17 @@ static const nsModuleComponentInfo gDOMModuleInfo[] = { NS_BASE_DOM_EXCEPTION_CID, nsnull, nsBaseDOMExceptionConstructor - } + }, + { "Window Command Table", + NS_WINDOWCOMMANDTABLE_CID, + "", + CreateWindowCommandTableConstructor + }, + { "Window Command Controller", + NS_WINDOWCONTROLLER_CID, + NS_WINDOWCONTROLLER_CONTRACTID, + CreateWindowControllerWithSingletonCommandTable + }, }; void PR_CALLBACK diff --git a/mozilla/editor/composer/src/nsComposerCommands.cpp b/mozilla/editor/composer/src/nsComposerCommands.cpp index bdccc674f35..5f9696a1c35 100644 --- a/mozilla/editor/composer/src/nsComposerCommands.cpp +++ b/mozilla/editor/composer/src/nsComposerCommands.cpp @@ -56,6 +56,7 @@ #include "nsICommandParams.h" #include "nsComponentManagerUtils.h" #include "nsCRT.h" + //prototype nsresult GetListState(nsIEditor *aEditor, PRBool *aMixed, PRUnichar **tagStr); nsresult PasteAsQuotation(nsIEditor *aEditor, PRInt32 aSelectionType); @@ -66,7 +67,6 @@ nsresult GetListItemState(nsIEditor *aEditor, PRBool *aMixed, PRUnichar **_retva //defines -#define COMMAND_NAME "cmd_name" #define STATE_ENABLED "state_enabled" #define STATE_ALL "state_all" #define STATE_ATTRIBUTE "state_attribute" @@ -322,7 +322,7 @@ nsStyleUpdatingCommand::ToggleState(nsIEditor *aEditor, const char* aTagName) nsCOMPtr htmlEditor = do_QueryInterface(aEditor); if (!htmlEditor) return NS_ERROR_NO_INTERFACE; - PRBool styleSet; + //create some params now... nsresult rv; nsCOMPtr params = do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv); @@ -332,6 +332,7 @@ nsStyleUpdatingCommand::ToggleState(nsIEditor *aEditor, const char* aTagName) rv = GetCurrentState(aEditor, aTagName, params); if (NS_FAILED(rv)) return rv; + PRBool styleSet; rv = params->GetBooleanValue(STATE_ALL,&styleSet); if (NS_FAILED(rv)) return rv; @@ -425,12 +426,14 @@ nsListCommand::ToggleState(nsIEditor *aEditor, const char* aTagName) return rv; nsAutoString listType; listType.AssignWithConversion(mTagName); - nsString empty; if (inList) rv = editor->RemoveList(listType); else + { + nsString empty; rv = editor->MakeOrChangeList(listType, PR_FALSE, empty); - + } + return rv; } @@ -613,9 +616,7 @@ nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) nsresult rv = NS_OK; if (editor) { - NS_NAMED_LITERAL_STRING(indentStr, "indent"); - nsAutoString aIndent(indentStr); - rv = editor->Indent(aIndent); + rv = editor->Indent(NS_LITERAL_STRING("indent")); } return rv; @@ -624,17 +625,7 @@ nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) NS_IMETHODIMP nsIndentCommand::DoCommandParams(const char *aCommandName, nsICommandParams *aParams, nsISupports *refCon) { - nsCOMPtr editor = do_QueryInterface(refCon); - - nsresult rv = NS_OK; - if (editor) - { - NS_NAMED_LITERAL_STRING(indentStr, "indent"); - nsAutoString aIndent(indentStr); - rv = editor->Indent(aIndent); - } - - return rv; + return DoCommand(aCommandName, refCon); } NS_IMETHODIMP @@ -651,8 +642,7 @@ nsIndentCommand::GetCommandStateParams(const char *aCommandName, nsICommandParam NS_IMETHODIMP nsOutdentCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { - nsCOMPtr editor = do_QueryInterface(refCon); - nsCOMPtr htmlEditor = do_QueryInterface(editor); + nsCOMPtr htmlEditor = do_QueryInterface(refCon); if (htmlEditor) { PRBool canIndent, canOutdent; @@ -674,11 +664,9 @@ nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) nsresult rv = NS_OK; if (editor) { - NS_NAMED_LITERAL_STRING(indentStr, "outdent"); - nsAutoString aIndent(indentStr); nsCOMPtr htmlEditor = do_QueryInterface(editor); if (htmlEditor) - rv = htmlEditor->Indent(aIndent); + rv = htmlEditor->Indent(NS_LITERAL_STRING("outdent")); } return rv; @@ -687,19 +675,7 @@ nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon) NS_IMETHODIMP nsOutdentCommand::DoCommandParams(const char *aCommandName, nsICommandParams *aParams, nsISupports *refCon) { - nsCOMPtr editor = do_QueryInterface(refCon); - - nsresult rv = NS_OK; - if (editor) - { - NS_NAMED_LITERAL_STRING(indentStr, "outdent"); - nsAutoString aIndent(indentStr); - nsCOMPtr htmlEditor = do_QueryInterface(editor); - if (htmlEditor) - rv = htmlEditor->Indent(aIndent); - } - - return rv; + return DoCommand(aCommandName, refCon); } NS_IMETHODIMP @@ -731,14 +707,8 @@ NS_IMETHODIMP nsMultiStateCommand::IsCommandEnabled(const char * aCommandName, nsISupports *refCon, PRBool *outCmdEnabled) { nsCOMPtr editor = do_QueryInterface(refCon); - if (editor) - { // should be disabled sometimes, like if the current selection is an image - *outCmdEnabled = PR_TRUE; - } - else - *outCmdEnabled = PR_FALSE; - + *outCmdEnabled = editor ? PR_TRUE : PR_FALSE; return NS_OK; } @@ -746,14 +716,11 @@ nsMultiStateCommand::IsCommandEnabled(const char * aCommandName, nsISupports *re NS_IMETHODIMP nsMultiStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon) { - nsCOMPtr editor = do_QueryInterface(refCon); - - nsresult rv = NS_OK; #ifdef DEBUG printf("who is calling nsMultiStateCommand::DoCommand (no implementation)? %s\n", aCommandName); #endif - return rv; + return NS_OK; } NS_IMETHODIMP @@ -839,7 +806,6 @@ nsresult nsParagraphStateCommand::SetState(nsIEditor *aEditor, nsString& newState) { NS_ASSERTION(aEditor, "Need an editor here"); - nsCOMPtr htmlEditor = do_QueryInterface(aEditor); if (!htmlEditor) return NS_ERROR_FAILURE; @@ -894,8 +860,6 @@ nsFontFaceStateCommand::SetState(nsIEditor *aEditor, nsString& newState) if (!htmlEditor) return NS_ERROR_FAILURE; nsresult rv; - - nsCOMPtr ttAtom = getter_AddRefs(NS_NewAtom("tt")); nsCOMPtr fontAtom = getter_AddRefs(NS_NewAtom("font")); @@ -985,10 +949,10 @@ nsFontSizeStateCommand::GetCurrentState(nsIEditor *aEditor, // acceptable values for "newState" are: // -2 -// -1 +// -1 // 0 // +1 -// +2 +// +2 // +3 // medium // normal @@ -1069,13 +1033,10 @@ nsresult nsFontColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState) { NS_ASSERTION(aEditor, "Need an editor here"); - nsCOMPtr htmlEditor = do_QueryInterface(aEditor); if (!htmlEditor) return NS_ERROR_FAILURE; nsresult rv; - - nsCOMPtr fontAtom = getter_AddRefs(NS_NewAtom("font")); if (newState.IsEmpty() || newState.Equals(NS_LITERAL_STRING("normal"))) { @@ -1137,7 +1098,6 @@ nsHighlightColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState) if (!htmlEditor) return NS_ERROR_FAILURE; nsresult rv; - nsCOMPtr fontAtom = getter_AddRefs(NS_NewAtom("font")); if (!newState.Length() || newState.Equals(NS_LITERAL_STRING("normal"))) { @@ -1558,7 +1518,6 @@ RemoveTextProperty(nsIEditor *aEditor, const PRUnichar *prop, const PRUnichar *a return NS_ERROR_NOT_INITIALIZED; // OK, I'm really hacking now. This is just so that we can accept 'all' as input. nsAutoString allStr(prop); - nsAutoString aAttr(attr); ToLowerCase(allStr); PRBool doingAll = (allStr.Equals(NS_LITERAL_STRING("all"))); @@ -1571,6 +1530,7 @@ RemoveTextProperty(nsIEditor *aEditor, const PRUnichar *prop, const PRUnichar *a else { nsAutoString aProp(prop); + nsAutoString aAttr(attr); err = RemoveOneProperty(editor,aProp, aAttr); } diff --git a/mozilla/editor/composer/src/nsComposerCommands.h b/mozilla/editor/composer/src/nsComposerCommands.h index 6a3f312a46e..8e95472f1ae 100644 --- a/mozilla/editor/composer/src/nsComposerCommands.h +++ b/mozilla/editor/composer/src/nsComposerCommands.h @@ -44,6 +44,8 @@ #include "nsIControllerCommand.h" #include "nsString.h" +class nsIEditor; + // This is a virtual base class for commands registered with the composer controller. // Note that such commands are instantiated once per composer, so can store state. // Also note that IsCommandEnabled can be called with an editor that may not @@ -70,7 +72,6 @@ public: }; - #define NS_DECL_COMPOSER_COMMAND(_cmd) \ class _cmd : public nsBaseComposerCommand \ { \ @@ -289,11 +290,9 @@ NS_DECL_COMPOSER_COMMAND(nsCloseCommand) // Generic commands - // File menu NS_DECL_COMPOSER_COMMAND(nsNewCommands) // handles 'new' anything - // Edit menu NS_DECL_COMPOSER_COMMAND(nsPasteQuotationCommand) NS_DECL_COMPOSER_COMMAND(nsPasteNoFormattingCommand) diff --git a/mozilla/editor/composer/src/nsComposerCommandsUpdater.cpp b/mozilla/editor/composer/src/nsComposerCommandsUpdater.cpp index ad1ac15b9ad..6bdd52d21bb 100644 --- a/mozilla/editor/composer/src/nsComposerCommandsUpdater.cpp +++ b/mozilla/editor/composer/src/nsComposerCommandsUpdater.cpp @@ -61,6 +61,8 @@ NS_IMPL_ISUPPORTS4(nsComposerCommandsUpdater, nsISelectionListener, nsIDocumentS NS_IMETHODIMP nsComposerCommandsUpdater::NotifyDocumentCreated() { + // Trigger an nsIObserve notification that the document has been created + UpdateOneCommand("obs_documentCreated"); return NS_OK; } @@ -69,7 +71,10 @@ nsComposerCommandsUpdater::NotifyDocumentWillBeDestroyed() { // cancel any outstanding udpate timer if (mUpdateTimer) + { mUpdateTimer->Cancel(); + mUpdateTimer = nsnull; + } return NS_OK; } @@ -321,6 +326,20 @@ nsComposerCommandsUpdater::CallUpdateCommands(const nsAString& aCommandGroup) return NS_OK; } +nsresult +nsComposerCommandsUpdater::UpdateOneCommand(const char *aCommand) +{ + if (!mDocShell) return NS_ERROR_FAILURE; + + nsCOMPtr commandManager = do_GetInterface(mDocShell); + nsCOMPtr commandUpdater = do_QueryInterface(commandManager); + if (!commandUpdater) return NS_ERROR_FAILURE; + + commandUpdater->CommandStatusChanged(aCommand); + + return NS_OK; +} + PRBool nsComposerCommandsUpdater::SelectionIsCollapsed() { diff --git a/mozilla/editor/composer/src/nsComposerCommandsUpdater.h b/mozilla/editor/composer/src/nsComposerCommandsUpdater.h index b6f4b472fb5..9325c318d52 100644 --- a/mozilla/editor/composer/src/nsComposerCommandsUpdater.h +++ b/mozilla/editor/composer/src/nsComposerCommandsUpdater.h @@ -92,6 +92,7 @@ protected: PRBool SelectionIsCollapsed(); nsresult UpdateDirtyState(PRBool aNowDirty); + nsresult UpdateOneCommand(const char* aCommand); nsresult CallUpdateCommands(const nsAString& aCommand); nsresult PrimeUpdateTimer(); diff --git a/mozilla/editor/composer/src/nsComposerController.cpp b/mozilla/editor/composer/src/nsComposerController.cpp index 4de27d7235a..2f9718ddeba 100644 --- a/mozilla/editor/composer/src/nsComposerController.cpp +++ b/mozilla/editor/composer/src/nsComposerController.cpp @@ -40,95 +40,16 @@ * ***** END LICENSE BLOCK ***** */ #include "nsIComponentManager.h" +#include "nsIControllerCommandTable.h" #include "nsComposerController.h" - -#if 0 -#include "nsIEditor.h" -#include "nsIEditorMailSupport.h" -#include "nsIFormControlFrame.h" -#include "nsISelection.h" -#include "nsIHTMLEditor.h" -#include "nsXPIDLString.h" - -#include "nsISelectionController.h" -#include "nsIDocument.h" -#include "nsIPresShell.h" - -#include "nsEditorCommands.h" -#endif - #include "nsComposerCommands.h" -NS_IMPL_ADDREF(nsComposerController) -NS_IMPL_RELEASE(nsComposerController) - -NS_INTERFACE_MAP_BEGIN(nsComposerController) - NS_INTERFACE_MAP_ENTRY(nsIController) - NS_INTERFACE_MAP_ENTRY(nsICommandController) - NS_INTERFACE_MAP_ENTRY(nsIEditorController) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditorController) -NS_INTERFACE_MAP_END - - -nsComposerController::nsComposerController() -{ - NS_INIT_ISUPPORTS(); -} - -nsComposerController::~nsComposerController() -{ -} - -NS_IMETHODIMP nsComposerController::Init(nsISupports *aCommandRefCon) -{ - nsresult rv; - - // get our ref to the singleton command manager - // This will create mCommandManager and register commands if not already done. - rv = GetComposerCommandManager(getter_AddRefs(mCommandManager)); - if (NS_FAILED(rv)) return rv; - - mCommandRefCon = aCommandRefCon; // no addref - - // the following (7?) lines can be removed when the JS commands are stateless and in C++ - mCommandManager = do_CreateInstance(NS_CONTROLLERCOMMANDMANAGER_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - - // register the commands. - rv = nsComposerController::RegisterComposerCommands(mCommandManager); - if (NS_FAILED(rv)) return rv; - - return NS_OK; -} - -NS_IMETHODIMP -nsComposerController::SetCommandRefCon(nsISupports *aCommandRefCon) -{ - mCommandRefCon = aCommandRefCon; // no addref - return NS_OK; -} - -NS_IMETHODIMP -nsComposerController::GetInterface(const nsIID & aIID, void * *result) -{ - NS_ENSURE_ARG_POINTER(result); - - if (NS_SUCCEEDED(QueryInterface(aIID, result))) - return NS_OK; - - if (mCommandManager && aIID.Equals(NS_GET_IID(nsIControllerCommandManager))) - return mCommandManager->QueryInterface(aIID, result); - - return NS_NOINTERFACE; -} - #define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName) \ { \ _cmdClass* theCmd; \ NS_NEWXPCOM(theCmd, _cmdClass); \ if (!theCmd) return NS_ERROR_OUT_OF_MEMORY; \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \ } @@ -137,15 +58,15 @@ nsComposerController::GetInterface(const nsIID & aIID, void * *result) _cmdClass* theCmd; \ NS_NEWXPCOM(theCmd, _cmdClass); \ if (!theCmd) return NS_ERROR_OUT_OF_MEMORY; \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); #define NS_REGISTER_NEXT_COMMAND(_cmdClass, _cmdName) \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); #define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName) \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \ } @@ -153,13 +74,23 @@ nsComposerController::GetInterface(const nsIID & aIID, void * *result) { \ _cmdClass* theCmd = new _cmdClass(_styleTag); \ if (!theCmd) return NS_ERROR_OUT_OF_MEMORY; \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ + NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \ + } + +#define NS_REGISTER_TAG_COMMAND(_cmdClass, _cmdName, _tagName) \ + { \ + _cmdClass* theCmd = new _cmdClass(_tagName); \ + if (!theCmd) return NS_ERROR_OUT_OF_MEMORY; \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \ } // static -nsresult nsComposerController::RegisterComposerCommands(nsIControllerCommandManager *inCommandManager) +nsresult +nsComposerController::RegisterHTMLEditorCommands( + nsIControllerCommandTable *inCommandTable) { nsresult rv; @@ -216,66 +147,7 @@ nsresult nsComposerController::RegisterComposerCommands(nsIControllerCommandMana return NS_OK; } -/* ======================================================================= - * nsIController - * ======================================================================= */ - -NS_IMETHODIMP -nsComposerController::IsCommandEnabled(const char * aCommand, - PRBool *aResult) -{ - NS_ENSURE_ARG_POINTER(aResult); - return mCommandManager->IsCommandEnabled(aCommand, mCommandRefCon, aResult); -} - -NS_IMETHODIMP -nsComposerController::SupportsCommand(const char * aCommand, - PRBool *aResult) -{ - NS_ENSURE_ARG_POINTER(aResult); - return mCommandManager->SupportsCommand(aCommand, mCommandRefCon, aResult); -} - -NS_IMETHODIMP -nsComposerController::DoCommand(const char *aCommand) -{ - return mCommandManager->DoCommand(aCommand, mCommandRefCon); -} - -NS_IMETHODIMP -nsComposerController::OnEvent(const char * aEventName) -{ - return NS_OK; -} - -nsWeakPtr nsComposerController::sComposerCommandManager = NULL; - -// static -nsresult nsComposerController::GetComposerCommandManager(nsIControllerCommandManager* *outCommandManager) -{ - NS_ENSURE_ARG_POINTER(outCommandManager); - - nsCOMPtr cmdManager = do_QueryReferent(sComposerCommandManager); - if (!cmdManager) - { - nsresult rv; - cmdManager = do_CreateInstance(NS_CONTROLLERCOMMANDMANAGER_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - - // register the commands. This just happens once per instance - rv = nsComposerController::RegisterComposerCommands(cmdManager); - if (NS_FAILED(rv)) return rv; - - // save the singleton in our static weak reference - sComposerCommandManager = getter_AddRefs(NS_GetWeakReference(cmdManager, &rv)); - if (NS_FAILED(rv)) return rv; - } - - NS_ADDREF(*outCommandManager = cmdManager); - return NS_OK; -} - - +#if 0 // GetCommandStateWithParams /* cmd_bold,cmd_italic,cmd_underline ->state commands @@ -299,3 +171,5 @@ NS_IMETHODIMP nsComposerController::DoCommandWithParams(const char *aCommand, ns return NS_ERROR_NOT_INITIALIZED; return mCommandManager->DoCommandParams(aCommand, aCommandParams,mCommandRefCon); } + +#endif \ No newline at end of file diff --git a/mozilla/editor/composer/src/nsComposerController.h b/mozilla/editor/composer/src/nsComposerController.h index 523ec6f11dd..bd4cf0ca19d 100644 --- a/mozilla/editor/composer/src/nsComposerController.h +++ b/mozilla/editor/composer/src/nsComposerController.h @@ -39,66 +39,27 @@ #ifndef nsComposerController_h__ #define nsComposerController_h__ -#define NS_COMPOSERCONTROLLER_CID \ -{ 0x50e95301, 0x17a8, 0x11d4, { 0x9f, 0x7e, 0xdd, 0x53, 0x0d, 0x5f, 0x05, 0x7c } } -#include "nsString.h" -#include "nsIEditorController.h" -#include "nsIController.h" -#include "nsIInterfaceRequestor.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsIControllerCommand.h" -#include "nsIControllerCommandManager.h" -#include "nsWeakPtr.h" +class nsIControllerCommandTable; -// the editor controller is used for composer only (and other HTML compose -// areas). The refCon that gets passed to its commands is an nsIEditor. -class nsComposerController : public nsIController, - public nsICommandController, - public nsIEditorController, - public nsIInterfaceRequestor +// The plaintext editor controller is used for basic text editing and html editing +// commands in composer +// The refCon that gets passed to its commands is initially nsIEditingSession, +// and after successfule editor creation it is changed to nsIEditor. +#define NS_EDITORDOCSTATECONTROLLER_CID \ + { 0x50e95301, 0x17a8, 0x11d4, { 0x9f, 0x7e, 0xdd, 0x53, 0x0d, 0x5f, 0x05, 0x7c } } + +// The HTMLEditor controller is used only for HTML editors and takes nsIEditor as refCon +#define NS_HTMLEDITORCONTROLLER_CID \ + { 0x62db0002, 0xdbb6, 0x43f4, { 0x8f, 0xb7, 0x9d, 0x25, 0x38, 0xbc, 0x57, 0x47 } } + + +class nsComposerController { public: - - nsComposerController(); - virtual ~nsComposerController(); - - // nsISupports - NS_DECL_ISUPPORTS - - // nsIController - NS_DECL_NSICONTROLLER - - /** init the controller */ - NS_IMETHOD Init(nsISupports *aCommandRefCon); - - /** Set the cookie that is passed to commands - */ - NS_IMETHOD SetCommandRefCon(nsISupports *aCommandRefCon); - - // nsIInterfaceRequestor - NS_DECL_NSIINTERFACEREQUESTOR - - //nsICommandController - NS_DECL_NSICOMMANDCONTROLLER - -protected: - - //if editor is null then look to mContent. this is for dual use of window and content - //attached controller. - nsISupports *mCommandRefCon; - - nsCOMPtr mCommandManager; // our reference to the command manager - -private: - - static nsresult GetComposerCommandManager(nsIControllerCommandManager* *outCommandManager); - static nsresult RegisterComposerCommands(nsIControllerCommandManager* inCommandManager); - - // the singleton command manager - static nsWeakPtr sComposerCommandManager; // common composer commands - + static nsresult RegisterEditorDocStateCommands(nsIControllerCommandTable* inCommandTable); + static nsresult RegisterHTMLEditorCommands(nsIControllerCommandTable* inCommandTable); }; #endif /* nsComposerController_h__ */ diff --git a/mozilla/editor/composer/src/nsComposerRegistration.cpp b/mozilla/editor/composer/src/nsComposerRegistration.cpp index c635985f122..09b1c5bf626 100644 --- a/mozilla/editor/composer/src/nsComposerRegistration.cpp +++ b/mozilla/editor/composer/src/nsComposerRegistration.cpp @@ -44,6 +44,19 @@ #include "nsEditorSpellCheck.h" // for the CID #include "nsEditorService.h" #include "nsComposeTxtSrvFilter.h" +#include "nsIController.h" +#include "nsIControllerContext.h" +#include "nsIControllerCommandTable.h" + +#define NS_HTMLEDITOR_COMMANDTABLE_CID \ +{ 0x7a727843, 0x6ae1, 0x11d7, { 0xa5eb, 0x00, 0x03, 0x93, 0x63, 0x65, 0x92 } } + +#define NS_HTMLEDITOR_DOCSTATE_COMMANDTABLE_CID \ +{ 0x800e07bc, 0x6ae1, 0x11d7, { 0x959b, 0x00, 0x03, 0x93, 0x63, 0x65, 0x92 } } + + +static NS_DEFINE_CID(kHTMLEditorCommandTableCID, NS_HTMLEDITOR_COMMANDTABLE_CID); + //////////////////////////////////////////////////////////////////////// // Define the contructor function for the objects @@ -53,7 +66,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorShell) NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditingSession) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsComposerController) NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorService) NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorSpellCheck) @@ -63,7 +75,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorSpellCheck) // Here we are creating the same object with two different contract IDs // and then initializing it different. // Basically, we need to tell the filter whether it is doing mail or not -static nsresult +static NS_METHOD nsComposeTxtSrvFilterConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult, PRBool aIsForMail) { @@ -85,7 +97,7 @@ nsComposeTxtSrvFilterConstructor(nsISupports *aOuter, REFNSIID aIID, return rv; } -static NS_IMETHODIMP +static NS_METHOD nsComposeTxtSrvFilterConstructorForComposer(nsISupports *aOuter, REFNSIID aIID, void **aResult) @@ -93,7 +105,7 @@ nsComposeTxtSrvFilterConstructorForComposer(nsISupports *aOuter, return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, PR_FALSE); } -static NS_IMETHODIMP +static NS_METHOD nsComposeTxtSrvFilterConstructorForMail(nsISupports *aOuter, REFNSIID aIID, void **aResult) @@ -102,34 +114,111 @@ nsComposeTxtSrvFilterConstructorForMail(nsISupports *aOuter, } +// Constructor for a controller set up with a command table specified +// by the CID passed in. This function uses do_GetService to get the +// command table, so that every controller shares a single command +// table, for space-efficiency. +// +// The only reason to go via the service manager for the command table +// is that it holds onto the singleton for us, avoiding static variables here. +static nsresult +CreateControllerWithSingletonCommandTable(const nsCID& inCommandTableCID, nsIController **aResult) +{ + nsresult rv; + nsCOMPtr controller = do_CreateInstance("@mozilla.org/embedcomp/base-command-controller;1", &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr composerCommandTable = do_GetService(inCommandTableCID, &rv); + if (NS_FAILED(rv)) return rv; + + // this guy is a singleton, so make it immutable + composerCommandTable->MakeImmutable(); + + nsCOMPtr controllerContext = do_QueryInterface(controller, &rv); + if (NS_FAILED(rv)) return rv; + + rv = controllerContext->Init(composerCommandTable); + if (NS_FAILED(rv)) return rv; + + *aResult = controller; + NS_ADDREF(*aResult); + return NS_OK; +} + + +// Tere we make an instance of the controller that holds composer commands. +// We set it up with a singleton command table. +static NS_METHOD +nsHTMLEditorControllerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + nsCOMPtr controller; + nsresult rv = CreateControllerWithSingletonCommandTable(kHTMLEditorCommandTableCID, getter_AddRefs(controller)); + if (NS_FAILED(rv)) return rv; + + return controller->QueryInterface(aIID, aResult); +} + +// Constructor for a command table that is pref-filled with HTML editor commands +static NS_METHOD +nsHTMLEditorCommandTableConstructor(nsISupports *aOuter, REFNSIID aIID, + void **aResult) +{ + nsresult rv; + nsCOMPtr commandTable = + do_CreateInstance(NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = nsComposerController::RegisterHTMLEditorCommands(commandTable); + if (NS_FAILED(rv)) return rv; + + // we don't know here whether we're being created as an instance, + // or a service, so we can't become immutable + + return commandTable->QueryInterface(aIID, aResult); +} + + //////////////////////////////////////////////////////////////////////// // Define a table of CIDs implemented by this module along with other // information like the function to create an instance, contractid, and // class name. // static const nsModuleComponentInfo components[] = { - { "Composer Controller", NS_COMPOSERCONTROLLER_CID, - "@mozilla.org/editor/composercontroller;1", - nsComposerControllerConstructor, }, + + { "HTML Editor Controller", NS_HTMLEDITORCONTROLLER_CID, + "@mozilla.org/editor/htmleditorcontroller;1", + nsHTMLEditorControllerConstructor, }, + + { "HTML Editor command table", NS_HTMLEDITOR_COMMANDTABLE_CID, + "", // no point using a contract-ID + nsHTMLEditorCommandTableConstructor, }, + { "Editor Shell Component", NS_EDITORSHELL_CID, "@mozilla.org/editor/editorshell;1", nsEditorShellConstructor, }, + { "Editor Shell Spell Checker", NS_EDITORSHELL_CID, "@mozilla.org/editor/editorspellcheck;1", nsEditorShellConstructor, }, + { "Editing Session", NS_EDITINGSESSION_CID, "@mozilla.org/editor/editingsession;1", nsEditingSessionConstructor, }, + { "Editor Service", NS_EDITORSERVICE_CID, "@mozilla.org/editor/editorservice;1", nsEditorServiceConstructor,}, + { "Editor Spell Checker", NS_EDITORSPELLCHECK_CID, "@mozilla.org/editor/editorspellchecker;1", nsEditorSpellCheckConstructor,}, + { "Editor Startup Handler", NS_EDITORSERVICE_CID, "@mozilla.org/commandlinehandler/general-startup;1?type=editor", nsEditorServiceConstructor, nsEditorService::RegisterProc, nsEditorService::UnregisterProc, }, + { "Edit Startup Handler", NS_EDITORSERVICE_CID, "@mozilla.org/commandlinehandler/general-startup;1?type=edit", nsEditorServiceConstructor, }, + // HACK: Photon only needs the mail variant, and // this was somehow getting in the way... #if 0 diff --git a/mozilla/editor/composer/src/nsEditingSession.cpp b/mozilla/editor/composer/src/nsEditingSession.cpp index 84588552ac3..ff17ebb40b3 100644 --- a/mozilla/editor/composer/src/nsEditingSession.cpp +++ b/mozilla/editor/composer/src/nsEditingSession.cpp @@ -20,7 +20,10 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Simon Fraser + * Simon Fraser + * Michael Judge + * Charles Manske + * Kathleen Brade * * * Alternatively, the contents of this file may be used under the terms of @@ -51,12 +54,13 @@ #include "nsIControllers.h" #include "nsIController.h" -#include "nsIEditorController.h" +#include "nsIControllerContext.h" +#include "nsICommandManager.h" +#include "nsPICommandUpdater.h" #include "nsIPresShell.h" #include "nsComposerCommandsUpdater.h" - #include "nsEditingSession.h" #include "nsIComponentManager.h" @@ -69,7 +73,7 @@ #if DEBUG -#define NOISY_DOC_LOADING 1 +//#define NOISY_DOC_LOADING 1 #endif /*--------------------------------------------------------------------------- @@ -78,7 +82,12 @@ ----------------------------------------------------------------------------*/ nsEditingSession::nsEditingSession() -: mDoneSetup(PR_FALSE), mStateMaintainer(nsnull), mEditorClassString(nsnull) +: mDoneSetup(PR_FALSE) +, mStateMaintainer(nsnull) +, mEditorClassString(nsnull) +, mEditorType(nsnull) +, mBaseCommandControllerId(0) +, mHTMLCommandControllerId(0) { NS_INIT_ISUPPORTS(); } @@ -93,7 +102,8 @@ nsEditingSession::~nsEditingSession() NS_IF_RELEASE(mStateMaintainer); } -NS_IMPL_ISUPPORTS3(nsEditingSession, nsIEditingSession, nsIWebProgressListener, nsISupportsWeakReference) +NS_IMPL_ISUPPORTS3(nsEditingSession, nsIEditingSession, nsIWebProgressListener, + nsISupportsWeakReference) /*--------------------------------------------------------------------------- @@ -120,19 +130,28 @@ nsEditingSession::Init(nsIDOMWindow *aWindow) MakeWindowEditable aEditorType string, "html" "htmlsimple" "text" "textsimple" - void makeWindowEditable(in nsIDOMWindow aWindow, in string aEditorType, in boolean inDoAfterUriLoad); + void makeWindowEditable(in nsIDOMWindow aWindow, in string aEditorType, + in boolean aDoAfterUriLoad); ----------------------------------------------------------------------------*/ -NS_IMETHODIMP -nsEditingSession::MakeWindowEditable(nsIDOMWindow *aWindow, const char *aEditorType, PRBool inDoAfterUriLoad) -{ - // Always remove existing editor - TearDownEditorOnWindow(aWindow); +#define DEFAULT_EDITOR_TYPE "html" - PRBool htmlController = PR_FALSE; - mEditorClassString = nsnull; +NS_IMETHODIMP +nsEditingSession::MakeWindowEditable(nsIDOMWindow *aWindow, + const char *aEditorType, + PRBool aDoAfterUriLoad) +{ + mEditorType.Truncate(); mEditorFlags = 0; + // Always remove existing editor + TearDownEditorOnWindow(aWindow); + + //temporary to set editor type here. we will need different classes soon. + if (!aEditorType) + aEditorType = DEFAULT_EDITOR_TYPE; + mEditorType = aEditorType; + mEditorClassString = "@mozilla.org/editor/htmleditor;1"; if (!strcmp(aEditorType, "textmail")) @@ -145,12 +164,10 @@ nsEditingSession::MakeWindowEditable(nsIDOMWindow *aWindow, const char *aEditorT } else if (!strcmp(aEditorType, "htmlmail")) { - htmlController = PR_TRUE; mEditorFlags = nsIPlaintextEditor::eEditorMailMask; } else //if (!strcmp(aEditorType, "html")) or null is defaulted to html { - htmlController = PR_TRUE; } if (!mEditorClassString) return NS_ERROR_INVALID_ARG; @@ -163,13 +180,19 @@ nsEditingSession::MakeWindowEditable(nsIDOMWindow *aWindow, const char *aEditorT if (NS_FAILED(rv)) return rv; // set the flag on the docShell to say that it's editable - rv = editorDocShell->MakeEditable(inDoAfterUriLoad); + rv = editorDocShell->MakeEditable(aDoAfterUriLoad); if (NS_FAILED(rv)) return rv; - rv = SetupFrameControllers(aWindow, htmlController); + // Setup commands common to plaintext and html editors, + // including the document creation observers + // the first is an editor controller + rv = SetupEditorCommandController("@mozilla.org/editor/editorcontroller;1", + aWindow, + NS_STATIC_CAST(nsIEditingSession*, this), + &mBaseCommandControllerId); if (NS_FAILED(rv)) return rv; - if (!inDoAfterUriLoad) + if (!aDoAfterUriLoad) { rv = SetupEditorOnWindow(aWindow); if (NS_FAILED(rv)) return rv; @@ -183,10 +206,12 @@ nsEditingSession::MakeWindowEditable(nsIDOMWindow *aWindow, const char *aEditorT boolean windowIsEditable (in nsIDOMWindow aWindow); ----------------------------------------------------------------------------*/ -NS_IMETHODIMP nsEditingSession::WindowIsEditable(nsIDOMWindow *aWindow, PRBool *outIsEditable) +NS_IMETHODIMP +nsEditingSession::WindowIsEditable(nsIDOMWindow *aWindow, PRBool *outIsEditable) { nsCOMPtr editorDocShell; - nsresult rv = GetEditorDocShellFromWindow(aWindow, getter_AddRefs(editorDocShell)); + nsresult rv = GetEditorDocShellFromWindow(aWindow, + getter_AddRefs(editorDocShell)); if (NS_FAILED(rv)) return rv; return editorDocShell->GetEditable(outIsEditable); @@ -207,40 +232,53 @@ nsEditingSession::SetupEditorOnWindow(nsIDOMWindow *aWindow) nsCOMPtr docShell; rv = GetDocShellFromWindow(aWindow, getter_AddRefs(docShell)); if (NS_FAILED(rv)) return rv; - - nsCOMPtr editorDocShell(do_QueryInterface(docShell, &rv)); + + nsCOMPtr presShell; + rv = docShell->GetPresShell(getter_AddRefs(presShell)); if (NS_FAILED(rv)) return rv; - + if (!presShell) return NS_ERROR_FAILURE; + + nsCOMPtr editorDocShell = do_QueryInterface(docShell, &rv); + if (NS_FAILED(rv)) return rv; + nsCOMPtr editor(do_CreateInstance(mEditorClassString, &rv)); if (NS_FAILED(rv)) return rv; // set the editor on the docShell. The docShell now owns it. rv = editorDocShell->SetEditor(editor); if (NS_FAILED(rv)) return rv; - - nsCOMPtr presShell; - rv = docShell->GetPresShell(getter_AddRefs(presShell)); - if (NS_FAILED(rv)) return rv; - if (!presShell) return NS_ERROR_FAILURE; - + + // setup the HTML editor command controller + PRBool needHTMLController = mEditorType.Equals(NS_LITERAL_CSTRING("htmlmail")) + || mEditorType.Equals(NS_LITERAL_CSTRING("html")); + + if (needHTMLController) + { + // The third controller takes an nsIEditor as the context + rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1", + aWindow, editor, + &mHTMLCommandControllerId); + if (NS_FAILED(rv)) return rv; + } + nsCOMPtr contentViewer; rv = docShell->GetContentViewer(getter_AddRefs(contentViewer)); if (NS_FAILED(rv)) return rv; if (!contentViewer) return NS_ERROR_FAILURE; - + nsCOMPtr domDoc; rv = contentViewer->GetDOMDocument(getter_AddRefs(domDoc)); if (NS_FAILED(rv)) return rv; if (!domDoc) return NS_ERROR_FAILURE; - - nsCOMPtr selCon = do_QueryInterface(presShell); - rv = editor->Init(domDoc, presShell, nsnull /* root content */, selCon, mEditorFlags); + nsCOMPtr selCon = do_QueryInterface(presShell); + rv = editor->Init(domDoc, presShell, nsnull /* root content */, + selCon, mEditorFlags); if (NS_FAILED(rv)) return rv; rv = editor->PostCreate(); if (NS_FAILED(rv)) return rv; - // set the editor on the controller + // Set context on all controllers to be the editor rv = SetEditorOnControllers(aWindow, editor); if (NS_FAILED(rv)) return rv; @@ -270,9 +308,7 @@ nsEditingSession::SetupEditorOnWindow(nsIDOMWindow *aWindow) nsCOMPtr txnMgr; editor->GetTransactionManager(getter_AddRefs(txnMgr)); if (txnMgr) - { txnMgr->AddListener(NS_STATIC_CAST(nsITransactionListener*, mStateMaintainer)); - } return NS_OK; } @@ -291,7 +327,7 @@ nsEditingSession::TearDownEditorOnWindow(nsIDOMWindow *aWindow) nsCOMPtr editorDocShell; rv = GetEditorDocShellFromWindow(aWindow, getter_AddRefs(editorDocShell)); - if (NS_FAILED(rv)) return rv; + if (NS_FAILED(rv)) return rv; nsCOMPtr editor; rv = editorDocShell->GetEditor(getter_AddRefs(editor)); @@ -301,36 +337,47 @@ nsEditingSession::TearDownEditorOnWindow(nsIDOMWindow *aWindow) rv = editorDocShell->SetEditor(nsnull); if (NS_FAILED(rv)) return rv; - if (mStateMaintainer && editor) + if (mStateMaintainer) { - // If we had an editor -- we are loading a new URL into the existing - // window or creating a different editor on the same document. - - // Remove all the listeners - nsCOMPtr selection; - editor->GetSelection(getter_AddRefs(selection)); - nsCOMPtr selPriv = do_QueryInterface(selection); - if (selPriv) + if (editor) { - rv = selPriv->RemoveSelectionListener(NS_STATIC_CAST(nsISelectionListener*, mStateMaintainer)); + // If we had an editor -- we are loading a new URL into the existing + // window or creating a different editor on the same document. + + // Remove all the listeners + nsCOMPtr selection; + editor->GetSelection(getter_AddRefs(selection)); + nsCOMPtr selPriv = do_QueryInterface(selection); + if (selPriv) + { + rv = selPriv->RemoveSelectionListener(NS_STATIC_CAST(nsISelectionListener*, mStateMaintainer)); + if (NS_FAILED(rv)) return rv; + } + + rv = editor->RemoveDocumentStateListener(NS_STATIC_CAST(nsIDocumentStateListener*, mStateMaintainer)); if (NS_FAILED(rv)) return rv; + + nsCOMPtr txnMgr; + editor->GetTransactionManager(getter_AddRefs(txnMgr)); + if (txnMgr) + { + rv = txnMgr->RemoveListener(NS_STATIC_CAST(nsITransactionListener*, mStateMaintainer)); + if (NS_FAILED(rv)) return rv; + } + + // null out the editor on the controllers + rv = SetEditorOnControllers(aWindow, nsnull); + if (NS_FAILED(rv)) return rv; } - - rv = editor->RemoveDocumentStateListener(NS_STATIC_CAST(nsIDocumentStateListener*, mStateMaintainer)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr txnMgr; - editor->GetTransactionManager(getter_AddRefs(txnMgr)); - if (txnMgr) + else { - rv = txnMgr->RemoveListener(NS_STATIC_CAST(nsITransactionListener*, mStateMaintainer)); - if (NS_FAILED(rv)) return rv; + // No editor: we have a new window and previous controllers + // were destroyed with the contentWindow. + // Clear IDs to trigger creation of new controllers + mBaseCommandControllerId = 0; + mHTMLCommandControllerId = 0; } - // null out the editor on the controllers - rv = SetEditorOnControllers(aWindow, nsnull); - if (NS_FAILED(rv)) return rv; - mStateMaintainer->Release(); mStateMaintainer = nsnull; } @@ -345,10 +392,12 @@ nsEditingSession::TearDownEditorOnWindow(nsIDOMWindow *aWindow) nsIEditor getEditorForFrame (in nsIDOMWindow aWindow); ----------------------------------------------------------------------------*/ NS_IMETHODIMP -nsEditingSession::GetEditorForWindow(nsIDOMWindow *aWindow, nsIEditor **outEditor) +nsEditingSession::GetEditorForWindow(nsIDOMWindow *aWindow, + nsIEditor **outEditor) { nsCOMPtr editorDocShell; - nsresult rv = GetEditorDocShellFromWindow(aWindow, getter_AddRefs(editorDocShell)); + nsresult rv = GetEditorDocShellFromWindow(aWindow, + getter_AddRefs(editorDocShell)); if (NS_FAILED(rv)) return rv; return editorDocShell->GetEditor(outEditor); @@ -364,8 +413,11 @@ nsEditingSession::GetEditorForWindow(nsIDOMWindow *aWindow, nsIEditor **outEdito ----------------------------------------------------------------------------*/ NS_IMETHODIMP -nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) +nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRUint32 aStateFlags, nsresult aStatus) { + // // A Request has started... // @@ -437,7 +489,12 @@ nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aReque ----------------------------------------------------------------------------*/ NS_IMETHODIMP -nsEditingSession::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) +nsEditingSession::OnProgressChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRInt32 aCurSelfProgress, + PRInt32 aMaxSelfProgress, + PRInt32 aCurTotalProgress, + PRInt32 aMaxTotalProgress) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; @@ -449,7 +506,8 @@ nsEditingSession::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRe ----------------------------------------------------------------------------*/ NS_IMETHODIMP -nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) +nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsIURI *aURI) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; @@ -461,7 +519,10 @@ nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRe ----------------------------------------------------------------------------*/ NS_IMETHODIMP -nsEditingSession::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage) +nsEditingSession::OnStatusChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + nsresult aStatus, + const PRUnichar *aMessage) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; @@ -473,7 +534,8 @@ nsEditingSession::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequ ----------------------------------------------------------------------------*/ NS_IMETHODIMP -nsEditingSession::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) +nsEditingSession::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRUint32 state) { NS_NOTREACHED("notification excluded in AddProgressListener(...)"); return NS_OK; @@ -508,19 +570,20 @@ nsresult nsEditingSession::StartDocumentLoad(nsIWebProgress *aWebProgress) { #ifdef NOISY_DOC_LOADING - printf("Editing session StartDocumentLoad\n"); + printf("======= StartDocumentLoad ========\n"); #endif - NS_ENSURE_ARG(aWebProgress); + NS_ENSURE_ARG_POINTER(aWebProgress); // If we have an editor here, then we got a reload after making the editor. // We need to blow it away and make a new one at the end of the load. nsCOMPtr domWindow; aWebProgress->GetDOMWindow(getter_AddRefs(domWindow)); - if (domWindow) { nsresult rv = TearDownEditorOnWindow(domWindow); + if (NS_FAILED(rv)) + return rv; } return NS_OK; @@ -533,9 +596,10 @@ nsEditingSession::StartDocumentLoad(nsIWebProgress *aWebProgress) Called on end of load in a single frame ----------------------------------------------------------------------------*/ nsresult -nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress, nsIChannel* aChannel, nsresult aStatus) +nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress, + nsIChannel* aChannel, nsresult aStatus) { - NS_ENSURE_ARG(aWebProgress); + NS_ENSURE_ARG_POINTER(aWebProgress); #ifdef NOISY_DOC_LOADING printf("Editing shell EndDocumentLoad\n"); @@ -550,8 +614,9 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress, nsIChannel* aCha nsCOMPtr docShell; nsresult rv = GetDocShellFromWindow(domWindow, getter_AddRefs(docShell)); if (NS_FAILED(rv)) return rv; // better error handling? - - nsCOMPtr editorDocShell(do_QueryInterface(docShell)); + + nsCOMPtr editorDocShell = do_QueryInterface(docShell); + // did someone set the flag to make this shell editable? if (editorDocShell) { @@ -561,6 +626,8 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress, nsIChannel* aCha if (makeEditable) { nsresult rv = SetupEditorOnWindow(domWindow); + if (NS_FAILED(rv)) + return rv; } } @@ -587,7 +654,8 @@ nsEditingSession::StartPageLoad(nsIWebProgress *aWebProgress) Called on end load of the entire page (incl. subframes) ----------------------------------------------------------------------------*/ nsresult -nsEditingSession::EndPageLoad(nsIWebProgress *aWebProgress, nsIChannel* aChannel, nsresult aStatus) +nsEditingSession::EndPageLoad(nsIWebProgress *aWebProgress, + nsIChannel* aChannel, nsresult aStatus) { return NS_OK; } @@ -605,9 +673,10 @@ nsEditingSession::EndPageLoad(nsIWebProgress *aWebProgress, nsIChannel* aChannel is returned. ----------------------------------------------------------------------------*/ nsresult -nsEditingSession::GetDocShellFromWindow(nsIDOMWindow *inWindow, nsIDocShell** outDocShell) +nsEditingSession::GetDocShellFromWindow(nsIDOMWindow *aWindow, + nsIDocShell** outDocShell) { - nsCOMPtr scriptGO(do_QueryInterface(inWindow)); + nsCOMPtr scriptGO = do_QueryInterface(aWindow); if (!scriptGO) return NS_ERROR_FAILURE; nsresult rv = scriptGO->GetDocShell(outDocShell); @@ -624,13 +693,15 @@ nsEditingSession::GetDocShellFromWindow(nsIDOMWindow *inWindow, nsIDocShell** ou is returned. ----------------------------------------------------------------------------*/ nsresult -nsEditingSession::GetEditorDocShellFromWindow(nsIDOMWindow *inWindow, nsIEditorDocShell** outDocShell) +nsEditingSession::GetEditorDocShellFromWindow(nsIDOMWindow *aWindow, + nsIEditorDocShell** outDocShell) { nsCOMPtr docShell; - nsresult rv = GetDocShellFromWindow(inWindow, getter_AddRefs(docShell)); + nsresult rv = GetDocShellFromWindow(aWindow, getter_AddRefs(docShell)); if (NS_FAILED(rv)) return rv; - return docShell->QueryInterface(NS_GET_IID(nsIEditorDocShell), (void **)outDocShell); + return docShell->QueryInterface(NS_GET_IID(nsIEditorDocShell), + (void **)outDocShell); } /*--------------------------------------------------------------------------- @@ -657,56 +728,59 @@ nsEditingSession::PrepareForEditing() nsCOMPtr webProgress = do_GetInterface(docShell); if (!webProgress) return NS_ERROR_FAILURE; - nsresult rv = webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_ALL); - if (NS_FAILED(rv)) return rv; - - return NS_OK; + return webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_ALL); } - /*--------------------------------------------------------------------------- - SetupFrameControllers + SetupEditorCommandController - Set up the controller for this frame. + Create a command controller, append to controllers, + get and return the controller ID, and set the context ----------------------------------------------------------------------------*/ nsresult -nsEditingSession::SetupFrameControllers(nsIDOMWindow *inWindow, PRBool aSetupComposerController) +nsEditingSession::SetupEditorCommandController( + const char *aControllerClassName, + nsIDOMWindow *aWindow, + nsISupports *aContext, + PRUint32 *aControllerId) { + NS_ENSURE_ARG_POINTER(aControllerClassName); + NS_ENSURE_ARG_POINTER(aWindow); + NS_ENSURE_ARG_POINTER(aContext); + NS_ENSURE_ARG_POINTER(aControllerId); + nsresult rv; - - nsCOMPtr domWindowInt(do_QueryInterface(inWindow, &rv)); + nsCOMPtr domWindowInt = + do_QueryInterface(aWindow, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr controllers; rv = domWindowInt->GetControllers(getter_AddRefs(controllers)); if (NS_FAILED(rv)) return rv; - // the first is an editor controller, and takes an nsIEditor as the refCon - nsCOMPtr controller(do_CreateInstance("@mozilla.org/editor/editorcontroller;1", &rv)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr editorController(do_QueryInterface(controller)); - rv = editorController->Init(nsnull); // we set the editor later when we have one - if (NS_FAILED(rv)) return rv; - - rv = controllers->InsertControllerAt(0, controller); - if (NS_FAILED(rv)) return rv; - - if (aSetupComposerController) + // We only have to create each singleton controller once + // We know this has happened once we have a controllerId value + if (!*aControllerId) { - // the second is an composer controller, and also takes an nsIEditor as the refCon - controller = do_CreateInstance("@mozilla.org/editor/composercontroller;1", &rv); + nsresult rv; + nsCOMPtr controller; + controller = do_CreateInstance(aControllerClassName, &rv); if (NS_FAILED(rv)) return rv; - nsCOMPtr composerController(do_QueryInterface(controller)); - rv = composerController->Init(nsnull); // we set the editor later when we have one - if (NS_FAILED(rv)) return rv; - - rv = controllers->InsertControllerAt(1, controller); + // We must insert at head of the list to be sure our + // controller is found before other implementations + // (e.g., not-implemented versions by browser) + rv = controllers->InsertControllerAt(0,controller); if (NS_FAILED(rv)) return rv; - } - return NS_OK; + + // Remember the ID for the controller + rv = controllers->GetControllerId(controller, aControllerId); + if (NS_FAILED(rv)) return rv; + } + + // Set the context + return SetContextOnControllerById(controllers, aContext, *aControllerId); } /*--------------------------------------------------------------------------- @@ -716,39 +790,50 @@ nsEditingSession::SetupFrameControllers(nsIDOMWindow *inWindow, PRBool aSetupCom Set the editor on the controller(s) for this window ----------------------------------------------------------------------------*/ nsresult -nsEditingSession::SetEditorOnControllers(nsIDOMWindow *inWindow, nsIEditor* inEditor) +nsEditingSession::SetEditorOnControllers(nsIDOMWindow *aWindow, + nsIEditor* aEditor) { nsresult rv; // set the editor on the controller - nsCOMPtr domWindowInt(do_QueryInterface(inWindow, &rv)); + nsCOMPtr domWindowInt = + do_QueryInterface(aWindow, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr controllers; rv = domWindowInt->GetControllers(getter_AddRefs(controllers)); if (NS_FAILED(rv)) return rv; - // find the editor controllers by QIing each one. This sucks. - // Controllers need to have IDs of some kind. - PRUint32 numControllers; - rv = controllers->GetControllerCount(&numControllers); - if (NS_FAILED(rv)) return rv; - - for (PRUint32 i = 0; i < numControllers; i ++) + nsCOMPtr editorAsISupports = do_QueryInterface(aEditor); + if (mBaseCommandControllerId) { - nsCOMPtr thisController; - controllers->GetControllerAt(i, getter_AddRefs(thisController)); - - nsCOMPtr editorController(do_QueryInterface(thisController)); // ok with nil controller - if (editorController) - { - rv = editorController->SetCommandRefCon(inEditor); - if (NS_FAILED(rv)) break; - } + rv = SetContextOnControllerById(controllers, editorAsISupports, + mBaseCommandControllerId); + if (NS_FAILED(rv)) return rv; } - if (NS_FAILED(rv)) return rv; - return NS_OK; + if (mHTMLCommandControllerId) + rv = SetContextOnControllerById(controllers, editorAsISupports, + mHTMLCommandControllerId); + + return rv; } +nsresult +nsEditingSession::SetContextOnControllerById(nsIControllers* aControllers, + nsISupports* aContext, + PRUint32 aID) +{ + NS_ENSURE_ARG_POINTER(aControllers); + // aContext can be null (when destroying editor) + nsCOMPtr controller; + aControllers->GetControllerById(aID, getter_AddRefs(controller)); + + // ok with nil controller + nsCOMPtr editorController = + do_QueryInterface(controller); + if (!editorController) return NS_ERROR_FAILURE; + + return editorController->SetCommandContext(aContext); +} diff --git a/mozilla/editor/composer/src/nsEditingSession.h b/mozilla/editor/composer/src/nsEditingSession.h index a94490050df..c5478cd9dd3 100644 --- a/mozilla/editor/composer/src/nsEditingSession.h +++ b/mozilla/editor/composer/src/nsEditingSession.h @@ -47,6 +47,10 @@ #include "nsIEditor.h" +#ifndef __gen_nsIControllers_h__ +#include "nsIControllers.h" +#endif + #ifndef __gen_nsIDocShell_h__ #include "nsIDocShell.h" #endif @@ -88,14 +92,20 @@ public: // nsIEditingSession NS_DECL_NSIEDITINGSESSION - protected: nsresult GetDocShellFromWindow(nsIDOMWindow *inWindow, nsIDocShell** outDocShell); nsresult GetEditorDocShellFromWindow(nsIDOMWindow *inWindow, nsIEditorDocShell** outDocShell); - nsresult SetupFrameControllers(nsIDOMWindow *inWindow, PRBool aSetupComposerController); - - nsresult SetEditorOnControllers(nsIDOMWindow *inWindow, nsIEditor* inEditor); + + nsresult SetupEditorCommandController(const char *aControllerClassName, + nsIDOMWindow *aWindow, + nsISupports *aContext, + PRUint32 *aControllerId); + nsresult SetEditorOnControllers(nsIDOMWindow *aWindow, + nsIEditor* aEditor); + nsresult SetContextOnControllerById(nsIControllers* aControllers, + nsISupports* aContext, + PRUint32 aID); nsresult PrepareForEditing(); @@ -114,7 +124,10 @@ protected: nsComposerCommandsUpdater *mStateMaintainer; // we hold the owning ref to this. const char * mEditorClassString; //we need this to hold onto the type for invoking editor after loading uri + nsCString mEditorType; PRUint32 mEditorFlags; + PRUint32 mBaseCommandControllerId; + PRUint32 mHTMLCommandControllerId; }; diff --git a/mozilla/editor/idl/nsIHTMLEditor.idl b/mozilla/editor/idl/nsIHTMLEditor.idl index 57e508b8750..cb89b4d80f9 100644 --- a/mozilla/editor/idl/nsIHTMLEditor.idl +++ b/mozilla/editor/idl/nsIHTMLEditor.idl @@ -340,7 +340,8 @@ interface nsIHTMLEditor : nsISupports void insertElementAtSelection(in nsIDOMElement aElement, in boolean aDeleteSelection); - /** Set the documents title. + /** + * Set the documents title. */ void setDocumentTitle(in AString aTitle); @@ -596,7 +597,18 @@ interface nsIHTMLEditor : nsISupports */ attribute boolean isCSSEnabled; + /** + * Add listener for insertion override + * @param inFilter function which callers want called during insertion + */ + void addInsertionListener(in nsIContentFilter inFilter); + + /** + * Remove listener for insertion override + * @param inFilter function which callers do not want called during insertion + */ + void removeInsertionListener(in nsIContentFilter inFilter); nsIDOMCSSStyleRule parseStyleAttrIntoCSSRule(in AString aString); diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index 9f782e8f3cd..ecec917f326 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -2578,10 +2578,12 @@ nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationTyp case eDocumentStateChanged: { + printf("document state change is possible\n"); PRBool docIsDirty; rv = GetDocumentModified(&docIsDirty); if (NS_FAILED(rv)) return rv; + printf("document is dirty=%d, mDocDirtyState=%d\n", docIsDirty, mDocDirtyState); if (docIsDirty == mDocDirtyState) return NS_OK; @@ -2589,10 +2591,12 @@ nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationTyp for (i = 0; i < numListeners;i++) { + printf("listener for loop %d\n", i); nsCOMPtr iSupports = getter_AddRefs(mDocStateListeners->ElementAt(i)); nsCOMPtr thisListener = do_QueryInterface(iSupports); if (thisListener) { + printf("listener found\n"); rv = thisListener->NotifyDocumentStateChanged(mDocDirtyState); if (NS_FAILED(rv)) break; diff --git a/mozilla/editor/libeditor/base/nsEditorController.cpp b/mozilla/editor/libeditor/base/nsEditorController.cpp index b61a3641702..223c7fc1316 100644 --- a/mozilla/editor/libeditor/base/nsEditorController.cpp +++ b/mozilla/editor/libeditor/base/nsEditorController.cpp @@ -42,69 +42,17 @@ #include "nsIComponentManager.h" #include "nsEditorController.h" #include "nsIEditor.h" - #include "nsEditorCommands.h" +#include "nsIControllerCommandTable.h" -NS_IMPL_ADDREF(nsEditorController) -NS_IMPL_RELEASE(nsEditorController) - -NS_INTERFACE_MAP_BEGIN(nsEditorController) - NS_INTERFACE_MAP_ENTRY(nsIController) - NS_INTERFACE_MAP_ENTRY(nsICommandController) - NS_INTERFACE_MAP_ENTRY(nsIEditorController) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditorController) -NS_INTERFACE_MAP_END - -nsEditorController::nsEditorController() -: mCommandRefCon(nsnull) -{ - NS_INIT_ISUPPORTS(); -} - -nsEditorController::~nsEditorController() -{ -} - -NS_IMETHODIMP nsEditorController::Init(nsISupports *aCommandRefCon) -{ - nsresult rv; - - // get our ref to the singleton command manager - rv = GetEditorCommandManager(getter_AddRefs(mCommandManager)); - if (NS_FAILED(rv)) return rv; - - mCommandRefCon = aCommandRefCon; // no addref - return NS_OK; -} - -NS_IMETHODIMP nsEditorController::SetCommandRefCon(nsISupports *aCommandRefCon) -{ - mCommandRefCon = aCommandRefCon; // no addref - return NS_OK; -} - -NS_IMETHODIMP nsEditorController::GetInterface(const nsIID & aIID, void * *result) -{ - NS_ENSURE_ARG_POINTER(result); - - if (NS_SUCCEEDED(QueryInterface(aIID, result))) - return NS_OK; - - if (mCommandManager && aIID.Equals(NS_GET_IID(nsIControllerCommandManager))) - return mCommandManager->QueryInterface(aIID, result); - - return NS_NOINTERFACE; -} - #define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName) \ { \ _cmdClass* theCmd; \ NS_NEWXPCOM(theCmd, _cmdClass); \ if (!theCmd) return NS_ERROR_OUT_OF_MEMORY; \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \ } @@ -113,21 +61,21 @@ NS_IMETHODIMP nsEditorController::GetInterface(const nsIID & aIID, void * *resul _cmdClass* theCmd; \ NS_NEWXPCOM(theCmd, _cmdClass); \ if (!theCmd) return NS_ERROR_OUT_OF_MEMORY; \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); #define NS_REGISTER_NEXT_COMMAND(_cmdClass, _cmdName) \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); #define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName) \ - rv = inCommandManager->RegisterCommand(_cmdName, \ + rv = inCommandTable->RegisterCommand(_cmdName, \ NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \ } // static -nsresult nsEditorController::RegisterEditorCommands(nsIControllerCommandManager *inCommandManager) +nsresult nsEditorController::RegisterEditorCommands(nsIControllerCommandTable *inCommandTable) { nsresult rv; @@ -187,67 +135,4 @@ nsresult nsEditorController::RegisterEditorCommands(nsIControllerCommandManager return NS_OK; } -/* ======================================================================= - * nsIController - * ======================================================================= */ - -NS_IMETHODIMP nsEditorController::IsCommandEnabled(const char *aCommand, PRBool *aResult) -{ - NS_ENSURE_ARG_POINTER(aResult); - return mCommandManager->IsCommandEnabled(aCommand, mCommandRefCon, aResult); -} - -NS_IMETHODIMP nsEditorController::SupportsCommand(const char *aCommand, PRBool *aResult) -{ - NS_ENSURE_ARG_POINTER(aResult); - return mCommandManager->SupportsCommand(aCommand, mCommandRefCon, aResult); -} - -NS_IMETHODIMP nsEditorController::DoCommand(const char *aCommand) -{ - return mCommandManager->DoCommand(aCommand, mCommandRefCon); -} - -NS_IMETHODIMP nsEditorController::DoCommandWithParams(const char *aCommand, nsICommandParams *aParams) -{ - return mCommandManager->DoCommandParams(aCommand, aParams, mCommandRefCon); -} - -NS_IMETHODIMP nsEditorController::GetCommandStateWithParams(const char *aCommand, nsICommandParams *aParams) -{ - return mCommandManager->GetCommandState(aCommand, aParams, mCommandRefCon); -} - -NS_IMETHODIMP nsEditorController::OnEvent(const char * aEventName) -{ - return NS_OK; -} - - -nsWeakPtr nsEditorController::sEditorCommandManager = NULL; - -// static -nsresult nsEditorController::GetEditorCommandManager(nsIControllerCommandManager* *outCommandManager) -{ - NS_ENSURE_ARG_POINTER(outCommandManager); - - nsCOMPtr cmdManager = do_QueryReferent(sEditorCommandManager); - if (!cmdManager) - { - nsresult rv; - cmdManager = do_CreateInstance(NS_CONTROLLERCOMMANDMANAGER_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - - // register the commands. This just happens once per instance - rv = nsEditorController::RegisterEditorCommands(cmdManager); - if (NS_FAILED(rv)) return rv; - - // save the singleton in our static weak reference - sEditorCommandManager = getter_AddRefs(NS_GetWeakReference(cmdManager, &rv)); - if (NS_FAILED(rv)) return rv; - } - - NS_ADDREF(*outCommandManager = cmdManager); - return NS_OK; -} diff --git a/mozilla/editor/libeditor/base/nsEditorController.h b/mozilla/editor/libeditor/base/nsEditorController.h index 833be005f07..4fe1f67895f 100644 --- a/mozilla/editor/libeditor/base/nsEditorController.h +++ b/mozilla/editor/libeditor/base/nsEditorController.h @@ -42,69 +42,16 @@ #define NS_EDITORCONTROLLER_CID \ { 0x26fb965c, 0x9de6, 0x11d3, { 0xbc, 0xcc, 0x0, 0x60, 0xb0, 0xfc, 0x76, 0xbd } } - -#include "nsIController.h" -#include "nsIEditorController.h" -#include "nsIControllerCommand.h" -#include "nsIControllerCommandManager.h" -#include "nsIInterfaceRequestor.h" -#include "nsIInterfaceRequestorUtils.h" - -#include "nsHashtable.h" -#include "nsString.h" -#include "nsWeakPtr.h" - -class nsIEditor; +class nsIControllerCommandTable; // the editor controller is used for both text widgets, and basic text editing // commands in composer. The refCon that gets passed to its commands is an nsIEditor. -class nsEditorController : public nsIController, - public nsIEditorController, - public nsIInterfaceRequestor, - public nsICommandController +class nsEditorController { public: - - nsEditorController(); - virtual ~nsEditorController(); - - // nsISupports - NS_DECL_ISUPPORTS - - // nsIController - NS_DECL_NSICONTROLLER - - // nsICommandController - NS_DECL_NSICOMMANDCONTROLLER - - /** init the controller */ - NS_IMETHOD Init(nsISupports *aCommandRefCon); - - /** Set the cookie that is passed to commands - */ - NS_IMETHOD SetCommandRefCon(nsISupports *aCommandRefCon); - - // nsIInterfaceRequestor - NS_DECL_NSIINTERFACEREQUESTOR - -protected: - - //if editor is null then look to mContent. this is for dual use of window and content - //attached controller. - nsISupports *mCommandRefCon; - - nsCOMPtr mCommandManager; // our reference to the command manager - -private: - - static nsresult GetEditorCommandManager(nsIControllerCommandManager* *outCommandManager); - static nsresult RegisterEditorCommands(nsIControllerCommandManager* inCommandManager); - - // the singleton command manager - static nsWeakPtr sEditorCommandManager; // common editor (i.e. text widget) commands - + static nsresult RegisterEditorCommands(nsIControllerCommandTable* inCommandTable); }; #endif /* nsEditorController_h__ */ diff --git a/mozilla/editor/libeditor/build/nsEditorRegistration.cpp b/mozilla/editor/libeditor/build/nsEditorRegistration.cpp index c957ef95998..b831e628aa6 100644 --- a/mozilla/editor/libeditor/build/nsEditorRegistration.cpp +++ b/mozilla/editor/libeditor/build/nsEditorRegistration.cpp @@ -20,6 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Michael Judge + * Charles Manske * * * Alternatively, the contents of this file may be used under the terms of @@ -37,33 +39,85 @@ * ***** END LICENSE BLOCK ***** */ #include "nsIGenericFactory.h" - #include "nsEditorCID.h" #include "nsEditor.h" // for gInstanceCount -#include "nsHTMLEditor.h" #include "nsPlaintextEditor.h" - #include "nsEditorController.h" //CID +#include "nsIController.h" +#include "nsIControllerContext.h" +#include "nsIControllerCommandTable.h" +#include "nsIServiceManager.h" +#ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY +#include "nsHTMLEditor.h" #include "nsTextServicesDocument.h" #include "nsTextServicesCID.h" +#endif + +#define NS_EDITORCOMMANDTABLE_CID \ +{ 0x8b975b0a, 0x6ae5, 0x11d7, { 0xa44c, 0x00, 0x03, 0x93, 0x63, 0x65, 0x92 } } + +static NS_DEFINE_CID(kEditorCommandTableCID, NS_EDITORCOMMANDTABLE_CID); -//////////////////////////////////////////////////////////////////////// -// Define the contructor function for the objects -// -// NOTE: This creates an instance of objects by using the default constructor -// NS_GENERIC_FACTORY_CONSTRUCTOR(nsPlaintextEditor) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorController) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsTextServicesDocument) + +// Constructor of a controller which is set up to use, internally, a +// singleton command-table pre-filled with editor commands. +static NS_METHOD +nsEditorControllerConstructor(nsISupports *aOuter, REFNSIID aIID, + void **aResult) +{ + nsresult rv; + nsCOMPtr controller = do_CreateInstance("@mozilla.org/embedcomp/base-command-controller;1", &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr editorCommandTable = do_GetService(kEditorCommandTableCID, &rv); + if (NS_FAILED(rv)) return rv; + + // this guy is a singleton, so make it immutable + editorCommandTable->MakeImmutable(); + + nsCOMPtr controllerContext = do_QueryInterface(controller, &rv); + if (NS_FAILED(rv)) return rv; + + rv = controllerContext->Init(editorCommandTable); + if (NS_FAILED(rv)) return rv; + + return controller->QueryInterface(aIID, aResult); +} + + +// Constructor for a command-table pref-filled with editor commands +static NS_METHOD +nsEditorCommandTableConstructor(nsISupports *aOuter, REFNSIID aIID, + void **aResult) +{ + nsresult rv; + nsCOMPtr commandTable = + do_CreateInstance(NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = nsEditorController::RegisterEditorCommands(commandTable); + if (NS_FAILED(rv)) return rv; + + // we don't know here whether we're being created as an instance, + // or a service, so we can't become immutable + + return commandTable->QueryInterface(aIID, aResult); +} + + +#ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY +NS_GENERIC_FACTORY_CONSTRUCTOR(nsTextServicesDocument) #ifdef ENABLE_EDITOR_API_LOG #include "nsHTMLEditorLog.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLEditorLog) #else NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLEditor) #endif +#endif //////////////////////////////////////////////////////////////////////// // Define a table of CIDs implemented by this module along with other @@ -73,6 +127,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLEditor) static const nsModuleComponentInfo components[] = { { "Text Editor", NS_TEXTEDITOR_CID, "@mozilla.org/editor/texteditor;1", nsPlaintextEditorConstructor, }, + +#ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY #ifdef ENABLE_EDITOR_API_LOG { "HTML Editor", NS_HTMLEDITOR_CID, "@mozilla.org/editor/htmleditor;1", nsHTMLEditorLogConstructor, }, @@ -80,12 +136,21 @@ static const nsModuleComponentInfo components[] = { { "HTML Editor", NS_HTMLEDITOR_CID, "@mozilla.org/editor/htmleditor;1", nsHTMLEditorConstructor, }, #endif +#endif + { "Editor Controller", NS_EDITORCONTROLLER_CID, "@mozilla.org/editor/editorcontroller;1", nsEditorControllerConstructor, }, + + { "Editor Command Table", NS_EDITORCOMMANDTABLE_CID, + "", // no point in using a contract ID + nsEditorCommandTableConstructor, }, + +#ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY { NULL, NS_TEXTSERVICESDOCUMENT_CID, "@mozilla.org/textservices/textservicesdocument;1", nsTextServicesDocumentConstructor }, +#endif }; //////////////////////////////////////////////////////////////////////// diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp index e91545a8b5d..ed3f2f2d628 100644 --- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -84,6 +84,7 @@ #include "nsIDOMRange.h" #include "nsIDOMNSRange.h" #include "nsISupportsArray.h" +#include "nsCOMArray.h" #include "nsVoidArray.h" #include "nsFileSpec.h" #include "nsIFile.h" @@ -450,7 +451,7 @@ nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAString & aInputString, res = GetStartNodeAndOffset(selection, address_of(parentNode), &offsetOfNewNode); if (!parentNode) res = NS_ERROR_FAILURE; if (NS_FAILED(res)) return res; - + // if there are any invisible br's after our insertion point, remove them. // this is because if there is a br at end of what we paste, it will make // the invisible br visible. @@ -936,7 +937,8 @@ NS_IMETHODIMP nsHTMLEditor::PrepareTransferable(nsITransferable **transferable) return NS_OK; } -NS_IMETHODIMP nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransferable , PRBool aHavePrivFlavor ) +NS_IMETHODIMP nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransferable, + PRBool aHavePrivFlavor) { // Create generic Transferable for getting the data nsresult rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull, @@ -952,7 +954,10 @@ NS_IMETHODIMP nsHTMLEditor::PrepareHTMLTransferable(nsITransferable **aTransfera // we want to get out of the transferable if ((mFlags & eEditorPlaintextMask) == 0) // This should only happen in html editors, not plaintext { - if (!aHavePrivFlavor) (*aTransferable)->AddDataFlavor(kNativeHTMLMime); + if (!aHavePrivFlavor) + { + (*aTransferable)->AddDataFlavor(kNativeHTMLMime); + } (*aTransferable)->AddDataFlavor(kHTMLMime); (*aTransferable)->AddDataFlavor(kFileMime); //(*aTransferable)->AddDataFlavor(kJPEGImageMime); @@ -1059,7 +1064,6 @@ nsHTMLEditor::ParseCFHTML(nsCString & aCfhtml, PRUnichar **aStuffToPaste, PRUnic return NS_OK; } - NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable, const nsAString & aContextStr, const nsAString & aInfoStr, @@ -1079,6 +1083,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable #ifdef DEBUG_clipboard printf("Got flavor [%s]\n", bestFlavor); #endif + if (mPasteFlavor.Equals(NS_LITERAL_STRING(kNativeHTMLMime))) { // note cf_html uses utf8, hence use length = len, not len/2 as in flavors below @@ -1143,7 +1148,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable return rv; nsCOMPtr fileURL(do_QueryInterface(uri)); - if ( fileURL ) + if (fileURL) { PRBool insertAsImage = PR_FALSE; nsCAutoString fileextension; @@ -1218,6 +1223,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) dragService->GetCurrentSession(getter_AddRefs(dragSession)); if (!dragSession) return NS_OK; + // transferable hooks here + PRBool isAllowed = PR_TRUE; + DoAllowDropHook(aDropEvent, dragSession, &isAllowed); + if (!isAllowed) + return NS_OK; + // find out if we have our internal html flavor on the clipboard. We don't want to mess // around with cfhtml if we do. PRBool bHavePrivateHTMLFlavor = PR_FALSE; @@ -1267,18 +1278,18 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) { nsAutoString text; textDataObj = do_QueryInterface(contextDataObj); - textDataObj->GetData ( text ); + textDataObj->GetData(text); NS_ASSERTION(text.Length() <= (contextLen/2), "Invalid length!"); - contextStr.Assign ( text.get(), contextLen / 2 ); + contextStr.Assign(text.get(), contextLen / 2); } if (infoDataObj) { nsAutoString text; textDataObj = do_QueryInterface(infoDataObj); - textDataObj->GetData ( text ); + textDataObj->GetData(text); NS_ASSERTION(text.Length() <= (infoLen/2), "Invalid length!"); - infoStr.Assign ( text.get(), infoLen / 2 ); + infoStr.Assign(text.get(), infoLen / 2); } // We never have to delete if selection is already collapsed @@ -1286,7 +1297,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) nsCOMPtr newSelectionParent; PRInt32 newSelectionOffset = 0; - if ( doPlaceCaret ) + if (doPlaceCaret) { // check if the user pressed the key to force a copy rather than a move // if we run into problems here, we'll just assume the user doesn't want a copy @@ -1298,7 +1309,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) nsCOMPtr mouseEvent ( do_QueryInterface(aDropEvent) ); if (mouseEvent) -#if defined(XP_MACOSX) || defined(XP_MAC) +#if defined(XP_MAC) || defined(XP_MACOSX) mouseEvent->GetAltKey(&userWantsCopy); #else mouseEvent->GetCtrlKey(&userWantsCopy); @@ -1356,6 +1367,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) if (!newSelectionParent) return NS_ERROR_FAILURE; } + // We never have to delete if selection is already collapsed PRBool cursorIsInSelection = PR_FALSE; // Check if mouse is in the selection @@ -1414,6 +1426,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) doPlaceCaret = PR_FALSE; } + // handle transferable hooks + PRBool doInsert = PR_TRUE; + DoInsertionHook(aDropEvent, trans, &doInsert); + if (!doInsert) + return NS_OK; + rv = InsertFromTransferable(trans, contextStr, infoStr, newSelectionParent, newSelectionOffset, deleteSelection); } @@ -1423,229 +1441,120 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDrag) { - if (!aCanDrag) - return NS_ERROR_NULL_POINTER; - - /* we really should be checking the XY coordinates of the mouseevent and ensure that - * that particular point is actually within the selection (not just that there is a selection) - */ - *aCanDrag = PR_FALSE; - - // KLUDGE to work around bug 50703 - // After double click and object property editing, - // we get a spurious drag event - if (mIgnoreSpuriousDragEvent) - { -#ifdef DEBUG_cmanske - printf(" *** IGNORING SPURIOUS DRAG EVENT!\n"); -#endif - mIgnoreSpuriousDragEvent = PR_FALSE; - return NS_OK; - } - - nsCOMPtr selection; - nsresult res = GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res)) return res; - - PRBool isCollapsed; - res = selection->GetIsCollapsed(&isCollapsed); - if (NS_FAILED(res)) return res; - - // if we are collapsed, we have no selection so nothing to drag - if ( isCollapsed ) - return NS_OK; - - nsCOMPtr eventTarget; - - nsCOMPtr nsevent(do_QueryInterface(aDragEvent)); - - if (nsevent) { - res = nsevent->GetOriginalTarget(getter_AddRefs(eventTarget)); - if (NS_FAILED(res)) { - return res; - } - } - - if ( eventTarget ) - { - nsCOMPtr eventTargetDomNode = do_QueryInterface(eventTarget); - if ( eventTargetDomNode ) - { - PRBool isTargetedCorrectly = PR_FALSE; - res = selection->ContainsNode(eventTargetDomNode, PR_FALSE, &isTargetedCorrectly); - if (NS_FAILED(res)) return res; - - *aCanDrag = isTargetedCorrectly; - } - } - - return NS_OK; + return nsPlaintextEditor::CanDrag(aDragEvent, aCanDrag); } -NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) +nsresult +nsHTMLEditor::PutDragDataInTransferable(nsITransferable **aTransferable) { - nsresult rv; - - nsCOMPtr eventTarget; - rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget)); + NS_ENSURE_ARG_POINTER(aTransferable); + *aTransferable = nsnull; + nsCOMPtr docEncoder; + nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder)); if (NS_FAILED(rv)) return rv; - nsCOMPtr domnode = do_QueryInterface(eventTarget); + NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - /* get the selection to be dragged */ - nsCOMPtr selection; - rv = GetSelection(getter_AddRefs(selection)); + // grab a string + nsAutoString buffer, parents, info; + + // find out if we're a plaintext control or not + PRUint32 editorFlags = 0; + rv = GetFlags(&editorFlags); if (NS_FAILED(rv)) return rv; - /* create an array of transferables */ - nsCOMPtr transferableArray; - NS_NewISupportsArray(getter_AddRefs(transferableArray)); - if (transferableArray == nsnull) - return NS_ERROR_OUT_OF_MEMORY; + PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0); + if (!bIsPlainTextControl) + { + // encode the selection as html with contextual info + rv = docEncoder->EncodeToStringWithContext(buffer, parents, info); + if (NS_FAILED(rv)) return rv; + } + else + { + // encode the selection + rv = docEncoder->EncodeToString(buffer); + if (NS_FAILED(rv)) return rv; + } - /* get the drag service */ - nsCOMPtr dragService = - do_GetService("@mozilla.org/widget/dragservice;1", &rv); + // if we have an empty string, we're done; otherwise continue + if ( buffer.IsEmpty() ) + return NS_OK; + + nsCOMPtr dataWrapper, contextWrapper, infoWrapper; + + dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + rv = dataWrapper->SetData(buffer); if (NS_FAILED(rv)) return rv; /* create html flavor transferable */ nsCOMPtr trans = do_CreateInstance(kCTransferableCID); NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE); - nsCOMPtr domdoc; - rv = GetDocument(getter_AddRefs(domdoc)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr doc = do_QueryInterface(domdoc); - if (doc) + if (bIsPlainTextControl) { - // find out if we're a plaintext control or not - PRUint32 editorFlags = 0; - rv = GetFlags(&editorFlags); + // Add the unicode flavor to the transferable + rv = trans->AddDataFlavor(kUnicodeMime); if (NS_FAILED(rv)) return rv; - PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0); - - // get correct mimeType and document encoder flags set - nsAutoString mimeType; - PRUint32 docEncoderFlags = 0; - if (bIsPlainTextControl) - { - docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted; - mimeType = NS_LITERAL_STRING(kUnicodeMime); - } - else - mimeType = NS_LITERAL_STRING(kHTMLMime); - - // set up docEncoder - nsCOMPtr docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID); - NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - - rv = docEncoder->Init(doc, mimeType, docEncoderFlags); + // QI the data object an |nsISupports| so that when the transferable holds + // onto it, it will addref the correct interface. + nsCOMPtr genericDataObj(do_QueryInterface(dataWrapper)); + rv = trans->SetTransferData(kUnicodeMime, genericDataObj, + buffer.Length() * sizeof(PRUnichar)); if (NS_FAILED(rv)) return rv; - - rv = docEncoder->SetSelection(selection); + } + else + { + contextWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); + NS_ENSURE_TRUE(contextWrapper, NS_ERROR_FAILURE); + infoWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); + NS_ENSURE_TRUE(infoWrapper, NS_ERROR_FAILURE); + + contextWrapper->SetData(parents); + infoWrapper->SetData(info); + + rv = trans->AddDataFlavor(kHTMLMime); if (NS_FAILED(rv)) return rv; - // grab a string - nsAutoString buffer, parents, info; + nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID); + NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE); - if (!bIsPlainTextControl) + rv = trans->SetConverter(htmlConverter); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr genericDataObj(do_QueryInterface(dataWrapper)); + rv = trans->SetTransferData(kHTMLMime, genericDataObj, + buffer.Length() * sizeof(PRUnichar)); + if (NS_FAILED(rv)) return rv; + + if (!parents.IsEmpty()) { - // encode the selection as html with contextual info - rv = docEncoder->EncodeToStringWithContext(buffer, parents, info); - if (NS_FAILED(rv)) return rv; + // Add the htmlcontext DataFlavor to the transferable + trans->AddDataFlavor(kHTMLContext); + genericDataObj = do_QueryInterface(contextWrapper); + trans->SetTransferData(kHTMLContext, genericDataObj, + parents.Length() * sizeof(PRUnichar)); } - else + if (!info.IsEmpty()) { - // encode the selection - rv = docEncoder->EncodeToString(buffer); - if (NS_FAILED(rv)) return rv; - } - - // if we have an empty string, we're done; otherwise continue - if ( !buffer.IsEmpty() ) - { - nsCOMPtr dataWrapper, contextWrapper, infoWrapper; - - dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); - NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE); - rv = dataWrapper->SetData(buffer); - if (NS_FAILED(rv)) return rv; - - if (bIsPlainTextControl) - { - // Add the unicode flavor to the transferable - rv = trans->AddDataFlavor(kUnicodeMime); - if (NS_FAILED(rv)) return rv; - - // QI the data object an |nsISupports| so that when the transferable holds - // onto it, it will addref the correct interface. - nsCOMPtr genericDataObj ( do_QueryInterface(dataWrapper) ); - rv = trans->SetTransferData(kUnicodeMime, genericDataObj, buffer.Length() * 2); - if (NS_FAILED(rv)) return rv; - } - else - { - contextWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); - NS_ENSURE_TRUE(contextWrapper, NS_ERROR_FAILURE); - infoWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); - NS_ENSURE_TRUE(infoWrapper, NS_ERROR_FAILURE); - - contextWrapper->SetData ( parents ); - infoWrapper->SetData ( info ); - - rv = trans->AddDataFlavor(kHTMLMime); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID); - NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE); - - rv = trans->SetConverter(htmlConverter); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr genericDataObj ( do_QueryInterface(dataWrapper) ); - rv = trans->SetTransferData(kHTMLMime, genericDataObj, buffer.Length() * 2); - if (NS_FAILED(rv)) return rv; - - if (parents.Length()) - { - // Add the htmlcontext DataFlavor to the transferable - trans->AddDataFlavor(kHTMLContext); - genericDataObj = do_QueryInterface(contextWrapper); - trans->SetTransferData(kHTMLContext, genericDataObj, parents.Length()*2); - } - if (info.Length()) - { - // Add the htmlinfo DataFlavor to the transferable - trans->AddDataFlavor(kHTMLInfo); - genericDataObj = do_QueryInterface(infoWrapper); - trans->SetTransferData(kHTMLInfo, genericDataObj, info.Length()*2); - } - } - - /* add the transferable to the array */ - rv = transferableArray->AppendElement(trans); - if (NS_FAILED(rv)) return rv; - - /* invoke drag */ - unsigned int flags; - // in some cases we'll want to cut rather than copy... hmmmmm... - flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE; - - rv = dragService->InvokeDragSession( domnode, transferableArray, nsnull, flags); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr nsevent(do_QueryInterface(aDragEvent)); - - if (nsevent) { - nsevent->PreventBubble(); - } + // Add the htmlinfo DataFlavor to the transferable + trans->AddDataFlavor(kHTMLInfo); + genericDataObj = do_QueryInterface(infoWrapper); + trans->SetTransferData(kHTMLInfo, genericDataObj, + info.Length() * sizeof(PRUnichar)); } } - return rv; + *aTransferable = trans; + NS_ADDREF(*aTransferable); + return NS_OK; } +NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) +{ + return nsPlaintextEditor::DoDrag(aDragEvent); +} PRBool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard) { @@ -1679,14 +1588,14 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType) // Get Clipboard Service nsresult rv; - nsCOMPtr clipboard( do_GetService( kCClipboardCID, &rv ) ); - if ( NS_FAILED(rv) ) + nsCOMPtr clipboard(do_GetService(kCClipboardCID, &rv)); + if (NS_FAILED(rv)) return rv; - + // find out if we have our internal html flavor on the clipboard. We don't want to mess // around with cfhtml if we do. - PRBool bHavePrivateHTMLFlavor = HavePrivateHTMLFlavor( clipboard ); - + PRBool bHavePrivateHTMLFlavor = HavePrivateHTMLFlavor(clipboard); + // Get the nsITransferable interface for getting the data from the clipboard nsCOMPtr trans; rv = PrepareHTMLTransferable(getter_AddRefs(trans), bHavePrivateHTMLFlavor); @@ -1694,20 +1603,23 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType) { // Get the Data from the clipboard if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable()) - { - nsAutoString contextStr, infoStr; + { // also get additional html copy hints, if present - if (bHavePrivateHTMLFlavor) { + nsAutoString contextStr, infoStr; + + // also get additional html copy hints, if present + if (bHavePrivateHTMLFlavor) + { nsCOMPtr contextDataObj, infoDataObj; PRUint32 contextLen, infoLen; nsCOMPtr textDataObj; - + nsCOMPtr contextTrans = do_CreateInstance(kCTransferableCID); NS_ENSURE_TRUE(contextTrans, NS_ERROR_NULL_POINTER); contextTrans->AddDataFlavor(kHTMLContext); clipboard->GetData(contextTrans, aSelectionType); contextTrans->GetTransferData(kHTMLContext, getter_AddRefs(contextDataObj), &contextLen); - + nsCOMPtr infoTrans = do_CreateInstance(kCTransferableCID); NS_ENSURE_TRUE(infoTrans, NS_ERROR_NULL_POINTER); infoTrans->AddDataFlavor(kHTMLInfo); @@ -1718,25 +1630,32 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType) { nsAutoString text; textDataObj = do_QueryInterface(contextDataObj); - textDataObj->GetData ( text ); + textDataObj->GetData(text); NS_ASSERTION(text.Length() <= (contextLen/2), "Invalid length!"); - contextStr.Assign ( text.get(), contextLen / 2 ); + contextStr.Assign(text.get(), contextLen / 2); } if (infoDataObj) { nsAutoString text; textDataObj = do_QueryInterface(infoDataObj); - textDataObj->GetData ( text ); + textDataObj->GetData(text); NS_ASSERTION(text.Length() <= (infoLen/2), "Invalid length!"); - infoStr.Assign ( text.get(), infoLen / 2 ); + infoStr.Assign(text.get(), infoLen / 2); } } + + // handle transferable hooks + PRBool doInsert = PR_TRUE; + DoInsertionHook(nsnull, trans, &doInsert); + if (!doInsert) + return NS_OK; + rv = InsertFromTransferable(trans, contextStr, infoStr, nsnull, 0, PR_TRUE); - } } + return rv; } @@ -2285,7 +2204,7 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString, nsCOMPtr contextfrag; nsCOMPtr contextLeaf, junk; PRInt32 contextDepth = 0; - if (aContextStr.Length()) + if (!aContextStr.IsEmpty()) { res = ParseFragment(aContextStr, tagStack, address_of(contextAsNode)); NS_ENSURE_SUCCESS(res, res); @@ -2332,7 +2251,7 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString, // get the infoString contents nsAutoString numstr1, numstr2; - if (aInfoStr.Length()) + if (!aInfoStr.IsEmpty()) { PRInt32 err, sep; sep = aInfoStr.FindChar((PRUnichar)','); diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index 35cbff60092..9a0a98c67d8 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -42,7 +42,7 @@ #define nsHTMLEditor_h__ #include "nsCOMPtr.h" - +#include "nsCOMArray.h" #include "nsPlaintextEditor.h" #include "nsIEditor.h" #include "nsIHTMLEditor.h" @@ -409,7 +409,7 @@ public: PRInt32 *outOffset = 0); /* ------------ Overrides of nsEditor interface methods -------------- */ - + nsresult EndUpdateViewBatch(); /** prepare the editor for use */ @@ -509,7 +509,6 @@ public: PRBool aMozBRDoesntCount = PR_FALSE, PRBool aListOrCellNotEmpty = PR_FALSE, PRBool aSafeToAskFrames = PR_FALSE); - nsresult IsEmptyNodeImpl(nsIDOMNode *aNode, PRBool *outIsEmptyBlock, PRBool aMozBRDoesntCount, @@ -723,6 +722,7 @@ protected: // factored methods for handling insertion of data from transferables (drag&drop or clipboard) NS_IMETHOD PrepareTransferable(nsITransferable **transferable); NS_IMETHOD PrepareHTMLTransferable(nsITransferable **transferable, PRBool havePrivFlavor); + nsresult PutDragDataInTransferable(nsITransferable **aTransferable); NS_IMETHOD InsertFromTransferable(nsITransferable *transferable, const nsAString & aContextStr, const nsAString & aInfoStr, diff --git a/mozilla/editor/libeditor/text/Makefile.in b/mozilla/editor/libeditor/text/Makefile.in index 55cfd510ded..02a4888ef25 100644 --- a/mozilla/editor/libeditor/text/Makefile.in +++ b/mozilla/editor/libeditor/text/Makefile.in @@ -45,6 +45,7 @@ REQUIRES = xpcom \ gfx \ widget \ unicharutil \ + docshell \ $(NULL) CPPSRCS = \ diff --git a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp index 2e876fdeaee..73ecbf84b77 100644 --- a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp @@ -657,7 +657,10 @@ nsTextEditorDragListener::DragOver(nsIDOMEvent* aDragEvent) PRBool canDrop = CanDrop(aDragEvent); dragSession->SetCanDrop(canDrop); - + + // We need to consume the event to prevent the browser's + // default drag listeners from being fired. (Bug 199133) + aDragEvent->PreventDefault(); // consumed if (canDrop) @@ -779,7 +782,6 @@ nsTextEditorDragListener::CanDrop(nsIDOMEvent* aEvent) dragService->GetCurrentSession(getter_AddRefs(dragSession)); if (!dragSession) return PR_FALSE; - // XXX should we filter out some types for plaintext-only editors? PRBool flavorSupported = PR_FALSE; dragSession->IsDataFlavorSupported(kUnicodeMime, &flavorSupported); diff --git a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp index a4b679c59f4..ed42d096baf 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp @@ -106,6 +106,10 @@ #include "nsITransferable.h" #include "nsIDragService.h" #include "nsIDOMNSUIEvent.h" +#include "nsIDocShell.h" +#include "nsIClipboardDragDropHooks.h" +#include "nsIClipboardDragDropHookList.h" +#include "nsISimpleEnumerator.h" // Misc #include "nsEditorUtils.h" @@ -188,6 +192,12 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) dragService->GetCurrentSession(getter_AddRefs(dragSession)); if (!dragSession) return NS_OK; + // transferable hooks + PRBool isAllowed = PR_TRUE; + DoAllowDropHook(aDropEvent, dragSession, &isAllowed); + if (!isAllowed) + return NS_OK; + // Get the nsITransferable interface for getting the data from the drop nsCOMPtr trans; rv = PrepareTransferable(getter_AddRefs(trans)); @@ -221,7 +231,7 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) nsCOMPtr mouseEvent ( do_QueryInterface(aDropEvent) ); if (mouseEvent) -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) mouseEvent->GetAltKey(&userWantsCopy); #else mouseEvent->GetCtrlKey(&userWantsCopy); @@ -331,6 +341,11 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) doPlaceCaret = PR_FALSE; } + PRBool doInsert = PR_TRUE; + DoInsertionHook(aDropEvent, trans, &doInsert); + if (!doInsert) + return NS_OK; + rv = InsertTextFromTransferable(trans); } @@ -378,7 +393,7 @@ NS_IMETHODIMP nsPlaintextEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDr } } - if ( eventTarget ) + if (eventTarget) { nsCOMPtr eventTargetDomNode = do_QueryInterface(eventTarget); if ( eventTargetDomNode ) @@ -391,6 +406,42 @@ NS_IMETHODIMP nsPlaintextEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDr } } + if (NS_FAILED(res)) return res; + if (!*aCanDrag) return NS_OK; + + nsCOMPtr domdoc; + GetDocument(getter_AddRefs(domdoc)); + nsCOMPtr doc = do_QueryInterface(domdoc); + if (!doc) return NS_ERROR_FAILURE; + + nsCOMPtr isupp; + doc->GetContainer(getter_AddRefs(isupp)); + nsCOMPtr docShell = do_QueryInterface(isupp); + nsCOMPtr hookObj = do_GetInterface(docShell); + if (!hookObj) return NS_ERROR_FAILURE; + + nsCOMPtr enumerator; + hookObj->GetHookEnumerator(getter_AddRefs(enumerator)); + if (!enumerator) return NS_ERROR_FAILURE; + + nsCOMPtr override; + PRBool hasMoreHooks = PR_FALSE; + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) + && hasMoreHooks) + { + res = enumerator->GetNext(getter_AddRefs(isupp)); + if (NS_FAILED(res)) break; + override = do_QueryInterface(isupp); + if (override) + { + res = override->AllowStartDrag(aDragEvent, aCanDrag); + NS_ASSERTION(NS_SUCCEEDED(res), "hook failure in AllowStartDrag"); + } + + if (!*aCanDrag) + break; + } + return NS_OK; } @@ -398,14 +449,14 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) { nsresult rv; - nsCOMPtr eventTarget; - rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget)); + nsCOMPtr trans; + rv = PutDragDataInTransferable(getter_AddRefs(trans)); if (NS_FAILED(rv)) return rv; - nsCOMPtr domnode = do_QueryInterface(eventTarget); + if (!trans) return NS_OK; // maybe there was nothing to copy? - /* get the selection to be dragged */ - nsCOMPtr selection; - rv = GetSelection(getter_AddRefs(selection)); + /* get the drag service */ + nsCOMPtr dragService = + do_GetService("@mozilla.org/widget/dragservice;1", &rv); if (NS_FAILED(rv)) return rv; /* create an array of transferables */ @@ -414,109 +465,63 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) if (transferableArray == nsnull) return NS_ERROR_OUT_OF_MEMORY; - /* get the drag service */ - nsCOMPtr dragService = - do_GetService("@mozilla.org/widget/dragservice;1", &rv); + /* add the transferable to the array */ + rv = transferableArray->AppendElement(trans); if (NS_FAILED(rv)) return rv; - /* create html flavor transferable */ - nsCOMPtr trans = do_CreateInstance(kCTransferableCID); - NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE); - + // check our transferable hooks (if any) nsCOMPtr domdoc; - rv = GetDocument(getter_AddRefs(domdoc)); - if (NS_FAILED(rv)) return rv; - + GetDocument(getter_AddRefs(domdoc)); nsCOMPtr doc = do_QueryInterface(domdoc); - if (doc) + if (!doc) return NS_ERROR_FAILURE; + + nsCOMPtr isupp; + doc->GetContainer(getter_AddRefs(isupp)); + nsCOMPtr docShell = do_QueryInterface(isupp); + nsCOMPtr hookObj = do_GetInterface(docShell); + if (!hookObj) return NS_ERROR_FAILURE; + + nsCOMPtr enumerator; + hookObj->GetHookEnumerator(getter_AddRefs(enumerator)); + if (!enumerator) return NS_ERROR_FAILURE; + + nsCOMPtr override; + PRBool canInvokeDrag = PR_TRUE; + PRBool hasMoreHooks = PR_FALSE; + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) + && hasMoreHooks) { - // find out if we're a plaintext control or not - PRUint32 editorFlags = 0; - rv = GetFlags(&editorFlags); - if (NS_FAILED(rv)) return rv; - - PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0); - - // get correct mimeType and document encoder flags set - nsAutoString mimeType; - PRUint32 docEncoderFlags = 0; - if (bIsPlainTextControl) + rv = enumerator->GetNext(getter_AddRefs(isupp)); + if (NS_FAILED(rv)) break; + override = do_QueryInterface(isupp); + if (override) { - docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted; - mimeType = NS_LITERAL_STRING(kUnicodeMime); + nsresult hookResult = override->OnCopyOrDrag(trans, &canInvokeDrag); + NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnCopyOrDrag"); } - else - mimeType = NS_LITERAL_STRING(kHTMLMime); - - // set up docEncoder - nsCOMPtr docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID); - NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - rv = docEncoder->Init(doc, mimeType, docEncoderFlags); - if (NS_FAILED(rv)) return rv; - - rv = docEncoder->SetSelection(selection); - if (NS_FAILED(rv)) return rv; - - // grab a string - nsAutoString buffer; - rv = docEncoder->EncodeToString(buffer); - if (NS_FAILED(rv)) return rv; - - // if we have an empty string, we're done; otherwise continue - if ( !buffer.IsEmpty() ) - { - nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); - NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE); - - rv = dataWrapper->SetData( buffer ); - if (NS_FAILED(rv)) return rv; - - if (bIsPlainTextControl) - { - // Add the unicode flavor to the transferable - rv = trans->AddDataFlavor(kUnicodeMime); - if (NS_FAILED(rv)) return rv; - } - else - { - rv = trans->AddDataFlavor(kHTMLMime); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID); - NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE); - - rv = trans->SetConverter(htmlConverter); - if (NS_FAILED(rv)) return rv; - } - - // QI the data object an |nsISupports| so that when the transferable holds - // onto it, it will addref the correct interface. - nsCOMPtr nsisupportsDataWrapper ( do_QueryInterface(dataWrapper) ); - rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime, - nsisupportsDataWrapper, buffer.Length() * 2); - if (NS_FAILED(rv)) return rv; - - /* add the transferable to the array */ - rv = transferableArray->AppendElement(trans); - if (NS_FAILED(rv)) return rv; - - /* invoke drag */ - unsigned int flags; - // in some cases we'll want to cut rather than copy... hmmmmm... - flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE; - - rv = dragService->InvokeDragSession( domnode, transferableArray, nsnull, flags); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr nsevent(do_QueryInterface(aDragEvent)); - - if (nsevent) { - nsevent->PreventBubble(); - } - } + // if one of our overrides says we can't invoke drag, return now + if (!canInvokeDrag) + return NS_OK; } + /* invoke drag */ + nsCOMPtr eventTarget; + rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget)); + if (NS_FAILED(rv)) return rv; + nsCOMPtr domnode = do_QueryInterface(eventTarget); + + unsigned int flags; + // in some cases we'll want to cut rather than copy... hmmmmm... + flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE; + + rv = dragService->InvokeDragSession(domnode, transferableArray, nsnull, flags); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr nsevent(do_QueryInterface(aDragEvent)); + if (nsevent) + nsevent->PreventBubble(); + return rv; } @@ -538,6 +543,12 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType) // Get the Data from the clipboard if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable()) { + // handle transferable hooks + PRBool doInsert = PR_TRUE; + DoInsertionHook(nsnull, trans, &doInsert); + if (!doInsert) + return NS_OK; + rv = InsertTextFromTransferable(trans); } } @@ -591,3 +602,196 @@ NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPa *aCanPaste = haveFlavors; return NS_OK; } +nsresult +nsPlaintextEditor::SetupDocEncoder(nsIDocumentEncoder **aDocEncoder) +{ + nsCOMPtr domdoc; + nsresult rv = GetDocument(getter_AddRefs(domdoc)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr doc = do_QueryInterface(domdoc); + if (!doc) return NS_ERROR_FAILURE; + + // find out if we're a plaintext control or not + PRUint32 editorFlags = 0; + rv = GetFlags(&editorFlags); + if (NS_FAILED(rv)) return rv; + + PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0); + + // get correct mimeType and document encoder flags set + nsAutoString mimeType; + PRUint32 docEncoderFlags = 0; + if (bIsPlainTextControl) + { + docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted; + mimeType = NS_LITERAL_STRING(kUnicodeMime); + } + else + mimeType = NS_LITERAL_STRING(kHTMLMime); + + // set up docEncoder + nsCOMPtr encoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID); + if (!encoder) + return NS_ERROR_OUT_OF_MEMORY; + + rv = encoder->Init(doc, mimeType, docEncoderFlags); + if (NS_FAILED(rv)) return rv; + + /* get the selection to be dragged */ + nsCOMPtr selection; + rv = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(rv)) return rv; + + rv = encoder->SetSelection(selection); + if (NS_FAILED(rv)) return rv; + + *aDocEncoder = encoder; + NS_ADDREF(*aDocEncoder); + return NS_OK; +} + +nsresult +nsPlaintextEditor::PutDragDataInTransferable(nsITransferable **aTransferable) +{ + *aTransferable = nsnull; + nsCOMPtr docEncoder; + nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder)); + if (NS_FAILED(rv)) return rv; + + // grab a string + nsAutoString buffer; + rv = docEncoder->EncodeToString(buffer); + if (NS_FAILED(rv)) return rv; + + // if we have an empty string, we're done; otherwise continue + if (buffer.IsEmpty()) + return NS_OK; + + nsCOMPtr dataWrapper = + do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = dataWrapper->SetData(buffer); + if (NS_FAILED(rv)) return rv; + + /* create html flavor transferable */ + nsCOMPtr trans = do_CreateInstance(kCTransferableCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // find out if we're a plaintext control or not + PRUint32 editorFlags = 0; + rv = GetFlags(&editorFlags); + if (NS_FAILED(rv)) return rv; + + PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0); + if (bIsPlainTextControl) + { + // Add the unicode flavor to the transferable + rv = trans->AddDataFlavor(kUnicodeMime); + if (NS_FAILED(rv)) return rv; + } + else + { + rv = trans->AddDataFlavor(kHTMLMime); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID); + NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE); + + rv = trans->SetConverter(htmlConverter); + if (NS_FAILED(rv)) return rv; + } + + // QI the data object an |nsISupports| so that when the transferable holds + // onto it, it will addref the correct interface. + nsCOMPtr nsisupportsDataWrapper = do_QueryInterface(dataWrapper); + rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime, + nsisupportsDataWrapper, buffer.Length() * sizeof(PRUnichar)); + if (NS_FAILED(rv)) return rv; + + *aTransferable = trans; + NS_ADDREF(*aTransferable); + return NS_OK; +} + +nsresult +nsPlaintextEditor::DoAllowDropHook(nsIDOMEvent* aDropEvent, + nsIDragSession *aSession, PRBool *aAllowDrop) +{ + *aAllowDrop = PR_TRUE; + + nsCOMPtr domdoc; + GetDocument(getter_AddRefs(domdoc)); + nsCOMPtr doc = do_QueryInterface(domdoc); + if (!doc) return NS_ERROR_FAILURE; + + nsCOMPtr isupp; + doc->GetContainer(getter_AddRefs(isupp)); + nsCOMPtr docShell = do_QueryInterface(isupp); + nsCOMPtr hookObj = do_GetInterface(docShell); + if (!hookObj) return NS_ERROR_FAILURE; + + nsCOMPtr enumerator; + hookObj->GetHookEnumerator(getter_AddRefs(enumerator)); + if (!enumerator) return NS_ERROR_FAILURE; + + nsCOMPtr override; + PRBool hasMoreHooks = PR_FALSE; + nsresult res = NS_OK; + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) && hasMoreHooks) + { + res = enumerator->GetNext(getter_AddRefs(isupp)); + if (NS_FAILED(res)) break; + override = do_QueryInterface(isupp); + if (override) + { + nsresult hookResult = override->AllowDrop(aDropEvent, aSession, aAllowDrop); + NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in AllowDrop"); + } + + if (!*aAllowDrop) + break; + } + + return res; +} + + +nsresult +nsPlaintextEditor::DoInsertionHook(nsIDOMEvent* aDropEvent, + nsITransferable *aTrans, PRBool *aDoInsert) +{ + nsCOMPtr domdoc; + GetDocument(getter_AddRefs(domdoc)); + nsCOMPtr doc = do_QueryInterface(domdoc); + if (!doc) return NS_ERROR_FAILURE; + + nsCOMPtr isupp; + doc->GetContainer(getter_AddRefs(isupp)); + nsCOMPtr docShell = do_QueryInterface(isupp); + nsCOMPtr hookObj = do_GetInterface(docShell); + if (!hookObj) return NS_ERROR_FAILURE; + + nsCOMPtr enumerator; + hookObj->GetHookEnumerator(getter_AddRefs(enumerator)); + if (!enumerator) return NS_ERROR_FAILURE; + + nsCOMPtr override; + PRBool hasMoreHooks = PR_FALSE; + nsresult res = NS_OK; + while (*aDoInsert && + NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) && hasMoreHooks) + { + res = enumerator->GetNext(getter_AddRefs(isupp)); + if (NS_FAILED(res)) break; + override = do_QueryInterface(isupp); + if (override) + { + nsresult hookResult = override->OnPasteOrDrop(aDropEvent, aTrans, aDoInsert); + NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop"); + } + } + + return res; +} diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp index 15e48ce8d9f..328c6437a75 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp @@ -362,6 +362,8 @@ nsPlaintextEditor::InstallEventListeners() NS_ASSERTION(mDocWeak, "no document set on this editor"); if (!mDocWeak) return NS_ERROR_NOT_INITIALIZED; + if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; + nsresult result; // get a key listener result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this); diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.h b/mozilla/editor/libeditor/text/nsPlaintextEditor.h index dbc1cac4543..23a9905a094 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextEditor.h +++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.h @@ -55,6 +55,7 @@ class nsIDOMKeyEvent; class nsITransferable; class nsIDOMEventReceiver; class nsIDocumentEncoder; +class nsIDragSession; /** * The text editor implementation. @@ -228,6 +229,11 @@ protected: // factored methods for handling insertion of data from transferables (drag&drop or clipboard) NS_IMETHOD PrepareTransferable(nsITransferable **transferable); NS_IMETHOD InsertTextFromTransferable(nsITransferable *transferable); + virtual nsresult SetupDocEncoder(nsIDocumentEncoder **aDocEncoder); + virtual nsresult PutDragDataInTransferable(nsITransferable **aTransferable); + virtual nsresult DoAllowDropHook(nsIDOMEvent* aDropEvent, nsIDragSession *aSession, PRBool *aAllowDrop); + virtual nsresult DoInsertionHook(nsIDOMEvent* aDropEvent, + nsITransferable *aTrans, PRBool *aDoInsert); /** simple utility to handle any error with event listener allocation or registration */ void HandleEventListenerError(); diff --git a/mozilla/editor/ui/dialogs/content/EdInsertTable.js b/mozilla/editor/ui/dialogs/content/EdInsertTable.js index 471df03fce3..c63a5da287d 100644 --- a/mozilla/editor/ui/dialogs/content/EdInsertTable.js +++ b/mozilla/editor/ui/dialogs/content/EdInsertTable.js @@ -230,6 +230,11 @@ function onAccept() gActiveEditor.endTransaction(); + // HACK ! Make sure that if the caret is placed in the (newly created) + // table, the resizing handles are correcly shown + var objectResizer = gActiveEditor.QueryInterface(Components.interfaces.nsIHTMLObjectResizer) + objectResizer.checkResizingState(gActiveEditor.selection); + SaveWindowLocation(); return true; } diff --git a/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index 492635c6bf0..cbf49edb3f8 100644 --- a/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -68,7 +68,6 @@ #include "nsIPrompt.h" #include "nsRect.h" #include "nsIWebBrowserChromeFocus.h" -#include "nsIDragDropOverride.h" #include "nsIContent.h" #include "imgIContainer.h" #include "nsContextMenuInfo.h" @@ -830,11 +829,8 @@ nsDocShellTreeOwner :: AddChromeListeners ( ) if ( mChromeDragHandler ) { nsCOMPtr rcvr; GetEventReceiver(mWebBrowser, getter_AddRefs(rcvr)); - nsCOMPtr srcOverride ( do_QueryInterface(mWebBrowserChrome) ); - nsCOMPtr siteOverride ( do_QueryInterface(mWebBrowserChrome) ); nsCOMPtr rcvrTarget(do_QueryInterface(rcvr)); - mChromeDragHandler->HookupTo(rcvrTarget, NS_STATIC_CAST(nsIWebNavigation*, mWebBrowser), - srcOverride, siteOverride); + mChromeDragHandler->HookupTo(rcvrTarget, NS_STATIC_CAST(nsIWebNavigation*, mWebBrowser)); } }