Index: test/keystrokes/firefox/line_nav_bug_549128.py
===================================================================
--- test/keystrokes/firefox/line_nav_bug_549128.py	(revision 4263)
+++ test/keystrokes/firefox/line_nav_bug_549128.py	(working copy)
@@ -81,9 +81,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "5. Line Down",
-    ["BUG? - Note that the braille is messed up here and on many lines that follow in this test. This is mostly an FF bug, but something we should be handling better.",
-     "BRAILLE LINE:  ''",
-     "     VISIBLE:  '', cursor=1",
+    ["BRAILLE LINE:  '  2 (5 oz.) Top Sirloins'",
+     "     VISIBLE:  '  2 (5 oz.) Top Sirloins', cursor=2",
      "SPEECH OUTPUT: '  2 (5 oz.) Top Sirloins",
      "'"]))
 
@@ -91,8 +90,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "6. Line Down",
-    ["BRAILLE LINE:  ''",
-     "     VISIBLE:  '', cursor=1",
+    ["BRAILLE LINE:  '  4 (4 oz.) Foobar Steaks Burgers'",
+     "     VISIBLE:  '  4 (4 oz.) Foobar Steaks Burger', cursor=2",
      "SPEECH OUTPUT: '  4 (4 oz.) Foobar Steaks Burgers",
      "'"]))
 
@@ -100,8 +99,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "7. Line Down",
-    ["BRAILLE LINE:  ''",
-     "     VISIBLE:  '', cursor=1",
+    ["BRAILLE LINE:  '  6 (5.75 oz.) Stuffed Baked Potatoes'",
+     "     VISIBLE:  '  6 (5.75 oz.) Stuffed Baked Pot', cursor=2",
      "SPEECH OUTPUT: '  6 (5.75 oz.) Stuffed Baked Potatoes",
      "'"]))
 
@@ -109,8 +108,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "8. Line Down",
-    ["BRAILLE LINE:  ''",
-     "     VISIBLE:  '', cursor=1",
+    ["BRAILLE LINE:  '  2 (4.5 oz.) Stuffed Sole with Scallops and Crab'",
+     "     VISIBLE:  '  2 (4.5 oz.) Stuffed Sole with ', cursor=2",
      "SPEECH OUTPUT: '  2 (4.5 oz.) Stuffed Sole with Scallops and Crab",
      "'"]))
 
@@ -118,8 +117,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "9. Line Down",
-    ["BRAILLE LINE:  ''",
-     "     VISIBLE:  '', cursor=1",
+    ["BRAILLE LINE:  '  1 (6 in.) Chocolate Lover's Cake'",
+     "     VISIBLE:  '  1 (6 in.) Chocolate Lover's Ca', cursor=2",
      "SPEECH OUTPUT: '  1 (6 in.) Chocolate Lover's Cake",
      "'"]))
 
@@ -127,8 +126,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "10. Line Down",
-    ["BRAILLE LINE:  ''",
-     "     VISIBLE:  '', cursor=1",
+    ["BRAILLE LINE:  'Regular $133.00, Now $59.99'",
+     "     VISIBLE:  'Regular $133.00, Now $59.99', cursor=2",
      "SPEECH OUTPUT: 'Regular $133.00, Now $59.99",
      "'"]))
 
@@ -153,8 +152,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "1. Line Up",
-    ["BRAILLE LINE:  'R'",
-     "     VISIBLE:  'R', cursor=1",
+    ["BRAILLE LINE:  'Regular $133.00, Now $59.99'",
+     "     VISIBLE:  'Regular $133.00, Now $59.99', cursor=1",
      "SPEECH OUTPUT: 'Regular $133.00, Now $59.99",
      "'"]))
 
@@ -162,8 +161,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "2. Line Up",
-    ["BRAILLE LINE:  ' '",
-     "     VISIBLE:  ' ', cursor=1",
+    ["BRAILLE LINE:  '  1 (6 in.) Chocolate Lover's Cake'",
+     "     VISIBLE:  '  1 (6 in.) Chocolate Lover's Ca', cursor=1",
      "SPEECH OUTPUT: '  1 (6 in.) Chocolate Lover's Cake",
      "'"]))
 
@@ -171,8 +170,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "3. Line Up",
-    ["BRAILLE LINE:  ' '",
-     "     VISIBLE:  ' ', cursor=1",
+    ["BRAILLE LINE:  '  2 (4.5 oz.) Stuffed Sole with Scallops and Crab'",
+     "     VISIBLE:  '  2 (4.5 oz.) Stuffed Sole with ', cursor=1",
      "SPEECH OUTPUT: '  2 (4.5 oz.) Stuffed Sole with Scallops and Crab",
      "'"]))
 
@@ -180,8 +179,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "4. Line Up",
-    ["BRAILLE LINE:  ' '",
-     "     VISIBLE:  ' ', cursor=1",
+    ["BRAILLE LINE:  '  6 (5.75 oz.) Stuffed Baked Potatoes'",
+     "     VISIBLE:  '  6 (5.75 oz.) Stuffed Baked Pot', cursor=1",
      "SPEECH OUTPUT: '  6 (5.75 oz.) Stuffed Baked Potatoes",
      "'"]))
 
@@ -189,8 +188,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "5. Line Up",
-    ["BRAILLE LINE:  ' '",
-     "     VISIBLE:  ' ', cursor=1",
+    ["BRAILLE LINE:  '  4 (4 oz.) Foobar Steaks Burgers'",
+     "     VISIBLE:  '  4 (4 oz.) Foobar Steaks Burger', cursor=1",
      "SPEECH OUTPUT: '  4 (4 oz.) Foobar Steaks Burgers",
      "'"]))
 
@@ -198,8 +197,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "6. Line Up",
-    ["BRAILLE LINE:  ' '",
-     "     VISIBLE:  ' ', cursor=1",
+    ["BRAILLE LINE:  '  2 (5 oz.) Top Sirloins'",
+     "     VISIBLE:  '  2 (5 oz.) Top Sirloins', cursor=1",
      "SPEECH OUTPUT: '  2 (5 oz.) Top Sirloins",
      "'"]))
 
Index: test/keystrokes/firefox/line_nav_bug_547573.py
===================================================================
--- test/keystrokes/firefox/line_nav_bug_547573.py	(revision 4263)
+++ test/keystrokes/firefox/line_nav_bug_547573.py	(working copy)
@@ -252,7 +252,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "25. Line Down",
-    ["BRAILLE LINE:  'Link  • Self-extracting Binary File - This file can be used to install the JDK in a location chosen by the user. This one can be installed by anyone (not only root users), and it can'",
+    ["BUG? - We're getting more than one line's worth",
+     "BRAILLE LINE:  'Link Install formats - This version of the JDK is available in two installation formats. • Self-extracting Binary File - This file can be used to install the JDK in a location chosen by the user. This one can be installed by anyone (not only root users), and it can'",
      "     VISIBLE:  '• Self-extracting Binary File - ', cursor=1",
      "SPEECH OUTPUT: 'link Install formats - This version of the JDK is available in two installation formats. • Self-extracting Binary File - This file can be used to install the JDK in a location chosen by the user. This one can be installed by anyone (not only root users), and it can'"]))
 
@@ -756,7 +757,7 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "87. Line Down",
-    ["BRAILLE LINE:  'Link  The RPM packages creates two links /usr/java/latest and /usr/java/default.'",
+    ["BRAILLE LINE:  'Link 5. Exit the root shell. The RPM packages creates two links /usr/java/latest and /usr/java/default.'",
      "     VISIBLE:  'The RPM packages creates two lin', cursor=1",
      "SPEECH OUTPUT: 'link 5. Exit the root shell.",
      " The RPM packages creates two links /usr/java/latest and /usr/java/default.  ",
@@ -963,8 +964,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "12. Line Up",
-    ["BRAILLE LINE:  'Link 5. Exit the root shell. '",
-     "     VISIBLE:  'Link 5. Exit the root shell. ', cursor=6",
+    ["BRAILLE LINE:  'Link 5. Exit the root shell. The RPM packages creates two links /usr/java/latest and /usr/java/default.'",
+     "     VISIBLE:  '5. Exit the root shell. The RPM ', cursor=1",
      "SPEECH OUTPUT: 'link 5. Exit the root shell.",
      " The RPM packages creates two links /usr/java/latest and /usr/java/default.  ",
      "'"]))
@@ -1054,7 +1055,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "23. Line Up",
-    ["BRAILLE LINE:  'Link 2. Become root by running the su command and entering the super-user password. Link 3. Extract and install the contents of the downloaded file. '",
+    ["BUG? - We're getting more than one line's worth",
+     "BRAILLE LINE:  'Link 2. Become root by running the su command and entering the super-user password. Link 3. Extract and install the contents of the downloaded file. Change directory to where the downloaded file is located and run these commands to first set the executable permissions and then run the binary to extract and'",
      "     VISIBLE:  '2. Become root by running the su', cursor=1",
      "SPEECH OUTPUT: 'link 2. Become root by running the su command and entering the super-user password. link 3. Extract and install the contents of the downloaded file. Change directory to where the downloaded file is located and run these commands to first set the executable permissions and then run the binary to extract and'"]))
 
@@ -1078,7 +1080,7 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "26. Line Up",
-    ["BRAILLE LINE:  'Link 1. Download and check the file size. '",
+    ["BRAILLE LINE:  'Link 1. Download and check the file size. You can download to any directory you choose.'",
      "     VISIBLE:  '1. Download and check the file s', cursor=1",
      "SPEECH OUTPUT: 'link 1. Download and check the file size. You can download to any directory you choose.'"]))
 
@@ -1433,7 +1435,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "70. Line Up",
-    ["BRAILLE LINE:  'Link Install formats - This version of the JDK is available in two installation formats. '",
+    ["BUG? - We're getting more than one line's worth",
+     "BRAILLE LINE:  'Link Install formats - This version of the JDK is available in two installation formats. • Self-extracting Binary File - This file can be used to install the JDK in a location chosen by the user. This one can be installed by anyone (not only root users), and it can'",
      "     VISIBLE:  'Install formats - This version o', cursor=1",
      "SPEECH OUTPUT: 'link Install formats - This version of the JDK is available in two installation formats. • Self-extracting Binary File - This file can be used to install the JDK in a location chosen by the user. This one can be installed by anyone (not only root users), and it can'"]))
 
Index: test/keystrokes/firefox/line_nav_enter_bug.py
===================================================================
--- test/keystrokes/firefox/line_nav_enter_bug.py	(revision 4263)
+++ test/keystrokes/firefox/line_nav_enter_bug.py	(working copy)
@@ -86,9 +86,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "Line Down",
-    ["BUG? - We're missing some info in braille",
-     "BRAILLE LINE:  'reported bugs Link  search Link  browse Link '",
-     "     VISIBLE:  'reported bugs Link  search Link ', cursor=1",
+    ["BRAILLE LINE:  'reported bugs Link , and please search Link  or browse Link  for the bug.'",
+     "     VISIBLE:  'reported bugs Link , and please ', cursor=1",
      "SPEECH OUTPUT: 'reported bugs link , and please search link  or browse link  for the bug.'"]))
 
 sequence.append(utils.StartRecordingAction())
@@ -135,9 +134,8 @@
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "Line Down",
-    ["BUG? - We're missing the colon in the braille",
-     "BRAILLE LINE:  'version Link '",
-     "     VISIBLE:  'version Link ', cursor=1",
+    ["BRAILLE LINE:  'version Link :'",
+     "     VISIBLE:  'version Link :', cursor=1",
      "SPEECH OUTPUT: 'version link :'"]))
 
 sequence.append(utils.StartRecordingAction())
@@ -461,9 +459,8 @@
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
     "Line Up",
-    ["BUG? - We're missing some info in braille",
-     "BRAILLE LINE:  'reported bugs Link  search Link  browse Link '",
-     "     VISIBLE:  'reported bugs Link  search Link ', cursor=1",
+    ["BRAILLE LINE:  'reported bugs Link , and please search Link  or browse Link  for the bug.'",
+     "     VISIBLE:  'reported bugs Link , and please ', cursor=1",
      "SPEECH OUTPUT: 'reported bugs link , and please search link  or browse link  for the bug.'"]))
 
 sequence.append(utils.StartRecordingAction())
Index: src/orca/scripts/apps/gnome-terminal.py
===================================================================
--- src/orca/scripts/apps/gnome-terminal.py	(revision 4263)
+++ src/orca/scripts/apps/gnome-terminal.py	(working copy)
@@ -269,12 +269,13 @@
             if matchFound:
                 self.echoPreviousWord(event.source)
 
-    def getTextLineAtCaret(self, acc):
+    def getTextLineAtCaret(self, acc, offset=None):
         """Gets the line of text where the caret is.
 
         Argument:
         - obj: an Accessible object that implements the AccessibleText
-               interface
+          interface
+        - offset: an optional caret offset to use.
 
         Returns the [string, caretOffset, startOffset] for the line of text
         where the caret is.
Index: src/orca/scripts/toolkits/Gecko/script.py
===================================================================
--- src/orca/scripts/toolkits/Gecko/script.py	(revision 4263)
+++ src/orca/scripts/toolkits/Gecko/script.py	(working copy)
@@ -4677,36 +4677,69 @@
 
         self._updateLineCache(obj, characterOffset)
 
-    def getTextLineAtCaret(self, obj):
-        """Gets the line of text where the caret is. This is an override to
-        accomodate the intricities of our caret navigation management.
+    def getTextLineAtCaret(self, obj, offset=None):
+        """Gets the portion of the line of text where the caret (or optional
+        offset) is. This is an override to accomodate the intricities of our
+        caret navigation management and to deal with bogus line information
+        being returned by Gecko when using getTextAtOffset.
 
         Argument:
         - obj: an Accessible object that implements the AccessibleText
-               interface
+          interface
+        - offset: an optional caret offset to use.
 
         Returns the [string, caretOffset, startOffset] for the line of text
         where the caret is.
         """
 
-        contextObj, contextCaret = self.getCaretContext()
+        # We'll let the default script handle entries and other entry-like
+        # things (e.g. the text portion of a dojo spin button).
+        #
+        isEntry = obj.getState().contains(pyatspi.STATE_EDITABLE) \
+                  or obj.getRole() in [pyatspi.ROLE_ENTRY,
+                                       pyatspi.ROLE_TEXT,
+                                       pyatspi.ROLE_PASSWORD_TEXT]
 
-        if contextObj == obj and \
-                not obj.getState().contains(pyatspi.STATE_EDITABLE):
+        if not self.inDocumentContent(obj) or isEntry:
+            return default.Script.getTextLineAtCaret(self, obj, offset)
+
+        # Find the current line.
+        #
+        contents = self.currentLineContents
+        contextObj, contextOffset = self.getCaretContext()
+        if self.findObjectOnLine(contextObj, contextOffset, contents) < 0:
+            contents = self.getLineContentsAtOffset(contextObj, contextOffset)
+
+        # Determine the caretOffset.
+        #
+        if self.isSameObject(obj, contextObj):
+            caretOffset = contextOffset
+        else:
             try:
-                ti = obj.queryText()
-            except NotImplementedError:
-                return ["", 0, 0]
+                text = obj.queryText()
+            except:
+                caretOffset = 0
             else:
-                string, startOffset, endOffset = ti.getTextAtOffset(
-                    contextCaret, pyatspi.TEXT_BOUNDARY_LINE_START)
-                caretOffset = contextCaret
-        else:
-            string, caretOffset, startOffset = \
-                default.Script.getTextLineAtCaret(self, obj)
+                caretOffset = text.caretOffset
 
+        # The reason we typically use this method is to present the contents
+        # of the current line, so our initial assumption is that the obj
+        # being passed in is also on this line. We'll try that first. We
+        # might have multiple instances of obj, in which case we'll have
+        # to consider the offset as well.
+        #
+        for content in contents:
+            candidate, startOffset, endOffset, string = content
+            if self.isSameObject(candidate, obj) \
+               and (offset is None or (startOffset <= offset <= endOffset)):
+                return string, caretOffset, startOffset
 
-        return string, caretOffset, startOffset
+        # If we're still here, obj presumably is not on this line. This
+        # shouldn't happen, but if it does we'll let the default script
+        # handle it for now.
+        #
+        #print "getTextLineAtCaret failed"
+        return default.Script.getTextLineAtCaret(self, obj, offset)
 
     def getTextAttributes(self, acc, offset, get_defaults=False):
         """Get the text attributes run for a given offset in a given accessible
Index: src/orca/default.py
===================================================================
--- src/orca/default.py	(revision 4263)
+++ src/orca/default.py	(working copy)
@@ -6591,12 +6591,14 @@
         else:
             return top.name
 
-    def getTextLineAtCaret(self, obj):
+    def getTextLineAtCaret(self, obj, offset=None):
         """Gets the line of text where the caret is.
 
         Argument:
         - obj: an Accessible object that implements the AccessibleText
-               interface
+          interface
+        - offset: an optional caret offset to use. (Not used here at the
+          moment, but needed in the Gecko script)
 
         Returns the [string, caretOffset, startOffset] for the line of text
         where the caret is.
Index: src/orca/braille.py
===================================================================
--- src/orca/braille.py	(revision 4263)
+++ src/orca/braille.py	(working copy)
@@ -475,7 +475,8 @@
         self.accessible = accessible
         if orca_state.activeScript:
             [string, self.caretOffset, self.lineOffset] = \
-                 orca_state.activeScript.getTextLineAtCaret(self.accessible)
+                 orca_state.activeScript.getTextLineAtCaret(self.accessible,
+                                                            startOffset)
         else:
             string = ""
 
@@ -527,7 +528,8 @@
         """
 
         [string, caretOffset, lineOffset] = \
-                 orca_state.activeScript.getTextLineAtCaret(self.accessible)
+                 orca_state.activeScript.getTextLineAtCaret(self.accessible,
+                                                            self.startOffset)
         string = string.decode("UTF-8")
 
         cursorOffset = min(caretOffset - lineOffset, len(string))
