Accessible* nsAccessiblePivot::SearchForward(Accessible* aAccessible, nsIAccessibleTraversalRule* aRule, bool aSearchCurrent, nsresult* aResult) { *aResult = NS_OK; // Initial position could be not set, in that case begin search from root. Accessible* root = GetActiveRoot(); Accessible* accessible = (!aAccessible) ? root : aAccessible; RuleCache cache(aRule); uint16_t filtered = nsIAccessibleTraversalRule::FILTER_IGNORE; accessible = AdjustStartPosition(accessible, cache, &filtered, aResult); NS_ENSURE_SUCCESS(*aResult, nullptr); if (aSearchCurrent && (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)) return accessible; while (true) { Accessible* firstChild = nullptr; while (!(filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) && (firstChild = accessible->FirstChild())) { accessible = firstChild; *aResult = cache.ApplyFilter(accessible, &filtered); NS_ENSURE_SUCCESS(*aResult, nullptr); if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH) return accessible; } Accessible* sibling = nullptr; Accessible* temp = accessible; do { if (temp == root) break; sibling = temp->NextSibling(); if (sibling) break; } while ((temp = temp->Parent())); if (!sibling) break; accessible = sibling; *aResult = cache.ApplyFilter(accessible, &filtered); NS_ENSURE_SUCCESS(*aResult, nullptr); if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH) return accessible; } return nullptr; }
void TextRange::Text(nsAString& aText) const { Accessible* current = mStartContainer->GetChildAtOffset(mStartOffset); uint32_t startIntlOffset = mStartOffset - mStartContainer->GetChildOffset(current); while (current && TextInternal(aText, current, startIntlOffset)) { current = current->Parent(); if (!current) break; current = current->NextSibling(); } }
HyperTextAccessible* nsAccessiblePivot::SearchForText(Accessible* aAccessible, bool aBackward) { Accessible* root = GetActiveRoot(); Accessible* accessible = aAccessible; while (true) { Accessible* child = nullptr; while ((child = (aBackward ? accessible->LastChild() : accessible->FirstChild()))) { accessible = child; if (child->IsHyperText()) return child->AsHyperText(); } Accessible* sibling = nullptr; Accessible* temp = accessible; do { if (temp == root) break; if (temp != aAccessible && temp->IsHyperText()) return temp->AsHyperText(); sibling = aBackward ? temp->PrevSibling() : temp->NextSibling(); if (sibling) break; } while ((temp = temp->Parent())); if (!sibling) break; accessible = sibling; if (accessible->IsHyperText()) return accessible->AsHyperText(); } return nullptr; }
NS_IMETHODIMP nsAccessiblePivot::MoveNextByText(TextBoundaryType aBoundary, bool* aResult) { NS_ENSURE_ARG(aResult); *aResult = false; int32_t tempStart = mStartOffset, tempEnd = mEndOffset; Accessible* tempPosition = mPosition; Accessible* root = GetActiveRoot(); while (true) { Accessible* curPosition = tempPosition; HyperTextAccessible* text = nullptr; // Find the nearest text node using a preorder traversal starting from // the current node. if (!(text = tempPosition->AsHyperText())) { text = SearchForText(tempPosition, false); if (!text) return NS_OK; if (text != curPosition) tempStart = tempEnd = -1; tempPosition = text; } // If the search led to the parent of the node we started on (e.g. when // starting on a text leaf), start the text movement from the end of that // node, otherwise we just default to 0. if (tempEnd == -1) tempEnd = text == curPosition->Parent() ? text->GetChildOffset(curPosition) : 0; // If there's no more text on the current node, try to find the next text // node; if there isn't one, bail out. if (tempEnd == static_cast<int32_t>(text->CharacterCount())) { if (tempPosition == root) return NS_OK; // If we're currently sitting on a link, try move to either the next // sibling or the parent, whichever is closer to the current end // offset. Otherwise, do a forward search for the next node to land on // (we don't do this in the first case because we don't want to go to the // subtree). Accessible* sibling = tempPosition->NextSibling(); if (tempPosition->IsLink()) { if (sibling && sibling->IsLink()) { tempStart = tempEnd = -1; tempPosition = sibling; } else { tempStart = tempPosition->StartOffset(); tempEnd = tempPosition->EndOffset(); tempPosition = tempPosition->Parent(); } } else { tempPosition = SearchForText(tempPosition, false); if (!tempPosition) return NS_OK; tempStart = tempEnd = -1; } continue; } AccessibleTextBoundary startBoundary, endBoundary; switch (aBoundary) { case CHAR_BOUNDARY: startBoundary = nsIAccessibleText::BOUNDARY_CHAR; endBoundary = nsIAccessibleText::BOUNDARY_CHAR; break; case WORD_BOUNDARY: startBoundary = nsIAccessibleText::BOUNDARY_WORD_START; endBoundary = nsIAccessibleText::BOUNDARY_WORD_END; break; default: return NS_ERROR_INVALID_ARG; } nsAutoString unusedText; int32_t newStart = 0, newEnd = 0, currentEnd = tempEnd; text->TextAtOffset(tempEnd, endBoundary, &newStart, &tempEnd, unusedText); text->TextBeforeOffset(tempEnd, startBoundary, &newStart, &newEnd, unusedText); int32_t potentialStart = newEnd == tempEnd ? newStart : newEnd; tempStart = potentialStart > tempStart ? potentialStart : currentEnd; // The offset range we've obtained might have embedded characters in it, // limit the range to the start of the first occurrence of an embedded // character. Accessible* childAtOffset = nullptr; for (int32_t i = tempStart; i < tempEnd; i++) { childAtOffset = text->GetChildAtOffset(i); if (childAtOffset && nsAccUtils::IsEmbeddedObject(childAtOffset)) { tempEnd = i; break; } } // If there's an embedded character at the very start of the range, we // instead want to traverse into it. So restart the movement with // the child as the starting point. if (childAtOffset && nsAccUtils::IsEmbeddedObject(childAtOffset) && tempStart == static_cast<int32_t>(childAtOffset->StartOffset())) { tempPosition = childAtOffset; tempStart = tempEnd = -1; continue; } *aResult = true; Accessible* startPosition = mPosition; int32_t oldStart = mStartOffset, oldEnd = mEndOffset; mPosition = tempPosition; mStartOffset = tempStart; mEndOffset = tempEnd; NotifyOfPivotChange(startPosition, oldStart, oldEnd, nsIAccessiblePivot::REASON_TEXT); return NS_OK; } }
uint32_t AccGroupInfo::TotalItemCount(Accessible* aContainer, bool* aIsHierarchical) { uint32_t itemCount = 0; switch (aContainer->Role()) { case roles::TABLE: if (nsCoreUtils::GetUIntAttr(aContainer->GetContent(), nsGkAtoms::aria_rowcount, (int32_t*)&itemCount)) { break; } if (TableAccessible* tableAcc = aContainer->AsTable()) { return tableAcc->RowCount(); } break; case roles::ROW: if (Accessible* table = nsAccUtils::TableFor(aContainer)) { if (nsCoreUtils::GetUIntAttr(table->GetContent(), nsGkAtoms::aria_colcount, (int32_t*)&itemCount)) { break; } if (TableAccessible* tableAcc = table->AsTable()) { return tableAcc->ColCount(); } } break; case roles::OUTLINE: case roles::LIST: case roles::MENUBAR: case roles::MENUPOPUP: case roles::COMBOBOX: case roles::GROUPING: case roles::TREE_TABLE: case roles::COMBOBOX_LIST: case roles::LISTBOX: case roles::DEFINITION_LIST: case roles::EDITCOMBOBOX: case roles::RADIO_GROUP: case roles::PAGETABLIST: { Accessible* childItem = AccGroupInfo::FirstItemOf(aContainer); if (!childItem) { childItem = aContainer->FirstChild(); if (childItem && childItem->IsTextLeaf()) { // First child can be a text leaf, check its sibling for an item. childItem = childItem->NextSibling(); } } if (childItem) { GroupPos groupPos = childItem->GroupPosition(); itemCount = groupPos.setSize; if (groupPos.level && aIsHierarchical) { *aIsHierarchical = true; } } break; } default: break; } return itemCount; }