diff --git a/editor/base/nsTextEditRules.cpp b/editor/base/nsTextEditRules.cpp index 370e9ad23ef9..b782ccbdd589 100644 --- a/editor/base/nsTextEditRules.cpp +++ b/editor/base/nsTextEditRules.cpp @@ -201,6 +201,10 @@ nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection) // detect empty doc res = CreateBogusNodeIfNeeded(selection); + if (NS_FAILED(res)) return res; + + // create moz-br and adjust selection if needed + res = AdjustSelection(selection, aDirection); } return res; } @@ -1444,3 +1448,67 @@ nsTextEditRules::DeleteEmptyTextNode(nsIDOMNode *aNode) } return PR_FALSE; } + + +nsresult +nsTextEditRules::AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aDirection) +{ + if (!aSelection) return NS_ERROR_NULL_POINTER; + + // if the selection isn't collapsed, do nothing. + PRBool bCollapsed; + nsresult res = aSelection->GetIsCollapsed(&bCollapsed); + if (NS_FAILED(res)) return res; + if (!bCollapsed) return res; + + // get the (collapsed) selection location + nsCOMPtr selNode, temp; + PRInt32 selOffset; + res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset); + if (NS_FAILED(res)) return res; + temp = selNode; + + // are we in an editable node? + while (!mEditor->IsEditable(selNode)) + { + // scan up the tree until we find an editable place to be + res = nsEditor::GetNodeLocation(temp, &selNode, &selOffset); + if (NS_FAILED(res)) return res; + if (!selNode) return NS_ERROR_FAILURE; + temp = selNode; + } + + // are we in a text node? + nsCOMPtr textNode = do_QueryInterface(selNode); + if (textNode) + return NS_OK; // we LIKE it when we are in a text node. that RULZ + + // do we need to insert a special mozBR? We do if we are: + // 1) after a block element AND + // 2) at the end of the body OR before another block + + nsCOMPtr priorNode, nextNode; + res = mEditor->GetPriorHTMLSibling(selNode, selOffset, &priorNode); + if (NS_FAILED(res)) return res; + res = mEditor->GetNextHTMLSibling(selNode, selOffset, &nextNode); + if (NS_FAILED(res)) return res; + + // is priorNode a block? + if (priorNode && mEditor->IsBlockNode(priorNode)) + { + if (!nextNode || mEditor->IsBlockNode(nextNode)) + { + nsCOMPtr brNode; + res = CreateMozBR(selNode, selOffset, &brNode); + if (NS_FAILED(res)) return res; + res = nsEditor::GetNodeLocation(brNode, &selNode, &selOffset); + if (NS_FAILED(res)) return res; + // selection stays *before* moz-br, sticking to it + aSelection->SetHint(PR_TRUE); + res = aSelection->Collapse(selNode,selOffset); + if (NS_FAILED(res)) return res; + } + } + return res; +} + diff --git a/editor/base/nsTextEditRules.h b/editor/base/nsTextEditRules.h index 82fa89e8116f..b241f9c39702 100644 --- a/editor/base/nsTextEditRules.h +++ b/editor/base/nsTextEditRules.h @@ -167,6 +167,8 @@ protected: PRBool DeleteEmptyTextNode(nsIDOMNode *aNode); + nsresult AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aDirection); + // data members nsHTMLEditor *mEditor; // note that we do not refcount the editor nsString mPasswordText; // a buffer we use to store the real value of password editors diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index 370e9ad23ef9..b782ccbdd589 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -201,6 +201,10 @@ nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection) // detect empty doc res = CreateBogusNodeIfNeeded(selection); + if (NS_FAILED(res)) return res; + + // create moz-br and adjust selection if needed + res = AdjustSelection(selection, aDirection); } return res; } @@ -1444,3 +1448,67 @@ nsTextEditRules::DeleteEmptyTextNode(nsIDOMNode *aNode) } return PR_FALSE; } + + +nsresult +nsTextEditRules::AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aDirection) +{ + if (!aSelection) return NS_ERROR_NULL_POINTER; + + // if the selection isn't collapsed, do nothing. + PRBool bCollapsed; + nsresult res = aSelection->GetIsCollapsed(&bCollapsed); + if (NS_FAILED(res)) return res; + if (!bCollapsed) return res; + + // get the (collapsed) selection location + nsCOMPtr selNode, temp; + PRInt32 selOffset; + res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset); + if (NS_FAILED(res)) return res; + temp = selNode; + + // are we in an editable node? + while (!mEditor->IsEditable(selNode)) + { + // scan up the tree until we find an editable place to be + res = nsEditor::GetNodeLocation(temp, &selNode, &selOffset); + if (NS_FAILED(res)) return res; + if (!selNode) return NS_ERROR_FAILURE; + temp = selNode; + } + + // are we in a text node? + nsCOMPtr textNode = do_QueryInterface(selNode); + if (textNode) + return NS_OK; // we LIKE it when we are in a text node. that RULZ + + // do we need to insert a special mozBR? We do if we are: + // 1) after a block element AND + // 2) at the end of the body OR before another block + + nsCOMPtr priorNode, nextNode; + res = mEditor->GetPriorHTMLSibling(selNode, selOffset, &priorNode); + if (NS_FAILED(res)) return res; + res = mEditor->GetNextHTMLSibling(selNode, selOffset, &nextNode); + if (NS_FAILED(res)) return res; + + // is priorNode a block? + if (priorNode && mEditor->IsBlockNode(priorNode)) + { + if (!nextNode || mEditor->IsBlockNode(nextNode)) + { + nsCOMPtr brNode; + res = CreateMozBR(selNode, selOffset, &brNode); + if (NS_FAILED(res)) return res; + res = nsEditor::GetNodeLocation(brNode, &selNode, &selOffset); + if (NS_FAILED(res)) return res; + // selection stays *before* moz-br, sticking to it + aSelection->SetHint(PR_TRUE); + res = aSelection->Collapse(selNode,selOffset); + if (NS_FAILED(res)) return res; + } + } + return res; +} + diff --git a/editor/libeditor/text/nsTextEditRules.h b/editor/libeditor/text/nsTextEditRules.h index 82fa89e8116f..b241f9c39702 100644 --- a/editor/libeditor/text/nsTextEditRules.h +++ b/editor/libeditor/text/nsTextEditRules.h @@ -167,6 +167,8 @@ protected: PRBool DeleteEmptyTextNode(nsIDOMNode *aNode); + nsresult AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aDirection); + // data members nsHTMLEditor *mEditor; // note that we do not refcount the editor nsString mPasswordText; // a buffer we use to store the real value of password editors