Index: src/orca/scripts/apps/evolution/script.py
===================================================================
--- src/orca/scripts/apps/evolution/script.py	(revision 3898)
+++ src/orca/scripts/apps/evolution/script.py	(working copy)
@@ -664,7 +664,8 @@
             parent = obj.parent
             if parent.getRole() == pyatspi.ROLE_TABLE:
                 parentTable = parent.queryTable()
-                row = parentTable.getRowAtIndex(obj.getIndexInParent())
+                index = self.getCellIndex(obj)
+                row = parentTable.getRowAtIndex(index)
                 utterances = []
                 regions = []
                 for i in range(0, parentTable.nColumns):
@@ -720,9 +721,9 @@
 
             parent = event.source.parent
             parentTable = parent.queryTable()
-            row = parentTable.getRowAtIndex(event.source.getIndexInParent())
-            column = \
-                parentTable.getColumnAtIndex(event.source.getIndexInParent())
+            index = self.getCellIndex(event.source)
+            row = parentTable.getRowAtIndex(index)
+            column = parentTable.getColumnAtIndex(index)
 
             # If we are on the same row, then just speak/braille the table
             # cell as if settings.readTableCellRow was False.
@@ -1502,10 +1503,10 @@
                    self.isDesiredFocusedItem(oldLocusOfFocus, rolesList):
                     parent = event.source.parent
                     parentTable = parent.queryTable()
-                    newRow = parentTable.getRowAtIndex( \
-                                  event.source.getIndexInParent())
-                    oldRow = parentTable.getRowAtIndex( \
-                                  oldLocusOfFocus.getIndexInParent())
+                    newIndex = self.getCellIndex(event.source)
+                    newRow = parentTable.getRowAtIndex(newIndex)
+                    oldIndex = self.getCellIndex(oldLocusOfFocus)
+                    oldRow = parentTable.getRowAtIndex(oldIndex)
                     nRows = parentTable.nRows
                     if (newRow != oldRow) and (oldRow != nRows):
                         return
Index: src/orca/scripts/apps/pidgin/where_am_i.py
===================================================================
--- src/orca/scripts/apps/pidgin/where_am_i.py	(revision 3898)
+++ src/orca/scripts/apps/pidgin/where_am_i.py	(working copy)
@@ -93,8 +93,8 @@
         utterances = []
         if doubleClick:
             table = parent.queryTable()
-            row = table.getRowAtIndex(
-              orca_state.locusOfFocus.getIndexInParent())
+            index = self._script.getCellIndex(orca_state.locusOfFocus)
+            row = table.getRowAtIndex(index)
             # Translators: this in reference to a row in a table.
             #
             text = _("row %d of %d") % ((row+1), table.nRows)
@@ -120,9 +120,8 @@
                               "??? parent=%s" % parent.getRoleName())
                 return
             else:
-                row = \
-                    table.getRowAtIndex(
-                       orca_state.locusOfFocus.getIndexInParent())
+                index = self._script.getCellIndex(orca_state.locusOfFocus)
+                row = table.getRowAtIndex(index)
                 # Translators: this in reference to a row in a table.
                 #
                 text = _("row %d of %d") % ((row+1), table.nRows)
Index: src/orca/scripts/apps/pidgin/script.py
===================================================================
--- src/orca/scripts/apps/pidgin/script.py	(revision 3898)
+++ src/orca/scripts/apps/pidgin/script.py	(working copy)
@@ -902,8 +902,9 @@
                 return []
 
         nodes = []        
-        row = table.getRowAtIndex(obj.getIndexInParent())
-        col = table.getColumnAtIndex(obj.getIndexInParent() + 1)
+        index = self.getCellIndex(obj)
+        row = table.getRowAtIndex(index)
+        col = table.getColumnAtIndex(index + 1)
         nodeLevel = self.getNodeLevel(obj)
         done = False
 
Index: src/orca/scripts/apps/Thunderbird/script.py
===================================================================
--- src/orca/scripts/apps/Thunderbird/script.py	(revision 3898)
+++ src/orca/scripts/apps/Thunderbird/script.py	(working copy)
@@ -97,7 +97,8 @@
         #
         if obj.getRole() == pyatspi.ROLE_TABLE_CELL:
             table = parent.queryTable()
-            row = table.getRowAtIndex(obj.getIndexInParent())
+            index = self.getCellIndex(obj)
+            row = table.getRowAtIndex(index)
             acc = table.getAccessibleAt(row, 0)
             orca.setLocusOfFocus(event, acc)
             consume = True
Index: src/orca/scripts/apps/soffice/speech_generator.py
===================================================================
--- src/orca/scripts/apps/soffice/speech_generator.py	(revision 3898)
+++ src/orca/scripts/apps/soffice/speech_generator.py	(working copy)
@@ -147,9 +147,10 @@
             except NotImplementedError:
                 parentTable = None
 
+            index = self._script.getCellIndex(obj)
             if self._script.pointOfReference.has_key("lastColumn") and \
                self._script.pointOfReference["lastColumn"] != \
-               parentTable.getColumnAtIndex(obj.getIndexInParent()):
+               parentTable.getColumnAtIndex(index):
                 if self._script.dynamicColumnHeaders.has_key(table):
                     row = self._script.dynamicColumnHeaders[table]
                     header = self._script.getDynamicRowHeaderCell(obj, row)
@@ -170,7 +171,7 @@
 
             if self._script.pointOfReference.has_key("lastRow") and \
                self._script.pointOfReference["lastRow"] != \
-               parentTable.getRowAtIndex(obj.getIndexInParent()):
+               parentTable.getRowAtIndex(index):
                 if self._script.dynamicRowHeaders.has_key(table):
                     column = self._script.dynamicRowHeaders[table]
                     header = self._script.getDynamicColumnHeaderCell(obj,
@@ -194,9 +195,9 @@
             if not already_focused:
                 if settings.readTableCellRow:
                     parent = obj.parent
-                    row = parentTable.getRowAtIndex(obj.getIndexInParent())
-                    column = \
-                        parentTable.getColumnAtIndex(obj.getIndexInParent())
+                    index = self._script.getCellIndex(obj)
+                    row = parentTable.getRowAtIndex(index)
+                    column = parentTable.getColumnAtIndex(index)
 
                     # This is an indication of whether we should speak all the
                     # table cells (the user has moved focus up or down a row),
Index: src/orca/scripts/apps/soffice/where_am_i.py
===================================================================
--- src/orca/scripts/apps/soffice/where_am_i.py	(revision 3898)
+++ src/orca/scripts/apps/soffice/where_am_i.py	(working copy)
@@ -69,8 +69,8 @@
         # Translators: this represents the column we're
         # on in a table.
         #
-        text = _("column %d") % \
-               (table.getColumnAtIndex(obj.getIndexInParent()) + 1)
+        index = self._script.getCellIndex(obj)
+        text = _("column %d") % (table.getColumnAtIndex(index) + 1)
         utterances.append(text)
 
         # Speak the dynamic column header (if any).
@@ -95,7 +95,8 @@
 
         # Translators: this represents the row number of a table.
         #
-        text = _("row %d") % (table.getRowAtIndex(obj.getIndexInParent()) + 1)
+        index = self._script.getCellIndex(obj)
+        text = _("row %d") % (table.getRowAtIndex(index) + 1)
         utterances.append(text)
 
         # Speak the dynamic row header (if any).
Index: src/orca/scripts/apps/soffice/braille_generator.py
===================================================================
--- src/orca/scripts/apps/soffice/braille_generator.py	(revision 3898)
+++ src/orca/scripts/apps/soffice/braille_generator.py	(working copy)
@@ -69,9 +69,10 @@
         except NotImplementedError:
             parentTable = None
 
+        index = self._script.getCellIndex(obj)
         if self._script.pointOfReference.has_key("lastColumn") and \
               self._script.pointOfReference["lastColumn"] != \
-              parentTable.getColumnAtIndex(obj.getIndexInParent()):
+              parentTable.getColumnAtIndex(index):
             if self._script.dynamicColumnHeaders.has_key(table):
                 row = self._script.dynamicColumnHeaders[table]
                 header = self._script.getDynamicRowHeaderCell(obj, row)
@@ -92,7 +93,7 @@
 
         if self._script.pointOfReference.has_key("lastRow") and \
               self._script.pointOfReference['lastRow'] != \
-              parentTable.getRowAtIndex(obj.getIndexInParent()):
+              parentTable.getRowAtIndex(index):
             if self._script.dynamicRowHeaders.has_key(table):
                 column = self._script.dynamicRowHeaders[table]
                 header = self._script.getDynamicColumnHeaderCell(obj, column)
@@ -124,8 +125,9 @@
                                              settings.VERBOSITY_LEVEL_BRIEF
 
                 parent = obj.parent
-                row = parentTable.getRowAtIndex(obj.getIndexInParent())
-                column = parentTable.getColumnAtIndex(obj.getIndexInParent())
+                index = self._script.getCellIndex(obj)
+                row = parentTable.getRowAtIndex(index)
+                column = parentTable.getColumnAtIndex(index)
 
                 # This is an indication of whether we should speak all the
                 # table cells (the user has moved focus up or down a row),
Index: src/orca/scripts/apps/soffice/script.py
===================================================================
--- src/orca/scripts/apps/soffice/script.py	(revision 3898)
+++ src/orca/scripts/apps/soffice/script.py	(working copy)
@@ -394,7 +394,8 @@
             parentTable = None
 
         if parent and parentTable:
-            row = parentTable.getRowAtIndex(obj.getIndexInParent())
+            index = self.getCellIndex(obj)
+            row = parentTable.getRowAtIndex(index)
             accCell = parentTable.getAccessibleAt(row, column)
 
         return accCell
@@ -420,7 +421,8 @@
             parentTable = None
 
         if parent and parentTable:
-            column = parentTable.getColumnAtIndex(obj.getIndexInParent())
+            index = self.getCellIndex(obj)
+            column = parentTable.getColumnAtIndex(index)
             accCell = parentTable.getAccessibleAt(row, column)
 
         return accCell
@@ -482,14 +484,16 @@
                 parent.queryComponent().getAccessibleAtPoint(leftX, y, 0)
             if leftCell:
                 table = leftCell.parent.queryTable()
-                startIndex = table.getColumnAtIndex(leftCell.getIndexInParent())
+                index = self.getCellIndex(leftCell)
+                startIndex = table.getColumnAtIndex(index)
 
             rightX = extents.x + extents.width - 1
             rightCell = \
                 parent.queryComponent().getAccessibleAtPoint(rightX, y, 0)
             if rightCell:
                 table = rightCell.parent.queryTable()
-                endIndex = table.getColumnAtIndex(rightCell.getIndexInParent())
+                index = self.getCellIndex(rightCell)
+                endIndex = table.getColumnAtIndex(index)
 
         return [startIndex, endIndex]
 
@@ -725,7 +729,8 @@
                 parentTable = None
 
             if parent and parentTable:
-                row = parentTable.getRowAtIndex(cell.getIndexInParent())
+                index = self.getCellIndex(cell)
+                row = parentTable.getRowAtIndex(index)
 
         return row
 
@@ -749,7 +754,8 @@
                 parentTable = None
 
             if parent and parentTable:
-                column = parentTable.getColumnAtIndex(cell.getIndexInParent())
+                index = self.getCellIndex(cell)
+                column = parentTable.getColumnAtIndex(index)
 
         return column
 
@@ -1428,11 +1434,10 @@
                 except:
                     pass
                 else:
-                    column = table.getColumnAtIndex( \
-                                    newLocusOfFocus.getIndexInParent())
+                    index = self.getCellIndex(newLocusOfFocus)
+                    column = table.getColumnAtIndex(index)
                     self.pointOfReference['lastColumn'] = column
-                    row = table.getRowAtIndex( \
-                                    newLocusOfFocus.getIndexInParent())
+                    row = table.getRowAtIndex(index)
                     self.pointOfReference['lastRow'] = row
                 return
 
Index: src/orca/scripts/toolkits/Gecko/script.py
===================================================================
--- src/orca/scripts/toolkits/Gecko/script.py	(revision 3898)
+++ src/orca/scripts/toolkits/Gecko/script.py	(working copy)
@@ -3176,7 +3176,7 @@
                         contents += "\n"
                     elif obj.getRole() == pyatspi.ROLE_TABLE_CELL:
                         parent = obj.parent
-                        index = obj.getIndexInParent()
+                        index = self.getCellIndex(obj)
                         if parent.queryTable().getColumnAtIndex(index) != 0:
                             contents += " "
                     elif obj.getRole() == pyatspi.ROLE_LINK:
@@ -3761,11 +3761,35 @@
 
         return None
 
+    def getCellIndex(self, obj):
+        """Returns the index of the cell which should be used with the
+        table interface.  This is necessary because we cannot count on
+        the index we need being the same as the index in the parent.
+        See, for example, tables with captions and tables with rows
+        that have attributes."""
+
+        index = -1
+        parent = self.getAncestor(obj,
+                                 [pyatspi.ROLE_TABLE],
+                                 [pyatspi.ROLE_DOCUMENT_FRAME])
+        try:
+            table = parent.queryTable()
+        except:
+            pass
+        else:
+            attrs = dict([attr.split(':', 1) for attr in obj.getAttributes()])
+            index = attrs.get('table-cell-index')
+            if index:
+                index = int(index)
+            else:
+                index = obj.getIndexInParent()
+
+        return index
+
     def getCellCoordinates(self, obj):
         """Returns the [row, col] of a ROLE_TABLE_CELL or [0, 0]
         if the coordinates cannot be found.
         """
-
         if obj.getRole() != pyatspi.ROLE_TABLE_CELL:
             obj = self.getAncestor(obj,
                                    [pyatspi.ROLE_TABLE_CELL],
@@ -3777,8 +3801,9 @@
         except:
             pass
         else:
-            row = table.getRowAtIndex(obj.getIndexInParent())
-            col = table.getColumnAtIndex(obj.getIndexInParent())
+            index = self.getCellIndex(obj)
+            row = table.getRowAtIndex(index)
+            col = table.getColumnAtIndex(index)
             return [row, col]
 
         return [0, 0]
@@ -3793,14 +3818,19 @@
         - coordinates2: [row, col]
         """
 
+        if coordinates1 == coordinates2:
+            return True
+
         try:
             table = obj.queryTable()
         except:
             pass
         else:
-            index1 = table.getIndexAt(coordinates1[0], coordinates1[1])
-            index2 = table.getIndexAt(coordinates2[0], coordinates2[1])
-            return (index1 == index2)
+            cell1 = table.getAccessibleAt(coordinates1[0], 
+                                          coordinates1[1])
+            cell2 = table.getAccessibleAt(coordinates2[0],
+                                          coordinates2[1])
+            return self.isSameObject(cell1, cell2)
 
         return False
 
@@ -3866,12 +3896,20 @@
         """
 
         if obj and obj.getRole() == pyatspi.ROLE_TABLE_CELL:
-            table = obj.parent.queryTable()
-            row = table.getRowAtIndex(obj.getIndexInParent())
-            for col in xrange(table.nColumns):
-                cell = table.getAccessibleAt(row, col)
-                if not self.isHeader(cell):
-                    return False
+            parent = self.getAncestor(obj,
+                                      [pyatspi.ROLE_TABLE],
+                                      [pyatspi.ROLE_DOCUMENT_FRAME])
+            try:
+                table = parent.queryTable()
+            except:
+                return False
+            else:
+                index = self.getCellIndex(obj)
+                row = table.getRowAtIndex(index)
+                for col in xrange(table.nColumns):
+                    cell = table.getAccessibleAt(row, col)
+                    if not self.isHeader(cell):
+                        return False
 
         return True
 
@@ -3884,12 +3922,20 @@
         """
 
         if obj and obj.getRole() == pyatspi.ROLE_TABLE_CELL:
-            table = obj.parent.queryTable()
-            col = table.getColumnAtIndex(obj.getIndexInParent())
-            for row in xrange(table.nRows):
-                cell = table.getAccessibleAt(row, col)
-                if not self.isHeader(cell):
-                    return False
+            parent = self.getAncestor(obj,
+                                      [pyatspi.ROLE_TABLE],
+                                      [pyatspi.ROLE_DOCUMENT_FRAME])
+            try:
+                table = parent.queryTable()
+            except:
+                return False
+            else:
+                index = self.getCellIndex(obj)
+                col = table.getColumnAtIndex(index)
+                for row in xrange(table.nRows):
+                    cell = table.getAccessibleAt(row, col)
+                    if not self.isHeader(cell):
+                        return False
 
         return True
 
Index: src/orca/speechgenerator.py
===================================================================
--- src/orca/speechgenerator.py	(revision 3898)
+++ src/orca/speechgenerator.py	(working copy)
@@ -1436,8 +1436,9 @@
             if settings.readTableCellRow and parent_table \
                 and (not self._script.isLayoutOnly(obj.parent)):
                 parent = obj.parent
-                row = parent_table.getRowAtIndex(obj.getIndexInParent())
-                column = parent_table.getColumnAtIndex(obj.getIndexInParent())
+                index = self._script.getCellIndex(obj)
+                row = parent_table.getRowAtIndex(index)
+                column = parent_table.getColumnAtIndex(index)
 
                 # This is an indication of whether we should speak all the
                 # table cells (the user has moved focus up or down a row),
Index: src/orca/default.py
===================================================================
--- src/orca/default.py	(revision 3898)
+++ src/orca/default.py	(working copy)
@@ -2654,10 +2654,9 @@
                     table = None
                 if table and \
                       oldLocusOfFocus.getRole() == pyatspi.ROLE_TABLE_CELL:
-                    oldRow = table.getRowAtIndex( \
-                                           oldLocusOfFocus.getIndexInParent())
-                    oldCol = table.getColumnAtIndex( \
-                                           oldLocusOfFocus.getIndexInParent())
+                    index = self.getCellIndex(oldLocusOfFocus)
+                    oldRow = table.getRowAtIndex(index)
+                    oldCol = table.getColumnAtIndex(index)
                 else:
                     oldRow = -1
                     oldCol = -1
@@ -2667,10 +2666,9 @@
                 except:
                     pass
                 else:
-                    newRow = table.getRowAtIndex( \
-                                  newLocusOfFocus.getIndexInParent())
-                    newCol = table.getColumnAtIndex( \
-                                  newLocusOfFocus.getIndexInParent())
+                    index = self.getCellIndex(newLocusOfFocus)
+                    newRow = table.getRowAtIndex(index)
+                    newCol = table.getColumnAtIndex(index)
 
                     if (newRow != oldRow) or (oldParent != newParent):
                         desc = table.getRowDescription(newRow)
@@ -2825,11 +2823,10 @@
                 except:
                     pass
                 else:
-                    column = table.getColumnAtIndex( \
-                                    newLocusOfFocus.getIndexInParent())
+                    index = self.getCellIndex(newLocusOfFocus)
+                    column = table.getColumnAtIndex(index)
                     self.pointOfReference['lastColumn'] = column
-                    row = table.getRowAtIndex( \
-                                    newLocusOfFocus.getIndexInParent())
+                    row = table.getRowAtIndex(index)
                     self.pointOfReference['lastRow'] = row
         else:
             orca_state.noFocusTimeStamp = time.time()
@@ -5973,6 +5970,16 @@
 
         return -1
 
+    def getCellIndex(self, obj):
+        """Returns the index of the cell which should be used with the
+        table interface.  This is necessary because in some apps we
+        cannot count on getIndexInParent() returning the index we need.
+
+        Arguments:
+        -obj: the table cell whose index we need.
+        """
+        return obj.getIndexInParent()
+
     def isWordDelimiter(self, character):
         """Returns True if the given character is a word delimiter.
 
@@ -6178,8 +6185,9 @@
                 return []
 
         nodes = []
-        row = table.getRowAtIndex(obj.getIndexInParent())
-        col = table.getColumnAtIndex(obj.getIndexInParent())
+        index = self.getCellIndex(obj)
+        row = table.getRowAtIndex(index)
+        col = table.getColumnAtIndex(index)
         nodeLevel = self.getNodeLevel(obj)
         done = False
 
Index: src/orca/liveregions.py
===================================================================
--- src/orca/liveregions.py	(revision 3898)
+++ src/orca/liveregions.py	(working copy)
@@ -485,7 +485,8 @@
                 # Note: getRowHeader() fails for most markup.  We will use the
                 # relation when the markup is good (when getRowHeader() works) 
                 # so we won't see this code in those cases.  
-                row = itable.getRowAtIndex(obj.getIndexInParent())
+                index = self._script.getCellIndex(obj)
+                row = itable.getRowAtIndex(index)
                 header = itable.getAccessibleAt(row, 0)
                 # expand the header
                 return [self._script.expandEOCs(header).strip()]
Index: src/orca/where_am_I.py
===================================================================
--- src/orca/where_am_I.py	(revision 3898)
+++ src/orca/where_am_I.py	(working copy)
@@ -545,13 +545,14 @@
             nColumns = 0
         else:
             nColumns = table.nColumns
-            column = table.getColumnAtIndex(obj.getIndexInParent())
+            index = self._script.getCellIndex(obj)
+            column = table.getColumnAtIndex(index)
             header = table.getColumnHeader(column)
             if header:
                 text = self._getObjName(header)
                 utterances.append(text)
 
-            row = table.getRowAtIndex(obj.getIndexInParent())
+            row = table.getRowAtIndex(index)
             header = table.getRowHeader(row)
             if header:
                 text = self._getObjName(header)
@@ -1189,8 +1190,8 @@
             debug.println(self._debugLevel, "??? parent=%s" % parent.getRole())
             return []
         else:
-            row = table.getRowAtIndex(obj.getIndexInParent())
-
+            index = self._script.getCellIndex(obj)
+            row = table.getRowAtIndex(index)
             for i in range(0, table.nColumns):
                 acc = table.getAccessibleAt(row, i)
                 utterances.append(self._getTableCell(acc))
Index: src/orca/braillegenerator.py
===================================================================
--- src/orca/braillegenerator.py	(revision 3898)
+++ src/orca/braillegenerator.py	(working copy)
@@ -1222,7 +1222,8 @@
 
                     if label == None or len(label) == 0:
                         table = obj.parent.queryTable()
-                        n = table.getColumnAtIndex(obj.getIndexInParent())
+                        index = self._script.getCellIndex(obj)
+                        n = table.getColumnAtIndex(index)
                         accHeader = table.getColumnHeader(n)
                         regions[0].append(braille.Region(" "))
                         label = accHeader.name
@@ -1308,10 +1309,10 @@
             savedBrailleVerbosityLevel = settings.brailleVerbosityLevel
             settings.brailleVerbosityLevel = \
                                          settings.VERBOSITY_LEVEL_BRIEF
+            index = self._script.getCellIndex(obj)
+            row = table.getRowAtIndex(index)
+            column = table.getColumnAtIndex(index)
 
-            row = table.getRowAtIndex(obj.getIndexInParent())
-            column = table.getColumnAtIndex(obj.getIndexInParent())
-
             # This is an indication of whether we should speak all the
             # table cells (the user has moved focus up or down a row),
             # or just the current one (focus has moved left or right in
@@ -1655,7 +1656,8 @@
         except (NotImplementedError, AttributeError):
             table = None
         if parent and table:
-            row = table.getRowAtIndex(obj.getIndexInParent())
+            index = self._script.getCellIndex(obj)
+            row = table.getRowAtIndex(index)
             if (row >= 0) \
                 and (not obj.getRole() in [pyatspi.ROLE_ROW_HEADER,
                                            pyatspi.ROLE_TABLE_ROW_HEADER]):
@@ -1676,7 +1678,7 @@
                     text = desc
                 regions.append(braille.Region(text))
 
-            col = table.getColumnAtIndex(obj.getIndexInParent())
+            col = table.getColumnAtIndex(index)
             if (col >= 0) \
                 and (not obj.getRole() in [pyatspi.ROLE_COLUMN_HEADER,
                                            pyatspi.ROLE_TABLE_COLUMN_HEADER]):
