nsresult nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer, nsISelectionController *aSelectionController, bool aIsFirstVisiblePreferred, bool aFindPrev, nsIPresShell **aPresShell, nsPresContext **aPresContext) { NS_ENSURE_ARG_POINTER(aContainer); NS_ENSURE_ARG_POINTER(aPresShell); NS_ENSURE_ARG_POINTER(aPresContext); *aPresShell = nullptr; *aPresContext = nullptr; nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer)); if (!docShell) return NS_ERROR_FAILURE; nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell(); nsRefPtr<nsPresContext> presContext; docShell->GetPresContext(getter_AddRefs(presContext)); if (!presShell || !presContext) return NS_ERROR_FAILURE; nsIDocument* doc = presShell->GetDocument(); if (!doc) return NS_ERROR_FAILURE; nsCOMPtr<nsIContent> rootContent; nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(doc)); if (htmlDoc) { nsCOMPtr<nsIDOMHTMLElement> bodyEl; htmlDoc->GetBody(getter_AddRefs(bodyEl)); rootContent = do_QueryInterface(bodyEl); } if (!rootContent) rootContent = doc->GetRootElement(); nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootContent)); if (!rootNode) return NS_ERROR_FAILURE; if (!mSearchRange) { mSearchRange = new nsRange(doc); } nsCOMPtr<nsIDOMNode> searchRootNode = rootNode; // Hack for XMLPrettyPrinter. nsFind can't handle complex anonymous content. // If the root node has an XBL binding then there's not much we can do in // in general, but we can try searching the binding's first child, which // in the case of XMLPrettyPrinter contains the visible pretty-printed // content. nsXBLBinding* binding = rootContent->GetXBLBinding(); if (binding) { nsIContent* anonContent = binding->GetAnonymousContent(); if (anonContent) { searchRootNode = do_QueryInterface(anonContent->GetFirstChild()); } } mSearchRange->SelectNodeContents(searchRootNode); if (!mStartPointRange) { mStartPointRange = new nsRange(doc); } mStartPointRange->SetStart(searchRootNode, 0); mStartPointRange->Collapse(true); // collapse to start if (!mEndPointRange) { mEndPointRange = new nsRange(doc); } nsCOMPtr<nsINode> searchRootTmp = do_QueryInterface(searchRootNode); mEndPointRange->SetEnd(searchRootNode, searchRootTmp->Length()); mEndPointRange->Collapse(false); // collapse to end // Consider current selection as null if // it's not in the currently focused document nsCOMPtr<nsIDOMRange> currentSelectionRange; nsCOMPtr<nsIPresShell> selectionPresShell = GetPresShell(); if (aSelectionController && selectionPresShell && selectionPresShell == presShell) { nsCOMPtr<nsISelection> selection; aSelectionController->GetSelection( nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); if (selection) selection->GetRangeAt(0, getter_AddRefs(currentSelectionRange)); } if (!currentSelectionRange) { // Ensure visible range, move forward if necessary // This uses ignores the return value, but usese the side effect of // IsRangeVisible. It returns the first visible range after searchRange IsRangeVisible(presShell, presContext, mSearchRange, aIsFirstVisiblePreferred, true, getter_AddRefs(mStartPointRange), nullptr); } else { int32_t startOffset; nsCOMPtr<nsIDOMNode> startNode; if (aFindPrev) { currentSelectionRange->GetStartContainer(getter_AddRefs(startNode)); currentSelectionRange->GetStartOffset(&startOffset); } else { currentSelectionRange->GetEndContainer(getter_AddRefs(startNode)); currentSelectionRange->GetEndOffset(&startOffset); } if (!startNode) startNode = rootNode; // We need to set the start point this way, other methods haven't worked mStartPointRange->SelectNode(startNode); mStartPointRange->SetStart(startNode, startOffset); } mStartPointRange->Collapse(true); // collapse to start presShell.forget(aPresShell); presContext.forget(aPresContext); return NS_OK; }
nsresult nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer, nsISelectionController *aSelectionController, bool aIsFirstVisiblePreferred, bool aFindPrev, nsIPresShell **aPresShell, nsPresContext **aPresContext) { NS_ENSURE_ARG_POINTER(aContainer); NS_ENSURE_ARG_POINTER(aPresShell); NS_ENSURE_ARG_POINTER(aPresContext); *aPresShell = nullptr; *aPresContext = nullptr; nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer)); if (!docShell) return NS_ERROR_FAILURE; nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell(); nsRefPtr<nsPresContext> presContext; docShell->GetPresContext(getter_AddRefs(presContext)); if (!presShell || !presContext) return NS_ERROR_FAILURE; nsIDocument* doc = presShell->GetDocument(); if (!doc) return NS_ERROR_FAILURE; nsCOMPtr<nsIContent> rootContent; nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(doc)); if (htmlDoc) { nsCOMPtr<nsIDOMHTMLElement> bodyEl; htmlDoc->GetBody(getter_AddRefs(bodyEl)); rootContent = do_QueryInterface(bodyEl); } if (!rootContent) rootContent = doc->GetRootElement(); nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootContent)); if (!rootNode) return NS_ERROR_FAILURE; uint32_t childCount = rootContent->GetChildCount(); if (!mSearchRange) { mSearchRange = new nsRange(rootContent); } if (!mEndPointRange) { mEndPointRange = new nsRange(rootContent); } mSearchRange->SelectNodeContents(rootNode); mEndPointRange->SetEnd(rootNode, childCount); mEndPointRange->Collapse(false); // collapse to end // Consider current selection as null if // it's not in the currently focused document nsCOMPtr<nsIDOMRange> currentSelectionRange; nsCOMPtr<nsIPresShell> selectionPresShell = GetPresShell(); if (aSelectionController && selectionPresShell && selectionPresShell == presShell) { nsCOMPtr<nsISelection> selection; aSelectionController->GetSelection( nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); if (selection) selection->GetRangeAt(0, getter_AddRefs(currentSelectionRange)); } if (!mStartPointRange) { mStartPointRange = new nsRange(doc); } if (!currentSelectionRange) { // Ensure visible range, move forward if necessary // This uses ignores the return value, but usese the side effect of // IsRangeVisible. It returns the first visible range after searchRange IsRangeVisible(presShell, presContext, mSearchRange, aIsFirstVisiblePreferred, true, getter_AddRefs(mStartPointRange), nullptr); } else { int32_t startOffset; nsCOMPtr<nsIDOMNode> startNode; if (aFindPrev) { currentSelectionRange->GetStartContainer(getter_AddRefs(startNode)); currentSelectionRange->GetStartOffset(&startOffset); } else { currentSelectionRange->GetEndContainer(getter_AddRefs(startNode)); currentSelectionRange->GetEndOffset(&startOffset); } if (!startNode) startNode = rootNode; // We need to set the start point this way, other methods haven't worked mStartPointRange->SelectNode(startNode); mStartPointRange->SetStart(startNode, startOffset); } mStartPointRange->Collapse(true); // collapse to start *aPresShell = presShell; NS_ADDREF(*aPresShell); *aPresContext = presContext; NS_ADDREF(*aPresContext); return NS_OK; }