Back to index

lightning-sunbird  0.9+nobinonly
nsGlobalWindowCommands.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications, Inc.
00018  * Portions created by the Initial Developer are Copyright (C) 2003
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Kathleen Brade <brade@netscape.com>
00023  *   Simon Fraser   <sfraser@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 
00040 #include "nsGlobalWindowCommands.h"
00041 
00042 #include "nsIComponentManager.h"
00043 #include "nsIInterfaceRequestor.h"
00044 #include "nsIInterfaceRequestorUtils.h"
00045 #include "nsCRT.h"
00046 #include "nsString.h"
00047 
00048 #include "nsIControllerCommandTable.h"
00049 #include "nsICommandParams.h"
00050 
00051 #include "nsIDOMWindow.h"
00052 #include "nsIPresShell.h"
00053 #include "nsPresContext.h"
00054 #include "nsIScriptGlobalObject.h"
00055 #include "nsIDocShell.h"
00056 #include "nsISelectionController.h"
00057 #include "nsIEventStateManager.h"
00058 #include "nsIWebNavigation.h"
00059 #include "nsIContentViewerEdit.h"
00060 #include "nsIContentViewer.h"
00061 
00062 #include "nsIClipboardDragDropHooks.h"
00063 #include "nsIClipboardDragDropHookList.h"
00064 
00065 const char * const sSelectAllString = "cmd_selectAll";
00066 const char * const sSelectNoneString = "cmd_selectNone";
00067 const char * const sCopyImageLocationString = "cmd_copyImageLocation";
00068 const char * const sCopyImageContentsString = "cmd_copyImageContents";
00069 const char * const sCopyImageString = "cmd_copyImage";
00070 
00071 const char * const sScrollTopString = "cmd_scrollTop";
00072 const char * const sScrollBottomString = "cmd_scrollBottom";
00073 const char * const sScrollPageUpString = "cmd_scrollPageUp";
00074 const char * const sScrollPageDownString = "cmd_scrollPageDown";
00075 const char * const sMovePageUpString = "cmd_movePageUp";
00076 const char * const sMovePageDownString = "cmd_movePageDown";
00077 const char * const sScrollLineUpString = "cmd_scrollLineUp";
00078 const char * const sScrollLineDownString = "cmd_scrollLineDown";
00079 const char * const sScrollLeftString = "cmd_scrollLeft";
00080 const char * const sScrollRightString = "cmd_scrollRight";
00081 
00082 // These are so the browser can use editor navigation key bindings
00083 // helps with accessibility (boolean pref accessibility.browsewithcaret)
00084 
00085 const char * const sSelectCharPreviousString = "cmd_selectCharPrevious";
00086 const char * const sSelectCharNextString = "cmd_selectCharNext";
00087 
00088 const char * const sWordPreviousString = "cmd_wordPrevious";
00089 const char * const sWordNextString = "cmd_wordNext";
00090 const char * const sSelectWordPreviousString = "cmd_selectWordPrevious";
00091 const char * const sSelectWordNextString = "cmd_selectWordNext";
00092 
00093 const char * const sBeginLineString = "cmd_beginLine";
00094 const char * const sEndLineString = "cmd_endLine";
00095 const char * const sSelectBeginLineString = "cmd_selectBeginLine";
00096 const char * const sSelectEndLineString = "cmd_selectEndLine";
00097 
00098 const char * const sSelectLinePreviousString = "cmd_selectLinePrevious";
00099 const char * const sSelectLineNextString = "cmd_selectLineNext";
00100 
00101 const char * const sSelectPagePreviousString = "cmd_selectPagePrevious";
00102 const char * const sSelectPageNextString = "cmd_selectPageNext";
00103 
00104 const char * const sSelectTopString = "cmd_selectTop";
00105 const char * const sSelectBottomString = "cmd_selectBottom";
00106 
00107 
00108 #if 0
00109 #pragma mark -
00110 #endif
00111 
00112 // a base class for selection-related commands, for code sharing
00113 class nsSelectionCommandsBase : public nsIControllerCommand
00114 {
00115 public:
00116 
00117   NS_DECL_ISUPPORTS
00118   NS_DECL_NSICONTROLLERCOMMAND
00119 
00120 protected:
00121 
00122   // subclasses override DoSelectCommand
00123   virtual nsresult DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow) = 0;
00124 
00125   static nsresult  GetPresShellFromWindow(nsIDOMWindow *aWindow, nsIPresShell **aPresShell);
00126   static nsresult  GetSelectionControllerFromWindow(nsIDOMWindow *aWindow, nsISelectionController **aSelCon);
00127   static nsresult  GetEventStateManagerForWindow(nsIDOMWindow *aWindow, nsIEventStateManager **aEventStateManager);
00128 
00129   // no member variables, please, we're stateless!
00130 };
00131 
00132 // this class implements commands whose behavior depends on the 'browse with caret' setting
00133 class nsSelectMoveScrollCommand : public nsSelectionCommandsBase
00134 {
00135 protected:
00136 
00137   virtual nsresult DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow);
00138   
00139   nsresult    DoCommandBrowseWithCaretOn(const char *aCommandName, nsISelectionController *aSelectionController, nsIEventStateManager* aESM);
00140   nsresult    DoCommandBrowseWithCaretOff(const char *aCommandName, nsISelectionController *aSelectionController);
00141 
00142   // no member variables, please, we're stateless!
00143 };
00144 
00145 // this class implements other selection commands
00146 class nsSelectCommand : public nsSelectionCommandsBase
00147 {
00148 protected:
00149 
00150   virtual nsresult DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow);
00151 
00152   // no member variables, please, we're stateless!
00153 };
00154 
00155 #if 0
00156 #pragma mark -
00157 #endif
00158 
00159 
00160 NS_IMPL_ISUPPORTS1(nsSelectionCommandsBase, nsIControllerCommand)
00161 
00162 /* boolean isCommandEnabled (in string aCommandName, in nsISupports aCommandContext); */
00163 NS_IMETHODIMP
00164 nsSelectionCommandsBase::IsCommandEnabled(const char * aCommandName,
00165                                       nsISupports *aCommandContext,
00166                                       PRBool *outCmdEnabled)
00167 {
00168   // XXX this needs fixing. e.g. you can't scroll up if you're already at the top of
00169   // the document.
00170   *outCmdEnabled = PR_TRUE;
00171   return NS_OK;
00172 }
00173 
00174 /* void getCommandStateParams (in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext); */
00175 NS_IMETHODIMP
00176 nsSelectionCommandsBase::GetCommandStateParams(const char *aCommandName,
00177                                             nsICommandParams *aParams, nsISupports *aCommandContext)
00178 {
00179   // XXX we should probably return the enabled state
00180   return NS_ERROR_NOT_IMPLEMENTED;
00181 }
00182 
00183 NS_IMETHODIMP
00184 nsSelectionCommandsBase::DoCommand(const char *aCommandName, nsISupports *aCommandContext)
00185 {
00186   nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(aCommandContext);
00187   NS_ENSURE_TRUE(window, NS_ERROR_INVALID_ARG);       
00188 
00189   return DoSelectCommand(aCommandName, window);
00190 }
00191 
00192 /* void doCommandParams (in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext); */
00193 NS_IMETHODIMP
00194 nsSelectionCommandsBase::DoCommandParams(const char *aCommandName,
00195                                        nsICommandParams *aParams, nsISupports *aCommandContext)
00196 {
00197   return DoCommand(aCommandName, aCommandContext);
00198 }
00199 
00200 // protected methods
00201 
00202 nsresult
00203 nsSelectionCommandsBase::GetPresShellFromWindow(nsIDOMWindow *aWindow, nsIPresShell **aPresShell)
00204 {
00205   *aPresShell = nsnull;
00206 
00207   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aWindow));
00208   NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
00209 
00210   nsIDocShell *docShell = sgo->GetDocShell();
00211   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
00212 
00213   return docShell->GetPresShell(aPresShell);
00214 }
00215 
00216 nsresult
00217 nsSelectionCommandsBase::GetSelectionControllerFromWindow(nsIDOMWindow *aWindow, nsISelectionController **aSelCon)
00218 {
00219   *aSelCon = nsnull;
00220 
00221   nsCOMPtr<nsIPresShell> presShell;
00222   GetPresShellFromWindow(aWindow, getter_AddRefs(presShell));
00223   if (presShell)
00224     return CallQueryInterface(presShell, aSelCon);
00225 
00226   return NS_ERROR_FAILURE;
00227 }
00228 
00229 nsresult
00230 nsSelectionCommandsBase::GetEventStateManagerForWindow(nsIDOMWindow *aWindow,
00231                               nsIEventStateManager **aEventStateManager)
00232 {
00233   *aEventStateManager = nsnull;
00234 
00235   nsCOMPtr<nsIPresShell> presShell;
00236   GetPresShellFromWindow(aWindow, getter_AddRefs(presShell));
00237   if (presShell)
00238   {
00239     nsPresContext *presContext = presShell->GetPresContext();
00240     if (presContext) {
00241       NS_ADDREF(*aEventStateManager = presContext->EventStateManager());
00242       return NS_OK;
00243     }
00244   }
00245   return NS_ERROR_FAILURE;
00246 }
00247 
00248 #if 0
00249 #pragma mark -
00250 #endif
00251 
00252 nsresult
00253 nsSelectMoveScrollCommand::DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow)
00254 {
00255   nsCOMPtr<nsISelectionController> selCont;
00256   GetSelectionControllerFromWindow(aWindow, getter_AddRefs(selCont));
00257   NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);       
00258 
00259   PRBool caretOn = PR_FALSE;
00260   selCont->GetCaretEnabled(&caretOn);
00261 
00262   nsCOMPtr<nsIEventStateManager> esm;
00263   GetEventStateManagerForWindow(aWindow, getter_AddRefs(esm));
00264 
00265   nsresult rv;
00266   // We allow the caret to be moved with arrow keys on any window for which
00267   // the caret is enabled. In particular, this includes caret-browsing mode,
00268   // but we refer to this mode again in the test condition for readability.
00269   if (caretOn || (esm && esm->GetBrowseWithCaret()))
00270     rv = DoCommandBrowseWithCaretOn(aCommandName, selCont, esm);
00271   else
00272     rv = DoCommandBrowseWithCaretOff(aCommandName, selCont);
00273 
00274   return rv;
00275 }
00276 
00277 nsresult
00278 nsSelectMoveScrollCommand::DoCommandBrowseWithCaretOn(const char *aCommandName,
00279                   nsISelectionController *aSelectionController, nsIEventStateManager* aESM)
00280 {
00281   nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
00282 
00283   if (!nsCRT::strcmp(aCommandName, sScrollTopString))
00284     rv = aSelectionController->CompleteMove(PR_FALSE, PR_FALSE);
00285   else if (!nsCRT::strcmp(aCommandName,sScrollBottomString))
00286     rv = aSelectionController->CompleteMove(PR_TRUE, PR_FALSE);
00287   // cmd_MovePageUp/Down are used on Window/Unix. They move the caret
00288   // in caret browsing mode.
00289   else if (!nsCRT::strcmp(aCommandName, sMovePageUpString))
00290     rv = aSelectionController->PageMove(PR_FALSE, PR_FALSE);
00291   else if (!nsCRT::strcmp(aCommandName, sMovePageDownString))
00292     rv = aSelectionController->PageMove(PR_TRUE, PR_FALSE);
00293   // cmd_ScrollPageUp/Down are used on Mac, and for the spacebar on all platforms.
00294   // They do not move the caret in caret browsing mode.
00295   else if (!nsCRT::strcmp(aCommandName, sScrollPageUpString))
00296     rv = aSelectionController->ScrollPage(PR_FALSE);
00297   else if (!nsCRT::strcmp(aCommandName, sScrollPageDownString))
00298     rv = aSelectionController->ScrollPage(PR_TRUE);
00299   else if (!nsCRT::strcmp(aCommandName, sScrollLineUpString))
00300     rv = aSelectionController->LineMove(PR_FALSE, PR_FALSE);
00301   else if (!nsCRT::strcmp(aCommandName, sScrollLineDownString))
00302     rv = aSelectionController->LineMove(PR_TRUE, PR_FALSE);
00303   else if (!nsCRT::strcmp(aCommandName, sWordPreviousString))
00304     rv = aSelectionController->WordMove(PR_FALSE, PR_FALSE);
00305   else if (!nsCRT::strcmp(aCommandName, sWordNextString))
00306     rv = aSelectionController->WordMove(PR_TRUE, PR_FALSE);
00307   else if (!nsCRT::strcmp(aCommandName, sScrollLeftString))
00308     rv = aSelectionController->CharacterMove(PR_FALSE, PR_FALSE);
00309   else if (!nsCRT::strcmp(aCommandName, sScrollRightString))
00310     rv = aSelectionController->CharacterMove(PR_TRUE, PR_FALSE);
00311   else if (!nsCRT::strcmp(aCommandName, sBeginLineString))
00312     rv = aSelectionController->IntraLineMove(PR_FALSE, PR_FALSE);
00313   else if (!nsCRT::strcmp(aCommandName, sEndLineString))
00314     rv = aSelectionController->IntraLineMove(PR_TRUE, PR_FALSE);
00315 
00316   if (NS_SUCCEEDED(rv) && aESM)
00317   {
00318     PRBool dummy;
00319     aESM->MoveFocusToCaret(PR_TRUE, &dummy);
00320   }
00321 
00322   return rv;
00323 }
00324 
00325 nsresult
00326 nsSelectMoveScrollCommand::DoCommandBrowseWithCaretOff(const char *aCommandName, nsISelectionController *aSelectionController)
00327 {
00328   nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
00329 
00330   if (!nsCRT::strcmp(aCommandName, sScrollTopString))   
00331     rv = aSelectionController->CompleteScroll(PR_FALSE);
00332   else if (!nsCRT::strcmp(aCommandName,sScrollBottomString))
00333     rv = aSelectionController->CompleteScroll(PR_TRUE);
00334 
00335   // cmd_MovePageUp/Down are used on Window/Unix. They move the caret
00336   // in caret browsing mode.
00337   else if (!nsCRT::strcmp(aCommandName, sMovePageUpString))
00338     rv = aSelectionController->ScrollPage(PR_FALSE);
00339   else if (!nsCRT::strcmp(aCommandName, sMovePageDownString))
00340     rv = aSelectionController->ScrollPage(PR_TRUE);
00341   // cmd_ScrollPageUp/Down are used on Mac. They do not move the
00342   // caret in caret browsing mode.
00343   else if (!nsCRT::strcmp(aCommandName, sScrollPageUpString))
00344     rv = aSelectionController->ScrollPage(PR_FALSE);
00345   else if (!nsCRT::strcmp(aCommandName, sScrollPageDownString))
00346     rv = aSelectionController->ScrollPage(PR_TRUE);
00347 
00348   else if (!nsCRT::strcmp(aCommandName, sScrollLineUpString))
00349     rv = aSelectionController->ScrollLine(PR_FALSE);
00350   else if (!nsCRT::strcmp(aCommandName, sScrollLineDownString))
00351     rv = aSelectionController->ScrollLine(PR_TRUE);
00352   else if (!nsCRT::strcmp(aCommandName, sScrollLeftString))
00353     rv = aSelectionController->ScrollHorizontal(PR_TRUE);
00354   else if (!nsCRT::strcmp(aCommandName, sScrollRightString))
00355     rv = aSelectionController->ScrollHorizontal(PR_FALSE);
00356   // cmd_beginLine/endLine with caret browsing off
00357   // will act as cmd_scrollTop/Bottom
00358   else if (!nsCRT::strcmp(aCommandName, sBeginLineString))
00359     rv = aSelectionController->CompleteScroll(PR_FALSE);
00360   else if (!nsCRT::strcmp(aCommandName, sEndLineString))
00361     rv = aSelectionController->CompleteScroll(PR_TRUE);
00362 
00363   return rv;
00364 }
00365 
00366 
00367 #if 0
00368 #pragma mark -
00369 #endif
00370 
00371 nsresult
00372 nsSelectCommand::DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow)
00373 {
00374   nsCOMPtr<nsISelectionController> selCont;
00375   GetSelectionControllerFromWindow(aWindow, getter_AddRefs(selCont));
00376   NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);       
00377 
00378   nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
00379 
00380   // These commands are so the browser can use caret navigation key bindings -
00381   // Helps with accessibility - aaronl@netscape.com
00382   if (!nsCRT::strcmp(aCommandName, sSelectCharPreviousString))
00383     rv = selCont->CharacterMove(PR_FALSE, PR_TRUE);
00384   else if (!nsCRT::strcmp(aCommandName, sSelectCharNextString))
00385     rv = selCont->CharacterMove(PR_TRUE, PR_TRUE);
00386   else if (!nsCRT::strcmp(aCommandName, sSelectWordPreviousString))
00387     rv = selCont->WordMove(PR_FALSE, PR_TRUE);
00388   else if (!nsCRT::strcmp(aCommandName, sSelectWordNextString))
00389     rv = selCont->WordMove(PR_TRUE, PR_TRUE);
00390   else if (!nsCRT::strcmp(aCommandName, sSelectBeginLineString))
00391     rv = selCont->IntraLineMove(PR_FALSE, PR_TRUE);
00392   else if (!nsCRT::strcmp(aCommandName, sSelectEndLineString))
00393     rv = selCont->IntraLineMove(PR_TRUE, PR_TRUE);
00394   else if (!nsCRT::strcmp(aCommandName, sSelectLinePreviousString))
00395     rv = selCont->LineMove(PR_FALSE, PR_TRUE);
00396   else if (!nsCRT::strcmp(aCommandName, sSelectLineNextString))
00397     rv = selCont->LineMove(PR_TRUE, PR_TRUE);
00398   else if (!nsCRT::strcmp(aCommandName, sSelectTopString))
00399     rv = selCont->CompleteMove(PR_FALSE, PR_TRUE);
00400   else if (!nsCRT::strcmp(aCommandName, sSelectBottomString))
00401     rv = selCont->CompleteMove(PR_TRUE, PR_TRUE);
00402 
00403   return rv;
00404 }
00405 
00406 #if 0
00407 #pragma mark -
00408 #endif
00409 
00410 class nsClipboardBaseCommand : public nsIControllerCommand
00411 {
00412 public:
00413 
00414   NS_DECL_ISUPPORTS
00415   NS_DECL_NSICONTROLLERCOMMAND
00416 
00417 protected:
00418 
00419   virtual nsresult    IsClipboardCommandEnabled(const char * aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled) = 0;
00420   virtual nsresult    DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams) = 0;
00421   
00422   static nsresult     GetContentViewerEditFromContext(nsISupports *aContext, nsIContentViewerEdit **aEditInterface);
00423   
00424   // no member variables, please, we're stateless!
00425 };
00426 
00427 
00428 NS_IMPL_ISUPPORTS1(nsClipboardBaseCommand, nsIControllerCommand)
00429 
00430 
00431 /*---------------------------------------------------------------------------
00432 
00433   nsClipboardBaseCommand
00434 
00435 ----------------------------------------------------------------------------*/
00436 
00437 NS_IMETHODIMP
00438 nsClipboardBaseCommand::IsCommandEnabled(const char * aCommandName,
00439                                          nsISupports *aCommandContext,
00440                                          PRBool *outCmdEnabled)
00441 {
00442   NS_ENSURE_ARG_POINTER(outCmdEnabled);
00443   *outCmdEnabled = PR_FALSE;
00444 
00445   nsCOMPtr<nsIContentViewerEdit> contentEdit;
00446   GetContentViewerEditFromContext(aCommandContext,  getter_AddRefs(contentEdit));
00447   NS_ENSURE_TRUE(contentEdit, NS_ERROR_NOT_INITIALIZED);
00448 
00449   return IsClipboardCommandEnabled(aCommandName, contentEdit, outCmdEnabled);
00450 }
00451 
00452 NS_IMETHODIMP
00453 nsClipboardBaseCommand::DoCommand(const char *aCommandName,
00454                                   nsISupports *aCommandContext)
00455 {
00456   nsCOMPtr<nsIContentViewerEdit> contentEdit;
00457   GetContentViewerEditFromContext(aCommandContext,  getter_AddRefs(contentEdit));
00458   NS_ENSURE_TRUE(contentEdit, NS_ERROR_NOT_INITIALIZED);
00459 
00460   return DoClipboardCommand(aCommandName, contentEdit, nsnull);
00461 }
00462 
00463 NS_IMETHODIMP
00464 nsClipboardBaseCommand::GetCommandStateParams(const char *aCommandName,
00465                                               nsICommandParams *aParams,
00466                                               nsISupports *aCommandContext)
00467 {
00468   return NS_ERROR_NOT_IMPLEMENTED;
00469 }
00470 
00471 NS_IMETHODIMP
00472 nsClipboardBaseCommand::DoCommandParams(const char *aCommandName,
00473                                         nsICommandParams *aParams,
00474                                         nsISupports *aCommandContext)
00475 {
00476   nsCOMPtr<nsIContentViewerEdit> contentEdit;
00477   GetContentViewerEditFromContext(aCommandContext,  getter_AddRefs(contentEdit));
00478   NS_ENSURE_TRUE(contentEdit, NS_ERROR_NOT_INITIALIZED);
00479 
00480   return DoClipboardCommand(aCommandName, contentEdit, aParams);
00481 }
00482 
00483 nsresult
00484 nsClipboardBaseCommand::GetContentViewerEditFromContext(nsISupports *aContext,
00485                                                         nsIContentViewerEdit **aEditInterface)
00486 {
00487   NS_ENSURE_ARG(aEditInterface);
00488   *aEditInterface = nsnull;
00489 
00490   nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(aContext);
00491   NS_ENSURE_TRUE(window, NS_ERROR_INVALID_ARG);
00492 
00493   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(window));
00494   NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
00495 
00496   nsIDocShell *docShell = sgo->GetDocShell();
00497   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
00498 
00499   nsCOMPtr<nsIContentViewer> viewer;
00500   docShell->GetContentViewer(getter_AddRefs(viewer));
00501   nsCOMPtr<nsIContentViewerEdit> edit(do_QueryInterface(viewer));
00502   NS_ENSURE_TRUE(edit, NS_ERROR_FAILURE);
00503 
00504   *aEditInterface = edit;
00505   NS_ADDREF(*aEditInterface);
00506   return NS_OK;
00507 }
00508 
00509 #if 0
00510 #pragma mark -
00511 #endif
00512 
00513 #define NS_DECL_CLIPBOARD_COMMAND(_cmd)                                                     \
00514 class _cmd : public nsClipboardBaseCommand                                                  \
00515 {                                                                                           \
00516 protected:                                                                                  \
00517                                                                                             \
00518   virtual nsresult    IsClipboardCommandEnabled(const char* aCommandName,                   \
00519                                   nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled);      \
00520   virtual nsresult    DoClipboardCommand(const char* aCommandName,                          \
00521                                   nsIContentViewerEdit* aEdit, nsICommandParams* aParams);  \
00522   /* no member variables, please, we're stateless! */                                       \
00523 };
00524 
00525 NS_DECL_CLIPBOARD_COMMAND(nsClipboardCopyCommand)
00526 NS_DECL_CLIPBOARD_COMMAND(nsClipboardCutCommand)
00527 NS_DECL_CLIPBOARD_COMMAND(nsClipboardPasteCommand)
00528 NS_DECL_CLIPBOARD_COMMAND(nsClipboardCopyLinkCommand)
00529 NS_DECL_CLIPBOARD_COMMAND(nsClipboardImageCommands)
00530 NS_DECL_CLIPBOARD_COMMAND(nsClipboardSelectAllNoneCommands)
00531 NS_DECL_CLIPBOARD_COMMAND(nsClipboardGetContentsCommand)
00532 
00533 #if 0
00534 #pragma mark -
00535 #endif
00536 
00537 
00538 nsresult
00539 nsClipboardCutCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
00540 {
00541   return aEdit->GetCutable(outCmdEnabled);
00542 }
00543 
00544 nsresult
00545 nsClipboardCutCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
00546 {
00547   return aEdit->CutSelection();
00548 }
00549 
00550 #if 0
00551 #pragma mark -
00552 #endif
00553 
00554 nsresult
00555 nsClipboardCopyCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
00556 {
00557   return aEdit->GetCopyable(outCmdEnabled);
00558 }
00559 
00560 nsresult
00561 nsClipboardCopyCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
00562 {
00563   return aEdit->CopySelection();
00564 }
00565 
00566 #if 0
00567 #pragma mark -
00568 #endif
00569 
00570 nsresult
00571 nsClipboardPasteCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
00572 {
00573   return aEdit->GetPasteable(outCmdEnabled);
00574 }
00575 
00576 nsresult
00577 nsClipboardPasteCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
00578 {
00579   return aEdit->Paste();
00580 }
00581 
00582 
00583 #if 0
00584 #pragma mark -
00585 #endif
00586 
00587 nsresult
00588 nsClipboardCopyLinkCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
00589 {
00590   return aEdit->GetInLink(outCmdEnabled);
00591 }
00592 
00593 nsresult
00594 nsClipboardCopyLinkCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
00595 {
00596   return aEdit->CopyLinkLocation();
00597 }
00598 
00599 #if 0
00600 #pragma mark -
00601 #endif
00602 
00603 nsresult
00604 nsClipboardImageCommands::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
00605 {
00606   return aEdit->GetInImage(outCmdEnabled);
00607 }
00608 
00609 nsresult
00610 nsClipboardImageCommands::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
00611 {
00612   if (!nsCRT::strcmp(sCopyImageLocationString, aCommandName))
00613     return aEdit->CopyImage(nsIContentViewerEdit::COPY_IMAGE_TEXT);
00614   if (!nsCRT::strcmp(sCopyImageContentsString, aCommandName))
00615     return aEdit->CopyImage(nsIContentViewerEdit::COPY_IMAGE_DATA);
00616 
00617   PRInt32 copyFlags = nsIContentViewerEdit::COPY_IMAGE_ALL;
00618   if (aParams)
00619     aParams->GetLongValue("imageCopy", &copyFlags);
00620   return aEdit->CopyImage(copyFlags);
00621 }
00622 
00623 #if 0
00624 #pragma mark -
00625 #endif
00626 
00627 nsresult
00628 nsClipboardSelectAllNoneCommands::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
00629 {
00630   *outCmdEnabled = PR_TRUE;
00631   return NS_OK;
00632 }
00633 
00634 nsresult
00635 nsClipboardSelectAllNoneCommands::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
00636 {
00637   if (!nsCRT::strcmp(sSelectAllString, aCommandName))
00638     return aEdit->SelectAll();
00639 
00640   return aEdit->ClearSelection();
00641 }
00642 
00643 
00644 #if 0
00645 #pragma mark -
00646 #endif
00647 
00648 nsresult
00649 nsClipboardGetContentsCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
00650 {
00651   return aEdit->GetCanGetContents(outCmdEnabled);
00652 }
00653 
00654 nsresult
00655 nsClipboardGetContentsCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
00656 {
00657   NS_ENSURE_ARG(aParams);
00658 
00659   nsCAutoString mimeType("text/plain");
00660 
00661   nsXPIDLCString format;    // nsICommandParams needs to use nsACString
00662   if (NS_SUCCEEDED(aParams->GetCStringValue("format", getter_Copies(format))))
00663     mimeType.Assign(format);
00664   
00665   PRBool selectionOnly = PR_FALSE;
00666   aParams->GetBooleanValue("selection_only", &selectionOnly);
00667   
00668   nsAutoString contents;
00669   nsresult rv = aEdit->GetContents(mimeType.get(), selectionOnly, contents);
00670   if (NS_FAILED(rv))
00671     return rv;
00672     
00673   return aParams->SetStringValue("result", contents);
00674 }
00675 
00676 
00677 #if 0
00678 #pragma mark -
00679 #endif
00680 
00681 class nsWebNavigationBaseCommand : public nsIControllerCommand
00682 {
00683 public:
00684 
00685   NS_DECL_ISUPPORTS
00686   NS_DECL_NSICONTROLLERCOMMAND
00687 
00688 protected:
00689 
00690   virtual nsresult    IsWebNavCommandEnabled(const char * aCommandName, nsIWebNavigation* aWebNavigation, PRBool *outCmdEnabled) = 0;
00691   virtual nsresult    DoWebNavCommand(const char *aCommandName, nsIWebNavigation* aWebNavigation) = 0;
00692   
00693   static nsresult     GetWebNavigationFromContext(nsISupports *aContext, nsIWebNavigation **aWebNavigation);
00694   
00695   // no member variables, please, we're stateless!
00696 };
00697 
00698 #if 0   // Remove unless needed again, bug 204777
00699 class nsGoForwardCommand : public nsWebNavigationBaseCommand
00700 {
00701 protected:
00702 
00703   virtual nsresult    IsWebNavCommandEnabled(const char * aCommandName, nsIWebNavigation* aWebNavigation, PRBool *outCmdEnabled);
00704   virtual nsresult    DoWebNavCommand(const char *aCommandName, nsIWebNavigation* aWebNavigation);
00705   // no member variables, please, we're stateless!
00706 };
00707 
00708 class nsGoBackCommand : public nsWebNavigationBaseCommand
00709 {
00710 protected:
00711 
00712   virtual nsresult    IsWebNavCommandEnabled(const char * aCommandName, nsIWebNavigation* aWebNavigation, PRBool *outCmdEnabled);
00713   virtual nsresult    DoWebNavCommand(const char *aCommandName, nsIWebNavigation* aWebNavigation);
00714   // no member variables, please, we're stateless!
00715 };
00716 #endif
00717 
00718 /*---------------------------------------------------------------------------
00719 
00720   nsWebNavigationCommands
00721      no params
00722 ----------------------------------------------------------------------------*/
00723 
00724 NS_IMPL_ISUPPORTS1(nsWebNavigationBaseCommand, nsIControllerCommand)
00725 
00726 NS_IMETHODIMP
00727 nsWebNavigationBaseCommand::IsCommandEnabled(const char * aCommandName,
00728                                           nsISupports *aCommandContext,
00729                                           PRBool *outCmdEnabled)
00730 {
00731   NS_ENSURE_ARG_POINTER(outCmdEnabled);
00732   *outCmdEnabled = PR_FALSE;
00733 
00734   nsCOMPtr<nsIWebNavigation> webNav;
00735   GetWebNavigationFromContext(aCommandContext, getter_AddRefs(webNav));
00736   NS_ENSURE_TRUE(webNav, NS_ERROR_INVALID_ARG);
00737   
00738   return IsCommandEnabled(aCommandName, webNav, outCmdEnabled);
00739 }
00740 
00741 NS_IMETHODIMP
00742 nsWebNavigationBaseCommand::GetCommandStateParams(const char *aCommandName,
00743                                             nsICommandParams *aParams, nsISupports *aCommandContext)
00744 {
00745   // XXX we should probably return the enabled state
00746   return NS_ERROR_NOT_IMPLEMENTED;
00747 }
00748 
00749 NS_IMETHODIMP
00750 nsWebNavigationBaseCommand::DoCommand(const char *aCommandName,
00751                                    nsISupports *aCommandContext)
00752 {
00753   nsCOMPtr<nsIWebNavigation> webNav;
00754   GetWebNavigationFromContext(aCommandContext, getter_AddRefs(webNav));
00755   NS_ENSURE_TRUE(webNav, NS_ERROR_INVALID_ARG);
00756   
00757   return DoWebNavCommand(aCommandName, webNav);
00758 }
00759 
00760 /* void doCommandParams (in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext); */
00761 NS_IMETHODIMP
00762 nsWebNavigationBaseCommand::DoCommandParams(const char *aCommandName,
00763                                        nsICommandParams *aParams, nsISupports *aCommandContext)
00764 {
00765   return DoCommand(aCommandName, aCommandContext);
00766 }
00767 
00768 nsresult
00769 nsWebNavigationBaseCommand::GetWebNavigationFromContext(nsISupports *aContext, nsIWebNavigation **aWebNavigation)
00770 {
00771   nsCOMPtr<nsIInterfaceRequestor> windowReq = do_QueryInterface(aContext);
00772   CallGetInterface(windowReq.get(), aWebNavigation);
00773   return (*aWebNavigation) ? NS_OK : NS_ERROR_FAILURE;
00774 }
00775 
00776 #if 0
00777 #pragma mark -
00778 #endif
00779 
00780 #if 0   // Remove unless needed again, bug 204777
00781 nsresult
00782 nsGoForwardCommand::IsWebNavCommandEnabled(const char * aCommandName, nsIWebNavigation* aWebNavigation, PRBool *outCmdEnabled)
00783 {
00784   return aWebNavigation->GetCanGoForward(outCmdEnabled);
00785 }
00786 
00787 nsresult
00788 nsGoForwardCommand::DoWebNavCommand(const char *aCommandName, nsIWebNavigation* aWebNavigation)
00789 {
00790   return aWebNavigation->GoForward();
00791 }
00792 
00793 nsresult
00794 nsGoBackCommand::IsWebNavCommandEnabled(const char * aCommandName, nsIWebNavigation* aWebNavigation, PRBool *outCmdEnabled)
00795 {
00796   return aWebNavigation->GetCanGoBack(outCmdEnabled);
00797 }
00798 
00799 nsresult
00800 nsGoBackCommand::DoWebNavCommand(const char *aCommandName, nsIWebNavigation* aWebNavigation)
00801 {
00802   return aWebNavigation->GoBack();
00803 }
00804 #endif
00805 
00806 /*---------------------------------------------------------------------------
00807 
00808   nsClipboardDragDropHookCommand
00809       params        value type   possible values
00810       "addhook"     isupports    nsIClipboardDragDropHooks as nsISupports
00811       "removehook"  isupports    nsIClipboardDragDropHooks as nsISupports
00812 
00813 ----------------------------------------------------------------------------*/
00814 
00815 class nsClipboardDragDropHookCommand : public nsIControllerCommand
00816 {
00817 public:
00818 
00819   NS_DECL_ISUPPORTS
00820   NS_DECL_NSICONTROLLERCOMMAND
00821 
00822 protected:                                                                                   
00823   // no member variables, please, we're stateless!
00824 };
00825 
00826 
00827 NS_IMPL_ISUPPORTS1(nsClipboardDragDropHookCommand, nsIControllerCommand)
00828 
00829 NS_IMETHODIMP
00830 nsClipboardDragDropHookCommand::IsCommandEnabled(const char * aCommandName,
00831                                                  nsISupports *aCommandContext,
00832                                                  PRBool *outCmdEnabled)
00833 {
00834   *outCmdEnabled = PR_TRUE;
00835   return NS_OK;
00836 }
00837 
00838 NS_IMETHODIMP
00839 nsClipboardDragDropHookCommand::DoCommand(const char *aCommandName,
00840                                           nsISupports *aCommandContext)
00841 {
00842   return NS_ERROR_FAILURE;
00843 }
00844 
00845 NS_IMETHODIMP
00846 nsClipboardDragDropHookCommand::DoCommandParams(const char *aCommandName,
00847                                                 nsICommandParams *aParams,
00848                                                 nsISupports *aCommandContext)
00849 {
00850   NS_ENSURE_ARG(aParams);
00851 
00852   nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(aCommandContext);
00853   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
00854   NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
00855 
00856   nsIDocShell *docShell = sgo->GetDocShell();
00857 
00858   nsCOMPtr<nsIClipboardDragDropHookList> obj = do_GetInterface(docShell);
00859   if (!obj) return NS_ERROR_INVALID_ARG;
00860 
00861   nsCOMPtr<nsISupports> isuppHook;
00862 
00863   nsresult returnValue = NS_OK;
00864   nsresult rv = aParams->GetISupportsValue("addhook", getter_AddRefs(isuppHook));
00865   if (NS_SUCCEEDED(rv))
00866   {
00867     nsCOMPtr<nsIClipboardDragDropHooks> hook = do_QueryInterface(isuppHook);
00868     if (hook)
00869       returnValue = obj->AddClipboardDragDropHooks(hook);
00870     else
00871       returnValue = NS_ERROR_INVALID_ARG;
00872   }
00873 
00874   rv = aParams->GetISupportsValue("removehook", getter_AddRefs(isuppHook));
00875   if (NS_SUCCEEDED(rv))
00876   {
00877     nsCOMPtr<nsIClipboardDragDropHooks> hook = do_QueryInterface(isuppHook);
00878     if (hook)
00879     {
00880       rv = obj->RemoveClipboardDragDropHooks(hook);
00881       if (NS_FAILED(rv) && NS_SUCCEEDED(returnValue))
00882         returnValue = rv;
00883     }
00884     else
00885       returnValue = NS_ERROR_INVALID_ARG;
00886   }
00887 
00888   return returnValue;
00889 }
00890 
00891 NS_IMETHODIMP
00892 nsClipboardDragDropHookCommand::GetCommandStateParams(const char *aCommandName,
00893                                                       nsICommandParams *aParams,
00894                                                       nsISupports *aCommandContext)
00895 {
00896   NS_ENSURE_ARG_POINTER(aParams);
00897   return aParams->SetBooleanValue("state_enabled", PR_TRUE);
00898 }
00899 
00900 /*---------------------------------------------------------------------------
00901 
00902   RegisterWindowCommands
00903 
00904 ----------------------------------------------------------------------------*/
00905 
00906 #define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName)                \
00907   {                                                                 \
00908     _cmdClass* theCmd;                                              \
00909     NS_NEWXPCOM(theCmd, _cmdClass);                                 \
00910     if (!theCmd) return NS_ERROR_OUT_OF_MEMORY;                     \
00911     rv = inCommandTable->RegisterCommand(_cmdName,                  \
00912                    NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \
00913   }
00914 
00915 #define NS_REGISTER_FIRST_COMMAND(_cmdClass, _cmdName)              \
00916   {                                                                 \
00917     _cmdClass* theCmd;                                              \
00918     NS_NEWXPCOM(theCmd, _cmdClass);                                 \
00919     if (!theCmd) return NS_ERROR_OUT_OF_MEMORY;                     \
00920     rv = inCommandTable->RegisterCommand(_cmdName,                  \
00921                    NS_STATIC_CAST(nsIControllerCommand *, theCmd));
00922 
00923 #define NS_REGISTER_NEXT_COMMAND(_cmdClass, _cmdName)               \
00924     rv = inCommandTable->RegisterCommand(_cmdName,                  \
00925                    NS_STATIC_CAST(nsIControllerCommand *, theCmd));
00926 
00927 #define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName)               \
00928     rv = inCommandTable->RegisterCommand(_cmdName,                  \
00929                    NS_STATIC_CAST(nsIControllerCommand *, theCmd)); \
00930   }
00931 
00932 
00933 // static
00934 nsresult
00935 nsWindowCommandRegistration::RegisterWindowCommands(
00936                                nsIControllerCommandTable *inCommandTable)
00937 {
00938   nsresult rv;
00939 
00940   // XXX rework the macros to use a loop is possible, reducing code size
00941   
00942   // this set of commands is affected by the 'browse with caret' setting
00943   NS_REGISTER_FIRST_COMMAND(nsSelectMoveScrollCommand, sScrollTopString);
00944   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollBottomString);
00945   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sWordPreviousString);
00946   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sWordNextString);
00947   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sBeginLineString);
00948   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sEndLineString);
00949   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sMovePageUpString);
00950   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sMovePageDownString);
00951   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollPageUpString);
00952   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollPageDownString);
00953   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollLineUpString);
00954   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollLineDownString);
00955   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollLeftString);
00956   NS_REGISTER_LAST_COMMAND(nsSelectMoveScrollCommand, sScrollRightString);
00957 
00958   NS_REGISTER_FIRST_COMMAND(nsSelectCommand, sSelectCharPreviousString);
00959   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectCharNextString);
00960   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectWordPreviousString);
00961   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectWordNextString);
00962   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectBeginLineString);
00963   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectEndLineString);
00964   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectLinePreviousString);
00965   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectLineNextString);
00966   // XXX these commands were never implemented. fix me.
00967   // NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectPagePreviousString);
00968   // NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectPageNextString);
00969   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectTopString);
00970   NS_REGISTER_LAST_COMMAND(nsSelectCommand, sSelectBottomString);
00971 
00972   NS_REGISTER_ONE_COMMAND(nsClipboardCopyCommand, "cmd_copy");
00973   NS_REGISTER_ONE_COMMAND(nsClipboardCutCommand, "cmd_cut");
00974   NS_REGISTER_ONE_COMMAND(nsClipboardPasteCommand, "cmd_paste");
00975   NS_REGISTER_ONE_COMMAND(nsClipboardCopyLinkCommand, "cmd_copyLink");
00976   NS_REGISTER_FIRST_COMMAND(nsClipboardImageCommands, sCopyImageLocationString);
00977   NS_REGISTER_NEXT_COMMAND(nsClipboardImageCommands, sCopyImageContentsString);
00978   NS_REGISTER_LAST_COMMAND(nsClipboardImageCommands, sCopyImageString);
00979   NS_REGISTER_FIRST_COMMAND(nsClipboardSelectAllNoneCommands, sSelectAllString);
00980   NS_REGISTER_LAST_COMMAND(nsClipboardSelectAllNoneCommands, sSelectNoneString);
00981 
00982   NS_REGISTER_ONE_COMMAND(nsClipboardGetContentsCommand, "cmd_getContents");
00983 
00984 #if 0   // Remove unless needed again, bug 204777
00985   NS_REGISTER_ONE_COMMAND(nsGoBackCommand, "cmd_browserBack");
00986   NS_REGISTER_ONE_COMMAND(nsGoForwardCommand, "cmd_browserForward");
00987 #endif
00988 
00989   NS_REGISTER_ONE_COMMAND(nsClipboardDragDropHookCommand, "cmd_clipboardDragDropHook");
00990 
00991   return rv;
00992 }