From 4120467dac04a942eae51bb2445a9be3d07544e4 Mon Sep 17 00:00:00 2001 From: "akkana%netscape.com" Date: Tue, 22 Jun 1999 21:42:44 +0000 Subject: [PATCH] Use deep first/last child for Beginning/EndOfDocument methods git-svn-id: svn://10.0.0.236/trunk@36345 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/editor/base/nsEditor.cpp | 96 +++++++++++++++++++--- mozilla/editor/base/nsEditor.h | 5 ++ mozilla/editor/libeditor/base/nsEditor.cpp | 96 +++++++++++++++++++--- mozilla/editor/libeditor/base/nsEditor.h | 5 ++ 4 files changed, 178 insertions(+), 24 deletions(-) diff --git a/mozilla/editor/base/nsEditor.cpp b/mozilla/editor/base/nsEditor.cpp index 437d6a9cd0a..60a45e87bd6 100644 --- a/mozilla/editor/base/nsEditor.cpp +++ b/mozilla/editor/base/nsEditor.cpp @@ -582,7 +582,7 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell) mPresShell->SetCaretEnabled(PR_TRUE); - // Set the selection to the beginning, to make sure we have one: + // Set the selection to the beginning: BeginningOfDocument(); NS_POSTCONDITION(mDoc && mPresShell, "bad state"); @@ -1045,6 +1045,36 @@ NS_IMETHODIMP nsEditor::SelectAll() return result; } +// +// GetDeepFirst/LastChild borrowed from nsContentIterator +// +nsCOMPtr +nsEditor::GetDeepFirstChild(nsCOMPtr aRoot) +{ + nsCOMPtr deepFirstChild; + + if (aRoot) + { + nsCOMPtr cN (do_QueryInterface(aRoot)); + nsCOMPtr cChild; + cN->ChildAt(0,*getter_AddRefs(cChild)); + while ( cChild ) + { + cN = cChild; + nsCOMPtr cChildN; + int i = 0; + do { + cN->ChildAt(i++, *getter_AddRefs(cChild)); + cChildN = do_QueryInterface(cChild); + } while (cChild && cChildN && !IsEditable(cChildN)); + } + deepFirstChild = cN; + } + + nsCOMPtr deepFirstChildN (do_QueryInterface(deepFirstChild)); + return deepFirstChildN; +} + NS_IMETHODIMP nsEditor::BeginningOfDocument() { #ifdef ENABLE_JS_EDITOR_LOG @@ -1073,9 +1103,8 @@ NS_IMETHODIMP nsEditor::BeginningOfDocument() if ((NS_SUCCEEDED(result)) && bodyNode) { // Get the first child of the body node: - nsCOMPtr firstNode; - result = bodyNode->GetFirstChild(getter_AddRefs(firstNode)); - if (NS_SUCCEEDED(result)) + nsCOMPtr firstNode = GetDeepFirstChild(bodyNode); + if (firstNode) { result = selection->Collapse(firstNode, 0); ScrollIntoView(PR_TRUE); @@ -1086,6 +1115,44 @@ NS_IMETHODIMP nsEditor::BeginningOfDocument() return result; } +nsCOMPtr +nsEditor::GetDeepLastChild(nsCOMPtr aRoot) +{ + nsCOMPtr deepLastChild; + + if (aRoot) + { + nsCOMPtr cN (do_QueryInterface(aRoot)); + nsCOMPtr cChild; + PRInt32 numChildren; + + cN->ChildCount(numChildren); + + while ( numChildren ) + { + nsCOMPtr cChildN; + do { + cN->ChildAt(--numChildren, *getter_AddRefs(cChild)); + cChildN = (do_QueryInterface(cChild)); + } while (cChild && !IsEditable(cChildN)); + + if (cChild) + { + cChild->ChildCount(numChildren); + cN = cChild; + } + else + { + break; + } + } + deepLastChild = cN; + } + + nsCOMPtr deepLastChildN (do_QueryInterface(deepLastChild)); + return deepLastChildN; +} + NS_IMETHODIMP nsEditor::EndOfDocument() { #ifdef ENABLE_JS_EDITOR_LOG @@ -1113,14 +1180,18 @@ NS_IMETHODIMP nsEditor::EndOfDocument() result = nodeList->Item(0, getter_AddRefs(bodyNode)); if ((NS_SUCCEEDED(result)) && bodyNode) { - nsCOMPtr lastChild; - result = bodyNode->GetLastChild(getter_AddRefs(lastChild)); + nsCOMPtr lastChild = GetDeepLastChild(bodyNode); if ((NS_SUCCEEDED(result)) && lastChild) { - // XXX this is wrong, should iterate to collapse to - // XXX last child of last child of last ... - // XXX instead of beginning of last child of body. - result = selection->Collapse(lastChild, 0); + // See if the last child is a text node; if so, set offset: + PRUint32 offset = 0; + if (IsTextNode(lastChild)) + { + nsCOMPtr text (do_QueryInterface(lastChild)); + if (text) + text->GetLength(&offset); + } + result = selection->Collapse(lastChild, offset); ScrollIntoView(PR_FALSE); } } @@ -3833,7 +3904,7 @@ nsEditor::IsPreformatted(nsIDOMNode *aNode, PRBool *aResult) if (!aResult || !content) return NS_ERROR_NULL_POINTER; - if (!mPresShell) return NS_ERROR_NULL_POINTER; + if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; result = mPresShell->GetPrimaryFrameFor(content, &frame); if (NS_FAILED(result)) return result; @@ -4135,7 +4206,8 @@ nsAutoSelectionReset::nsAutoSelectionReset(nsIDOMSelection *aSel) mSel->GetAnchorOffset(&mStartOffset); mSel->GetFocusNode(getter_AddRefs(mEndNode)); mSel->GetFocusOffset(&mEndOffset); - mInitialized = PR_TRUE; + if (mStartNode && mEndNode) + mInitialized = PR_TRUE; } } diff --git a/mozilla/editor/base/nsEditor.h b/mozilla/editor/base/nsEditor.h index c5c4e785b0b..e7e841cc6f6 100644 --- a/mozilla/editor/base/nsEditor.h +++ b/mozilla/editor/base/nsEditor.h @@ -510,6 +510,11 @@ public: /** returns PR_TRUE if aNode is an editable node */ static PRBool IsEditable(nsIDOMNode *aNode); + /** Find the deep first and last children */ + static nsCOMPtr GetDeepFirstChild(nsCOMPtr aRoot); + static nsCOMPtr GetDeepLastChild(nsCOMPtr aRoot); + + /** from html rules code - migration in progress */ static nsresult GetTagString(nsIDOMNode *aNode, nsString& outString); static nsCOMPtr GetTag(nsIDOMNode *aNode); diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index 437d6a9cd0a..60a45e87bd6 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -582,7 +582,7 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell) mPresShell->SetCaretEnabled(PR_TRUE); - // Set the selection to the beginning, to make sure we have one: + // Set the selection to the beginning: BeginningOfDocument(); NS_POSTCONDITION(mDoc && mPresShell, "bad state"); @@ -1045,6 +1045,36 @@ NS_IMETHODIMP nsEditor::SelectAll() return result; } +// +// GetDeepFirst/LastChild borrowed from nsContentIterator +// +nsCOMPtr +nsEditor::GetDeepFirstChild(nsCOMPtr aRoot) +{ + nsCOMPtr deepFirstChild; + + if (aRoot) + { + nsCOMPtr cN (do_QueryInterface(aRoot)); + nsCOMPtr cChild; + cN->ChildAt(0,*getter_AddRefs(cChild)); + while ( cChild ) + { + cN = cChild; + nsCOMPtr cChildN; + int i = 0; + do { + cN->ChildAt(i++, *getter_AddRefs(cChild)); + cChildN = do_QueryInterface(cChild); + } while (cChild && cChildN && !IsEditable(cChildN)); + } + deepFirstChild = cN; + } + + nsCOMPtr deepFirstChildN (do_QueryInterface(deepFirstChild)); + return deepFirstChildN; +} + NS_IMETHODIMP nsEditor::BeginningOfDocument() { #ifdef ENABLE_JS_EDITOR_LOG @@ -1073,9 +1103,8 @@ NS_IMETHODIMP nsEditor::BeginningOfDocument() if ((NS_SUCCEEDED(result)) && bodyNode) { // Get the first child of the body node: - nsCOMPtr firstNode; - result = bodyNode->GetFirstChild(getter_AddRefs(firstNode)); - if (NS_SUCCEEDED(result)) + nsCOMPtr firstNode = GetDeepFirstChild(bodyNode); + if (firstNode) { result = selection->Collapse(firstNode, 0); ScrollIntoView(PR_TRUE); @@ -1086,6 +1115,44 @@ NS_IMETHODIMP nsEditor::BeginningOfDocument() return result; } +nsCOMPtr +nsEditor::GetDeepLastChild(nsCOMPtr aRoot) +{ + nsCOMPtr deepLastChild; + + if (aRoot) + { + nsCOMPtr cN (do_QueryInterface(aRoot)); + nsCOMPtr cChild; + PRInt32 numChildren; + + cN->ChildCount(numChildren); + + while ( numChildren ) + { + nsCOMPtr cChildN; + do { + cN->ChildAt(--numChildren, *getter_AddRefs(cChild)); + cChildN = (do_QueryInterface(cChild)); + } while (cChild && !IsEditable(cChildN)); + + if (cChild) + { + cChild->ChildCount(numChildren); + cN = cChild; + } + else + { + break; + } + } + deepLastChild = cN; + } + + nsCOMPtr deepLastChildN (do_QueryInterface(deepLastChild)); + return deepLastChildN; +} + NS_IMETHODIMP nsEditor::EndOfDocument() { #ifdef ENABLE_JS_EDITOR_LOG @@ -1113,14 +1180,18 @@ NS_IMETHODIMP nsEditor::EndOfDocument() result = nodeList->Item(0, getter_AddRefs(bodyNode)); if ((NS_SUCCEEDED(result)) && bodyNode) { - nsCOMPtr lastChild; - result = bodyNode->GetLastChild(getter_AddRefs(lastChild)); + nsCOMPtr lastChild = GetDeepLastChild(bodyNode); if ((NS_SUCCEEDED(result)) && lastChild) { - // XXX this is wrong, should iterate to collapse to - // XXX last child of last child of last ... - // XXX instead of beginning of last child of body. - result = selection->Collapse(lastChild, 0); + // See if the last child is a text node; if so, set offset: + PRUint32 offset = 0; + if (IsTextNode(lastChild)) + { + nsCOMPtr text (do_QueryInterface(lastChild)); + if (text) + text->GetLength(&offset); + } + result = selection->Collapse(lastChild, offset); ScrollIntoView(PR_FALSE); } } @@ -3833,7 +3904,7 @@ nsEditor::IsPreformatted(nsIDOMNode *aNode, PRBool *aResult) if (!aResult || !content) return NS_ERROR_NULL_POINTER; - if (!mPresShell) return NS_ERROR_NULL_POINTER; + if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; result = mPresShell->GetPrimaryFrameFor(content, &frame); if (NS_FAILED(result)) return result; @@ -4135,7 +4206,8 @@ nsAutoSelectionReset::nsAutoSelectionReset(nsIDOMSelection *aSel) mSel->GetAnchorOffset(&mStartOffset); mSel->GetFocusNode(getter_AddRefs(mEndNode)); mSel->GetFocusOffset(&mEndOffset); - mInitialized = PR_TRUE; + if (mStartNode && mEndNode) + mInitialized = PR_TRUE; } } diff --git a/mozilla/editor/libeditor/base/nsEditor.h b/mozilla/editor/libeditor/base/nsEditor.h index c5c4e785b0b..e7e841cc6f6 100644 --- a/mozilla/editor/libeditor/base/nsEditor.h +++ b/mozilla/editor/libeditor/base/nsEditor.h @@ -510,6 +510,11 @@ public: /** returns PR_TRUE if aNode is an editable node */ static PRBool IsEditable(nsIDOMNode *aNode); + /** Find the deep first and last children */ + static nsCOMPtr GetDeepFirstChild(nsCOMPtr aRoot); + static nsCOMPtr GetDeepLastChild(nsCOMPtr aRoot); + + /** from html rules code - migration in progress */ static nsresult GetTagString(nsIDOMNode *aNode, nsString& outString); static nsCOMPtr GetTag(nsIDOMNode *aNode);