Index: src/orca/Gecko.py
===================================================================
--- src/orca/Gecko.py	(revision 2248)
+++ src/orca/Gecko.py	(working copy)
@@ -3326,15 +3326,17 @@
 
         return nextObj
 
-    def findPreviousRole(self, roles):
+    def findPreviousRole(self, roles, currentObj=None):
         """Finds the caret offset at the beginning of the next object
         using the given roles list as a pattern to match.
 
         Arguments:
         -roles: a list of roles from rolenames.py
+        -currentObj: the object from which the search should begin
         """
 
-        [currentObj, characterOffset] = self.getCaretContext()
+        if not currentObj:
+            [currentObj, characterOffset] = self.getCaretContext()
 
         ancestors = []
         nestableRoles = [rolenames.ROLE_LIST, rolenames.ROLE_TABLE]
@@ -3351,23 +3353,23 @@
             if ((not obj in ancestors) or isNestedItem) \
                and (obj.role in roles) \
                and (not self.isLayoutOnly(obj)):
-                return self.findFirstCaretContext(obj, 0)
+                return obj
             else:
                 obj = self.findPreviousObject(obj)
 
-        return [None, -1]
+        return None
 
-    def findNextRole(self, roles):
+    def findNextRole(self, roles, currentObj=None):
         """Finds the caret offset at the beginning of the next object
         using the given roles list as a pattern to match or not match.
 
         Arguments:
         -roles: a list of roles from rolenames.py
-        -match: if True, the found object will have a role from roles;
-                if False, the found object will not have a role from roles
+        -currentObj: the object from which the search should begin
         """
 
-        [currentObj, characterOffset] = self.getCaretContext()
+        if not currentObj:
+            [currentObj, characterOffset] = self.getCaretContext()
 
         ancestors = []
         obj = currentObj.parent
@@ -3379,11 +3381,11 @@
         while obj:
             if (not obj in ancestors) and (obj.role in roles) \
                 and (not self.isLayoutOnly(obj)):
-                return self.findFirstCaretContext(obj, 0)
+                return obj
             else:
                 obj = self.findNextObject(obj)
 
-        return [None, -1]
+        return None
 
     ####################################################################
     #                                                                  #
@@ -4081,8 +4083,7 @@
         #self.dumpContents(inputEvent, contents)
 
     def goPreviousHeading(self, inputEvent):
-        [obj, characterOffset] = self.findPreviousRole(
-            [rolenames.ROLE_HEADING])
+        obj = self.findPreviousRole([rolenames.ROLE_HEADING])
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4096,7 +4097,7 @@
             speech.speak(_("No more headings."))
 
     def goNextHeading(self, inputEvent):
-        [obj, characterOffset] = self.findNextRole([rolenames.ROLE_HEADING])
+        obj = self.findNextRole([rolenames.ROLE_HEADING])
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4116,8 +4117,8 @@
         if obj.parent.role == rolenames.ROLE_HEADING:
             obj = obj.parent
         while obj and not found:
-            obj = self.findPreviousObject(obj)
-            if obj and (obj.role == rolenames.ROLE_HEADING):
+            obj = self.findPreviousRole([rolenames.ROLE_HEADING], obj)
+            if obj:
                 level = self.getHeadingLevel(obj)
                 if level == desiredLevel:
                     found = True
@@ -4138,8 +4139,8 @@
         level = 0
         [obj, characterOffset] = self.getCaretContext()
         while obj and not found:
-            obj = self.findNextObject(obj)
-            if obj and (obj.role == rolenames.ROLE_HEADING):
+            obj = self.findNextRole([rolenames.ROLE_HEADING], obj)
+            if obj:
                 level = self.getHeadingLevel(obj)
                 if level == desiredLevel:
                     found = True
@@ -4192,7 +4193,7 @@
         self.goPreviousHeadingAtLevel(inputEvent, 6)
 
     def goPreviousChunk(self, inputEvent):
-        [obj, characterOffset] = self.findPreviousRole(OBJECT_ROLES)
+        obj = self.findPreviousRole(OBJECT_ROLES)
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4207,7 +4208,7 @@
             speech.speak(_("No more large objects."))
 
     def goNextChunk(self, inputEvent):
-        [obj, characterOffset] = self.findNextRole(OBJECT_ROLES)
+        obj = self.findNextRole(OBJECT_ROLES)
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4222,15 +4223,22 @@
             speech.speak(_("No more large objects."))
 
     def goPreviousList(self, inputEvent):
-        [obj, characterOffset] = self.findPreviousRole([rolenames.ROLE_LIST])
+        [obj, characterOffset] = self.getCaretContext()
+        found = False
+        while obj and not found:
+            obj = self.findPreviousRole([rolenames.ROLE_LIST], obj)
+            # We need to be sure that the list in question is an (un)ordered
+            # list rather than a list in a form field. Form field lists are
+            # focusable; (un)ordered lists are not.
+            #
+            if obj and \
+               not (obj.state.count(atspi.Accessibility.STATE_FOCUSABLE)):
+                found = True
+
         if obj:
-            [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
-            parent = obj.parent
-            while parent.role != rolenames.ROLE_LIST:
-                parent = parent.parent
             nItems = 0
-            for i in range(0, parent.childCount):
-                if parent.child(i).role == rolenames.ROLE_LIST_ITEM:
+            for i in range(0, obj.childCount):
+                if obj.child(i).role == rolenames.ROLE_LIST_ITEM:
                     nItems += 1
             # Translators: this represents a list in HTML.
             #
@@ -4239,7 +4247,8 @@
                                   nItems) % nItems
             speech.speak(itemString)
             nestingLevel = 0
-            while parent.parent.role == rolenames.ROLE_LIST:
+            parent = obj.parent
+            while parent.role == rolenames.ROLE_LIST:
                 nestingLevel += 1
                 parent = parent.parent
             if nestingLevel:
@@ -4249,6 +4258,7 @@
                 # that's inside another list).
                 #
                 speech.speak(_("Nesting level %d") % nestingLevel)
+            [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
             self.updateBraille(obj)
             self.speakContents(self.getLineContentsAtOffset(obj,
@@ -4260,26 +4270,42 @@
             speech.speak(_("No more lists."))
 
     def goNextList(self, inputEvent):
-        [obj, characterOffset] = self.findNextRole([rolenames.ROLE_LIST])
+        [obj, characterOffset] = self.getCaretContext()
+        found = False
+        while obj and not found:
+            obj = self.findNextRole([rolenames.ROLE_LIST], obj)
+            # We need to be sure that the list in question is an (un)ordered
+            # list rather than a list in a form field. Form field lists are
+            # focusable; (un)ordered lists are not.
+            #
+            if obj and \
+               not (obj.state.count(atspi.Accessibility.STATE_FOCUSABLE)):
+                found = True
+
         if obj:
-            [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
-            parent = obj.parent
-            while parent.role != rolenames.ROLE_LIST:
-                parent = parent.parent
             nItems = 0
-            for i in range(0, parent.childCount):
-                if parent.child(i).role == rolenames.ROLE_LIST_ITEM:
+            for i in range(0, obj.childCount):
+                if obj.child(i).role == rolenames.ROLE_LIST_ITEM:
                     nItems += 1
+            # Translators: this represents a list in HTML.
+            #
             itemString = ngettext("List with %d item",
                                   "List with %d items",
                                   nItems) % nItems
             speech.speak(itemString)
             nestingLevel = 0
-            while parent.parent.role == rolenames.ROLE_LIST:
+            parent = obj.parent
+            while parent.role == rolenames.ROLE_LIST:
                 nestingLevel += 1
                 parent = parent.parent
             if nestingLevel:
+                # Translators: this represents a list item in HTML.
+                # The nesting level is how 'deep' the item is (e.g.,
+                # a level of 2 represents a list item inside a list
+                # that's inside another list).
+                #
                 speech.speak(_("Nesting level %d") % nestingLevel)
+            [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
             self.updateBraille(obj)
             self.speakContents(self.getLineContentsAtOffset(obj,
@@ -4291,8 +4317,7 @@
             speech.speak(_("No more lists."))
 
     def goPreviousListItem(self, inputEvent):
-        [obj, characterOffset] = self.findPreviousRole(
-            [rolenames.ROLE_LIST_ITEM])
+        obj = self.findPreviousRole([rolenames.ROLE_LIST_ITEM])
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4307,7 +4332,7 @@
             speech.speak(_("No more list items."))
 
     def goNextListItem(self, inputEvent):
-        [obj, characterOffset] = self.findNextRole([rolenames.ROLE_LIST_ITEM])
+        obj = self.findNextRole([rolenames.ROLE_LIST_ITEM])
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4326,18 +4351,18 @@
         # already started out on a link and need to move off of
         # it else we'll get stuck.
         #
-        [currentObj, characterOffset] = self.getCaretContext()
-        containingLink = self.getContainingLink(currentObj)
+        [obj, characterOffset] = self.getCaretContext()
+        containingLink = self.getContainingLink(obj)
         if containingLink:
-            obj = self.findPreviousObject(containingLink)
-        else:
-            obj = self.findPreviousObject(currentObj)
+            obj = containingLink
 
-        while obj and \
-              (obj.role != rolenames.ROLE_LINK or \
-               (obj.role == rolenames.ROLE_LINK and \
-                obj.state.count(atspi.Accessibility.STATE_VISITED))):
-            obj = self.findPreviousObject(obj)
+        found = False
+        while obj and not found:
+            obj = self.findPreviousRole([rolenames.ROLE_LINK], obj)
+            if obj and \
+               not obj.state.count(atspi.Accessibility.STATE_VISITED):
+                found = True
+
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4352,12 +4377,13 @@
 
     def goNextUnvisitedLink(self, inputEvent):
         [obj, characterOffset] = self.getCaretContext()
-        obj = self.findNextObject(obj)
-        while obj and \
-              (obj.role != rolenames.ROLE_LINK or \
-               (obj.role == rolenames.ROLE_LINK and \
-                obj.state.count(atspi.Accessibility.STATE_VISITED))):
-            obj = self.findNextObject(obj)
+        found = False
+        while obj and not found:
+            obj = self.findNextRole([rolenames.ROLE_LINK], obj)
+            if obj and \
+               not obj.state.count(atspi.Accessibility.STATE_VISITED):
+                found = True
+
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4375,17 +4401,18 @@
         # already started out on a link and need to move off of
         # it else we'll get stuck.
         #
-        [currentObj, characterOffset] = self.getCaretContext()
-        containingLink = self.getContainingLink(currentObj)
+        [obj, characterOffset] = self.getCaretContext()
+        containingLink = self.getContainingLink(obj)
         if containingLink:
-            obj = self.findPreviousObject(containingLink)
-        else:
-            obj = self.findPreviousObject(currentObj)
+            obj = containingLink
 
-        while obj and \
-              (obj.role != rolenames.ROLE_LINK or not \
-               obj.state.count(atspi.Accessibility.STATE_VISITED)):
-            obj = self.findPreviousObject(obj)
+        found = False
+        while obj and not found:
+            obj = self.findPreviousRole([rolenames.ROLE_LINK], obj)
+            if obj and \
+               obj.state.count(atspi.Accessibility.STATE_VISITED):
+                found = True
+
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4400,11 +4427,12 @@
 
     def goNextVisitedLink(self, inputEvent):
         [obj, characterOffset] = self.getCaretContext()
-        obj = self.findNextObject(obj)
-        while obj and \
-              (obj.role != rolenames.ROLE_LINK or not \
-               obj.state.count(atspi.Accessibility.STATE_VISITED)):
-            obj = self.findNextObject(obj)
+        found = False
+        while obj and not found:
+            obj = self.findNextRole([rolenames.ROLE_LINK], obj)
+            if obj and \
+               obj.state.count(atspi.Accessibility.STATE_VISITED):
+                found = True
         if obj:
             [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
             self.setCaretPosition(obj, characterOffset)
@@ -4418,7 +4446,7 @@
             speech.speak(_("No more visited links."))
 
     def goPreviousTable(self, inputEvent):
-        [obj, characterOffset] = self.findPreviousRole([rolenames.ROLE_TABLE])
+        obj = self.findPreviousRole([rolenames.ROLE_TABLE])
         if obj:
             nRows = obj.table.nRows
             nColumns = obj.table.nColumns
@@ -4457,7 +4485,7 @@
             speech.speak(_("No more tables."))
 
     def goNextTable(self, inputEvent):
-        [obj, characterOffset] = self.findNextRole([rolenames.ROLE_TABLE])
+        obj = self.findNextRole([rolenames.ROLE_TABLE])
         if obj:
             nRows = obj.table.nRows
             nColumns = obj.table.nColumns
