Bug 714164 Restore some global window commands that were removed as part of bug 669026 because they appeared to be unused r=ehsan sr=roc
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Thu, 05 Jan 2012 21:33:41 +0000
changeset 85090 ada466fe633f21adf9266ff8d6eebcb8fe24831b
parent 85089 b0e65467c4c834dcc2209fed1f9f44bfd157dedb
child 85091 ae1c4efbfb4911180f128d6da7dc408b2de26d59
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, roc
bugs714164, 669026
milestone12.0a1
Bug 714164 Restore some global window commands that were removed as part of bug 669026 because they appeared to be unused r=ehsan sr=roc
content/base/public/nsISelectionController.idl
content/html/content/src/nsTextEditorState.cpp
dom/base/nsGlobalWindowCommands.cpp
editor/libeditor/base/tests/test_selection_move_commands.xul
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
--- a/content/base/public/nsISelectionController.idl
+++ b/content/base/public/nsISelectionController.idl
@@ -46,17 +46,17 @@
 typedef short SelectionType;
 typedef short SelectionRegion;
 %}
 
 interface nsIDOMNode;
 interface nsISelection;
 interface nsISelectionDisplay;
 
-[scriptable, uuid(e0dd9365-470b-4ee8-b644-54add1c4c73f)]
+[scriptable, uuid(cf30315f-b65d-44c3-8c57-557e36d18fd2)]
 interface nsISelectionController : nsISelectionDisplay
 {
    const short SELECTION_NONE=0;
    const short SELECTION_NORMAL=1;
    const short SELECTION_SPELLCHECK=2;
    const short SELECTION_IME_RAWINPUT=4;
    const short SELECTION_IME_SELECTEDRAWTEXT=8;
    const short SELECTION_IME_CONVERTEDTEXT=16;
@@ -253,20 +253,21 @@ interface nsISelectionController : nsISe
    */
     void scrollPage(in boolean forward);
 
   /** ScrolLine will scroll line up or down dependent on the boolean
    *  @param aForward scroll forward or backwards in selection
    */
 	  void scrollLine(in boolean forward);
 
-  /** ScrolHorizontal will scroll left or right dependent on the boolean
-   *  @param aLeft if true will scroll left. if not will scroll right.
+  /** ScrollCharacter will scroll right or left dependent on the boolean
+   *  @param aRight if true will scroll right. if not will scroll left.
    */
-	  void scrollHorizontal(in boolean left);
+    void scrollCharacter(in boolean right);
+
   /** SelectAll will select the whole page
    */
     void selectAll();
 
   /** CheckVisibility will return true if textnode and offsets are actually rendered 
    *  in the current precontext.
    *  @param aNode textNode to test
    *  @param aStartOffset  offset in dom to first char of textnode to test
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -209,17 +209,17 @@ public:
   NS_IMETHOD WordExtendForDelete(bool aForward);
   NS_IMETHOD LineMove(bool aForward, bool aExtend);
   NS_IMETHOD IntraLineMove(bool aForward, bool aExtend);
   NS_IMETHOD PageMove(bool aForward, bool aExtend);
   NS_IMETHOD CompleteScroll(bool aForward);
   NS_IMETHOD CompleteMove(bool aForward, bool aExtend);
   NS_IMETHOD ScrollPage(bool aForward);
   NS_IMETHOD ScrollLine(bool aForward);
-  NS_IMETHOD ScrollHorizontal(bool aLeft);
+  NS_IMETHOD ScrollCharacter(bool aRight);
   NS_IMETHOD SelectAll(void);
   NS_IMETHOD CheckVisibility(nsIDOMNode *node, PRInt16 startOffset, PRInt16 EndOffset, bool *_retval);
 
 private:
   nsRefPtr<nsFrameSelection> mFrameSelection;
   nsCOMPtr<nsIContent>       mLimiter;
   nsIScrollableFrame        *mScrollFrame;
   nsWeakPtr mPresShellWeak;
@@ -568,22 +568,22 @@ nsTextInputSelectionImpl::ScrollLine(boo
 
   mScrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1),
                          nsIScrollableFrame::LINES,
                          nsIScrollableFrame::SMOOTH);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsTextInputSelectionImpl::ScrollHorizontal(bool aLeft)
+nsTextInputSelectionImpl::ScrollCharacter(bool aRight)
 {
   if (!mScrollFrame)
     return NS_ERROR_NOT_INITIALIZED;
 
-  mScrollFrame->ScrollBy(nsIntPoint(aLeft ? -1 : 1, 0),
+  mScrollFrame->ScrollBy(nsIntPoint(aRight ? 1 : -1, 0),
                          nsIScrollableFrame::LINES,
                          nsIScrollableFrame::SMOOTH);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::SelectAll()
 {
--- a/dom/base/nsGlobalWindowCommands.cpp
+++ b/dom/base/nsGlobalWindowCommands.cpp
@@ -71,16 +71,20 @@ const char * const sSelectNoneString = "
 const char * const sCopyImageLocationString = "cmd_copyImageLocation";
 const char * const sCopyImageContentsString = "cmd_copyImageContents";
 const char * const sCopyImageString = "cmd_copyImage";
 
 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 sScrollLineUpString = "cmd_scrollLineUp";
+const char * const sScrollLineDownString = "cmd_scrollLineDown";
+const char * const sScrollLeftString = "cmd_scrollLeft";
+const char * const sScrollRightString = "cmd_scrollRight";
 const char * const sMoveTopString = "cmd_moveTop";
 const char * const sMoveBottomString = "cmd_moveBottom";
 const char * const sMovePageUpString = "cmd_movePageUp";
 const char * const sMovePageDownString = "cmd_movePageDown";
 const char * const sLinePreviousString = "cmd_linePrevious";
 const char * const sLineNextString = "cmd_lineNext";
 const char * const sCharPreviousString = "cmd_charPrevious";
 const char * const sCharNextString = "cmd_charNext";
@@ -116,50 +120,44 @@ const char * const sSelectBottomString =
 #endif
 
 // a base class for selection-related commands, for code sharing
 class nsSelectionCommandsBase : public nsIControllerCommand
 {
 public:
 
   NS_DECL_ISUPPORTS
-  NS_DECL_NSICONTROLLERCOMMAND
+  NS_IMETHOD IsCommandEnabled(const char * aCommandName, nsISupports *aCommandContext, bool *_retval NS_OUTPARAM);
+  NS_IMETHOD GetCommandStateParams(const char * aCommandName, nsICommandParams *aParams, nsISupports *aCommandContext);
+  NS_IMETHOD DoCommandParams(const char * aCommandName, nsICommandParams *aParams, nsISupports *aCommandContext);
 
 protected:
 
-  // subclasses override DoSelectCommand
-  virtual nsresult DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow) = 0;
-
-  static nsresult  GetPresShellFromWindow(nsIDOMWindow *aWindow, nsIPresShell **aPresShell);
-  static nsresult  GetSelectionControllerFromWindow(nsIDOMWindow *aWindow, nsISelectionController **aSelCon);
+  static nsresult  GetPresShellFromWindow(nsPIDOMWindow *aWindow, nsIPresShell **aPresShell);
+  static nsresult  GetSelectionControllerFromWindow(nsPIDOMWindow *aWindow, nsISelectionController **aSelCon);
 
   // no member variables, please, we're stateless!
 };
 
 // this class implements commands whose behavior depends on the 'browse with caret' setting
 class nsSelectMoveScrollCommand : public nsSelectionCommandsBase
 {
-protected:
+public:
 
-  virtual nsresult DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow);
-  
-  nsresult    DoCommandBrowseWithCaretOn(const char *aCommandName,
-                                         nsIDOMWindow *aWindow,
-                                         nsISelectionController *aSelectionController);
-  nsresult    DoCommandBrowseWithCaretOff(const char *aCommandName, nsISelectionController *aSelectionController);
+  NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandContext);
 
   // no member variables, please, we're stateless!
 };
 
 // this class implements other selection commands
 class nsSelectCommand : public nsSelectionCommandsBase
 {
-protected:
+public:
 
-  virtual nsresult DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow);
+  NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandContext);
 
   // no member variables, please, we're stateless!
 };
 
 #if 0
 #pragma mark -
 #endif
 
@@ -182,223 +180,147 @@ nsSelectionCommandsBase::IsCommandEnable
 NS_IMETHODIMP
 nsSelectionCommandsBase::GetCommandStateParams(const char *aCommandName,
                                             nsICommandParams *aParams, nsISupports *aCommandContext)
 {
   // XXX we should probably return the enabled state
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP
-nsSelectionCommandsBase::DoCommand(const char *aCommandName, nsISupports *aCommandContext)
-{
-  nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(aCommandContext);
-  NS_ENSURE_TRUE(window, NS_ERROR_INVALID_ARG);       
-
-  return DoSelectCommand(aCommandName, window);
-}
-
 /* void doCommandParams (in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext); */
 NS_IMETHODIMP
 nsSelectionCommandsBase::DoCommandParams(const char *aCommandName,
                                        nsICommandParams *aParams, nsISupports *aCommandContext)
 {
   return DoCommand(aCommandName, aCommandContext);
 }
 
 // protected methods
 
 nsresult
-nsSelectionCommandsBase::GetPresShellFromWindow(nsIDOMWindow *aWindow, nsIPresShell **aPresShell)
+nsSelectionCommandsBase::GetPresShellFromWindow(nsPIDOMWindow *aWindow, nsIPresShell **aPresShell)
 {
   *aPresShell = nsnull;
+  NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aWindow));
-  NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
-
-  nsIDocShell *docShell = win->GetDocShell();
+  nsIDocShell *docShell = aWindow->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
   return docShell->GetPresShell(aPresShell);
 }
 
 nsresult
-nsSelectionCommandsBase::GetSelectionControllerFromWindow(nsIDOMWindow *aWindow, nsISelectionController **aSelCon)
+nsSelectionCommandsBase::GetSelectionControllerFromWindow(nsPIDOMWindow *aWindow, nsISelectionController **aSelCon)
 {
   *aSelCon = nsnull;
 
   nsCOMPtr<nsIPresShell> presShell;
   GetPresShellFromWindow(aWindow, getter_AddRefs(presShell));
   if (presShell)
     return CallQueryInterface(presShell, aSelCon);
 
   return NS_ERROR_FAILURE;
 }
 
 #if 0
 #pragma mark -
 #endif
 
+static const struct {
+  const char *reverse, *forward;
+  nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
+  nsresult (NS_STDCALL nsISelectionController::*move)(bool, bool);
+} browseCommands[] = {
+ { sScrollTopString, sScrollBottomString,
+   &nsISelectionController::CompleteScroll },
+ { sScrollPageUpString, sScrollPageDownString,
+   &nsISelectionController::ScrollPage },
+ { sScrollLineUpString, sScrollLineDownString,
+   &nsISelectionController::ScrollLine },
+ { sScrollLeftString, sScrollRightString,
+   &nsISelectionController::ScrollCharacter },
+ { sMoveTopString, sMoveBottomString,
+   &nsISelectionController::CompleteScroll,
+   &nsISelectionController::CompleteMove },
+ { sMovePageUpString, sMovePageDownString,
+   &nsISelectionController::ScrollPage,
+   &nsISelectionController::PageMove },
+ { sLinePreviousString, sLineNextString,
+   &nsISelectionController::ScrollLine,
+   &nsISelectionController::LineMove },
+ { sWordPreviousString, sWordNextString,
+   &nsISelectionController::ScrollCharacter,
+   &nsISelectionController::WordMove },
+ { sCharPreviousString, sCharNextString,
+   &nsISelectionController::ScrollCharacter,
+   &nsISelectionController::CharacterMove },
+ { sBeginLineString, sEndLineString,
+   &nsISelectionController::CompleteScroll,
+   &nsISelectionController::IntraLineMove }
+};
+
 nsresult
-nsSelectMoveScrollCommand::DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow)
+nsSelectMoveScrollCommand::DoCommand(const char *aCommandName, nsISupports *aCommandContext)
 {
+  nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(aCommandContext));
   nsCOMPtr<nsISelectionController> selCont;
-  GetSelectionControllerFromWindow(aWindow, getter_AddRefs(selCont));
+  GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont));
   NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);       
 
   // We allow the caret to be moved with arrow keys on any window for which
   // the caret is enabled. In particular, this includes caret-browsing mode
   // in non-chrome documents.
   bool caretOn = false;
   selCont->GetCaretEnabled(&caretOn);
   if (!caretOn) {
     caretOn = Preferences::GetBool("accessibility.browsewithcaret");
     if (caretOn) {
-      nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(aWindow);
-      if (piWindow) {
-        nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(piWindow->GetDocShell());
-        if (dsti) {
-          PRInt32 itemType;
-          dsti->GetItemType(&itemType);
-          if (itemType == nsIDocShellTreeItem::typeChrome) {
-            caretOn = false;
-          }
+      nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(piWindow->GetDocShell());
+      if (dsti) {
+        PRInt32 itemType;
+        dsti->GetItemType(&itemType);
+        if (itemType == nsIDocShellTreeItem::typeChrome) {
+          caretOn = false;
         }
       }
     }
   }
 
-  if (caretOn) {
-    return DoCommandBrowseWithCaretOn(aCommandName, aWindow, selCont);
-  }
-
-  return DoCommandBrowseWithCaretOff(aCommandName, selCont);
-}
-
-nsresult
-nsSelectMoveScrollCommand::DoCommandBrowseWithCaretOn(const char *aCommandName,
-                  nsIDOMWindow *aWindow, nsISelectionController *aSelectionController)
-{
-  nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
-
-  // cmd_MoveTop/Bottom are used on Window/Unix. They move the caret
-  // in caret browsing mode.
-  if (!nsCRT::strcmp(aCommandName, sMoveTopString))
-    rv = aSelectionController->CompleteMove(false, false);
-  else if (!nsCRT::strcmp(aCommandName,sMoveBottomString))
-    rv = aSelectionController->CompleteMove(true, false);
-  // cmd_ScrollTop/Bottom are used on Mac. They do not move the
-  // caret in caret browsing mode.
-  else if (!nsCRT::strcmp(aCommandName, sScrollTopString))
-    rv = aSelectionController->CompleteScroll(false);
-  else if (!nsCRT::strcmp(aCommandName,sScrollBottomString))
-    rv = aSelectionController->CompleteScroll(true);
-  // cmd_MovePageUp/Down are used on Window/Unix. They move the caret
-  // in caret browsing mode.
-  else if (!nsCRT::strcmp(aCommandName, sMovePageUpString))
-    rv = aSelectionController->PageMove(false, false);
-  else if (!nsCRT::strcmp(aCommandName, sMovePageDownString))
-    rv = aSelectionController->PageMove(true, false);
-  // cmd_ScrollPageUp/Down are used on Mac, and for the spacebar on all platforms.
-  // They do not move the caret in caret browsing mode.
-  else if (!nsCRT::strcmp(aCommandName, sScrollPageUpString))
-    rv = aSelectionController->ScrollPage(false);
-  else if (!nsCRT::strcmp(aCommandName, sScrollPageDownString))
-    rv = aSelectionController->ScrollPage(true);
-  else if (!nsCRT::strcmp(aCommandName, sLinePreviousString))
-    rv = aSelectionController->LineMove(false, false);
-  else if (!nsCRT::strcmp(aCommandName, sLineNextString))
-    rv = aSelectionController->LineMove(true, false);
-  else if (!nsCRT::strcmp(aCommandName, sWordPreviousString))
-    rv = aSelectionController->WordMove(false, false);
-  else if (!nsCRT::strcmp(aCommandName, sWordNextString))
-    rv = aSelectionController->WordMove(true, false);
-  else if (!nsCRT::strcmp(aCommandName, sCharPreviousString))
-    rv = aSelectionController->CharacterMove(false, false);
-  else if (!nsCRT::strcmp(aCommandName, sCharNextString))
-    rv = aSelectionController->CharacterMove(true, false);
-  else if (!nsCRT::strcmp(aCommandName, sBeginLineString))
-    rv = aSelectionController->IntraLineMove(false, false);
-  else if (!nsCRT::strcmp(aCommandName, sEndLineString))
-    rv = aSelectionController->IntraLineMove(true, false);
-
-  if (NS_SUCCEEDED(rv))
-  {
-    // adjust the focus to the new caret position
-    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
-    if (fm) {
-      nsCOMPtr<nsIDOMElement> result;
-      fm->MoveFocus(aWindow, nsnull, nsIFocusManager::MOVEFOCUS_CARET,
-                    nsIFocusManager::FLAG_NOSCROLL,
-                    getter_AddRefs(result));
+  for (int i = 0; i < mozilla::ArrayLength(browseCommands); i++) {
+    bool forward = !strcmp(aCommandName, browseCommands[i].forward);
+    if (forward || !strcmp(aCommandName, browseCommands[i].reverse)) {
+      if (caretOn && browseCommands[i].move &&
+          NS_SUCCEEDED((selCont->*(browseCommands[i].move))(forward, false))) {
+        // adjust the focus to the new caret position
+        nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+        if (fm) {
+          nsCOMPtr<nsIDOMElement> result;
+          fm->MoveFocus(piWindow, nsnull, nsIFocusManager::MOVEFOCUS_CARET,
+                        nsIFocusManager::FLAG_NOSCROLL,
+                        getter_AddRefs(result));
+        }
+        return NS_OK;
+      }
+      return (selCont->*(browseCommands[i].scroll))(forward);
     }
   }
-
-  return rv;
-}
-
-nsresult
-nsSelectMoveScrollCommand::DoCommandBrowseWithCaretOff(const char *aCommandName, nsISelectionController *aSelectionController)
-{
-  nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
-
-  // cmd_MoveTop/Bottom are used on Window/Unix. They move the caret
-  // in caret browsing mode.
-  if (!nsCRT::strcmp(aCommandName, sMoveTopString))
-    rv = aSelectionController->CompleteScroll(false);
-  else if (!nsCRT::strcmp(aCommandName,sMoveBottomString))
-    rv = aSelectionController->CompleteScroll(true);
-  // cmd_ScrollTop/Bottom are used on Mac. They do not move the
-  // caret in caret browsing mode.
-  else if (!nsCRT::strcmp(aCommandName, sScrollTopString))
-    rv = aSelectionController->CompleteScroll(false);
-  else if (!nsCRT::strcmp(aCommandName,sScrollBottomString))
-    rv = aSelectionController->CompleteScroll(true);
-
-  // cmd_MovePageUp/Down are used on Window/Unix. They move the caret
-  // in caret browsing mode.
-  else if (!nsCRT::strcmp(aCommandName, sMovePageUpString))
-    rv = aSelectionController->ScrollPage(false);
-  else if (!nsCRT::strcmp(aCommandName, sMovePageDownString))
-    rv = aSelectionController->ScrollPage(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 = aSelectionController->ScrollPage(false);
-  else if (!nsCRT::strcmp(aCommandName, sScrollPageDownString))
-    rv = aSelectionController->ScrollPage(true);
-
-  else if (!nsCRT::strcmp(aCommandName, sLinePreviousString))
-    rv = aSelectionController->ScrollLine(false);
-  else if (!nsCRT::strcmp(aCommandName, sLineNextString))
-    rv = aSelectionController->ScrollLine(true);
-  else if (!nsCRT::strcmp(aCommandName, sCharPreviousString))
-    rv = aSelectionController->ScrollHorizontal(true);
-  else if (!nsCRT::strcmp(aCommandName, sCharNextString))
-    rv = aSelectionController->ScrollHorizontal(false);
-  // cmd_beginLine/endLine with caret browsing off
-  // will act as cmd_moveTop/Bottom
-  else if (!nsCRT::strcmp(aCommandName, sBeginLineString))
-    rv = aSelectionController->CompleteScroll(false);
-  else if (!nsCRT::strcmp(aCommandName, sEndLineString))
-    rv = aSelectionController->CompleteScroll(true);
-
-  return rv;
+  return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 #if 0
 #pragma mark -
 #endif
 
 nsresult
-nsSelectCommand::DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow)
+nsSelectCommand::DoCommand(const char *aCommandName, nsISupports *aCommandContext)
 {
+  nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(aCommandContext));
   nsCOMPtr<nsISelectionController> selCont;
-  GetSelectionControllerFromWindow(aWindow, getter_AddRefs(selCont));
+  GetSelectionControllerFromWindow(piWindow, getter_AddRefs(selCont));
   NS_ENSURE_TRUE(selCont, NS_ERROR_NOT_INITIALIZED);       
 
   nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
 
   // These commands are so the browser can use caret navigation key bindings -
   // Helps with accessibility - aaronl@netscape.com
   if (!nsCRT::strcmp(aCommandName, sSelectCharPreviousString))
     rv = selCont->CharacterMove(false, true);
@@ -963,26 +885,30 @@ nsWindowCommandRegistration::RegisterWin
 {
   nsresult rv;
 
   // XXX rework the macros to use a loop is possible, reducing code size
   
   // this set of commands is affected by the 'browse with caret' setting
   NS_REGISTER_FIRST_COMMAND(nsSelectMoveScrollCommand, sScrollTopString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollBottomString);
+  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollPageUpString);
+  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollPageDownString);
+  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollLineUpString);
+  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollLineDownString);
+  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollLeftString);
+  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollRightString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sMoveTopString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sMoveBottomString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sWordPreviousString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sWordNextString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sBeginLineString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sEndLineString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sMovePageUpString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sMovePageDownString);
-  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollPageUpString);
-  NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollPageDownString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sLinePreviousString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sLineNextString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sCharPreviousString);
   NS_REGISTER_LAST_COMMAND(nsSelectMoveScrollCommand, sCharNextString);
 
   NS_REGISTER_FIRST_COMMAND(nsSelectCommand, sSelectCharPreviousString);
   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectCharNextString);
   NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectWordPreviousString);
--- a/editor/libeditor/base/tests/test_selection_move_commands.xul
+++ b/editor/libeditor/base/tests/test_selection_move_commands.xul
@@ -118,16 +118,26 @@ function execTests() {
   var pageHeight = -root.getBoundingClientRect().top;
   ok(pageHeight > 0, "cmd_scrollPageDown works");
   ok(pageHeight <= 100, "cmd_scrollPageDown doesn't scroll too much");
   doCommand("cmd_scrollBottom");
   doCommand("cmd_scrollPageUp");
   yield;
   testScrollCommand("cmd_scrollPageUp", root.scrollHeight - 100 - pageHeight);
 
+  doCommand("cmd_scrollTop");
+  doCommand("cmd_scrollLineDown");
+  yield;
+  var lineHeight = -root.getBoundingClientRect().top;
+  ok(lineHeight > 0, "Can scroll by lines");
+  doCommand("cmd_scrollBottom");
+  doCommand("cmd_scrollLineUp");
+  yield;
+  testScrollCommand("cmd_scrollLineUp", root.scrollHeight - 100 - lineHeight);
+
   var runSelectionTests = function(selectWordNextNode, selectWordNextOffset) {
     testMoveCommand("cmd_moveBottom", body, 23);
     testMoveCommand("cmd_moveTop", node(0), 0);
     testSelectCommand("cmd_selectBottom", body, 23);
     doCommand("cmd_moveBottom");
     testSelectCommand("cmd_selectTop", node(0), 0);
 
     doCommand("cmd_moveTop");
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2501,22 +2501,22 @@ PresShell::ScrollLine(bool aForward)
     if (viewManager) {
       viewManager->ForceUpdate();
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresShell::ScrollHorizontal(bool aLeft)
+PresShell::ScrollCharacter(bool aRight)
 {
   nsIScrollableFrame* scrollFrame =
     GetFrameToScrollAsScrollable(nsIPresShell::eHorizontal);
   if (scrollFrame) {
-    scrollFrame->ScrollBy(nsIntPoint(aLeft ? -1 : 1, 0),
+    scrollFrame->ScrollBy(nsIntPoint(aRight ? 1 : -1, 0),
                           nsIScrollableFrame::LINES,
                           nsIScrollableFrame::SMOOTH);
 //NEW FOR LINES    
     // force the update to happen now, otherwise multiple scrolls can
     // occur before the update is processed. (bug #7354)
 
   // I'd use Composite here, but it doesn't always work.
     // vm->Composite();
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -355,17 +355,17 @@ public:
   NS_IMETHOD CharacterExtendForBackspace();
   NS_IMETHOD WordMove(bool aForward, bool aExtend);
   NS_IMETHOD WordExtendForDelete(bool aForward);
   NS_IMETHOD LineMove(bool aForward, bool aExtend);
   NS_IMETHOD IntraLineMove(bool aForward, bool aExtend);
   NS_IMETHOD PageMove(bool aForward, bool aExtend);
   NS_IMETHOD ScrollPage(bool aForward);
   NS_IMETHOD ScrollLine(bool aForward);
-  NS_IMETHOD ScrollHorizontal(bool aLeft);
+  NS_IMETHOD ScrollCharacter(bool aRight);
   NS_IMETHOD CompleteScroll(bool aForward);
   NS_IMETHOD CompleteMove(bool aForward, bool aExtend);
   NS_IMETHOD SelectAll();
   NS_IMETHOD CheckVisibility(nsIDOMNode *node, PRInt16 startOffset, PRInt16 EndOffset, bool *_retval);
 
   // nsIDocumentObserver
   NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE
   NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE